Sergio Castillo Sergio Castillo - 3 months ago 9
C Question

How to handle global variables in interrupts

I am a newbie in this of embedded systems. For my final degree project I am developing a system working with a STM NUCLEO Board with a STM32F411RE microcontroller.

In addition, I am working with stmcube32 for loading initialization code.

At this point I am stuck, but first let me explain you a litle background:


  • I have three interrupt routines handling the same flag, as you can see in the source file stm32f4xx_it.c:

    void EXTI15_10_IRQHandler(void) {

    /* USER CODE BEGIN EXTI15_10_IRQn 0 */

    if (__HAL_GPIO_EXTI_GET_IT(BOTON1_Pin) != RESET) {
    __HAL_GPIO_EXTI_CLEAR_IT(BOTON1_Pin);
    boton_Flag = 1;
    }
    if (__HAL_GPIO_EXTI_GET_IT(BOTON2_Pin) != RESET) {
    __HAL_GPIO_EXTI_CLEAR_IT(BOTON2_Pin);
    boton_Flag = 2;
    }
    if (__HAL_GPIO_EXTI_GET_IT(BOTON3_Pin) != RESET) {
    __HAL_GPIO_EXTI_CLEAR_IT(BOTON3_Pin);
    boton_Flag = 3;
    }
    /* USER CODE END EXTI15_10_IRQn 0 */
    //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
    //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
    //HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
    /* USER CODE BEGIN EXTI15_10_IRQn 1 */

    /* USER CODE END EXTI15_10_IRQn 1 */
    }

  • In the header file stm32f4xx_it.h it is declared my global variable this way:

    extern volatile uint8_t boton_Flag;

  • BOTON_1
    ,
    BOTON_2
    ,
    BOTON_3
    are the names assigned to the pins, which are configured as interrupts by raising trigger edge detection.

  • While debugging, the three interrupts work perfectly when pressing the buttons, each one at its right time.

  • The variable
    boton_Flag
    is defined in main.c this way:

    volatile uint8_t boton_Flag = 0;

  • Inside the
    main
    function I pass my global variable
    boton_Flag
    to a function which is declared in controlpanel.h (I have
    #include "controlpanel.h"
    at the beginning of the file):

    int main(void) {

    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

    /* MCU Configuration----------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick.*/
    HAL_Init();

    /* Configure the system clock */
    SystemClock_Config();

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_TIM3_Init();
    MX_TIM4_Init();

    /* Initialize interrupts */
    MX_NVIC_Init();

    /* USER CODE BEGIN 2 */
    init_PanelConfig();

    numeroJugadores(boton_Flag);

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1) {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

    }
    /* USER CODE END 3 */
    }

  • The function
    numeroJugadores(boton_Flag);
    does the following:

    uint8_t numeroJugadores(uint8_t boton_Flag) {
    uint8_t players = 4;

    while (boton_Flag != 2);
    boton_Flag = 0;

    while (boton_Flag != 2) {
    if (boton_Flag == 1)
    boton_Flag = 0;
    {
    players++;
    if ((players > 4) || (players < 1) ) {
    players = 0;
    }
    }
    while (boton_Flag != 1);

    switch(players) {
    case 1:
    lcd_clear();
    lcd_goto(0, 0);
    lcd_on();
    lcd_puts("Numero de");
    lcd_goto(0, 1);
    lcd_puts("jugadores: 1");
    break;
    case 2:
    lcd_clear();
    lcd_goto(0, 0);
    lcd_on();
    lcd_puts("Numero de");
    lcd_goto(0, 1);
    lcd_puts("jugadores: 2");
    break;
    case 3:
    lcd_clear();
    lcd_goto(0, 0);
    lcd_on();
    lcd_puts("Numero de");
    lcd_goto(0, 1);
    lcd_puts("jugadores: 3");
    break;
    case 4:
    lcd_clear();
    lcd_goto(0, 0);
    lcd_on();
    lcd_puts("Numero de");
    lcd_goto(0, 1);
    lcd_puts("jugadores: 4");
    break;
    }
    }
    return players;
    }



So, what is my problem? When debugging, I realise that the program remains stuck in the first statement
while (boton_Flag != 2);
inside the function above.

It should stay there until I press the BOTON2 to change the flag to value 2 and this way the program keep running. However, when I press the button, in spite of the program JUMPS TO THE INTERRUPT AND CHANGES THE VALUE, when it returns to the function, the value is again 0 (its initialized value).

My conclusion, which may be wrong, is that I am not passing the variable to the function correctly, and the program interpret it as a local variable inside the function, but I am not sure at all.

I hope to have been explained as well as possible, if not, please let me know.

Answer

You're right, you aren't passing the variable correctly. The way you have it, when the function is called you create a local variable (local to the function) and assign it the value of your global boton_flag.

There are two ways that you could fix this:
1. Just use the global variable in the function. If it's already global there is no need to pass it to your function.
2. Pass boton_flag by reference. i.e. numeroJugadores(&boton_Flag);. If you do it this way, you'll have a pointer to boton_flag which slightly changes the code in numeroJugadores (you have to dereference boton_flag every time you use it).

Comments