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.

[参考译文] TMS320F28075:MCU 被配置为从器件、在其它总线正在传输数据时接收损坏的数据。

Guru**** 2391565 points
Other Parts Discussed in Thread: TMS320F28075, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1334665/tms320f28075-mcu-configured-as-slave-receiving-corrupt-data-when-other-buses-are-transferring-data

器件型号:TMS320F28075
主题中讨论的其他器件: C2000WARE

我在与另外两个器件通信的 SPI 总线上将 TMS320F28075配置为从器件。 如果只选择 TMS320并传输数据、则一切都很顺利。 但是、当选择 SPI 总线上的其他器件时、TMS320上的数据有时会损坏。 这里的关键字是 有时 ,因为数据并不总是损坏的。

以下是所发生情况的逻辑捕获:

此处发送了3条消息。 首先、选择 TMS320并且该传输成功。 然后、选择总线上的另一个器件、该传输也很好。 然后第3次传输、再次选择 TMS320。 TMS320此处接收到不正确的数据。

放大了第三条消息:

这是我调试时数据的样子(我应该看到:0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00):

我知道这不是最好的示例、因为这里发送的大多数数据都是0x00。 但我尝试过其他具有更具体值的消息、我将始终收到与上述 pic 相同的消息。 此外、我使用 CRC 来验证数据、因此很容易判断数据何时不正确。

此损坏的数据仅在 SPI 总线上的另一个器件传输完毕后才会立即发生。 因此我知道这与此相关。 如果 SPI 总线上没有其他传输、我看到没有损坏的数据。 我已经通过在没有其他设备的情况下运行30分钟的方法对此进行了测试。 我没有看到损坏的数据。  

奇怪的是、因为我已将 TMS320 SPI 配置为 RX 缓冲区上的中断为1。 当总线上的其它器件传输数据时、TMS320不会中断。 所以 RX 缓冲区没有被填满。 但是、数据仍然是损坏的。 另外、TMS320绝不会干扰其它器件的传输。

以下是在 TMS320上配置 SPI 的方法:

void McuCommsInit(void)
{
    //
    // GPIO55 is the SPISOMIA.
    //
    GPIO_setMasterCore(55, GPIO_CORE_CPU1);
    GPIO_setPinConfig(GPIO_55_SPISOMIA);
    GPIO_setPadConfig(55, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(55, GPIO_QUAL_ASYNC);

    //
    // GPIO54 is the SPISIMOA clock pin.
    //
    GPIO_setMasterCore(54, GPIO_CORE_CPU1);
    GPIO_setPinConfig(GPIO_54_SPISIMOA);
    GPIO_setPadConfig(54, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(54, GPIO_QUAL_ASYNC);

    //
    // GPIO57 is the SPISTEA.
    //
    GPIO_setMasterCore(57, GPIO_CORE_CPU1);
    GPIO_setPinConfig(GPIO_57_SPISTEA);
    GPIO_setPadConfig(57, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(57, GPIO_QUAL_ASYNC);

    //
    // GPIO56 is the SPICLKA.
    //
    GPIO_setMasterCore(56, GPIO_CORE_CPU1);
    GPIO_setPinConfig(GPIO_56_SPICLKA);
    GPIO_setPadConfig(56, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(56, GPIO_QUAL_ASYNC);

    SPI_disableModule(SPIA_BASE);
    SPI_setConfig(SPIA_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
        SPI_MODE_SLAVE, 2500000, 8);

    SPI_disableLoopback(SPIA_BASE);
    SPI_enableTalk(SPIA_BASE);
    SPI_enableFIFO(SPIA_BASE);

    SPI_resetTxFIFO(SPIA_BASE);
    SPI_resetRxFIFO(SPIA_BASE);

    SPI_enableModule(SPIA_BASE);

    SPI_enableInterrupt(SPIA_BASE, SPI_INT_RXFF);
    SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX16, SPI_FIFO_RX1);

    Interrupt_register(INT_SPIA_RX, &RxSpiInterrupt);
    Interrupt_enable(INT_SPIA_RX);

    GPIO_setInterruptPin(57, GPIO_INT_XINT1);
    GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_BOTH_EDGES);
    GPIO_enableInterrupt(GPIO_INT_XINT1);

    Interrupt_register(INT_XINT1, &ChipSelectInterrupt);
    Interrupt_enable(INT_XINT1);
}

以下是我读取 SPI 数据的方式:

void ReadSpiReceiveData(void)
{
    SPI_RxFIFOLevel rxFifoStat = SPI_getRxFIFOStatus(SPIA_BASE);
    uint8_t count = 0;

    while(rxFifoStat != SPI_FIFO_RXEMPTY)
    {
        count++;
        WriteToBuffer(SPI_readDataNonBlocking(SPIA_BASE));
        rxFifoStat = SPI_getRxFIFOStatus(SPIA_BASE);
    }

    SPI_resetRxFIFO(SPIA_BASE);
}

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

    你好,橄榄色

    感谢您提供详细的问题。 我有一些初步的跟进问题/建议:

    1. 您是否参考过 C2000Ware 的任何软件示例? 如果没有、我建议查看此器件的 driverlib 示例3 ({C2000Ware}\driverlib\f2807x\examples\cpu1\spi\spi_ex3_external_loopback_fifo_interrupts.c)、并遵循此处类似的 SPI 配置序列、以清除中断状态并在设置中断结束后重新启用 SPI。 (是否清除了中断标志并确认 RX 内部的中断?)
    2. 您是否能够正确地看到 ReadSpiReceiveData()的"计数"增量?
    3. 它可能有助于在 ReadSpiReceiveData()中切换 GPIO 以帮助跟踪活动。
    4. 简而言之、代码不会卡在您的"while 循环"中、对吧?
    5. 也许您能更详细地解释一下"RX 缓冲区没有被填满"的意思。 但是、数据仍然损坏"?
    6. 还需要检查的一点是确保该器件与其他器件的时钟模式相同。 根据制造商、它们可以称为不同的器件、但它们应使用与 SPI 时钟相同的方案锁存和传输数据。

    此致、

    艾里森

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

    尊敬的 Allison:

    1.好的,我修改了我的代码以更好地匹配他们的代码(说实话,没有太多的更新):

    void McuCommsInit(void)
    {
        //
        // GPIO55 is the SPISOMIA.
        //
        GPIO_setMasterCore(55, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_55_SPISOMIA);
        GPIO_setPadConfig(55, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(55, GPIO_QUAL_ASYNC);
    
        //
        // GPIO54 is the SPISIMOA clock pin.
        //
        GPIO_setMasterCore(54, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_54_SPISIMOA);
        GPIO_setPadConfig(54, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(54, GPIO_QUAL_ASYNC);
    
        //
        // GPIO57 is the SPISTEA.
        //
        GPIO_setMasterCore(57, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_57_SPISTEA);
        GPIO_setPadConfig(57, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(57, GPIO_QUAL_ASYNC);
    
        //
        // GPIO56 is the SPICLKA.
        //
        GPIO_setMasterCore(56, GPIO_CORE_CPU1);
        GPIO_setPinConfig(GPIO_56_SPICLKA);
        GPIO_setPadConfig(56, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(56, GPIO_QUAL_ASYNC);
    
        SPI_disableModule(SPIA_BASE);
        SPI_setConfig(SPIA_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
            SPI_MODE_SLAVE, 2500000, 8);
    
        SPI_disableLoopback(SPIA_BASE);
        SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_FREE_RUN);
    
        SPI_enableTalk(SPIA_BASE);
        SPI_enableFIFO(SPIA_BASE);
    
        SPI_resetTxFIFO(SPIA_BASE);
        SPI_resetRxFIFO(SPIA_BASE);
    
        SPI_enableInterrupt(SPIA_BASE, SPI_INT_RXFF);
        SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RXFF);
        SPI_setFIFOInterruptLevel(SPIA_BASE, SPI_FIFO_TX16, SPI_FIFO_RX1);
    
        Interrupt_register(INT_SPIA_RX, &RxSpiInterrupt);
        Interrupt_enable(INT_SPIA_RX);
    
        GPIO_setInterruptPin(57, GPIO_INT_XINT1);
        GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_BOTH_EDGES);
        GPIO_enableInterrupt(GPIO_INT_XINT1);
    
        Interrupt_register(INT_XINT1, &ChipSelectInterrupt);
        Interrupt_enable(INT_XINT1);
    
        SPI_enableModule(SPIA_BASE);
    }

    2.哎呀,忘了删除该仅用于调试的 count 变量。 但是、是的、接收函数可以在我完成的所有调试中正常工作。 如果 SPI 总线上没有其他器件发送、我将始终获得正确的数据。

    3.我已经完成了这项工作,看起来工作正常:

    4.正确,它永远不会卡在 while 循环中。

    5.如果我持续检查 RX 缓冲区并在不为空时切换 GPIO、则当另一个器件在总线上发送消息后、我永远不会看到 GPIO 切换。 因此总线上的另一个器件不填充 RX 缓冲区。 当 RX 缓冲区中有合法数据时、这就像是破坏了下一次读取一样。 清除损坏数据的唯一方法是接收一条供 TMS320使用的真实消息。 由于这种行为、我觉得 SPI 外设的硬件级别似乎正在发生一些事情。 不过我应该注意的是、我已经在逻辑分析仪上查看了信号、一切看起来都很好。 当其他器件发送数据时、TMS320的片选线路为高电平。

    6.其他设备只有一个不同的时钟速度,否则是相同的设置。 我尝试将它们更改为与 TMS320相同的速度、只是为了看看这是否会产生影响、结果看起来并没有。

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

    你好,橄榄色

    感谢更新。 请注意以下事项、确保我对情况保持一致:

    • 如果我理解正确、当 F2807x 器件是唯一的 SPI 从设备时、您就不会遇到通信问题。 但当在总线上有其他器件进行通信时、F2807x 的 SPI 在之后接收到不 正确的数据(但从 F2807x 发送的数据在此是否仍然正确?)
    • 我的理解是、您在每次 F2807x 上发生 RX 中断时都会看到一次 GPIO 切换(您是否可以在中断开始时将 GPIO 设置为高电平、在结束时设置为低电平、以便我们可以看到持续时间并验证进度?)

    还有几个问题:

    1. 问题是否一致、因为 当另一个设备与 F2807x 在两次传输之间进行通信时、您会看到这个接收到的数据问题?  
    2. 如果在另一个器件发送线路上的消息后未调用 RX 中断、您仍然可以在 RXEMU 寄存器中看到数据吗? 如果你在 RX 中断中设置一个断点、程序仍然会命中它吗?
    3. 我能不能问您如何读取 RX 缓冲区? 如果您直接在 CCS 中查看 RXBUF、这实际上可以清除 SPI INT 标志位、所以您需要改用 RXEMU 寄存器。   
    4. 总线上的"其他"器件是否也是 C2000器件?
    5. 简而言之、您使用的时钟模式应该是在时钟的上升沿发送数据、并在 SPI 时钟的下降沿锁存接收到的数据、对吗?
    6. 与 F2807x 器件不通信时、您是否使用/清除通话位?  

    很抱歉所有问题、只需尝试确保我对问题和症状有很好的了解

    此致、

    艾里森