Part Number: TMS320F28379D
I have a relative simple setup of a SCI running at 5M baud, using the FIFO's.
We have observed strange error when RX line detect an error at the same time at data is being transmitted from the TX fifo.
The good case:
In testing I created disturbance of the signal comming in on the RX-line, the RX detected these errors (mainly parity and framing). And the error flags was cleared by the RX-ISR, and communication continued with no further issues.
The bad case:
Because of a minor design flaw of my TX-ISR, it was staying in the interrupt for too long, causing the RX-ISR to be delayed, resulting in a RX-fifo overflow.
This error was handled in the exact same way as the errors in the good case above, as you will se in the code below, For sake of simplicity when ever there is an error detected i both to a RXFFOVRCLR and a SWRESET.
But the result was very different, thw two major problems is that.
1. The RX interrupt stopped happening for any further data.
2. The data that was being sent out by the TX-fifo became garbled.
Detail for problem 1. here is a screen shot of the lines and the ISR's

The RX_ERR_PIN, RX_IRQ_PIN and the TX_IQ are GPIO's that I set and clear on entry and exit of the ISR's (RX_ERR_PIN only set inside the if(error) scope, see code below).
What is really confusing is that I can show you a very similar capture where i also currupt the TX signal, but where the RX-interrupt continues like in the good case
Details for problem 2. here is a screen shot of two captures.

The top one is the erroneous one.
By comparing it to an error free version of the same telegram. I can see that that it stops halfway trough byte 3, and the immediately starts sending byte 7, confusing both the receiver and my logic-anayzer.
I assume this is a cause of the "initializes the SCI state machines" as stated in the TRM, my guess is that the FIFO is running as a ring buffer and the SWRESET moves the internal pointer to posistion 0, that then happens to be where byte seven is stored. and even reset the state of the TXSHF register,
Only flaw in that theory is that you would expect the skipped bytes to then be added to the end for the count of bytes to match.?..?
Well independent of the inner works/flaws of the chip I need to know how to handle this correctly.
Primary problem is the stopping of RX IRQ's that sometime, but not always happens. So I either need to know:
- Can i prevent this case from happening?
- If not How do I detect it, and recover?
Secondary problem is the corruption of TX data, my system can survive that a single TX-telegram is broken, hence secondary problem, but it is really not something one should design for.
I only see one way to avoid this TX corruption problem, and that is to wait for silence on TX before doing the SW reset, but that entails another problem.
- If the RX-ISR should wait for the TX-fifo + the TXSHF to be empty,
- That requires a delicate complex setup of nested IRQ's to ensure the whole telegram on TX is sent without any pauses, the receiver would interpret a pause of more that 11 bit's time as an idle, and thus end of telegram, and yes the telegram is larger than the FIFO buffer, so it potentially needs to be refilled n times before going silent.
- How do I detect that the TXSHF is empty?
- Staying in the RX-ISR for too long could starve other parts of the system.
Please advise
Code of RX ISR, the SCI_ERROR_COUNTING_ENABLED was enabled during the capture.
void HandleInterruptRx(USARTS eUsart)
{
GPIO_writePin(RX_ISR_PIN, 1);
// Get the specific USART data.
Usart *pUsart = &g_usarts[eUsart];
uint16_t* pRxBuf = pRxBuffer[eUsart];
//reset and start the idle detect timer
if(pUsart->pControl->SCIFFRX.bit.RXFFST > 0 && pUsart->pOnIdleCallback)
{
//restart the idle detection timer every time data received until the timer expires
CPUTimer_startTimer(IDLE_DETECTION_TIMER);
}
if(pUsart->pControl->SCIRXST.bit.RXERROR != 0 ||
pUsart->pControl->SCIFFRX.bit.RXFFOVF != 0)
{
GPIO_writePin(RX_ERR_PIN, 1);
if(pUsart->pControl->SCIFFRX.bit.RXFFST > 0)
{
pUsart->errors.parity ++;
pUsart->errors.parityDetected = 1;
}
#if SCI_ERROR_COUNTING_ENABLED == 1
if(startErrCnt)
{
if(pUsart->pControl->SCIRXST.bit.PE != 0)
{
halSci_RxErrCntParity++;
}
if(pUsart->pControl->SCIRXST.bit.FE != 0)
{
halSci_RxErrCntFraming++;
}
if(pUsart->pControl->SCIRXST.bit.BRKDT != 0)
{
halSci_RxErrCntBreak++;
}
if(pUsart->pControl->SCIRXST.bit.OE != 0)
{
halSci_RxErrCntOverRun++;
}
if(pUsart->pControl->SCIFFRX.bit.RXFFOVF != 0)
{
halSci_FFErrCntOflow++;
}
}
#endif
pUsart->pControl->SCIFFRX.bit.RXFFOVRCLR = 1; // Clear Overflow flag
pUsart->pControl->SCICTL1.bit.SWRESET = 0; // clear the error flags
pUsart->pControl->SCICTL1.bit.SWRESET = 1;
}
//read the data out if any
while(pUsart->pControl->SCIFFRX.bit.RXFFST > 0)
{
if(pRxBuf != NULL && rxBufferSize[eUsart] > 0)
{
pRxBuf[currentRxPos[eUsart]] = pUsart->pControl->SCIRXBUF.all;
#if SCI_ERROR_COUNTING_ENABLED == 1
if(startErrCnt)
{
if( pRxBuf[currentRxPos[eUsart]] & SCI_RXBUF_SCIFFFE )
{
halSci_FFErrCntFraming++;
}
if( pRxBuf[currentRxPos[eUsart]] & SCI_RXBUF_SCIFFPE )
{
halSci_FFErrCntParity++;
}
}
#endif
currentRxPos[eUsart]++;
nBytesInFrame[eUsart]++;
if(currentRxPos[eUsart] >= rxBufferSize[eUsart])
{
currentRxPos[eUsart] = 0;
}
}
else
{
pUsart->pControl->SCIRXBUF.all;
}
}
pUsart->pControl->SCIFFRX.bit.RXFFINTCLR = 1; // Clear Interrupt flag
GPIO_writePin(RX_ISR_PIN, 0);
GPIO_writePin(RX_ERR_PIN, 0);
}
Compiler: ti-cgt-c2000_22.6.0.LTS