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 stops generating interrupts when the micro-controller is configured as an SPI slave and the SPI module is operated at high clock speeds.

Part Number: TMS320F280023C

I'll refer to the device we are facing issues with as the "main micro-controller".

            System Description

  • In the system the main micro-controller interfaces with 2 devices.
  • The first device is a THVD1450DGKR with which the main micro-controller interfaces using SCI.
  • The second device is a TMS320F280023C and the main micro-controller interfaces with this device as an SPI slave.
  • Both the SPI and the SCI module are operated using an interrupt based code. SCI is operated with addressing enabled. SPI is operated with FIFO enabled.
    Observations and Problem
  • When a clock speed of 10Mhz is used on the SPI bus the SCI module stops generating interrupts after an indeterminate amount of time.
  • In the SCI module, the RXRDY flag is set but the interrupts do not propagate to the CPU. The code never enters the SCI_RX ISR. The SPI module however, continues to operate normally.
  • As stated before the code operates normally i.e (both SPI and SCI interrupts are generated) for some time before this condition/problem occurs.
  • If a clock speed of 1Mhz is used on the SPI bus, these problems are eliminated. Both the modules work as expected without stopping.

I want to understand what causes the SCI module to stop generating interrupts after a while when the SPI Slave is operated at a higher clock speed and how should I resolve this problem.
Please let me know if I can provide any further information regarding the code.

  • Hi Parth,

    Could you send the code for your SCI and SPI ISRs? I suspect something in your SPI ISR takes too long to execute when being triggered at 10Mhz, preventing your SCI ISR from executing. In the meantime, could you test an empty SPI and SCI ISR(do nothing but acknowledge the interrupt) to see if your SCI module still stops generating interrupts?

  • Hi Luke thanks for your reply. Here is the code you asked for. Let me know if any part of the code is unclear and difficult to understand.
    Meanwhile, I'll try running the empty ISR's with only acknowledge and I'll let you know if the same issue persists.

    SCI Interrupts

    __interrupt void sciaRX_isr(void)
    {
        rxrdy = SciaRegs.SCIRXST.bit.RXRDY;         //rx not empty flag
        brkdt = SciaRegs.SCIRXST.bit.BRKDT;         //brkdt
    
    
        /*check if there was any overrun,parity,framing error*/
        if (SciaRegs.SCIRXST.bit.RXERROR == 1)
        {
            sci_error_flag++;
            FE = SciaRegs.SCIRXST.bit.FE;
            PE = SciaRegs.SCIRXST.bit.PE;
            OE = SciaRegs.SCIRXST.bit.OE;
            enter_mute();
        }
        /*enter this if the errors have not caused the interrupt*/
    
        else if (rxrdy == 1) //rx caused the interrupt
        {
    
            if (i < packet_length)
            {
                packet_recd[i] = SciaRegs.SCIRXBUF.bit.SAR;
                switch (i)
                {
                case 0:
                {
                    packet_id = packet_recd[0];
                    if (packet_id == Servo_id)
                    {
                        SciaRegs.SCICTL1.bit.SLEEP = 0; //bring the uart peripheral out of sleep as it is being addressed!
                        crc_accum = 0; //reinitialise crc
                        index1 = ((crc_accum >> 8) ^ ((int16_t) packet_recd[i])) & 0xFF;
                        crc_accum = (crc_accum << 8) ^ crc_table[index1];
                        i++;                            //increment i
                        break;
                    }
                    else
                    {
                        enter_mute(); //if the address byte received doesn't match the one set by software stay in sleep
                    }
    
                    break;
                }
                default:
                {
                    if (i < (packet_length - 2))
                    {
                        index1 = ((crc_accum >> 8) ^ ((int16_t) packet_recd[i])) & 0xFF;
                        crc_accum = (crc_accum << 8) ^ crc_table[index1];
                        i++;
                        break;
                    }
    
                    if (i == packet_length - 2)
                    {
                        i++;
                        break;
                    }
    
                    if (i == (packet_length - 1))            //last CRC packet
                    {
                        if (crc_accum == (packet_recd[packet_length - 2]  | (packet_recd[packet_length - 1] << 8)))
                        {
                            /*access_flag=2 indicates interrupt can give data to main loop*/
                            GpioDataRegs.GPASET.bit.GPIO12 = 1;      //DE
                            GpioDataRegs.GPBSET.bit.GPIO32 = 1;      //NRE
                            txBuffSPI[HEADER_LEN] = packet_recd[1];
    
                            //Flush TXFIFO so that new data can be updated.
                            EALLOW;
                            SpibRegs.SPIFFTX.bit.TXFIFO = 0;
                            SpibRegs.SPIFFTX.bit.TXFIFO = 1;
                            txBuffIndex = 1;
                            EDIS;
    //                        thvd_comp = true;
                            /*****************data to be sent to uc*************************/
                            send_pack_len = 0;        //Reinitialize
                            index2 = 5;
    
                            for (int h = 0; h < index2; h++)
                            {
                                index11 = ((send_crc_accum >> 8)
                                        ^ ((int16_t) packet_send[h])) & 0xFF;
                                send_crc_accum = (send_crc_accum << 8)
                                        ^ crc_table[index11];
                            }
                            i = 0;                                  //Reinitialize i
                            packet_length = 4;          //Reinitialize packet_length
                            crc_accum = 0;                  //Reinitialize crc_accum
                            packet_send[index2] = send_crc_accum & 0x00FF;
                            index2++;
                            packet_send[index2] = (send_crc_accum >> 8) & 0x00FF;
                            index2++;
                            send_crc_accum = 0;
                            send_pack_len = index2;
    
                            if (send_pack_len > 0)
                            {
                                transmit = 1;
                                k=1;
                                SciaRegs.SCICTL1.bit.RXENA = 0;
                                SciaRegs.SCICTL1.bit.RXERRINTENA = 0;  //enable rx error interrupt
                                SciaRegs.SCICTL2.bit.RXBKINTENA = 0;
                                DELAY_US(5);
                                SciaRegs.SCICTL1.bit.TXENA = 1;
                                SciaRegs.SCICTL2.bit.TXINTENA = 1;
                                SciaRegs.SCITXBUF.bit.TXDT = packet_send[0]; //put the first byte of data to be sent
                            }
                            else
                            {
                                enter_mute();
                            }
                            break;
    
                        }
    
                        else
                        {
                            enter_mute();
                            break;
                        }
    
                    }
    
                    if (i > (packet_length + 2))
                    {
                        i = 0;
                        enter_mute();
                        break;
                    }
    
                }
                }
            }
        }
        SciaRegs.SCIFFRX.bit.RXFFOVRCLR =1;
        SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1;
        PieCtrlRegs.PIEACK.bit.ACK9 =1;
        rx++;
    }
    
    __interrupt void sciaTX_isr(void)
    {
        SciaRegs.SCIFFTX.bit.TXFFINTCLR = 1;
        PieCtrlRegs.PIEACK.bit.ACK9 =1;
        if (k > 0 && transmit == 1)
        {
            if (k < send_pack_len)
            {
                SciaRegs.SCITXBUF.bit.TXDT = packet_send[k];
                k++;
            }
            else if (k == send_pack_len)
            { //check for transmit completion through txempty flag
    
                while (SciaRegs.SCICTL2.bit.TXEMPTY == 0)
                {
                }
                k = 1;
                packet_length = 4;
                crc_accum = 0;
                i = 0;
                SciaRegs.SCICTL1.bit.RXENA = 1;
                SciaRegs.SCICTL1.bit.RXERRINTENA = 1;  //enable rx error interrupt
                SciaRegs.SCICTL2.bit.RXBKINTENA = 1;
                GpioDataRegs.GPACLEAR.bit.GPIO12 = 1;
                GpioDataRegs.GPBCLEAR.bit.GPIO32 = 1;
                SciaRegs.SCICTL2.bit.TXINTENA = 0;
                SciaRegs.SCICTL1.bit.SLEEP = 1;
            }
            else
            {
                enter_mute();
            }
        }
    
        else
        {
            enter_mute();
            //TBD
        }
    }


    SPI interrupts
    __interrupt void user_SpibRxISR()
    {
        uint16_t temp = 0;
        switch (spi_detect_start)
        {
        case false:
            temp = SpibRegs.SPIRXBUF;
            if (temp == START_BYTE)
            {
                rxBuffIndex = 0;
                rxBuffSPI[rxBuffIndex] = temp;
                rxBuffIndex++;
                spi_detect_start = true;
            }
            break;
        case true:
            rxBuffSPI[rxBuffIndex] = SpibRegs.SPIRXBUF;
            rxBuffIndex++;
            if (rxBuffIndex == BUFFLEN)
            {
    
                spi_detect_start = false;
                if (calculate_crc(rxBuffSPI) == (rxBuffSPI[BUFFLEN - 2] | rxBuffSPI[BUFFLEN - 1] << 8))
                {
                    for (int i = HEADER_LEN; i < (BUFFLEN - CRC_LEN); i++)
                    {
                        txBuffthvd[i - HEADER_LEN] = rxBuffSPI[i];
                    }
                }
            }
            break;
        default:
            break;
        }
        SpibRegs.SPIFFRX.bit.RXFFINTCLR = 1;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;
    }
    __interrupt void user_SpibTxISR()
    {
        SpibRegs.SPITXBUF = txBuffSPI[txBuffIndex] << 8;
        SpibRegs.SPIFFTX.bit.TXFFINTCLR = 1;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;
        txBuffIndex++;
        if (txBuffIndex == BUFFLEN)
            txBuffIndex = 0;
    }


    calculate_crc() function

    uint16_t calculate_crc(volatile uint16_t *packet)
    {
        uint16_t index11 = 0;
        uint16_t send_crc_accum = 0;
        for (int h = 0; h < (BUFFLEN - CRC_LEN); h++)
        {
            index11 = ((send_crc_accum >> 8) ^ ((int16_t) packet[h])) & 0xFF;
            send_crc_accum = (send_crc_accum << 8) ^ crc_table[index11];
        }
        return send_crc_accum;
    }


  • Hi Parth,

    Could you also try toggling a GPIO at the beginning and end of your SPI interrupt and measure on an oscilloscope to test whether it is completing? Perhaps your BUFFLEN and CRCLEN values are being affected which changes the duration of your calculate_crc function over time. Are SPI/SCI transmissions being sent to your F28002x repeatedly or periodically? Have you tried changing this line of code in your SPI interrupt:

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;

    to 

    PieCtrlRegs.PIEACK.bit.ACK6 =1;

    similar to how you acknowledge your SCI interrupt?

     Is there a specific nesting/priority strategy for configuring the interrupts that would be appropriate for this application?

  • Hi Luke,
    I can try toggling a GPIO. I'll have to check if there's any that I can easily probe.
    I am fairly sure that the ISR does get completed because.
    1) The code does stop in main() when I put a break-point.
    2) The SPI data which the master sends is being correctly received and updated.

    BUFFLEN and CRCLEN are #defines so safe to assume that they aren't changing.

    We have tried using both PieCtrlRegs.PIEACK.all = PIEACK_GROUP6; and PieCtrlRegs.PIEACK.bit.ACK6 =1; without any change in result.
    Also as far as I know the micro-controller has fixed priorities and has nesting disabled by default.

    Regards,
    Parth

  • Hey Parth,

    Another customer had a similar issue with SCI on this device, their solution was to disable SCI RX interrupts while transmitting:

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1133821/tms320f280025c-sci-interrupts-transmit-interrupts

    Let me know if this resolves your issue.

    --Luke