cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 USART Interrupt Error

paul23
Associate II
Posted on September 26, 2014 at 00:43

Hi,

I am having issue with the USART interrupt handler in my project. It seems to get stuck in the interrupt handler routine. The status register value is set to 0x1d8 but I don't seem to be able to clear the error state. The interrupt routine used is shown below and I am using the USART_GetITStatus to read error flags/rxne andtc from the status register and USART_ReceiveData to read the data. The communication seems to work for over an hour but then get stuck in the interrupt handler. Paul

void rs485UsartIRQHandler(void)
{
if (USART_GetITStatus(RS485_USART, USART_IT_PE) == SET)
{
USART_ReceiveData(RS485_USART);
millisSinceLastReceive = 0;
}
if (USART_GetITStatus(RS485_USART, USART_IT_FE) == SET)
{
USART_ReceiveData(RS485_USART);
millisSinceLastReceive = 0;
}
if (USART_GetITStatus(RS485_USART, USART_IT_NE) == SET)
{
USART_ReceiveData(RS485_USART);
millisSinceLastReceive = 0;
}
if (USART_GetITStatus(RS485_USART, USART_IT_ORE) == SET)
{
// Dummy read to clear ORE flag
USART_ReceiveData(RS485_USART);
millisSinceLastReceive = 0;
}
if (USART_GetITStatus(RS485_USART, USART_IT_RXNE) == SET)
{
uint8_t newData = USART_ReceiveData(RS485_USART);
Ringbuf_Put(receiveBuffer, &newData);
millisSinceLastReceive = 0;
}
if (USART_GetITStatus(RS485_USART, USART_IT_TC) == SET)
{
DMA_Cmd(RS485_TX_CHANNEL, DISABLE);
USART_ITConfig(RS485_USART, USART_IT_TC, DISABLE);
GPIO_ResetBits(RS485_DE_PORT, RS485_DE_PIN);
transmitterBusy = false;
}
}

8 REPLIES 8
stm322399
Senior
Posted on September 26, 2014 at 09:08

Some STM32 (maybe all of them) requires to clear ORE flag explicitely by writing to ICR register, reading DR is not enough. There must be a ClearFlag function to help you in this task.

Posted on September 26, 2014 at 09:31

Post the content of all control registers at the moment when the problem happens.

JW

paul23
Associate II
Posted on September 29, 2014 at 22:53

Hi,

The chip that I am using is a STM32F100VC so it doesn't have the ICR register like in the F3.

Juts retested it, the SR is now showing 0xF8 which is showing an overrun error but it does not get clear in the handler. I have step through the handler using gdb but the USART_GetITStatus is not set for the overrun flag.

The control registers value are:

CR1 = 0x202c // USART, Rx interrupt, RX and TX enabled.

CR2 = 0x0

CR3 = 0x80 // DMA transmitter

Paul

paul23
Associate II
Posted on September 29, 2014 at 22:55

The usart flag definition from the st library are:

#define USART_IT_PE ((uint16_t)0x0028)
#define USART_IT_TXE ((uint16_t)0x0727)
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_IT_RXNE ((uint16_t)0x0525)
#define USART_IT_IDLE ((uint16_t)0x0424)
#define USART_IT_LBD ((uint16_t)0x0846)
#define USART_IT_CTS ((uint16_t)0x096A)
#define USART_IT_ERR ((uint16_t)0x0060)
#define USART_IT_ORE ((uint16_t)0x0360)
#define USART_IT_NE ((uint16_t)0x0260)
#define USART_IT_FE ((uint16_t)0x0160)

Posted on September 30, 2014 at 09:01

> Juts retested it, the SR is now showing 0xF8 which is showing an overrun error but it does

> not get clear in the handler. I have step through the handler using gdb but the

> USART_GetITStatus is not set for the overrun flag.

It's a well deserved punishment for using the ''library''. Use your head and raw register access.

The ''library'' tries to be smart, and masks the flags read from the status register  by the respective interrupt enable bit. Particularly, for ORE it masks with the EIE bit, omitting the fact that ORE has another path to trigger an interrupt, through RXNEIE (see ''USART interrupt mapping diagram'', Fig.266 in RM0041 rev 4).

Btw. you are lucky you stumbled upon this, otherwise it might have remained as a bomb ticking in your code waiting for the (presumably rare) occurence of overflow...

My guess is that there's quite a lot of code out there with this bomb embedded...

JW

stm322399
Senior
Posted on September 30, 2014 at 09:05

Try USART_GetFlagStatus instead of USART_GetITStatus. The first does not care about your interrupt configuration and will detect the ORE condition.

Posted on September 30, 2014 at 09:15

This also may be a known ''library'' bug which may be ''corrected'' in a newer version.

As I don't use the ''library'' I have only a random selection of it for various families, and don't attempt to keep them up to date. In one of them I found

#define USART_IT_ORE_RX                      ((uint16_t)0x0325) /* In case interrupt is generated if the RXNEIE bit is set */

#define USART_IT_ORE_ER                      ((uint16_t)0x0360) /* In case interrupt is generated if the EIE bit is set */

while USART_IT_ORE is missing.

I still maintain that the ''library'' is superfluous and buggy, and recommend against using it.

JW

Posted on September 30, 2014 at 09:47

Release Notes for STM32F10x Standard Peripherals Library Drivers

[...]

V3.6.0 / 27-January-2012

[...]

  • stm32f10x_usart.h/.c

    • Update procedure to check on overrun error interrupt pending bit, defines for the following flag are added:

      • USART_IT_ORE_RX:

        this flag is set if 

        overrun error interrupt

        occurs and RXNEIE bit is set

      • USART_IT_ORE_ER:

        this flag is set if 

        overrun error interrupt

        occurs and EIE bit is set