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.

[参考译文] RM57L843:DMA 和 SPI (非 MIBSPI)-非连续芯片选择信号

Guru**** 2465890 points
Other Parts Discussed in Thread: HALCOGEN

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/662232/rm57l843-dma-and-spi-non-mibspi---not-continuous-chip-select-signal

器件型号:RM57L843
主题中讨论的其他器件:HALCOGEN

大家好!

我将 RM57 SPI (MIBSPI 兼容模式)与 DMA 配合使用。 我将 SPI3与 CS1线路结合使用。

我的代码与此主题中使用的代码几乎相同:

https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/384808

在此线程中、附加了一些代码(361.rm57_SPI_DMA.zip)、这有助于我成功测试 SPI - DMA 代码。

我遇到的唯一问题(与 361.rm57_SPI_DMA.zip 中提供的代码唯一区别)与芯片选择行有关。 我不使用 GPIO 来驱动片选信号、而是使用连接到 SPI3的 CS1线(我希望片选线由外设自动驱动、而不是使用 GPIO 手动驱动)。

我遇到的问题是、在整个 SPI 事务期间芯片选择不连续(在本例中为4字16位传输)、但是芯片选择在传输1或2个字后返回到高电平状态、如下图所示:

在上一个开发阶段、当不使用 DMA 但使用具有中断的 SPI 时、我能够使用连续芯片选择信号。

我是否可以采取任何措施来解决此问题? 还是被迫使用手动控制的 GPIO?

谢谢!

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

    检查以确保在 SPIDAT1中启用 CSHOLD。 从我看到的、HalCoGen 不直接支持这个配置、所以你必须使用其中一个用户代码段将它手工设定为1。

    在我可以在 SPI.c 驱动程序文件中看到的所有发送、接收、发送和接收函数中、CSHOLD 的配置如下:

    uint32 Chip_Select_Hold =(dataconfig _t->CS_Hold)? 0x10000000U:0U;

    但是,代码中没有任何数据通信图->CS_HOLD 设置为1的地方,因此这始终会导致 CSHOLD = 0。 这将导致您看到 CS 在消息之间取消断言的行为。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 、Chuck、

    感谢您回答我的问题。

    您认为 应该在 SPIDAT1中启用 CSHOLD 是正确的。 这就是 HalCoGen 在使用 SPI 和 SPI 中断时所做的事情。 这些呼叫:

    uint32 spiTransmitData (spiBASE-t * SPI、spiDAT1_t *数据通信 fu_t、uint32块大小、uint16 * srcbuff);
    void SendspiData (spibase_t * spi、spiDAT1_t * dataconfap_t、uint32 blocksize、uint16 * srcbuff);
    uint32 piReceiveData (spiBASE-t * SPI、spiDAT1_t * dataconfap_t、uint32 blocksize、uint16 * destbuff);
    void spiGetData (spiBASE-t * SPI、spiDAT1_t * dataconfap_t、uint32 blocksize、uint16 * destbuff);
    uint32 spiTransmitAndReceiveData (spiBASE-t * SPI、spiDAT1_t * dataconfap_t、uint32 blocksize、uint16 * srcbuff、uint16 * destbuff);
    void SendspiAndGetData (spiBASE-t * SPI、spiDAT1_t * dataconfap_t、uint32 blocksize、uint16 * srcbuff、uint16 * destbuff);
    void spiEnableLoopback (spiBASE-t * SPI、loopBackType_t Loopbacktype);

    提供参数  spiDAT1_t *dataconfi_t,以便在访问 SPI->DAT1寄存器以通过轮询或中断进行发送时配置芯片选择行为。

    但是、对于正在传输的 DMA、是将数据从 SRAM 缓冲区发送到 SPI->DAT0  SPI->DAT1寄存器的 DMA。

    为了方便您记录、为了支持我的以下问题、这是我正在使用的当前 DMA Tx 数据包配置:

    #define SPI3_TX_ADDR ((uint32_t)(&(spiREG3->DAT1))

    uint16_t DmaTxBuffer[size_dma_buffer]__attribute__((section ("sharedRAM"))={0xA1A2、0xA3A4、0xA5A6、0xA7A8};

    //配置 DMA 控制数据包
    m_dmaCtrlTxPkt.Sadd =(uint32_t) DmaTxBuffer;//源地址*/
    m_dmaCtrlTxPkt.DADD = SPI3_TX_ADDR;
    m_dmaCtrlTxPkt.CHCTRL = 0;//通道控制*/

    //为发送正确数据的每个帧生成 nCS:
    m_dmaCtrlTxPkt.FRCNT = 4;/*帧计数*
    m_dmaCtrlTxPkt.ELCNT = 1;/*元素计数*/

    m_dmaCtrlTxPkt.ELDOFFSET = 0;/*元素目标偏移量*/
    m_dmaCtrlTxPkt.ELSOFFSET = 0;/*元素源偏移*/
    m_dmaCtrlTxPkt.FRDOFFSET = 0;//帧目标偏移量
    m_dmaCtrlTxPkt.FRSOFFSET = 0;//帧目标偏移量
    m_dmaCtrlTxPkt.PORTASGN = Porta_Read_PORTB_WRITE;//端口分配*
    m_dmaCtrlTxPkt.RDSIZE = ACCESS_16_BIT;/*读取大小*/
    m_dmaCtrlTxPkt.WRSIZE = ACCESS_16_BIT;//写入大小*/
    m_dmaCtrlTxPkt.tType = frame_transfer;/* transfer type */
    m_dmaCtrlTxPkt.ADDMODERD = ADDR_INC1;/*地址模式读取*/
    m_dmaCtrlTxPkt.ADDMODEWR = ADDR_FIXED;//地址模式写入*/
    m_dmaCtrlTxPkt.AUTOINIT = AUTOINIT_OFF;/*自动初始化*/

    因此、您的解决方案(谢谢您的解决方案)让我想知道以下几点:

    1.如果    需要自动芯片选择信号(而不是手动 GPIO 行为)、是否应使用 SPI->DAT0或 SPI->DAT1寄存器作为 DMA 的目标地址? (我已经看到几个使用 SPI-DMA 且使用 SPI->DAT0的示例、就像我之前提到的主题中的示例: https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/384808)

    2.我知道我需要使用  spiDAT1_t * dataconfi_t 结构来配置芯片选择行为,但考虑到我不轮询,而不使用 SPI 中断,而是 DMA 中断,提供了什么函数来实现 DMA 功能? 如果此时没有用于此目的的函数(HalCoGen 不提供)、一个简单的代码片段会对我大有帮助。

    我之所以提出这一要求是因为对 SPI->DAT1寄存器的任何写操作都会在 TXDATA 域中产生写操作、如果处理不当、该域会触发发送。 在这种情况下、在配置芯片选择字段后、我应该在访问 SPI->DAT1之前设置 SPIEN = 0、并设置 SPIEN = 1吗? (这是我尝试过的、但如果我这么做、SPI 传输不再生成任何 nCS 信号)。

    想到的另一种解决方案是将用于 DMA 源地址的 SRAM 缓冲区用作32位字、以便能够适应整个 SPI->DAT1寄存器、 使用 NCS 配置填充高16位、使用要传输的数据填充低16位、但这将强制我执行 DMA 的32位访问:

    m_dmaCtrlTxPkt.RDSIZE = ACCESS_32_BIT;/*读取大小*/
    m_dmaCtrlTxPkt.WRSIZE = ACCESS_32_BIT;//写入大小*/

    这是可行的解决方案吗?

    的最后一个问题与帧与元素计数有关。 假设我要发送4个16位字、在每次 SPI 传输时都要发送连续片选信号、我希望能够使用该配置

    m_dmaCtrlTxPkt.FRCNT = 1;/*帧计数*
    m_dmaCtrlTxPkt.ELCNT = 4;/*元素计数*/

    但该配置会产生意外结果:只有与索引0和索引3相关的 DmaTxBuffer 缓冲区内容在 SPI 总线中传输

    RM57_SPI_DMA_FR4_ELEM1_nCS_after_each_element_take3.png

    或者、如果我使用以下配置、则 SPI 总线中会显示正确的数据(完整的缓冲器内容)

    //为发送正确数据的每个帧生成 nCS:
    m_dmaCtrlTxPkt.FRCNT = 4;/*帧计数*
    m_dmaCtrlTxPkt.ELCNT = 1;/*元素计数*/

    对此是否有任何解释?

    非常感谢您的帮助。 我迫不及待地想让它正常运行:)

    此致、

    JOR SAS

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!
    您是否认为您很快就能参加此申请?
    非常感谢。

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

    以下两个问题是否可能会指导我?

    1.如果需要自动芯片选择行为(而不是手动 GPIO 行为)、是否应使用 SPI->DAT0或 SPI->DAT1寄存器作为 SPI DMA 的目标地址?
    我可以看到 SPI->DAT1是唯一提供芯片选择配置的器件。
    (我已经看到几个使用 SPI-DMA 且使用 SPI->DAT0的示例、就像我之前提到的线程中的示例:
    e2e.ti.com/.../384808
    但我认为它们通过 GPIO 实现芯片选择控制)。

    2.我知道我需要使用 spiDAT1_t * dataconfi_t 结构来配置芯片选择行为,但假设我不使用 SPI 轮询,不使用 SPI 中断,而是 DMA 中断:
    如何使用 spiDAT_t*结构通过 DMA 强制执行自动芯片选择行为(而无需手动 GPIO 芯片选择功能)?
    (我成功地将其与 SPI 中断配合使用、但不能与 DMA 中断配合使用)。

    感谢您的支持、

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

    请参阅  

    解决方案。

    再次感谢您的帮助。

    Halcogen <> FreeRTOS 未记录的问题导致10天以上的损失。

    JOR SAS。