2014-05-14 07:18 AM
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.
2014-05-14 07:30 AM
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.2014-05-14 07:32 AM
> 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)...2014-05-14 07:43 AM
> 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
2014-05-15 12:46 AM
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.