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.

TMS320F280023C: SCI Module stops operating after Overflow Error.

Part Number: TMS320F280023C
Other Parts Discussed in Thread: C2000WARE

HI,

I am using the SCI-A peripheral of the micro-controller to interface with a THVD1450DGK. I have observed that after the peripheral encounters an Overflow Error(OE)  about 10-15 times it stops generating interrupts.

Checking the peripheral registers show that all the RXRDY and OE flags in the SCIRXST registers are set and the RXBKINTENA and RXERRINTENA bits are set as well. The interrupts are also enabled at the PIE level.

Following is the code for my RX interrupt. Help will be appreciated.

__interrupt void sciaRX_isr(void)
{
// Check if interrupt was entered because of an error. In that case put SCI module into a reset state.
    if (SciaRegs.SCIRXST.bit.RXERROR == 1)
    {
        //check which error happened.
        if (SciaRegs.SCIRXST.bit.OE)
            sciOEErrorCountThvd++;
        if (SciaRegs.SCIRXST.bit.PE)
            sciPEErrorCountThvd++;
        if (SciaRegs.SCIRXST.bit.FE)
            sciFEErrorCountThvd++;
        if (SciaRegs.SCIRXST.bit.BRKDT)
            sciBRKDTErrorCountThvd++;

        //SW_RESET SCI
        SciaRegs.SCICTL1.bit.SWRESET = 0;
        SciaRegs.SCICTL1.bit.SWRESET = 1;


        sciErrorCountThvd++;
        enter_mute();
    }
    /*enter this if the errors have not caused the interrupt*/
    else if (SciaRegs.SCIRXST.bit.RXRDY) //rx caused the interrupt
    {
        if (SciaRegs.SCIRXST.bit.RXWAKE == 1) // Address byte has been received. RXWAKE is set when address bit is detected in the word.
        {
            rxIndexThvd = 0;
        }
        rxPackThvd[rxIndexThvd] = SciaRegs.SCIRXBUF.bit.SAR;
        switch (rxIndexThvd)
        {
            case 0: //Looking for address byte.
            {
                if (rxPackThvd[0] == SENSOR_ID) // If address byte matches sensor_id
                {

                    rxIndexThvd++; //increase rxIndexthvd to accept next character.
                    SciaRegs.SCICTL1.bit.SLEEP = 0; //bring the uart peripheral out of sleep as it is being addressed!
                    break;
                }
                else
                {
                    rxIndexThvd = 0; //reset rxindexThvd
                    enter_mute(); //if the address byte received doesn't match the one set by software stay in sleep
                }

                break;
            }
            case 1:
            {
                //index 1 will be the instruction type.
                //insert code here to evaluate rxPackLenThvd based on isntruction type.
                //if rxPackLenThvd is fixed leave this if statement empty.
                rxIndexThvd++;
                break;

            }
            default:
            {
                if (rxIndexThvd == (rxPackLenThvd - 1))            //last byte in packet has been received.
                {
                    if (calculate_crc(rxPackThvd, rxPackLenThvd)
                            == ((rxPackThvd[rxPackLenThvd - 2] | (rxPackThvd[rxPackLenThvd - 1] << 8)))) //crc check over here
                    {
                        rxPackCount++;

                        // Return type code Start
                        /*
                         * */
                        // Return Type Code End
                        if (txPackLenThvd > 0) // means that data has to be sent back to the uC
                        {
                            GpioDataRegs.GPBSET.bit.GPIO33 = 1;      //NRE
                            GpioDataRegs.GPASET.bit.GPIO16 = 1;      //DE

                            thvd_copy_shdbuff(); // functions copies shadow buffer into main transmit buffer.
                            SciaRegs.SCICTL1.bit.RXENA = 0;
                            SciaRegs.SCICTL1.bit.RXERRINTENA = 0;
                            SciaRegs.SCICTL2.bit.RXBKINTENA = 0; // disable RX interrupts and RX

                            SciaRegs.SCICTL1.bit.TXENA = 1;// enable TX and TXINT
                            SciaRegs.SCICTL2.bit.TXINTENA = 1;

                            SciaRegs.SCITXBUF.bit.TXDT = txPackThvd[0]; //put the first packet of data to be sent
                            txIndexThvd = 1; //set txIndexThvd to 1 as first byte has already been loaded.
                        }
                        else //if there is nothing to transmit then enter mute again.
                        {
                            enter_mute();
                        }
                        break;

                    }
                    else //crc failed
                    {
                        crcErrorCountThvd++;
                        enter_mute();
                        break;
                    }

                }
                rxIndexThvd++;
            }
        }

    }

    //acknowledge Group interrupt
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
}


enter_mute() function

void enter_mute(void)
{
    GpioDataRegs.GPBCLEAR.bit.GPIO33 = 1; // clear NRE
    GpioDataRegs.GPACLEAR.bit.GPIO16 = 1; // clear DE

    SciaRegs.SCICTL1.bit.SWRESET = 0; // reset

    SciaRegs.SCICTL1.bit.RXENA = 1;   //enable rx
    SciaRegs.SCICTL1.bit.RXERRINTENA = 1;  //enable rx error interrupt
    SciaRegs.SCICTL2.bit.RXBKINTENA = 1;  //enable rxrdy/ break detect interrupt
    SciaRegs.SCICTL1.bit.TXENA = 0; // Disable transmistter

    SciaRegs.SCICTL1.bit.SWRESET = 1; //bring out from reset

    SciaRegs.SCICTL1.bit.SLEEP = 1; //set the UART module in sleep mode till the module receives a stream of data is addressing it
}


calculate_crc() function
uint16_t calculate_crc(volatile uint16_t *packet, uint16_t packLen)
{
    uint16_t index = 0;
    uint16_t crc = 0;
    for (int h = 0; h < packLen - 2; h++)
    {
        index = ((crc >> 8) ^ ((int16_t) packet[h])) & 0xFF;
        crc = (crc << 8) ^ crc_table[index];
    }
    return crc;
}

  • Hi,

    Thanks for your question. Additional interrupts will not fire if you do not clear the previous error interrupts.

    My guess would be that, if you check at the very end of your last ISR (right before the interrupts stop occurring), the error bits will still be set (meaning they were not properly cleared in the ISR).

    Regards,

    Vince

  • Hi Vincent,

    Thanks for your reply. I'll check for the condition you have described and get back to you. Meanwhile, I had a few doubts regarding this issue due some misunderstanding on my part on how interrupts are supposed to work.

    1. What should I do to prevent this issue? According to your guess checking for errors and handling them at the very end of the ISR instead of the beginning should solve this issue, right?
    2. When would the condition you have described arise? One case I can think of is that I entered the RX ISR due to the RX ready flag being set, but while I was servicing the ISR and Overflow Error occurred (i.e after the error checks in the ISR were done). In such a scenario shouldn't the SCI peripheral raise an interrupt again(this time for the overflow condition) after the current interrupt has finished executing?
    3. I checked the Technical Reference Manual (Section 3.5 and Section 26.11) and couldn't  find any references to the issue I have described, as in, rules for handling error flags. Could you point me to a reference where there is some literature on this?

    Regards,
    Parth.

  • Hi Parth,

    Thanks for your follow-up. To answer the questions in order:

    What should I do to prevent this issue? According to your guess checking for errors and handling them at the very end of the ISR instead of the beginning should solve this issue, right?

    That is one way to solve it. The interrupts work in that if you clear them before exiting the ISR, and they are still set at the PIE level, they will re-enter the ISR. Basically, as soon as you exit an ISR, the next ISR gets processed, and if the specific error flag is still set, it will re-enter the interrupt.

    When would the condition you have described arise? One case I can think of is that I entered the RX ISR due to the RX ready flag being set, but while I was servicing the ISR and Overflow Error occurred (i.e after the error checks in the ISR were done). In such a scenario shouldn't the SCI peripheral raise an interrupt again(this time for the overflow condition) after the current interrupt has finished executing?

    The SCI would indeed raise an interrupt again in the condition you described, immediately after the first ISR has returned (assuming a higher priority interrupt isn't waiting). That is what I am assuming is happening and why you are getting repeated OEs being set.

    I checked the Technical Reference Manual (Section 3.5 and Section 26.11) and couldn't  find any references to the issue I have described, as in, rules for handling error flags. Could you point me to a reference where there is some literature on this?

    We typically recommend using the method used in C2000Ware, we have an example for SCI loopback interrupts that has an ISR code example for clearing overflow/interrupts. You can add checking of errors before the clearing overflow if desired to handle those situations differently.

    {c2000ware_root}\driverlib\f28002x\examples\sci\sci_ex2_loopback_interrupts.c

    Regards,

    Vince

  • Hi Vince,
    Thanks for the clarification.

    The interrupts work in that if you clear them before exiting the ISR, and they are still set at the PIE level, they will re-enter the ISR. Basically, as soon as you exit an ISR, the next ISR gets processed, and if the specific error flag is still set, it will re-enter the interrupt.
    The SCI would indeed raise an interrupt again in the condition you described, immediately after the first ISR has returned (assuming a higher priority interrupt isn't waiting). That is what I am assuming is happening and why you are getting repeated OEs being set

    Doesn't this mean that if a peripheral level error flag remains uncleared in an ISR it should re-enter the ISR if there are no other higher priority interrupts pending?  Because that isn't what's happening. 

    Meanwhile I'll checkout the code which you are referring to.

    Regards,
    Parth

  • Hi Parth,

    Doesn't this mean that if a peripheral level error flag remains uncleared in an ISR it should re-enter the ISR if there are no other higher priority interrupts pending?  Because that isn't what's happening. 

    I think I misunderstood your initial post then. I thought you meant it was getting trapped in the ISR and not leaving it. Can you confirm where in the code the process is when it stops receiving interrupts? Basically: a screenshot of the stack trace and code window in CCS with the debugger paused when it has stopped receiving data.

    Regards,

    Vince

  • Hi Vincent,

    I have been unable to get back to office as I'm unwell. Hence the delay. I'll update you with a reply as soon as possible.

    Regards,Parth