14
\$\begingroup\$

I am using an STM32F105 to communicate with a Linx GPS chip using a UART.

If I don't use interrupts (if I just poll the RX flag) then it works just fine. But I'm getting unexpected results when trying to use interrupts.

For example, if I only enable the RXNE ("RX not empty") interrupt using USART_ITConfig(USARTx, USART_IT_RXNE), then the code should only vector to the ISR for this one specific event. But the interrupt is being triggered for an Overrun condition, too.

As far as clearing the flags, it seems that the method depends on the flag. To clear the Overrun flag (USART_IT_ORE), the User Manual explains that I should first read the USARTx_SR register, then read the USARTx_DR register. This does work; the flag is cleared.

There is also a USART_ClearITPendingBit() function, but it only accepts a small subset of flags.

There are eight different interrupt sources that can be selectively enabled, and ten different flags. Is there a summary somewhere of how to manage all of these flags?

asked Mar 14, 2016 at 21:09
\$\endgroup\$

4 Answers 4

24
\$\begingroup\$

Generally, you only need to handle the interrupt flags which you have specifically enabled with USART_ITConfig().

However, if you enable the RXNE interrupt (USART_ITConfig(USARTx, USART_IT_RXNE)) then this also enables the Overrun interrupt! So you must handle both of those.

intmap

The USART flags can be confusing. There are separate status flags and interrupt flags and they share similar names. For example: USART_IT_RXNE and USART_FLAG_RXNE.

In addition, there are various methods to clear these flags. For example, the USART_ClearITPendingBit() function only works for four (of the ten) possible flags.

Here is a summary of the interrupt flags and how to use them. These are specific for the STM32F105, but are representative:


USART_IT_TXE - "Transmit Data register empty"

  • It is cleared automatically when calling USART_SendData()

USART_IT_RXNE - "Receive Data register not empty"

  • It is cleared automatically when calling USART_ReceiveData(USARTx)

  • It can be cleared manually by calling USART_ClearITPendingBit(USARTx, USART_IT_RXNE)


USART_IT_TC - "Transmission complete"

  • It is cleared automatically by:

    • USART_GetITStatus(USARTx, USART_IT_TC) followed by
    • USART_SendData()
  • It can be also be cleared manually by calling USART_ClearITPendingBit(USARTx, USART_IT_TC)


USART_IT_CTS - "CTS change"

  • Cleared by calling USART_ClearITPendingBit(USARTx, USART_IT_CTS)

USART_IT_LBD - "LIN Break detected"

  • Cleared by calling USART_ClearITPendingBit(USARTx, USART_IT_LBD)

USART_IT_PE - "Parity error"

  • Cleared by:
    • USART_GetITStatus(USARTx, USART_IT_PE) followed by
    • USART_ReceiveData(USARTx)

USART_IT_NE - "Noise error"

  • Cleared by:
    • USART_GetITStatus(USARTx, USART_IT_NE) followed by
    • USART_ReceiveData(USARTx)

USART_IT_ORE - "Overrun error"

  • Cleared by:
    • USART_GetITStatus(USARTx, USART_IT_ORE) followed by
    • USART_ReceiveData(USARTx)()

USART_IT_IDLE - "Idle line detected"

  • Cleared by:
    • USART_GetITStatus(USARTx, USART_IT_IDLE) followed by
    • USART_ReceiveData(USARTx)()
answered Mar 14, 2016 at 21:09
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Yep, I answered my own question :) If I had found a list like this earlier, it would have saved me a good amount of time. I hope it helps someone! \$\endgroup\$ Commented Mar 14, 2016 at 22:17
  • 2
    \$\begingroup\$ This answer is gold; very clear reference of how to clear each of these interrupts. \$\endgroup\$ Commented Sep 22, 2016 at 23:21
3
\$\begingroup\$

Just want to add some my experience on this problem, I follow the instructions:

USART_IT_ORE - "Overrun error"

Cleared by: USART_GetITStatus(USARTx, USART_IT_ORE) followed by USART_ReceiveData(USARTx)()

Is seems not work, and the following command work for me instead:

USART_GetFlagStatus(USARTx, USART_IT_ORE) followed by USART_ReceiveData(USARTx)

If you look into the functions:

USART_GetFlagStatus() and USART_ReceiveData()

You will find what exactly Bitsmack wrote before... "First read the USARTx_SR register, then read the USARTx_DR register."

Hopefully it work for you and save lot more time on this issue.=)

answered Oct 12, 2018 at 16:59
\$\endgroup\$
5
  • \$\begingroup\$ Thanks for your information! I don't recognize USART_GetFlat(). Can you tell me where it comes from? \$\endgroup\$ Commented Oct 12, 2018 at 17:05
  • \$\begingroup\$ I am sorry that I wrongly typed on the command,, it should be USART_GetFlagStatus() followed by USART_ReceiveData(), the original post was corrected. Thanks Bitsmack. \$\endgroup\$ Commented Oct 18, 2018 at 1:59
  • \$\begingroup\$ Excellent, thank you! It looks like the function names have changed. Are you using a Standard Peripheral Library or one of the STMCube HALs? For which family of microcontrollers? \$\endgroup\$ Commented Oct 18, 2018 at 7:27
  • \$\begingroup\$ Thanks for the good answer. BUT: I receive one character on STM32L476, no further bytes are received (no signal on oszi), but permanent receive a FE (framing error) interrupt. Cannot even clear this interrupt. Any ideas what's the reason? \$\endgroup\$ Commented May 1, 2021 at 19:21
  • 1
    \$\begingroup\$ @peets - There is a way to clear the Framing Error (FE) flag. You need to call LL_USART_ClearFlag_ORE(USARTx_INSTANCE); which writes to the ICR register WRITE_REG(USARTx->ICR, USART_ICR_ORECF);. That should clear the Framing Error (FE) flag. Also, if you have Error Interrupt Enable (EIE) set, you may enter error handling code which sits forever. If you're getting framing errors check baud rate and line breaks (UART line staying low for period of time). \$\endgroup\$ Commented Jul 18, 2022 at 17:06
1
\$\begingroup\$

reading status and data registers clears overrun error.

uint32_t cnt_rx2_overrun;
void USART2_IRQHandler(void)
{
 uint32_t status = USART2->SR;
 uint8_t ch;
 if (status & USART_SR_RXNE) { // rx data
 ch = USART2->DR;
 // parse data
 }
 else if (status & USART_SR_ORE){ // overrun error
 ch = USART2->DR; // reading clears the ORE flag
 cnt_rx2_overrun++;
 }
}
```
answered Oct 28, 2021 at 16:01
\$\endgroup\$
0
\$\begingroup\$

This code is working very well for me, running on STM32L4: The buffer to store the received data (guc_RXBuffer) and buffer index (gui16_RXWritePointer) are global variables, treated in the main loop, outside the interrupt routine. Each error can be monitored using the global error counters, optional.

 void USART2_IRQHandler(void)
{
 /* USER CODE BEGIN USART2_IRQn 0 */
 uint32_t ui32_ISR_Reg;
 ui32_ISR_Reg = USART2->ISR; // get the Interrupt and status register content
 if(ui32_ISR_Reg & 0x0F) { // One or more Error flags are active (Overrun, Noise, Framing, Parity)
 USART2->RQR = USART_RQR_RXFRQ; // Clear the RXNE flag and discard the received data without reading it
 if(ui32_ISR_Reg & USART_ISR_ORE) { // Overrun
 USART2->ICR = USART_ICR_ORECF; // Clear the Overrun error flag
// gui16_LoRa_ORE++;
 }
 if(ui32_ISR_Reg & USART_ISR_NE) { // Noise
 USART2->ICR = USART_ICR_NCF; // Clear the Noise error flag
// gui16_LoRa_NE++;
 }
 if(ui32_ISR_Reg & USART_ISR_FE) { // Framing
 USART2->ICR = USART_ICR_FECF; // Clear the Framing error flag
// gui16_LoRa_FE++;
 }
 if(ui32_ISR_Reg & USART_ISR_PE) { // Parity
 USART2->ICR = USART_ICR_PECF; // Clear the Parity error flag
// gui16_LoRa_PE++;
 }
 return;
 }
 if((USART2->CR1 & USART_CR1_RXNEIE) && (ui32_ISR_Reg & USART_ISR_RXNE)) { // RXNE flag will be cleared by reading of DR register
guc_RXBuffer[gui16_RXWritePointer] = (unsigned char)(USART2->RDR & 0xFFU); // reading DR register
 } 
 return; // avoid calling the HAL_UART_IRQHandler bellow
 /* USER CODE END USART2_IRQn 0 */
 HAL_UART_IRQHandler(&huart2);
 /* USER CODE BEGIN USART2_IRQn 1 */
 /* USER CODE END USART2_IRQn 1 */
}
answered May 30, 2024 at 12:52
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.