Forum: Mikrocontroller und Digitale Elektronik infinite loop, externer Interrupt, STM32F746, HAL-Library


von epika (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

siehe Code unten. Ich versuche via HAL-Library ein externen 
Interrupt-Eingang zu integrieren.

Sobald der Eingang triggert, stürzt das Programm ab, bzw. geht gemäss 
Debugger in eine "infinite loop", siehe auch Bild Anhang.
Die LED im loop blinkt dann auch nicht mehr.

Was mache ich falsch? :-(
Wo findet man eigentlich all diese HAL-Funktionen/Dokumentation (geht 
das überhaupt ohne CubeMx?)? Aktuell behelfe ich mir da mit der 
Google-Suche. Aber das ist mühsam.

Mit Arduino (stm32duino) kann ich einfach attachInterrupt() machen, und 
es läuft.

1
#include "stm32f7xx.h"
2
#include "stm32f7xx_hal_def.h"
3
#include "../Utilities/STM32746G-Discovery/stm32746g_discovery.h"
4
5
static void SystemClock_Config(void);
6
static void MX_GPIO_Init(void);
7
void Error_Handler(void);
8
9
int main(void)
10
{
11
12
    HAL_Init();
13
    //NVIC_SetPriority(SysTick_IRQn, -1);
14
15
    /* Configure the system clock to 216 MHz */
16
    SystemClock_Config();
17
  
18
    MX_GPIO_Init();
19
20
21
22
23
    while (1)
24
    {
25
  HAL_Delay(5);
26
        HAL_Delay(500);
27
        //HAL_GPIO_TogglePin( GPIOI , GPIO_PIN_8);
28
        HAL_GPIO_TogglePin( GPIOA , GPIO_PIN_7);
29
    }
30
}
31
32
static void SystemClock_Config(void)
33
{
34
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
35
    RCC_OscInitTypeDef RCC_OscInitStruct;
36
37
    /* Enable Power Control clock */
38
    __HAL_RCC_PWR_CLK_ENABLE();
39
40
    /* The voltage scaling allows optimizing the power consumption when the device is
41
     clocked below the maximum system frequency, to update the voltage scaling value
42
     regarding system frequency refer to product datasheet.  */
43
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
44
45
    /*##-1- System Clock Configuration #########################################*/
46
    /* Enable HSE Oscillator and activate PLL with HSE as source */
47
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
48
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
49
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
50
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
51
    RCC_OscInitStruct.PLL.PLLM = 25;
52
    RCC_OscInitStruct.PLL.PLLN = 400;
53
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
54
    RCC_OscInitStruct.PLL.PLLQ = 8;
55
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
56
57
    /* Activate the Over-Drive mode */
58
    HAL_PWREx_EnableOverDrive();
59
60
    /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
61
     clocks dividers */
62
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
63
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
64
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
65
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
66
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
67
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6);
68
69
}
70
71
static void MX_GPIO_Init(void)
72
{
73
  GPIO_InitTypeDef GPIO_InitStruct = {0};
74
75
  /* GPIO Ports Clock Enable */
76
  //__HAL_RCC_GPIOB_CLK_ENABLE();
77
  __HAL_RCC_GPIOI_CLK_ENABLE();
78
  __HAL_RCC_GPIOA_CLK_ENABLE();
79
80
  /*Configure GPIO pin : PI13 */
81
  GPIO_InitStruct.Pin = GPIO_PIN_13;
82
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
83
  GPIO_InitStruct.Pull = GPIO_NOPULL;
84
  HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
85
86
  GPIO_InitStruct.Pin = GPIO_PIN_7;
87
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
88
  GPIO_InitStruct.Pull = GPIO_NOPULL;
89
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
90
91
  GPIO_InitStruct.Pin = GPIO_PIN_8;
92
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
93
  GPIO_InitStruct.Pull = GPIO_NOPULL;
94
  HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
95
96
  /* EXTI interrupt init*/
97
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0);
98
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
99
  //NVIC_SetPriority(SysTick_IRQn, -1);
100
101
}
102
103
/* USER CODE BEGIN 4 */
104
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
105
{
106
  //HAL_GPIO_TogglePin( GPIOI , GPIO_PIN_8);
107
  //HAL_GPIO_TogglePin( GPIOA , GPIO_PIN_7);
108
  /*
109
  if(GPIO_Pin == GPIO_PIN_13)
110
  {
111
  }
112
  */
113
  //__NOP();
114
}
115
/* USER CODE END 4 */
116
void Error_Handler(void)
117
{
118
  /* USER CODE BEGIN Error_Handler_Debug */
119
  /* User can add his own implementation to report the HAL error return state */
120
  /* USER CODE END Error_Handler_Debug */
121
}

von utzutr (Gast)


Lesenswert?

du nutzt zwar die callback .. aber ich vermisse die eigentliche ISR  mit 
der HAL  ISR funktion ( die am ende deine callback aufruft )

von PittyJ (Gast)


Lesenswert?

Für z.B. Uart muss ich immer noch eine IQRHandler aktivieren.

void USART3_IRQHandler(void)
{
    HAL_UART_IRQHandler(g_cp_HandleUart[2]);
}

g_cp_HandleUart[] ist mein globales Handle-Array


Vielleicht braucht GPIO das auch so ähnlich?

Die IRQs, die verfügbar sind, stehen bei mir in
startup_stm32h743zitx.s
..
  .word     USART1_IRQHandler
  .word     USART2_IRQHandler
--

von epika (Gast)


Lesenswert?

utzutr schrieb:
> du nutzt zwar die callback .. aber ich vermisse die eigentliche ISR  mit
> der HAL  ISR funktion ( die am ende deine callback aufruft )

wird wohl schon im stm32fxx_hal_gpio.c definiert:
1
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
2
{
3
  /* Prevent unused argument(s) compilation warning */
4
  UNUSED(GPIO_Pin);
5
  
6
  /* NOTE: This function Should not be modified, when the callback is needed,
7
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
8
   */
9
}


Gibt es eigentlich (offizielle) Beispiele/Dokumentation zu dieser 
HAL-Library?

von epika (Gast)


Lesenswert?

äh falscher Code, hier wird die Callback aufgerufen, im 
stm32fxx_hal_gpio.c - File:
1
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
2
{
3
  /* EXTI line interrupt detected */
4
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
5
  {
6
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
7
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
8
  }
9
}

von Thilo L. (bc107)


Lesenswert?

Kommt mir bekannt vor... Deine INT-Routine wird nicht im 
Interrupt-Vektor eingetragen, sodass dort über den Default Vector bei 
Eintreten eines Interrupts in diese Endlos-Schleife gesprungen wird.
Ich weiß jetzt nicht mehr auswending, was genau ich damals im Code 
ändern musste, aber schau Dir mal Deine Interrupt Vector Table an und 
checke, ob an der relevanten Stelle Deine gewollte INT-Routine 
eingetragen ist.

von Hans (Gast)


Lesenswert?

Interrupt Flag wird nicht gelöscht. Deswegen andauernd Interrupts was 
der Compiler wohl als "infinite loop" übersetzt.

von Johannes S. (Gast)


Lesenswert?

epika schrieb:
> Wo findet man eigentlich all diese HAL-Funktionen/Dokumentation (geht
> das überhaupt ohne CubeMx?)

z.B. auf github im STM32CubeF7 Repo sind Beispiele und Doku.
Wie schon genannt, fehlt vermutlich die eigentliche ISR und der 
Interrupt landet im Defaulthandler.

https://github.com/STMicroelectronics/STM32CubeF7/blob/e96f98542c6782d97bdd0c50833ee4b70130f3a7/Projects/STM32F746ZG-Nucleo/Examples/GPIO/GPIO_EXTI/Src/stm32f7xx_it.c#L155-L158

von pegel (Gast)


Lesenswert?

Ich nutze statt irgend eines Delay immer:
1
//main.c:
2
/* USER CODE BEGIN 4 */
3
void HAL_SYSTICK_Callback(void){
4
...}
5
/* USER CODE END 4 */

Um diese zu nutzen, muss ich in der stm32fxxx_it.c im SysTick_Handler 
den Aufruf von HAL_SYSTICK_IRQHandler eintragen, von dem die Funktion 
HAL_SYSTICK_Callback aufgerufen wird.
Dieses Prinzip ist für alle Interrupt/Callback identisch:
1
void SysTick_Handler(void)
2
{
3
  /* USER CODE BEGIN SysTick_IRQn 0 */
4
5
  /* USER CODE END SysTick_IRQn 0 */
6
  HAL_IncTick();
7
  /* USER CODE BEGIN SysTick_IRQn 1 */
8
  HAL_SYSTICK_IRQHandler();
9
  /* USER CODE END SysTick_IRQn 1 */
10
}

von epika (Gast)


Lesenswert?

Thilo L. schrieb:
> aber schau Dir mal Deine Interrupt Vector Table an und
> checke, ob an der relevanten Stelle Deine gewollte INT-Routine
> eingetragen ist.

also CubeMx fügt folgendes im stm32f7xx_it.c hinzu:
1
void EXTI15_10_IRQHandler(void)
2
{
3
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */
4
5
  /* USER CODE END EXTI15_10_IRQn 0 */
6
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
7
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */
8
9
  /* USER CODE END EXTI15_10_IRQn 1 */
10
}

und das hier ist schon vorhanden:
1
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
2
{
3
  /* EXTI line interrupt detected */
4
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
5
  {
6
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
7
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
8
  }
9
}

Hans schrieb:
> Interrupt Flag wird nicht gelöscht. Deswegen andauernd Interrupts was
> der Compiler wohl als "infinite loop" übersetzt.

In den Beispielen im Internet, wenn man die Callback 
"HAL_GPIO_EXTI_Callback" verwendet, finde ich keine Zeile die das Flag 
löscht.
Wenn man direkt "void EXTI15_10_IRQHandler(void)" verwendet, dann 
schon... muss ich da noch eine Zeile hinzufügen um das Flag zu löschen? 
Wieso macht CubeMx dies nicht automatisch :-D ??

ijo, nicht einfach....

von epika (Gast)


Lesenswert?

epika schrieb:
> Wieso macht CubeMx dies nicht automatisch :-D ??
1
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

wird hier schon gelöscht.
Also lag es wohl am fehlenden Code:
1
void EXTI15_10_IRQHandler(void)
2
{
3
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */
4
  /* USER CODE END EXTI15_10_IRQn 0 */
5
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
6
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */
7
  /* USER CODE END EXTI15_10_IRQn 1 */
8
}

muss ich morgen testen....

von Jens R. (tmaniac)


Lesenswert?

Hast du einen ST Link oder anderen Debugger?

Die Infinite Loop ist der Auffangbehälter des ErrorHandlers.
Um zu wissen wie man da hin gekommen ist, muss man den CallStack 
anschauen. Dann kann man auch die ErrorCodes interpretieren welche die 
HAL abspeichert.

von Bingo Bingo (Gast)


Lesenswert?

Setze nur mal versuchsweise ein

extern "C"

vor:

void EXTI15_10_IRQHandler(void)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.