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.

[参考译文] TMS320F280025C:在主机和从机端同步 SPI 发送和接收缓冲器

Guru**** 2439560 points
Other Parts Discussed in Thread: TMS320F280025C, SYSCONFIG

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1038547/tms320f280025c-synchronizing-spi-transmit-and-receive-buffers-at-master-and-slave-ends

器件型号:TMS320F280025C
Thread 中讨论的其他器件: SysConfig

我已经使用 DMA 控制器配置了 SPI。 有两个 DMA 通道:一个用于传输、另一个用于接收。 在主器件侧和从器件侧都有两个数组。 在理想情况下、发送数组索引与接收数组索引相同。 但是、如果任何设备重置、则阵列索引未对齐。 例如、如果主器件和从器件最初都处于索引号10、则在任何器件复位后、其中一个器件的阵列索引设置为0。 这会导致复位器件的数组索引0上的数据写入正常器件的数组索引10。  主器件可向从器件发送信号、以通过数字 I/O 或 UART 复位其 SPI 传输。 问题是、考虑到从器件连接到 DMA 控制器、在从器件侧复位 SPI 发送和接收的最佳方式是什么? 我似乎需要同时复位 DMA 控制器通道和 SPI FIFO、但我不知道这样做的正确和最佳方法。

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

    我已根据我的理解将以下内容发挥作用:

    void SPI_DMA_Reset()
    {
        //Disabling DMA transmission channel trigger
        DMA_disableTrigger(DMA_CH5_BASE);
        //Disabling DMA reception channel trigger
        DMA_disableTrigger(DMA_CH6_BASE);
        //Disabling SPI FIFOs
        SPI_disableFIFO(SPIB_BASE);
        //Resetting transmit FIFO
        SPI_resetTxFIFO(SPIB_BASE);
        //Resetting receive FIFO
        SPI_resetRxFIFO(SPIB_BASE);
        //Re-enabling SPI FIFO
        SPI_enableFIFO(SPIB_BASE);
        SPI_setFIFOInterruptLevel(SPIB_BASE, SPI_FIFO_TX8, SPI_FIFO_RX8);
        //
           // Initialize DMA
           //
           DMA_initController();
    
           //
           // Configure DMA Ch5 for TX. When there is enough space in the FIFO, data
           // will be transferred from the sData buffer to the SPI module's transmit
           // buffer register.
           //
           DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(SPIB_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_SPIBTX, DMA_CFG_ONESHOT_DISABLE |
                          DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
    
           //
           // Configure DMA Ch5 interrupts
           //
           DMA_setInterruptMode(DMA_CH5_BASE, DMA_INT_AT_BEGINNING);
           DMA_enableInterrupt(DMA_CH5_BASE);
           DMA_enableTrigger(DMA_CH5_BASE);
    
           //
           // Configure DMA Ch6 for RX. When the FIFO contains at least 8 words to
           // read, data will be transferred from the SPI module's receive buffer
           // register to the rData buffer.
           //
           DMA_configAddresses(DMA_CH6_BASE, rData,
                               (uint16_t *)(SPIB_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_SPIBRX, 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);
    }
    

    请检查"SPI_DMA_Reset()"中的所有函数调用是否都是必需的、或者是否有更有效的方法。 我不想重置我的整个控制器。

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

    阿萨德

    建议的修改很少:-

    1) 1)禁用和启用 SPI FIFO 选项将自动清空 SPI FIFO 内容。 因此、您无需单独复位 TX FIFO 和 RX FIFO。

    2) dma_initController()函数提供对 dma 的硬复位,并强制您完全重新初始化 dma。 您可以使用以下命令将 dma_initcontller 替换为软复位

    EALLOW;

    HWREGH (DMA_CH5_base + DMA_O_CONTROL)|= DMA_CONTROL_SOFTRESET;

    NOP;//访问任何其它 DMA 寄存器所需的一个周期强制延迟

    HWREGH (DMA_CH6_BASE + DMA_O_CONTROL)|= DMA_CONTROL_SOFTRESET;

    NOP;//访问任何其它 DMA 寄存器所需的一个周期强制延迟

    EDIS;

    这样、您就不需要重新完全重新配置 DMA 了。

    修改的代码:

    void SPI_DMA_Reset ()

       //禁用 DMA 传输通道触发器
       DMA_disableTrigger (DMA_CH5_base);
       //禁用 DMA 接收通道触发器
       DMA_disableTrigger (DMA_CH6_BASE);
       
       //禁用 SPI FIFO
       SPI_disableFIFO (SPIB_BASE);
       //重新启用 SPI FIFO
       SPI_enableFIFO (SPIB_BASE);
       
       SPI_setFIFOInterruptLevel (SPIB_BASE、SPI_FIFO_TX8、SPI_FIFO_RX8);
       
       // DMA 通道软复位
       EALLOW;

       HWREGH (DMA_CH5_base + DMA_O_CONTROL)|= DMA_CONTROL_SOFTRESET;

       NOP;//访问任何其它 DMA 寄存器所需的一个周期强制延迟

       HWREGH (DMA_CH6_BASE + DMA_O_CONTROL)|= DMA_CONTROL_SOFTRESET;

       NOP;//访问任何其它 DMA 寄存器所需的一个周期强制延迟

       EDIS;
       
       //禁用 DMA 传输通道触发器
       DMA_enableTrigger (DMA_CH5_base);
       //禁用 DMA 接收通道触发器
       DMA_enableTrigger (DMA_CH6_BASE);

    此致、

    曼诺伊

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

    非常感谢您的出色回答。 让我实施它并向您提供反馈。

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

    尊敬的 Manoj:

       我面临基于 DMA 的 SPI 通信的异常问题。 SPI 配置为具有8级深度发送和接收 FIFO 的从器件。 DMA 突发大小设置为8、传输大小设置为4、以便一次完整的 DMA 传输应传输32个字。 您可以从该线程开头的代码中看到、我已经配置了两个 DMA 通道。 DMA 通道5配置为将 sData (32长度 uint16)数组的内容传输到 SPI 发送缓冲区:

    DMA_configAddes (DMA_CH5_base、(uint16_t *)(SPIB_BASE + SPI_O_TXBUF)、
    sData);

    DMA 通道6配置为将数据从 SPI 缓冲器传输到 RDATA 阵列(32长度 uint16)。  

    为了进行测试、我已经用固定值(0x02)初始化了 sData 数组。 但是、主设备(本例中为 Arduino)正在读取传输数据的一个字移位版本。 我已连接逻辑分析仪来捕获该场景。 快照如下所示:

    在上图中、数据格式为 MOSI | MISO。 用逗号分隔16位传输。 MISO (TMS320F280025C)数据是 MOSI (Arduino 数据)的字移版本。 我有另一个项目、在该项目中、相同的配置工作正常、即 MISO 和 MOSI 是来自相应器件的预期数据、但在我的当前项目中、我无法实现相同的逻辑。 我已经尝试比较这两个项目、但无法找出任何 DMA 或 SPI 配置差异。 我们非常感谢您的帮助。 我将连接 SPI 和 DMA 配置代码、如下所示:

    #define FIFO_LVL    8               // FIFO interrupt level
    #define BURST       FIFO_LVL        // Each burst will empty the FIFO
    #define TRANSFER    4              // It will take 4 bursts of 8 to transfer
    uint16_t sData[32];                // Send data buffer for DMA transmission
    uint16_t rData[32];                // Receive data buffer for DMA reception
    
    
    // Place buffers in GSRAM so that DMA can access these
    #pragma DATA_SECTION(sData, "ramgs0");
    #pragma DATA_SECTION(rData, "ramgs0");
    void initDMA()
    {
        //
           // Initialize DMA
           //
           DMA_initController();
    
           //
           // Configure DMA Ch5 for TX. When there is enough space in the FIFO, data
           // will be transferred from the sData buffer to the SPI module's transmit
           // buffer register.
           //
           DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(SPIB_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_SPIBTX, DMA_CFG_ONESHOT_DISABLE |
                          DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
    
           //
           // Configure DMA Ch5 interrupts
           //
           DMA_setInterruptMode(DMA_CH5_BASE, DMA_INT_AT_BEGINNING);
           DMA_enableInterrupt(DMA_CH5_BASE);
           DMA_enableTrigger(DMA_CH5_BASE);
    
           //
           // Configure DMA Ch6 for RX. When the FIFO contains at least 8 words to
           // read, data will be transferred from the SPI module's receive buffer
           // register to the rData buffer.
           //
           DMA_configAddresses(DMA_CH6_BASE, rData,
                               (uint16_t *)(SPIB_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_SPIBRX, 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);
    }
    
    void SPI_init()
    {
    	
    	//mySPI0 initialization
    	SPI_disableModule(mySPI0_BASE);
    	SPI_setConfig(mySPI0_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
    				  SPI_MODE_SLAVE, 1000000, 	16);
    	SPI_enableFIFO(mySPI0_BASE);
    	SPI_setFIFOInterruptLevel(mySPI0_BASE, SPI_FIFO_TX8, SPI_FIFO_RX8);
    	SPI_disableLoopback(mySPI0_BASE);
    	SPI_setEmulationMode(mySPI0_BASE, SPI_EMULATION_FREE_RUN);
    	SPI_enableModule(mySPI0_BASE);
    }
    

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

    尊敬的 Manoj:

    经过很多努力并尝试解决了这个问题。 我知道 SysConfig 工具的 SPI 驱动程序生成存在一些问题。 在我的上一个项目 中、SPI 配置是手动完成的、但在当前代码中、代码是使用 SysConfig 工具生成的。 我已从 SysConfig 软件部分删除 SPI 外设、并复制了手动配置代码。 现在、SPI 按预期工作。 我明天将为您提供有关 DMA 和 SPI 复位代码的反馈。 再次感谢。

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

    尊敬的 Manoj:

      我已经测试了您发送的 SPI 和 DMA 复位代码。 我观察到、执行复位代码时 SPI 通信停止。 如果我复位控制器的电源、则 SPI 通信再次开始。 我认为复位代码中缺少一些内容。 请检查。

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

    阿萨德

    我对您的代码没有了解和初始化。 您是否尝试了解 SPI 传输为何未启动? DMA 是否被触发?

    到达底部的唯一方法是调试问题。

    此致、

    曼诺伊

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

    您好、Manoj、

      请在下面找到初始化 DMA 和 SPI 以实现成功通信的代码:

    void initSPIFIFO()
    {
        //Configuring pins
        // GPIO40 is the SPISIMOB clock pin.
        //
        GPIO_setPinConfig(GPIO_30_SPIB_SIMO);
        GPIO_setPadConfig(40, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(40, GPIO_QUAL_ASYNC);
    
        //
        // GPIO41 is the SPISOMIB.
        //
        GPIO_setPinConfig(GPIO_31_SPIB_SOMI);
        GPIO_setPadConfig(41, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(41, GPIO_QUAL_ASYNC);
    
        //
        // GPIO22 is the SPICLKB.
        //
        GPIO_setPinConfig(GPIO_28_SPIB_CLK);
        GPIO_setPadConfig(22, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(22, GPIO_QUAL_ASYNC);
    
        //
        // GPIO5 is the SPISTEA.
        //
        GPIO_setPinConfig(GPIO_29_SPIB_STE);
        GPIO_setPadConfig(5, GPIO_PIN_TYPE_PULLUP);
        GPIO_setQualificationMode(5, GPIO_QUAL_ASYNC);
        //
        // Must put SPI into reset before configuring it
        //
        SPI_disableModule(SPIB_BASE);
    
        //
        // FIFO configuration
        //
        SPI_enableFIFO(SPIB_BASE);
        SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
        SPI_setFIFOInterruptLevel(SPIB_BASE, (SPI_TxFIFOLevel) FIFO_LVL,
                                  (SPI_RxFIFOLevel) FIFO_LVL);
    
        //
        // SPI configuration. Use a 500kHz SPICLK and 16-bit word size.
        //
        SPI_setConfig(SPIB_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1,
                      SPI_MODE_SLAVE, 1000000, 16);
        SPI_disableLoopback(SPIB_BASE);
        SPI_enableModule(SPIB_BASE);
    }
    
    //************************************************************************************
    //
    // Function to Configure DMA controller. Setup two channels, one for SPI transmission
    //and second for SPI reception.
    //
    //************************************************************************************
    void initDMA()
    {
        //
           // Initialize DMA
           //
           DMA_initController();
    
           //
           // Configure DMA Ch5 for TX. When there is enough space in the FIFO, data
           // will be transferred from the sData buffer to the SPI module's transmit
           // buffer register.
           //
           DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(SPIB_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_SPIBTX, DMA_CFG_ONESHOT_DISABLE |
                          DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
    
           //
           // Configure DMA Ch5 interrupts
           //
           DMA_setInterruptMode(DMA_CH5_BASE, DMA_INT_AT_END);
           DMA_enableInterrupt(DMA_CH5_BASE);
           DMA_enableTrigger(DMA_CH5_BASE);
    
           //
           // Configure DMA Ch6 for RX. When the FIFO contains at least 8 words to
           // read, data will be transferred from the SPI module's receive buffer
           // register to the rData buffer.
           //
           DMA_configAddresses(DMA_CH6_BASE, rData,
                               (uint16_t *)(SPIB_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_SPIBRX, 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);
    }

    执行顺序是在 initSPIFO 之前调用 initDMA。 但是、下面给出的复位代码会导致 SPI 通信完全停止。 我正在努力解决此代码的问题。 如果您想添加一些测试点 、请告诉我。

    void SPI_DMA_Reset()
    {
        //Disabling DMA transmission channel trigger
        DMA_disableTrigger(DMA_CH5_BASE);
        //Disabling DMA reception channel trigger
        DMA_disableTrigger(DMA_CH6_BASE);
        
        //Disabling SPI FIFOs
        SPI_disableFIFO(SPIB_BASE);
        //Re-enabling SPI FIFO
        SPI_enableFIFO(SPIB_BASE);
        
        SPI_setFIFOInterruptLevel(SPIB_BASE, SPI_FIFO_TX8, SPI_FIFO_RX8);
        
        // DMA channel softreset
        EALLOW;
    
        HWREGH(DMA_CH5_BASE + DMA_O_CONTROL) |= DMA_CONTROL_SOFTRESET;
    
        NOP; //One cycle mandatory delay required to access any other DMA register
    
        HWREGH(DMA_CH6_BASE + DMA_O_CONTROL) |= DMA_CONTROL_SOFTRESET;
    
        NOP; //One cycle mandatory delay required to access any other DMA register
    
        EDIS;
        
        //Disabling DMA transmission channel trigger
        DMA_enableTrigger(DMA_CH5_BASE);
        //Disabling DMA reception channel trigger
        DMA_enableTrigger(DMA_CH6_BASE);
    }

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

    1) 1)在代码中、您已配置 SPI TX FIFO 中断来触发 DMA CH5。 您是否检查了是否正在设置 SPIFFTX.TXFFINT?

    2) 2)如果 SPIFFTX.TXFFINT = 1、您是否检查 DMACH5.CONTL.PERINTFLG 是否已设置

    3) 3)在代码中、您已配置 SPI RX FIFO 中断来触发 DMA CH6。 您是否检查是否正在设置 SPIFFRX.RXFFINT?

    4) 4)如果 SPIFFTX.TXFFINT = 1、您是否检查 DMACH6.CONTL.PERINTFLG 是否已设置

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

    您好、Manoj、

      我想我们忘记了启动 DMA 通道。 我已将以下两行添加到您的复位代码中:

    DMA_startChannel (DMA_CH6_BASE);
    DMA_startChannel (DMA_CH5_base);

    SPI 通信现在恢复。 现在、我需要验证是否每个东西都根据需要复位。

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

    阿萨德

    了解所取得的进展很好。 我很高兴事情朝着正确的方向发展。

    此致、

    曼诺伊

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

    我希望您能够启动并运行该项目。 我可以关闭此主题吗?

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

    您可以关闭该线程。 我参与了其他一些与项目相关的任务、但没有机会验证每件事情是否都按预期工作。 但是、我希望我们能够通过您推荐的设置来实现目标。