This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28379D: SCI SWRESET causes bad data on TX line.

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

  • Hi Martin,

    Thank you for your questions. I need to spend some time analyzing the captures you provided so I will provide a response by tomorrow.

    Best Regards,

    Marlyn

  • Hi Martin,

    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?

    I believe what could be happening is due to the fact that the SCI interrupt to the PIE is the ORed version of both RXFFINT and RXFFOVFINT. Please take a look at my last response in this thread and implement the suggested way to handle clearing the interrupt: (2) TMS320F28069: SCI received overflow but did not enter interrupt - C2000 microcontrollers forum - C2000Tm︎ microcontrollers - TI E2E support forums

    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.

    I am working with our design team to help advice on this situation. I will respond back as soon as I get a response. 

    Best Regards,

    Marlyn

  • Hi Martin,

    I wanted to let you know that I am still working with our design team on the issue I commented on above.

    Best Regards,

    Marlyn

  • Hi

    I have also been looking into this. As we need it to work in our product.

    One idea that I had, but not fully tested yet, is to completely ignore the error flags in the SCIRXST, including not having rx error interrupt enabled.

    Thrn i ony look at FF overflow flag, and the PE and FE flags read out of the fifo using RXBUFF.

    As fa as I can see this will cover all RX error scenarios, except BREAK detection, which I don't need to explicitly detect, and I still get a parity or framing error if a BKREAK condition .shiuld occour.

    And i should still get a normal RXFF interrupt in all error scenarios, as far as I can see (not tested).

    Do You or your design team see any problems in that approach?

  • Hi Martin,

    Here is what I heard back from design: Doing a SWRESET will reset TXRDY and TXEMPTY in SCICTL2 register to “1”. A SWRESET should not be done while TX is in progress. After a SWREST, a TXFIFORESET should be done and the data should be refilled.

    Do You or your design team see any problems in that approach?

    I haven't personally tried to do something like this but I don't see any immediate issues. If you do get an error though and its detected in your code, you run into the same concern of doing a SWRESET possibly while TX is in progress. 

    Best Regards,

    Marlyn

  • Hi

    First:
    Hard to put politely but that feedback from design team is quite useless, only stating what is already known. And in no way try to solve the problem at hand.

    Second:
    Why would I still need to do a SW reset??

    As explained in TMS320F28379D: Request for details on SCI error handling I can read the SCIFFFE and SCIFFPE from SCIRXBUF, that will tell me if there was a parity or framing error on that specific byte/frame, this is why i can ignore the FE and OE bits from SCIRXST.

    And BRKDT I want to ignore completely, as this application do not need to detect break condition.

    Also I am only  concerned about overflow of the FIFO, what i can get from SCIFFRX->RXFFOVF, even if this overflow also triggers the OE flag in SCIRXST, I can ignore that flag.

    The  SCIFFFE  and SCIFFPE flags is only present together with the affected byte/frame, and do not need to be reset.

    The RXFFOVF in cleared by writing a '1' to RXFFOVRCLR.

    So why would I still need to issue a SW-reset?

  • Hi Martin,

    So why would I still need to issue a SW-reset?

    Thank you for clarifying. Yes, sorry, if you aren't using the flags in the SCIRXST register and don't wish to clear those if an error does occur then you should not need to do a SW-reset. 

    Hard to put politely but that feedback from design team is quite useless, only stating what is already known. And in no way try to solve the problem at hand.

    Please let me know if you would like for me to reach back out to our design team for further clarification on any of the issues or items. With your new approach I don't suspect you running into the same issue since you wont be using SWRESET. 

    Best Regards,

    Marlyn

  • Well another question that might go back to that design team.

    In my quest to solve this, i found that if a break condition should occur it actually blocks the RX part from receiving any further data.... This is hinted a bit in the reference on page 2288 about the BRKDT flag

    It
    is not cleared by receipt of a character after the break is detected. In
    order to receive more characters, the SCI must be reset by toggling
    the SW RESET bit or by a system reset.

    I would not call that clearly stated.

    But that only eeds me to the question I have.

    I find that doing a channel reset, will also clear the flags.This channel reset toggles the SCIRST flag of the SCIFFTX register. But the description is quite vague.

    SCI Reset
    0 Write 0 to reset the SCI transmit and receive channels. SCI FIFO
    register configuration bits will be left as is.
    1 SCI FIFO can resume transmit or receive. SCIRST should be 1
    even for Autobaud logic to work.
    Reset type: SYSRSn

    By experimenting it looks like this one actuallu does a sw-reset + TxFofo-reset + RxFifoReset ???

    So yes that is my question, what does this channel reset do?

    And also can you or You please confirm that a sw-reset is the only way to get the RX running again after a break detection?

  • Thanks for your feedback Martin!

    By experimenting it looks like this one actuallu does a sw-reset + TxFofo-reset + RxFifoReset ???

    So yes that is my question, what does this channel reset do?

    I've sent your question to our design team for further commentary on their side. I'll let you know once I hear back.

    And also can you or You please confirm that a sw-reset is the only way to get the RX running again after a break detection?

    Yes, The only way is to do a sw reset or a system reset. I've asked our design team to double confirm this as well. Will keep you updated.

    Best Regards,

    Marlyn

  • Yes, The only way is to do a sw reset or a system reset. I've asked our design team to double confirm this as well. Will keep you updated.

    Just to be clear, I am only interested in getting the receiver to receive new data. I don't care about the flag itself. In the best scenario I could convince the SCI not to detect those break conditions at all. Or to ignore the flag.

  • Thanks Martin, I understand. Unfortunately that is how the SCI responds to a break detect, even if you choose to ignore the flag (ie. not check for that flag within your application). Like I said, I will discuss with our design team if there are other methods that don't involve doing a reset if a break detect does occur.

    Best Regards,

    Marlyn

  • Hi Martin,

    By experimenting it looks like this one actuallu does a sw-reset + TxFofo-reset + RxFifoReset ???

    Yes, this is correct, SCIRST performs a SWREST + TXFIFORESET + RXFIFORESET.

    Just to be clear, I am only interested in getting the receiver to receive new data. I don't care about the flag itself. In the best scenario I could convince the SCI not to detect those break conditions at all. Or to ignore the flag.

    The only way to get the RX running after a break detect is to do a channel reset (SCIRST), software reset (SWRESET), or system reset. 

    Best Regards,

    Marlyn