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:当微控制器配置为 SPI 从器件且 SPI 模块以高时钟速度运行时、SCI 停止生成中断。

Guru**** 2387080 points
Other Parts Discussed in Thread: TMS320F280023C
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1174948/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

器件型号:TMS320F280023C

我将我们面临的问题称为"主微控制器"。

           系统说明

  • 在系统中、主微控制器与2个器件连接。
  • 第一个器件是 THVD1450DGKR、主微控制器使用 SCI 与该器件进行连接。
  • 第二个器件是 TMS320F280023C、主微控制器将此器件作为 SPI 从器件进行连接。
  • SPI 和 SCI 模块均使用基于中断的代码运行。 SCI 在启用寻址的情况下运行。 SPI 在启用 FIFO 的情况下运行。
    观察结果和问题
  • 当 SPI 总线上使用10MHz 的时钟速度时、SCI 模块在一段不确定的时间后停止生成中断。
  • 在 SCI 模块中、RXRDY 标志被置位、但中断不会传播到 CPU。 代码永远不会进入 SCI_RX ISR。 然而、SPI 模块继续正常运行。
  • 如代码正常运行之前所述、即在这种情况/问题发生之前的一段时间内(同时生成 SPI 和 SCI 中断)。
  • 如果在 SPI 总线上使用1MHz 的时钟速度、则可以消除这些问题。 这两个模块均按预期工作、不会停止。

我想了解当 SPI 从器件以更高的时钟速度运行时、SCI 模块在一段时间后停止生成中断的原因、以及我应该如何解决这个问题。
请告诉我、我是否可以提供有关该代码的更多信息。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Parth、

    您能否发送 SCI 和 SPI ISR 的代码? 我怀疑 SPI ISR 中的某些内容在以10MHz 触发时执行时间过长、从而阻止 SCI ISR 执行。 同时、您能否测试一个空的 SPI 和 SCI ISR (只确认中断)来查看 SCI 模块是否仍然停止生成中断?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Luke、感谢您的回复。 这是您要求的代码。 如果代码的任何部分不清楚且难以理解、请告诉我。
    同时、我将尝试以仅确认的方式运行空 ISR、并告知您同一问题是否仍然存在。

    SCI 中断

    __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 中断
    __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()函数

    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;
    }


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Parth、

    您是否还可以尝试在 SPI 中断的开始和结束时切换 GPIO、并在示波器上进行测量以测试其是否完成? 也许您的 BUFFLEN 和 CRCLEN 值 会受到影响 、这会随着时间的推移而改变您的 calculate_CRC 函数的持续时间。 是重复还是定期向 F28002x 发送 SPI/SCI 传输? 您是否尝试在 SPI 中断中更改此代码行:

    PieCtrlRegs.PIEACX.ALL = PIEACK_group6;

    更改为  

    PieCtrlRegs.PIEACK.bit.ACK6 =1;

    与您确认 SCI 中断的方式类似?

     是否有一个用于配置适合此应用的中断的特定嵌套/优先级策略?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Luke、
    我可以尝试切换 GPIO。 我必须检查是否有任何我可以轻松探测的东西。
    我非常确信 ISR 确实会完成、因为。
    1) 1)当我放置一个断点时、代码确实会在 main()中停止。
    2) 2)正确接收和更新主器件发送的 SPI 数据。

    BUFFLEN CRCLEN 是#define、因此可以安全地假设它们不会改变。

    我们已经尝试使用 PieCtrlRegs.PIEACK.all = PIEACK_group6; PieCtrlRegs.PIEACk.bit.ACK6 =1;结果没有任何变化。
    此外、据我所知、微控制器具有固定的优先级、并且默认情况下禁用嵌套。

    此致、
    Parth

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、Parth、

    另一位客户在该器件上遇到了类似的 SCI 问题、他们的解决方案是在发送时禁用 SCI RX 中断:

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

    请告诉我这是否能解决您的问题。

    -Luke