Elmore
Elmore

Reputation: 276

STM32: Unable to exit interrupt handler for UART interrupt

I'm implementing a simple UART receive-transmit protocol on STM32F103, the library/boilerplate code I'm using here is LL, not HAL (as HAL includes insane amounts of overhead)

My problem is that after successfully entering the interrupt handler "USART1_IRQHandler" it keeps cycling on forever. My code is here:

    void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    int ii = 0;
    for(ii=0; ii<4;  ii++){
        LL_mDelay(40);
        LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);
        LL_mDelay(40);
        LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);

    }
    uint8_t cc = LL_USART_ReceiveData8(USART1);
    LL_USART_TransmitData8(USART1, cc);
    LL_mDelay(130);

    //LL_USART_ClearFlag_RXNE(USART1);
    //NVIC_ClearPendingIRQ( USART1_IRQn );

  /* USER CODE END USART1_IRQn 0 */
  /* USER CODE BEGIN USART1_IRQn 1 */
  /* USER CODE END USART1_IRQn 1 */
}

and in main.c I have:

LL_USART_EnableIT_RXNE(USART1);
  while (1)
  {

        LL_mDelay(300);
        LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);
        LL_mDelay(300);
        LL_GPIO_TogglePin(GPIOA, LL_GPIO_PIN_5);

        //LL_USART_EnableIT_TC(USART1);

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }

The GPIO_Toggle commands are just there to blink an led so I know what's going on. Here's waht happens: When I power the MC up, it enters the main loop and blinks slowly. When I send something (~10 bytes) through UART, the led starts blinking fast, indicating that it has entered the interrupt handler. PProblem is that it never stops and keeps spinning around in the interrupt handler.

I've tried using the now commented functions

LL_USART_ClearFlag_RXNE(USART1);
NVIC_ClearPendingIRQ( USART1_IRQn );

either alone or in combination but they have absolutely no effect on anything. What am I doing wrong? How can I exit the handler?

Upvotes: 2

Views: 3832

Answers (2)

ajxs
ajxs

Reputation: 3618

The system time utilised for controlling delays is updated by a periodic sysTick interrupt. If the RXNE interrupt has a higher priority than the sysTick interrupt it won't be handled while you're inside your RXNE IRQ handler, so the time will never increment and your delay end time will never be reached. Depending on how your delay is implemented, it may just put the CPU in a spinlock that can never exit.

Upvotes: 1

0___________
0___________

Reputation: 67476

Actually everything in your USART interrupt handler is wrong.

  1. You do not check what has caused the interrupt. If it is RXNE flag you should just load the value from the DR register. You do not need to clear any flags. If it is TXE flag you can store the data to the DR register. You cant clear this flag any other way. If you do not have any data to send you need to disable the TXE interrupt. Otherwise it will trigger continuously.

You can't just read and write the data register when you want to. You need to know if you are allowed to

You should also control the error statuses.

  1. You must not use any delays in the interrupt routines. Keep it as fast as possible.
  2. Do not touch NVIC exept for enabling and disabling the interrupts, as for now you do not know what it is for.

Upvotes: 4

Related Questions