Hi
I have experimented with the behaviour of the UART Rx overrun flag when its interrupt is not used and belive that I can now explain your initial problem.
If the overrun flag is set, it is necessary to clear it before the receiver will continue to operate normally (there is a note about this in the user's manual). In order to clear the flag it is necessary to read the status register with the flag set and then read the data register.
In your original code this is not guaranteed, which can be explained as follows:
register UINT16 StatReg = UART_S1_REG(offset); /* Read status register (s2 too ?)*/ <--- flag is not set here (A)
if (StatReg & (UART_S1_NF_MASK | UART_S1_OR_MASK | UART_S1_FE_MASK | UART_S1_PF_MASK)) <-- so is not handled here
{ /* Is any error flag set? */
(void)UART_D_REG(offset); /* Dummy read 8-bit character from receiver */
StatReg &= (UINT16)(~(UINT16)UART_S1_RDRF_MASK); /* Clear the receive data flag to discard the errorneous data */
if (StatReg & UART_S1_RDRF_MASK) /* Is the receiver's interrupt flag set? */
{
gUartPmon[comPort].RxInter++;
UART_RxIsr(comPort); <-- some where in this routine the data register is read (B)
}
If the overrun takes place between the initial read of the status register and the point where the data register is read (between (A) and (B), the read of the data register will not reset the overrun flag (since the status register hasn't been read "with it set"). The result is that the overrun flag remains set and the receiver will not receive any further data.
This means that there is a "window" in your interrupt routine that allows this to take plöace - the longer the code is before the data register is read, the larger the window and the greater the chance of it occurring.
When you use the interrupt flag to re-enter the interrupt routine, the overflow hander corrects the situation by re-entereing teh interrupt routine - but, without an interrupt on the overrun flag, the UART will block until the sequence is performed.
There is however a simple workaround when not handling the overrun interrupt, which is as follows.
if (StatReg & UART_S1_RDRF_MASK) /* Is the receiver's interrupt flag set? */
{
gUartPmon[comPort].RxInter++;
UART_RxIsr(comPort);
if (UART_S1_REG(offset) & UART_S1_OR_MASK) {
| | (void)UART_D_REG(offset); /* Dummy read 8-bit character from receiver */ |
}
}
Here the status register is checked for the overrun "after" the read has taken place. This will catch the case where the data register read didn't automatically clear it and then reset it.
In fact the first check in the routine for an overrun error is in mainly redundent (unless you want to count how often an overrung takes place or similart) because of two reasons:
1. It is not reliable since the flag may be set after it has checked (as explained above)
2. There will always be a receive character in the data register for the interrupt to enter (when not using overrun interrupt) and so either the flag is reset by the standard data handling (the character before the overrun took place and nothing else is needed) or else the post-check will catch it
Regards
Mark