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.

[参考译文] TMS320F28388D:DMA + SPI 接收缓冲区问题

Guru**** 2524550 points
Other Parts Discussed in Thread: TMS320F28388D, SYSCONFIG, C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1350932/tms320f28388d-problem-with-dma-spi-reception-buffer

器件型号:TMS320F28388D
主题中讨论的其他器件: SysConfigC2000WARE

您好!

我来找你是因为我有一段时间的问题,我似乎不能解决。
我有两个微控制器通过 SPI 彼此通信。 我的 SPI 以全双工模式工作、我的从器件正确地从主器件接收信息并同时发送回数据。 示波器上的信号很干净。

我的问题与在将 TMS320F28388D 配置为主器件并具有 SPI + DMA 的 TMS320F28388D 上的接收有关。
当我启动一个传输/接收时、我接收到的帧的开始从我的接收缓冲区的第4个字节开始。

这里我的 DMA 设置 :

    /*********************************/
    /* DMA Channel 1, SPI-A transmit */
    /*********************************/
    GV_sDmaRegs.CH1.MODE.bit.CHINTE   = 0;          /* 0: Interrupt disabled                                        */
    GV_sDmaRegs.CH1.MODE.bit.DATASIZE = 0;          /* 0: 16-bit data transfer size                                 */
    GV_sDmaRegs.CH1.MODE.bit.ONESHOT  = 0;


    GV_sDmaRegs.CH1.BURST_SIZE.all    = 0;          /* 1 word/burst                                                 */
    GV_sDmaRegs.CH1.SRC_BURST_STEP    = 1;          /* Move to next word in buffer                                  */
    GV_sDmaRegs.CH1.DST_BURST_STEP    = 0;          /* Don't move destination address                               */


    GV_sDmaRegs.CH1.TRANSFER_SIZE     = C_DRVDMA_SIZE - 1U; /* C_DRVDMA_SIZE transfer size in bursts                */
    GV_sDmaRegs.CH1.SRC_TRANSFER_STEP = 1;           /* Move to next word in buffer after each word in a burst      */
    GV_sDmaRegs.CH1.DST_TRANSFER_STEP = 0;           /* Don't move destination address                              */


    GV_sDmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFE;         /* Put to maximum - don't want source wrap.                     */
    GV_sDmaRegs.CH1.DST_WRAP_SIZE = 0xFFFE;         /* Put to maximum - don't want destination wrap.                */


    GV_sDmaRegs.CH1.SRC_BEG_ADDR_SHADOW = (Uint32) GV_DRVDMA_transferTxDataCh1; /* Start address = DMA buffer       */
    GV_sDmaRegs.CH1.SRC_ADDR_SHADOW     = (Uint32) GV_DRVDMA_transferTxDataCh1; /* Start address = DMA buffer       */

    GV_sDmaRegs.CH1.DST_BEG_ADDR_SHADOW = C_DRVSPI_SPIA_ADDR + C_DRVSPI_SPITXBUF_OFFSET;   /* Start address         */
    GV_sDmaRegs.CH1.DST_ADDR_SHADOW     = C_DRVSPI_SPIA_ADDR + C_DRVSPI_SPITXBUF_OFFSET;   /* Start address         */


    GV_sDmaClaSrcSelRegs.DMACHSRCSEL1.bit.CH1 = 109; /* 109: SPIA_TXDMA as DMA channel 1 Trigger source             */
    GV_sDmaRegs.CH1.MODE.bit.PERINTSEL        = 1;   /* Peripheral interrupt select                                 */


    GV_sDmaRegs.CH1.MODE.bit.PERINTE          = 1;   /* Enable peripheral interrupt event                           */
    GV_sDmaRegs.CH1.CONTROL.bit.PERINTCLR     = 1;   /* Clear peripheral interrupt event flag.                      */






    /********************************/
    /* DMA Channel 2, SPI-A receive */
    /********************************/
    GV_sDmaRegs.CH2.MODE.bit.CHINTE   = 0;          /* 0: Interrupt disabled                                        */
    GV_sDmaRegs.CH2.MODE.bit.DATASIZE = 0;          /* 0: 16-bit data transfer size                                 */
    GV_sDmaRegs.CH2.MODE.bit.ONESHOT  = 0;
    GV_sDmaRegs.CH2.MODE.bit.CONTINUOUS  = 0;


    GV_sDmaRegs.CH2.BURST_SIZE.all    = 0;          /* 1 word/burst                                                 */
    GV_sDmaRegs.CH2.SRC_BURST_STEP    = 0;          /* Don't move in FIFO                                           */
    GV_sDmaRegs.CH2.DST_BURST_STEP    = 1;          /* Move to next word in destination address                     */


    GV_sDmaRegs.CH2.TRANSFER_SIZE     = C_DRVDMA_SIZE - 1U; /* C_DRVDMA_SIZE transfer size in bursts                */
    GV_sDmaRegs.CH2.SRC_TRANSFER_STEP = 0;           /* Don't move source address                                   */
    GV_sDmaRegs.CH2.DST_TRANSFER_STEP = 1;           /* Move to next word in buffer after each word in a burst      */


    GV_sDmaRegs.CH2.SRC_WRAP_SIZE = 0xFFFE;         /* Put to maximum - don't want source wrap.                     */
    GV_sDmaRegs.CH2.DST_WRAP_SIZE = 0xFFFE;         /* Put to maximum - don't want destination wrap.                */


    GV_sDmaRegs.CH2.SRC_BEG_ADDR_SHADOW = C_DRVSPI_SPIA_ADDR + C_DRVSPI_SPIRXBUF_OFFSET;   /* Start address         */
    GV_sDmaRegs.CH2.SRC_ADDR_SHADOW     = C_DRVSPI_SPIA_ADDR + C_DRVSPI_SPIRXBUF_OFFSET;   /* Start address         */

    GV_sDmaRegs.CH2.DST_BEG_ADDR_SHADOW = (Uint32) GV_DRVDMA_transferRxDataCh2; /* Start address = DMA buffer       */
    GV_sDmaRegs.CH2.DST_ADDR_SHADOW     = (Uint32) GV_DRVDMA_transferRxDataCh2; /* Start address = DMA buffer       */


    GV_sDmaClaSrcSelRegs.DMACHSRCSEL1.bit.CH2 = 110; /* 109: SPIA_RXDMA as DMA channel 1 Trigger source             */
    GV_sDmaRegs.CH2.MODE.bit.PERINTSEL        = 1;   /* Peripheral interrupt select                                 */


    GV_sDmaRegs.CH2.MODE.bit.PERINTE          = 1;   /* Enable peripheral interrupt event                           */
    GV_sDmaRegs.CH2.CONTROL.bit.PERINTCLR     = 1;   /* Clear peripheral interrupt event flag.                      */

带有:

C_DRVSPI_SPI_ADDR = 0x006100U

C_DRVSPI_SPIRXBUF_OFFSET = 0x07U

c_DRVDMA_size = 40u

这里是我的 SPI 设置、

    /* SPI-A Clear SPI Software Reset bit (SPISWRESET=  to 0 to force the SPI to the reset state */
    /* SPI-A Relinquish SPI from Reset, Reset on, rising edge in input, 8-bit char bits */
    GV_sSpiARegs.SPICCR.all = 0x0007U;

    /* SPI-A Master mode, normal SPI clocking scheme, enable talk and disable SPI interrupt (flag) */
    GV_sSpiARegs.SPICTL.all = 0x0006U;

    /* SPI-A Baud Rate is set */
    GV_sSpiARegs.SPIBRR.all = 19U;

    /* SPI-A FREE bit */
    /* Halting on a breakpoint will not halt the SPI */
    GV_sSpiARegs.SPIPRI.bit.FREE = 1;

    /* SPI-A RX FIFO, RXFIFORESET: Reset the FIFO pointer to zero, and hold in reset. */
    GV_sSpiARegs.SPIFFRX.all = 0U;

    /* SPI-A TX FIFO, SPIRST: Reset the SPI transmit and receive channels.                 */
    /*                        The SPI FIFO register configuration bits will be left as is. */
    /*                TXFIFO: Reset the FIFO pointer to zero, and hold in reset            */
    GV_sSpiARegs.SPIFFTX.all = 0U;

    /* SPI-A RX FIFO interrupt is disabled, FIFO interrupt level bits to default value */
    /* SPI-A is ready to receive (RX FIFO) */
    GV_sSpiARegs.SPIFFRX.all = 0xE041U;

    /* SPI-A Enable TX and RX FIFO and is ready to transmit (TX FIFO) */
    GV_sSpiARegs.SPIFFTX.all = 0xE041U;

    GV_sSpiARegs.SPIFFCT.all = 1;

    /* SPI-A is ready to transmit and receive the next character, set this bit before resuming operation */
    GV_sSpiARegs.SPICCR.bit.SPISWRESET = 1;

当我启动传输/接收时:

  • 首先启动 RX DMA:

GV_sDmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;
GV_sDmaRegs.CH2.CONTROL.bit.RUN = 1;

  • 然后选择 TX DMA:

GV_sDmaRegs.CH1.CONTROL.bit.RUN = 1;

系统地、在启动时、DMA 缓冲区的前3个字节是 SPIRXBUF 的当前状态重复3次、然后是从我的帧中丢失的4个字节(= 0)、然后是我的预期帧的一部分。

示例:

 

预期值:  

  • [0]--> 0x5A
  • [1]--> 0 (计数器)
  • [2]--> 2
  • [3]--> 3
  • [4]--> 4
  • [5]--> 5
  • [6]--> 6
  • [7]--> 7
  • ...
  • [37]--> 37
  • [38]--> 0 (相同计数器)
  • [39]--> 0xA5

所有下一个传输/接收,我有:

我在[4]的计数器与在[1]的计数器相同,因此我解释说我已经接收了整个帧,但我的 DMA 已经开始在第4个字节写入并循环(即使我没有设置换行)。

在调试中、激活 DMA RX 之后和 DMA TX 之前的断点显示无 DMA RX 触发、仅当我激活 TX 时。

如果你有任何线索,我无法理解这个问题。 谢谢!

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

    "妈,我不能给你生个孩子, 我不能给你生个孩子。"


    我修复了从设备的传输问题。

    这更正了我的计数器的一个问题、它在字节[4]和[1]上显示相同、因为现在我的内容是一致的。

    我在主器件上接收的第一个帧(全为0)看起来像这样:

    在几次接待之后:

    90应该是[0],165应该是[39]

    问题仍然相同、我的接收缓冲区始终在第4个位置启动。 并且我在下次 DMA 激活时接收到我的帧的第二部分。

    希望您能清楚了解  

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

    Armageddon、

    为了确保我理解、控制器 SPI-A 使用通道1进行传输、而使用通道2进行接收。 假设目标 SPI-B 使用通道 2 进行传输、使用通道1进行接收。 SPI-B 正在正确接收和发送数据(示波器截图显示了这一点)、并且 SPI-A 未 正确接收和发送数据、因为数据从与预期不同的帧开始。 系统在 SPI-A/B 端与 DMA 端都使用 FIFO。

    您能否确认控制器的范围看起来准确吗? 给我一天时间来回顾你的代码、同时在同一时间给你回复。

    我修复了从设备的传输问题。

    您能解释一下您在上面提供的代码中修改的内容吗?

    艾什瓦里亚

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

    您答对了。 SPI-A 使用 FIFO、它可以正确传输(我认为)、因为对从端的帧(SPI-B)进行解码没有问题。

    在示波器上、我可以看到我的40个字节。

    开始字节和结束字节位置很好。 (MOSI 和 MISO)。

    例如、在我的第一个帧中、MISO 在整个传输过程中为低电平、DMA 仅从接收缓冲区(SPI-A)的第4个字节中写入0。

    这个问题与下一个接收的问题是一样的、除了有数据并且我的接收端 N 显示在接收 N+1时我的缓冲器的开始位置。

    我的主要问题是为什么我无法在缓冲区的开头启动接收(SPI-A)、总是在4个字节后启动。


    我尚未纠正上述代码中的任何内容、我的问题之一是在从端(SPI-B)。 我的传输缓冲区在传输过程中被修改、导致主端(SPI-A)上的帧不一致、例如0、然后在帧的开头写入数据。

    我接收到的第一个帧仅为0。 然后我在接下来的帧中获取数据。

    论坛似乎有问题编辑帖子、很抱歉我的第一个帖子很令人困惑。

    感谢您的帮助

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

    Armageddon、

    与 SPI 相关的注意事项:

    由于 SPI 与 DMA 一起运行、因此 有一个特定的配置要求:RXFFST 大于或等于 RXFFIL。 此时、禁止激活 SPIRXDMA 的情况看起来与此相反。 附加 SPI DMA 操作的其他相关信息、以供查看。

    SPICCR。 SPICHAR = 0x7U (8位字传输)、因此请确保发送的数据为左对齐、因为 SPI 针对16位传输进行了优化。 建议启用高速模式以达到全双工速度、但这不是必需的、同时还要确保 SPI 具有相同的时钟频率。

    您是否还可以确认以下内容:

    1.  在 SPI RX/TX FIFO 和 SPIDAT 寄存器中看到什么?
    2. 为什么 GV_sSpiARegs.SPIFFCT.all = 1;?

    与 DMA 相关的注释:

    总的来说、我认为有些设置是针对一个通道完成的、而不是针对另一个通道完成的、因此需要确保您正在设置所有相关的位。 有关此上下文中 DMA 设置的更多信息、请参阅 SPI DMA 示例。

    1. CH1是否具有高优先级?
    2. DMA 何时生成中断(MODE.CHINTMODE)? 是否禁用了连续模式(MODE.CONTINUAL)?
    3. DMA 中断是否按预期工作? 您不需要配置单独的 SPI 中断、因为 SPI 传输是 DMA 的触发器、但您确实需要启用 DMA 通道中断。

    此外、如果您尚未查看 SysConfig/Driverlib、我强烈建议您这样做、因为它会生成代码、从而简化配置过程。  

    艾什瓦里亚

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

    尊敬的 Aishwarya Rajesh

    为了回答您的问题、我在重新启动测试之前进行了以下更改:

    • 我已将 CH1切换为高优先级、CH1PRIORITY = 1
    • 我已经更新了通道2 (RX)上的中断以使用 SPIA_TXDMA (109)
    • 我已激活 SPI 高速模式。

    在向您展示我的结果之前:

    • Gv_sSpiARegs.SPIFFCT.all = 1、因为它使我可以更轻松地 通过 范围查看我的字节
      我尝试将其设置为0和5、但没有注意到任何变化。

    • 测试模式。 两个通道的 CHINTMODE 都设置为0。
      我还尝试对两个通道将其设置为1、但都没有看到任何变化。

    • 我没有忘记以左对齐的方式发送数据。 在从器件侧看到我的帧没有问题。

    以下是初始化后寄存器的状态:


    当我启动 DMA RX (CH2)时、除了 DmaCh2Regs.control = 0x2000 (因为 RUNSTS = 1)外、寄存器不会移动。

    下面是启用 DMA TX (CH1)后寄存器的状态:


    结果是相同的、在我的第一次接收时、我有 SPIRXBUF 值的3个相同字节、然后是我的0。

    对于值得这么做的事情、这里是我的第一帧的信号图片。 绿色信号为 SCK、黄色为 MISO。



    再次感谢您的帮助!  

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

    尊敬的 Armageddon:

    感谢确认。 无需启用 CH1PRIORITY、但无论如何都应启用 CH1PRIORITY。 您可能只需要检查 SPISTS 寄存器中的 OVERRUN_FLAG 位、因为 SPITXDMA 被 设置了优先级从而导致 RX FIFO 溢出。

    对于 SPI、请确保除了接收数据外、发送数据也作为16位值存储在目标上。

    如果您还没有、我 还会尝试在中断中无断点的情况下运行代码、并随机暂停、看看这是否可以解决问题。  如果 示波器截图是通过断点运行的、如果问题是 CCS 调试器而非与软件设置无关、这可能会有所帮助。

    艾什瓦里亚

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

    尊敬的 Aishwarya Rajesh

    根据文档、当以三种方式之一清除该位时、我无法看到 OVERRH_FLAG 设置为1

    -写1到这个位

    -将0写入 SPI 软件复位(SPICCR.7)

    -重置系统

    这样就不会发生任何溢出。

    对于 SPI、请确保除了接收数据外、发送数据也作为16位值存储在目标上。

    [/报价]

    正如我之前所说的、我可以在从器件上解码我的传输。

    • 我没有忘记以左对齐的方式发送数据。 在从器件侧看到我的帧没有问题。

    [/报价]

    我尝试了您的建议、我在无断点的情况下启动代码、行为是相同的。 我的帧从第4个字节开始。

    我已经向您发送了我的所有 DMA + SPI 寄存器的屏幕截图、结果仍然不一致。
    您能否在您身边重现问题? 还是只有我?

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

    Armageddon、

    使用 C2000Ware SPI DMA 示例5和您的设置、我没有看到问题。  如果您可以向我发送友谊请求、我们可以看看您的 SPI 和 DMA 运行时 代码。  同时,让我进一步研究一下我的问题。

    艾什瓦里亚  

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

    感谢您的帮助。

    不幸的是、在5月13日前我无法访问该设备。
    我下次将尝试使用 C2000库来检查是否存在任何抖动。
    谢谢!

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

    Armageddon、

    如果你还没有,你可以尝试更多的事情。 确保 SPI 的 SPI 极性/时钟模式相同、检查 SPI/DMA GPIO 设置(SPI 应异步)、并确保具有单独的 TX 和 RX ISR、其中 确保在退出 ISR 之前清除中断组。

    这些建议仅基于配置。  您是否有权访问您的计划代码? 如果您的意思是这样、它就不需要运行了。

    艾什瓦里亚