Home > Net >  Interrupt not returning control to main
Interrupt not returning control to main

Time:04-09

Hi I'm using STM32G070 nucleo board and I was trying to learn how to use UART with interrupts. I made a simple led blinking program in the main and in the interrupt handler there is a simple echo program. The echo works fine but the led blinking never starts.

Below is my code:

//while loop for led blinking
while(1)
    {
        
        GPIOA->BSRR     |= (GPIO_BSRR_BS5);
        //delaySys is a blocking delay function that takes milli seconds as input
        delaySys(1000);
        GPIOA->BSRR     &=~(GPIO_BSRR_BS5);
        GPIOA->BSRR     |= (GPIO_BSRR_BR5);
        delaySys(1000);
        
    }
    

Next is my interrupt handler

void USART2_IRQHandler()
{
    
    if((USART2->ISR) & (USART_ISR_RXNE_RXFNE))
        {
            
            USART2->TDR = USART2->RDR;
            while(!((USART2->ISR) & (USART_ISR_TC)))
                ;
            NVIC_ClearPendingIRQ(USART2_IRQn);
            
        }
        
    if(((USART2->ISR) & (USART_ISR_TXE_TXFNF)))
    {
        
        //TRANSMISSION COMPLETE
        
        
    }
    
}

CodePudding user response:

If you expect a subsequent stream of bytes from the UART, it might sometimes be justified to hang in the ISR and poll, until you got the expected amount. However, the rest of the program will hang up and wait while you do.

You shouldn't need to call NVIC_ClearPendingIRQ from inside the ISR, because the flag causing the interrupt should be cleared automatically, typically by reading it followed by a data register access or such. Check the UART part of the manual for register descriptions.

A better but more complex way to deal with UART rx interrupts without stalling is to use DMA. I think most STM32 should have support for this, but I'm not sure.

Looking at your blinking code however, it's problematic:

    // light up 1000ms
    GPIOA->BSRR     |= (GPIO_BSRR_BS5);
    delaySys(1000);

    // lights off
    GPIOA->BSRR     &=~(GPIO_BSRR_BS5); 

    // light up some other LED? NOTE: BR5 not BS5
    GPIOA->BSRR     |= (GPIO_BSRR_BR5);
    delaySys(1000);

This can do one of two things:

  • If GPIO_BSRR_BS5 and GPIO_BSRR_BR5 are the same bit masks, then it lits up the LED approximately 1000ms and turns it off for approximately 50-100ns. The LED stays lit around 99.99% of the time.
  • If GPIO_BSRR_BS5 and GPIO_BSRR_BR5 are different bit masks, then one LED will blink with 1000ms duty cycle and another stay lit 100% of the time.

CodePudding user response:

Okay I did fix the problem somehow. I had enabled the interrupt for tx before but when I have disabled it, everything works fine. Seems like Tx was sending an interrupt request and was competing with main.

  • Related