cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 USART (overrun)

oversc0re
Associate II
Posted on May 14, 2014 at 16:18

Hello,

I am using USART 1 at 115200 and todayserious problems with USART overrun started to appear (yesterday everything was fine and I don't seem to remember any significant changes on this portion of the code). Single character transmission works, but as soon as I send two (or more) characters to the USART, overrun occurs. Only the first character is read, all others are lost. It looks like I can't read bytes from the data registers fast enough although I can't see why. Also I was pretty sure that the USART has a few bytes of FIFO buffer on the RX side but I'm not so sure anymore. Here's my UART interrupt routine:

void USART1_IRQHandler(void)
{
static int c;
#if CoOS
CoEnterISR();
#endif
// ---------- TXE interrupt ------------------
if( USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
c = rbFifo_get(&txFifo[0]);
if (c == -1) // Buffer empty, transmit complete
{
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); // Can't clear the TXE (cleared by writing into the DR) thus, disble int.
}
else
{
USART_SendData(USART1, c & 0xFF); // Send new char (TXE us cleared upon writing to TX reg.)
}
}
// ---------- RXNE interrupt ------------------
else if( USART_GetITStatus(USART1, USART_IT_RXNE) )
{
// Put data to circular buffer
if (rbFifo_put(&rxFifo[0],USART_ReceiveData(USART1)) == -1)
{
error(ERR_FIFO_FULL, 0x11);
}
#if CoOS
isr_SetFlag(USARTx_rxFlag[0]); // Flag character received
#endif
} else if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)
{
if (rbFifo_put(&rxFifo[0],USART_ReceiveData(USART1)) == -1)
{
error(ERR_FIFO_FULL, 0x11);
}
} else
{
error(ERR_UNHANDLED_INT,1);
USART1->SR = 0;
}
#if CoOS
CoExitISR();
#endif
}

Received bytes are just pushed to a RB fifo buffer and nothing else. Any suggestions on this matter would really be appreciated. Regards, over.
4 REPLIES 4
Posted on May 14, 2014 at 16:30

Also I was pretty sure that the USART has a few bytes of FIFO buffer on the RX side

It does not, there's a shift register, and a holding register which must be cleared before the last bit is shifted in.

Don't do this if-then-else thing, it assumes multiple events can't be signalled together, which is a false premise.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on May 14, 2014 at 16:32

> Also I was pretty sure that the USART has a few bytes of FIFO buffer on the RX side

Did you consult the manual (RM0008)?

No, the receiver is double-buffered (read: after a full frame is received, it is transferred from shift register into a single-item buffer), and if FIFO-like action is desired, DMA into SRAM has to be used.

> It looks like I can't read bytes from the data registers fast enough although I can't see why.

Other interrupts of the same/higher priority (including any OS-imposed stuff), lengthy FIFO push/pull routines (we can't see them)...

Posted on May 14, 2014 at 16:43

> Don't do this if-then-else thing, it assumes multiple events can't be signalled together, which is a false premise.

Also, the status register should be read only once, as reading it is part of the hardware clearing sequence of some of the flags in it (or, big care has to be taken, when is the data register read). This sort of precludes using the ''library''

USART_GetFlagStatus

(), but who said the ''library'' is useful. JW
oversc0re
Associate II
Posted on May 15, 2014 at 09:46

Thanx guys for your fast replies. I optimized the code as suggested (one SR read, no library routines, rechecked the FIFO, but It's as optimized as it can be). The result was a bit better but still not good enough.

Today as I was explaining the problem to a college, It crossed my mind that yesterday I lowered the clock speed from 8MHz to 4 MHz (power sensitive device). I restored the 8MHz clock and it is 99% better.

Sometimes ORE still occurs, so probably 16Mhz would be sufficient. 

Thanx again and regards, 

over.