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.

[参考译文] TMS320F280049:SPI 同步问题

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1337108/tms320f280049-issue-with-spi-synchronization

器件型号:TMS320F280049
Thread 中讨论的其他器件:TMS570LS3137TMS570LS0332

上下文

我们拥有一个使用以下微控制器的应用:

TMS320F280049CPZS - DSP

TMS570LS3137–主要

TMS570LS0332 -辅助

所有处理器均通过 SPI 接口相互通信。 SPI 和 DMA 模块在 DSP 中配置如下:

主器件与 DSP 之间的通信

SPI 总线:SPIA

SPI 比特率:8MHz

SPI 消息:每1毫秒64个字。

主设备是主设备。 DSP 是从设备。

DMA 通道:Ch5 (DSP 到主)和 CH6 (主到 DSP)。

DMA CH6:连续模式开启

DMA CH5:连续模式关闭

DMA 中断:INT_AT_END

辅助与 DSP 之间的通信

SPI 总线:SPIB

SPI 速度:8MHz

SPI 消息:每1毫秒64个字。

从控制器是主控制器。 DSP 是从设备。

DMA 通道:CH3 (DSP 到辅助通道)和 CH4 (主通道到辅助通道)。

DMA CH4:连续模式开启

DMA CH3:连续模式关闭

DMA 中断:INT_AT_END

 

问题

如果微控制器中的一个被强制复位而其它微控制器继续运行、那么不能正确地"理解" SPI 数据。 此问题是间歇性的(不会在每次复位时发生)。

检查 DMA 存储器、可以观察到数据偏移了给定数量的字。

假设

当强制复位时、SPI 从器件与主器件失去同步。 如果在传输数据时发生复位、则部分消息将丢失。 DMA 存储器存储不完整的消息流。

建议的解决方案

如果我们检测到不正确的数据流、请将 SPI 和 DMA 模块重置为其默认状态。 我们使用 CS 线路和 GPIO 中断使 SPI/DMA 进入已知状态。 但是、我们想确认适当的步骤集应该是为了使 SPI 和 DMA 模块都进入其初始状态(工作状态)。

我们需要在主器件与 DSP 之间进行通信、同时保持辅助器件与 DSP 之间的通信处于活动状态、反之亦然。

以下代码是否用于 main 和 DSP 之间的通信?

    //Disable SPI
    SPI_disableModule(SPIA_BASE);
    //Stop channel and clear trigger Flag
    DMA_stopChannel(DMA_CH6_BASE);
    DMA_clearTriggerFlag(DMA_CH6_BASE);
    //Soft Reset the DMA Channel 6
    DMA_triggerSoftReset(DMA_CH6_BASE);
    // Soft Reset Channel 5 and Flush SPI Tx Buffer
    DMA_triggerSoftReset(DMA_CH5_BASE);
    SPI_resetTxFIFO(SPIA_BASE);
    DMA_enableTrigger(DMA_CH5_BASE);
    //Enable SPI
    SPI_enableModule(SPIA_BASE);
    //Start Channel
    DMA_startChannel(DMA_CH6_BASE);

 

我们怀疑某些代码可能不是必需的、或者可能需要附加代码。

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

    您好、Jose、

    至于复位 SPI 和 DMA、一般过程是将 SPI 模块复位并禁用、重新配置和重新启用 DMA 通道。  可以在运行期间进行重置、但需要小心谨慎。  

    PRIORITYSTAT 寄存器显示传输是否  正在发生并可被用于跟踪总线上的状态。 我建议在禁用某个信道之前等待该信道不处于活动状态(或者您需要它执行的任何其他操作)。 HALT 和 RUN 位可用于此特定应用。

    艾什瓦里亚

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

    您好 Aishwarya:

    这是我们当前配置 DMA (启动时)的方式:

        // Initialize DMA
        DMA_initController();
     
        // Configure DMA Ch5 for TX. W
        DMA_stopChannel(DMA_CH5_BASE);
        DMA_clearTriggerFlag(DMA_CH5_BASE);
        DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(SPIA_BASE + SPI_O_TXBUF),
                            sData);
        DMA_configBurst(DMA_CH5_BASE, BURST, 1, 0);
        DMA_configTransfer(DMA_CH5_BASE, TRANSFER, 1, 0);
        DMA_configMode(DMA_CH5_BASE, DMA_TRIGGER_SPIATX, DMA_CFG_ONESHOT_DISABLE |
                       DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
     
        // Configure DMA Ch5 interrupts
        DMA_enableTrigger(DMA_CH5_BASE);
     
        // Configure DMA Ch6 for RX. 
    	DMA_stopChannel(DMA_CH6_BASE);
     
        DMA_clearTriggerFlag(DMA_CH6_BASE);
        DMA_configAddresses(DMA_CH6_BASE, rData,
                            (uint16_t *)(SPIA_BASE + SPI_O_RXBUF));
        DMA_configBurst(DMA_CH6_BASE, BURST, 0, 1);
        DMA_configTransfer(DMA_CH6_BASE, TRANSFER, 0, 1);
        DMA_configMode(DMA_CH6_BASE, DMA_TRIGGER_SPIARX, DMA_CFG_ONESHOT_DISABLE |
                       DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
     
        // Configure DMA Ch6 interrupts
        DMA_setInterruptMode(DMA_CH6_BASE, DMA_INT_AT_END);
        DMA_enableInterrupt(DMA_CH6_BASE);
        DMA_enableTrigger(DMA_CH6_BASE);
     
        
        DMA_startChannel(DMA_CH6_BASE);
        DMA_startChannel(DMA_CH5_BASE)

    您认为当我们需要复位 DMA 时、我们是否需要重新运行此配置?

    如果正确、我们可以考虑包含 以下内容的复位:

    /***************************/
        //Disable and Enable SPI
        SPI_disableModule(SPIA_BASE);
        SPI_enableModule(SPIA_BASE);
    /***************************/   
        //Disable DMA Channels
        DMA_stopChannel(DMA_CH6_BASE);
        DMA_stopChannel(DMA_CH5_BASE);
    /***************************/ 
        //Wait for DMA to be idle
        //(pseudocode)
        while(PRIORITYSTAT & 0x7 != FALSE); 
    /***************************/
        //Reconfigure
        // Initialize DMA
        DMA_initController();
     
        // Configure DMA Ch5 for TX. W
        DMA_clearTriggerFlag(DMA_CH5_BASE);
        DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(SPIA_BASE + SPI_O_TXBUF),
                            sData);
        DMA_configBurst(DMA_CH5_BASE, BURST, 1, 0);
        DMA_configTransfer(DMA_CH5_BASE, TRANSFER, 1, 0);
        DMA_configMode(DMA_CH5_BASE, DMA_TRIGGER_SPIATX, DMA_CFG_ONESHOT_DISABLE |
                       DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
     
        // Configure DMA Ch5 interrupts
        DMA_enableTrigger(DMA_CH5_BASE);
     
        // Configure DMA Ch6 for RX. 
        DMA_clearTriggerFlag(DMA_CH6_BASE);
        DMA_configAddresses(DMA_CH6_BASE, rData,
                            (uint16_t *)(SPIA_BASE + SPI_O_RXBUF));
        DMA_configBurst(DMA_CH6_BASE, BURST, 0, 1);
        DMA_configTransfer(DMA_CH6_BASE, TRANSFER, 0, 1);
        DMA_configMode(DMA_CH6_BASE, DMA_TRIGGER_SPIARX, DMA_CFG_ONESHOT_DISABLE |
                       DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
     
        // Configure DMA Ch6 interrupts
        DMA_setInterruptMode(DMA_CH6_BASE, DMA_INT_AT_END);
        DMA_enableInterrupt(DMA_CH6_BASE);
        DMA_enableTrigger(DMA_CH6_BASE);
    /***************************/
        // Renable
        DMA_startChannel(DMA_CH6_BASE);
        DMA_startChannel(DMA_CH5_BASE);
    /***************************/

    您能否确认这是不是我们所需要的东西?

    谢谢!

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

    您好、Jose、

    这位专家目前正在休假,到4月5日24日为止,因此请等待答复。 我会看看我能否调派另一位专家来协助。

    谢谢。此致、

    艾里森

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

    您好、Jose、

    很抱歉耽误你的时间。 通常情况下、对于接收 DMA、我建议在错误状态期间停止相关通道、并在错误状态结束时重新启动相应的通道、以便 DMA 根本不会传输任何错误数据。 假设您不 希望 DMA 覆盖 RDATA 中先前接收到的数据。 在您的应用中、主器件是否向 F280049从器件提供了发生复位的某些指示? 例如、CS 线路在传输过程中是否会变为无效? 您可能会在这种情况下生成中断、并在 ISR 中停止相应的 RX DMA 通道、然后在该条件不再存在时重新启动该通道。  

    请告诉我、这是否适用于您的用例、或者如果我误解了您要尝试实现的目标。

    此致、

    德拉尼

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

    您好!

    很抱歉这么晚才回复、这个部件周围正在进行很多工作。  我们并不关心在 RDATA 中覆盖以前接收的数据、理想情况下、一旦传输完成、数据就会被复制到另一个缓冲区、因此可以安全地覆盖数据;如果未接收到完整的消息、 也应该将其丢弃。   我们无法 知道其他处理器上是否发生了复位事件。   

    代码序列是否高于"停止相关通道并重新启动它"的正确方法?

    谢谢!

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

    您好、Jose、

    通过停止和启动相关的通道,我的意思就是  在错误 条件期间调用 dma_stopChannel ();然后在条件结束时调用 dma_startChannel ();。 但是、如果您不担心覆盖以前收到的数据、我相信您的方法会起作用。  

    此致、

    德拉尼