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.

[参考译文] CCS/MSP430FR5994:CCS + TIRTOS + SPI DMA

Guru**** 2390755 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/965025/ccs-msp430fr5994-ccs-tirtos-spi-dma

器件型号:MSP430FR5994

工具/软件:Code Composer Studio

大家好、我在 DMA 模式下的 SPI 端口有问题。 我将 SPI 端口与 EUSCI_B1模块搭配使用。
-我使用 CCS (TI 站点上的最后一个版本)。
- TI-RTOS 用于编程。
-使用了 Driverlib.h。

SPI 的配置是正确的、因为我可以在正常模式下发送数据。
只有 DMA 模式对我来说是个问题。 我在数据表中找到了通道和触发器的值。 代码的结构类似于我在 DMA 中测试 UART 模块时使用的结构、工作正常。
我要附上用于测试的代码。 voilà、我希望有人能告诉我、我的错误在哪里。
谢谢你。

#include

uint32_t RxSpiDmaAddr、TxSpiDmaAddr;

//
// main()
//
int main (空)

   WDT_A_HOLD (WDT_A_base);//停止 WDT
   PM5CTL0 &=~LOCKLPM5;

   InitClockSysDefault();
   init_gpio();
   init_spi_B1 ();

   /*启动 BIOS */
   _enable_interrupt ();
   BIOS_start();

   返回(0);


//
//初始化 SPI EUSCI_B1_BASE
//
空 Init_SPI_B1 (空)

   GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P5、
                                              SPI_MOSI + SPI_MISO + SPI_CLK、
                                              GPIO_PRIMARY_MODULE_FUNCTION);

   //初始化主设备
   EUSCI_B_SPI_initMasterParam param ={0};
   param.selectClockSource                = EUSCI_B_SPI_CLOCKSOURCE_SMCLK;
   param.clockSourceFrequency             = CS_getSMCLK();
   param.desiredSpiClock                  = 50000;
   param.msbFirst                         = EUSCI_B_SPI_MSB_FIRST;
   param.clockPhase                       = EUSCI_B_SPI_PHASE_DATA_Captured_ONFIRST_Changed_ON_NEXT;
   param.clockPolarity                    = EUSCI_B_SPI_CLOCKPOLARITY_INACT_LOW;
   param.spiMode                          = EUSCI_B_SPI_3引脚;
   EUSCI_B_SPI_initMaster (EUSCI_B1_BASE、&param);

   RxSpiDmaAddr = EUSCI_B_SPI_getReceiveBufferAddress (EUSCI_B1_BASE);
   TxSpiDmaAddr = EUSCI_B_SPI_getTransmitBufferAddress (EUSCI_B1_BASE);

   //启用 SPI 模块
   EUSCI_B_SPI_ENABLE (EUSCI_B1_BASE);
   ///EUSCI_B_SPI_clearInterrupt (EUSCI_B1_base、EUSCI_B_SPI_Receive_Interrupt+EUSCI_B_SPI_Transmit 中断);
   ///EUSCI_B_SPI_enableInterrupt (EUSCI_B1_base、EUSCI_B_SPI_Receive_Interrupt+EUSCI_B_SPI_Transmit 中断);


//
// Init_DMA
//
空 InitDmaSpi_TXD (字符数据[])

   DMA_initParam SpiDmaParam ={0};     //结构
   SpiDmaParam.channelSelect         = dma_channel_3;                // voir 数据表
   SpiDmaParam.transferModeSelect    = dma_transfer_single;
   SpiDmaParam.transferSize          =(uint16_t) strlen (数据);
   SpiDmaParam.triggerSourceSelect   = dma_TRIGGERSOURCE_19;         // voir 数据表
   SpiDmaParam.transferUnitSelect    = dma_size_SRCBYTE_DSTBYTE;
   SpiDmaParam.triggerTypeSelect     = DMA_TRIGGER_RISINGEDGE;
   dma_init (SpiDmaParam);

   dma_setSrcAddress (dma_channel_3、(uint32_t)&Data[0]、dma_direction 递增);
   dma_setDstAddress (dma_channel_3、TxSpiDmaAddr、dma_direction 不变);

   DMA_clearInterrupt (DMA_CHANNEL);
   DMA_enableInterrupt (DMA_CHANNEL);



//
// SPI DMA TXD
//
空 SPI_DMA_TXD_Task (UARg arg0、UARg arg1)


   while (1)
       {
       InitDmaSpi_TXD ("AZERTYUOP");
       DMA_enableTransfers (DMA_CHANNEL);//启用 DMA 上的传输
       Task_sleep (1000);
       }


//

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

    > SpiDmaParam.triggerTypeSelect     = DMA_TRIGG_RISINGEDGE;

    串行端口上(Tx) DMA 的一个相关因素是 TXIFG 从高电平开始、因此没有初始边沿。 请尝试改用 DMALEVEL:

    > SpiDmaParam.triggerTypeSelect     = DMA_TRIGGER_HIGH ;

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

    Bruce、您好!

    感谢您的回复、但我之前曾尝试过、但没有成功。
    其他建议?

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

    当你在 Task_sleep()和/或你的 DMA ISR 上达到一个断点时、DMA 的状态是什么?

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

    Bruce、您好!

    我忘记告诉您从未发生过 ISR DMA。 我附加了一个有关发送功能状态的屏幕截图。 我希望能帮助您理解。
    我已验证良好的 ISR DMA 矢量编号= 42

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

    您的图像似乎未正确连接。 我通常使用"插入/编辑介质"按钮(位于回形针左侧)来成功。

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

    手册中的内容为:"为了确保正常运行、仅当选择外部触发 DMAE0作为触发器时、才能使用电平触发器。" 不过、它不会说出什么问题。

    这似乎要求以其他方式启动第一次转让。 如果您幸运、手动切换 TXIFG 将具有所需的效果。 否则、您将必须将第一个字节写入 TXBUF 并让 DMAC 处理其余字节。

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

    我已经阅读这句话将近15年了、似乎从未如此正确。 佩德兰教授说,正如措辞所说的那样,这是不正确的,因为通过 DMALEVEL 和其他一些触发器可以明显地实现正常运行。 (一段时间前、我发送了一条文档投诉、呃、反馈询问这句话、但我没有听到任何声音。)

    我刚刚尝试了一个实验、该实验使用 DMALEVEL=1的 TXIFG 触发器来执行 DMA 操作、该操作没有写入 TXBUF (而是使用16字节 memcpy)。 我希望 TXIFG 在整个16个字节内保持高电平、但在一个字节 TXIFG=0时、DMA 被挂起。

    这意味着 DMA 会清除触发器、而不受实际传输所执行的任何操作的影响。 我想这并不是不合理的、但它改变了我的 DMA 工作方式思维模式。 在触发器表[数据表(SLASE54C) 表6-11]中读取、我意识到唯一的非内部触发器是 DMAE0、即 DMAE0是特殊的、因为它是唯一一个触发器实例、DMA 无法在内部清除。

    我想知道这是否是这句话所指的“适当运作”。 但我的设置是有问题的、这是没有人真正想做的事情。 禁止一类基于边缘情况的完全合理使用似乎是过分的。

    [PS:对劫持此线程表示歉意。]

    [编辑:更正了拼写错误]

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

    尊敬的 David:

    感谢您的回答。 对我帮助很大!

    然而、我发现 MSP430上 DMA 的运行是相当奇怪的。

    我解决了这个问题。 感谢你的帮助

    Soun

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

    感谢所有能回答我问题的人、这对我帮助很大。
    我在这里为那些需要的人输入了一段代码。

    #include
    #include
    #include "spi.h"
    #include "main.h"
    #include "dma_all.h"

    //
    //实例
    //


    //
    //变量
    //
    uint8_t SpiRxDdata;
    uint16_t SpiTransferSize;
    uint32_t * AdrBufPtr;

    //
    //初始化 SPI Commun B1
    //
    空 Init_SPI_B1 (空)

       GPIO_setPeripheralModuleFunctionOutputPin (GPIO_PORT_P5、
                                                  SPI_MOSI + SPI_MISO + SPI_CLK、
                                                  GPIO_PRIMARY_MODULE_FUNCTION);

       AdrBufPtr =&TxSpiDmaAddr;
       RxSpiDmaAddr = EUSCI_B_SPI_getReceiveBufferAddress (EUSCI_B1_BASE);
       TxSpiDmaAddr = EUSCI_B_SPI_getTransmitBufferAddress (EUSCI_B1_BASE);

              //初始化 SPI 主设备
       EUSCI_B_SPI_initMasterParam param ={0};
       param.selectClockSource                = EUSCI_B_SPI_CLOCKSOURCE_SMCLK;
       param.clockSourceFrequency             = CS_getSMCLK();
       param.desiredSpiClock                  = 1000000;
       param.msbFirst                         = EUSCI_B_SPI_MSB_FIRST;
       param.clockPhase                       = EUSCI_B_SPI_PHASE_DATA_Captured_ONFIRST_Changed_ON_NEXT;
       param.clockPolarity                    = EUSCI_B_SPI_CLOCKPOLARITY_INACT_LOW;
       param.spiMode                          = EUSCI_B_SPI_3引脚;
       EUSCI_B_SPI_initMaster (EUSCI_B1_BASE、&param);
       EUSCI_B_SPI_ENABLE (EUSCI_B1_BASE);

       //ISR 验证
       EUSCI_B_SPI_clearInterrupt (EUSCI_B1_base、EUSCI_B_SPI_Transmit 中断+ EUSCI_B_SPI_Receive_interrupt);
       EUSCI_B_SPI_enableInterrupt (EUSCI_B1_base、EUSCI_B_SPI_Transmit 中断+ EUSCI_B_SPI_Receive_interrupt);


    //
    // SPI DMA 上的发送字符串
    //
    void SpiDmaSend (字符串[])

       //初始化 DMA 主控方
       DMA_initParam SpiDmaParam ={0};
       SpiDmaParam.channelSelect              = DMA_SPI_CHANNEL;
       SpiDmaParam.transferModeSelect         = dma_transfer_single;
       SpiDmaParam.transferSize               =(uint16_t) strlen (String);
       SpiDmaParam.triggerSourceSelect        = dma_TRIGGERSOURCE_19;         // voir 数据表
       SpiDmaParam.transferUnitSelect         = dma_size_SRCBYTE_DSTBYTE;
       SpiDmaParam.triggerTypeSelect          = DMA_TRIGGER_RISINGEDGE;
       dma_init (SpiDmaParam);

       dma_setSrcAddress (dma_spi_channel、(uint32_t)&String[0]、dma_Directoration_Increment);
       dma_setDstAddress (dma_spi_channel、TxSpiDmaAddr、dma_direction 不变);

       // DMA 验证
       EUSCI_B_SPI_DisableInterrupt (EUSCI_B1_base、EUSCI_B_SPI_Transmit 中断);
       DMA_clearInterrupt (DMA_SPI_channel);
       DMA_enableInterrupt (DMA_SPI_channel);
       DMA_enableTransfers (DMA_SPI_channel);
       while (EUSCI_B_SPI_getInterruptStatus (EUSCI_B1_BASE、EUSCI_B_SPI_Transmit 中断));
       EUSCI_B_SPI_transmitData (EUSCI_B1_base、String[0]);



    //
    // IRQ_DMA (.int42)覆铜 DMA!!!
    //
    空 IRQ_DMA_ALL (无符号 int 索引)


       //dma_uart_channel
       if (dma_getInterruptStatus (dma_uart_channel)==dma_int_active)
           {
           //GPIO_toggleOutputOnPin (GPIO_PORT_P1、LEDVERTE);
           DMA_clearInterrupt (DMA_UART_channel);
           }

       //dma_spi_channel
       if (dma_getInterruptStatus (dma_spi_channel)==dma_int_active)
           {
           GPIO_toggleOutputOnPin (GPIO_PORT_P1、LEDVERTE);
           EUSCI_B_SPI_enableInterrupt (EUSCI_B1_BASE、EUSCI_B_SPI_Transmit 中断);
           DMA_clearInterrupt (DMA_SPI_channel);
           }

    //
    // SPI DMA 测试
    //
    空 SPI_DMA_Task (UARg arg0、UARg arg1)

       unsigned int 发布;

       while (1)
           {
           发布= Event_pend (h_DmaEvent、       // hande du registre 事件
                               EVENT_ID_NONE、    //和掩码
                               SPIDMA_Event、     // orMask
                               超时);

           if (已过帐和 SPIDMA_Event)
               {
               SpiDmaSend ("AZERTYUI");
               }

           Task_sleep (100);
           }



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

    我很高兴您能正常工作。 对于我来说 、DMA_TRIGGER_HIGH 可以正常工作、但我没有使用 TI-RTOS。