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.

[参考译文] RTOS/PROCESSOR-SDK-AM335X:QSPI-McSPI 器件驱动程序问题

Guru**** 2619895 points

Other Parts Discussed in Thread: AM3358

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/641756/rtos-processor-sdk-am335x-qspi-mcspi-device-driver-issue

器件型号:PROCESSOR-SDK-AM335X
主题中讨论的其他器件:AM3358

工具/软件:TI-RTOS

大家好、

我在使用 PDK 器件驱动程序"QSPI-MCSPI"的 SYS/BIOS 上以极短的间隔接收 SPI 数据时遇到问题。 我想在20MHz 时每50微秒发送32*16位值。 为了优化性能、我尝试通过 DMA 缓冲数据、但一旦我使用 memcpy 将数据存储在另一个缓冲区中、我就会丢失一些数据。 我也尝试不使用 DMA、但我也不知道。 您是否知道是否存在低于我要求的性能限制? 如果是、您是否有其他将 BeagleBone Black 与 AM3358芯片结合使用的想法? 我很高兴知道 DMA 缓冲的限制。

编辑:当我将逆变器设置为每90微秒一次时、我从 DMA 缓冲器中获取正确的数据。 每隔90微秒以下、就会在缓冲区的特定指数(索引:0xF、0x20、0x40)处产生数据输出、这些指数均为16的倍数。 我的缓冲区类型为"uint16_t"。 我用相同的结果多次测试了正极和负极场景。

编辑:作为概述、我将使用芯片选择线路从 STM32板发送数据。 了解 DMA 或 SPI 模块是否是底部传感器会让人感兴趣。 数据损坏发生在 DMA 数据包之间。 我尝试了64至2048 16位值(128至4096字节 DMA 缓冲区大小)之间的不同 DMA 缓冲区。

编辑:我100%确定数据丢失发生在两个 DMA 数据包之间。 当我将缓冲区增加到4096字节时、我得到4096个正确字节、但下一个 DMA 缓冲区不接收第一个数据字节。 是否有任何方法可以提高 DMA 性能?

此致

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    RTOS 团队已收到通知。 他们将在这里作出回应。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    David、
    我们需要对此进行研究并返回给您。

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

    你好,Lali,

    您目前是否有任何更新? 使用较低级别的 SPI API 来提高性能是否有意义? 我的应用程序将读取 SPI 数据并通过以太网将其发送出去。 此时、它被配置为每100微秒接收64 16位值、并每毫秒将其发送缓冲输出。 您能为该应用提供什么建议吗?

    编辑:即使使用该配置,我也会在 SPI 上获得 RX 溢出和 TX 下溢错误。

    此致

    David

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

    David、

    您是否在项目上设置了 SPI_DMA_ENABLE 编译标志?
    您在哪个处理器 SDK 示例上启动了项目?

    Lali

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

    你好,Lali,

    SPI DMA 被激活、系统通常与 DMA 一起工作、但不以我需要使用的传输速度工作、并在我的上一篇文章中进行了说明。 在我的方案中、可能无法使用具有 DMA 的 SPI 库、但我还不知道如何在没有该库的情况下使用 SPI 和 DMA。 为了回答您的问题、我使用"mcspi_slavemode"项目作为参考。 从更低层开始提高 SPI DMA 性能是否有意义? 如果是、您是否有任何有关如何执行该操作的提示?

    更新:也许有一个功能可以通过将接收到的数据直接放入以太网发送缓冲器来改进整个系统。 通常、我的应用应仅通过以太网 TCP/UDP 将接收到的 SPI 数据转发到 PC。 您是否有任何提示、或者您是否可以建议任何提供一些解释的论文?

    此致

    David

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

    抱歉回复很慢。 与内部的一些同事进行了核对。
    您使用的 TX/RX FIFO 阈值大小是多少?
    发送2个4096字节背对背数据包是否会导致相同的问题?

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

    你好、Lali、

    1.我尝试了多种不同的配置、并尝试满足 AM335x 用户手册中所述的所有要求。 我将缓冲区对齐到256位、目前我将 FIFO TX 和 RX 大小设置为16、但我也尝试将其设置为32甚至256。 如果有道理、我可以增大或减小缓冲区大小。 我必须在256到8192字节的范围内。
    2.对于发回4096字节数据包,您的意思是什么?

    更新1:启用涡轮模式以提高性能是否有意义?

    更新2:我分析了 PDK SPI 驱动程序、在使用 DMA 时、我可以看到每次调用 SPI_Transfer 函数时都会执行大量配置。 是否有办法避免这种配置以提高性能?

    摘录:

    静态空 MCSPI_DMA_primeTransfer_v1 (MCSPI_Handle McHandle、
    SPI_Transaction *事务)
    {
    SPI_Handle 句柄;
    SPI_v1_Object *对象;
    SPI_v1_chObject *chObj;
    uint32_t chNum;
    SPI_v1_HWAttrs const *hwAttrs;
    EDMA3_DRV_PaRAMRegs rxParamSet ={0};
    EDMA3_DRV_PaRAMRegs txParamSet ={0};
    EDMA3_DRV_PaRAMRegs dummyParamSet ={0};
    
    /*输入参数验证*/
    OSAL_ASSERT (!((mcHandle!= NULL)&&(事务!= NULL)));
    
    /*获取对象和 hwAttrs 的指针*/
    handle = mcHandle->handle;
    chNum = mcHandle->chnNum;
    对象=(SPI_v1_Object*)句柄->对象;
    chObj =&(object->chObject[chNum]);
    hwAttrs =(SPI_v1_HWAttrs*) handle->hwAttrs;
    
    /*设置传输模式和 FIFO 触发电平*/
    MCSPI_xferSetup_v1 (mcHandle、事务);
    
    /*接收参数集*/
    EDMA3_DRV_getPaRAM ((EDMA3_DRV_Handle) hwAttrs->edmaHandle、
    hwAttrs->rxDmaEventNumber,
    rxParamSet (&rxParamSet);
    
    /*发送参数集*/
    EDMA3_DRV_getPaRAM ((EDMA3_DRV_Handle) hwAttrs->edmaHandle、
    hwAttrs->txDmaEventNumber,
    txParamSet);
    
    /*根据事务参数更新参数组*/
    MCSPI_DMA_localEdmaUpdateParams_v1 (mcHandle、
    事务、
    rxParamSet (&Y)、
    txParamSet);
    
    /*虚拟参数集配置*/
    EDMA3_DRV_getPaRAM (hwAttrs->edmaHandle、
    EDMA3_DRV_LINK_CHANNEL、
    dummyParamSet (&U);
    
    dummyParamSet.aCnt =(uint16_t) MCSPI_EDMA3CC_PARAM_ACNT;
    dummyParamSet.linkAddr = MCSPI_EDMA3CC_PARAM_LINK_ADDRESS;
    dummyParamSet.op &=~(((uint32_t) 0x01U << MCSPI_EDMA3CC_opt_static_shift);
    
    /*现在,写入参数集。 *
    EDMA3_DRV_setPaRAM (hwAttrs->edmaHandle、
    EDMA3_DRV_LINK_CHANNEL、
    dummyParamSet (&U);
    
    /*写入 Rx 参数集*/
    EDMA3_DRV_setPaRAM ((EDMA3_DRV_Handle)(hwAttrs->edmaHandle)、
    hwAttrs->rxDmaEventNumber,
    rxParamSet (&rxParamSet);
    
    /*写入 Tx 参数集*/
    EDMA3_DRV_setPaRAM ((EDMA3_DRV_Handle)(hwAttrs->edmaHandle)、
    hwAttrs->txDmaEventNumber,
    txParamSet);
    
    /*链接虚拟参数集*/
    EDMA3_DRV_linkChannel (hwAttrs->edmaHandle、
    hwAttrs->txDmaEventNumber,
    EDMA3_DRV_LINK_CHANNEL);
    
    /*对 RX 端进行编程*/
    EDMA3_DRV_enableTransfer (hwAttrs->edmaHandle、
    hwAttrs->rxDmaEventNumber,
    EDMA3_DRV_TRIG_MODE_EVENT);
    
    /*对 TX 端进行编程*/
    EDMA3_DRV_enableTransfer (hwAttrs->edmaHandle、
    hwAttrs->txDmaEventNumber,
    EDMA3_DRV_TRIG_MODE_EVENT);
    
    /*为事务启用 McSPI DMA
    * MCSPI_CH (chNum) CONF ->用于接收 DMA 的 DMAR 位
    *
    McSPIDMAEnable ((uint32_t)(hwAttrs->baseAddr)、
    (((uint32_t) MCSPI_DMA_RX_EVENT |
    (uint32_t) MCSPI_DMA_TX_EVENT)、
    chNum);
    
    /*启用通道*/
    McSPIChannelEnable((UINT32_t)(hwAttrs->baseAddr), chNum);
    
    if ((SPI_MASTER =chObj->spiParams.mode)&&
    (hwAttrs->chMode =MCSPI_SINGLE_CH)
    {
    /*断言芯片选择信号*/
    McSPICSAssert((UINT32_t)(hwAttrs->baseAddr),chNum );
    }
    
    } 



    此致、

    David

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

    最大 SPI FIFO 大小为32字节、在双工模式下、建议设置 TX 和 RX FIFO 大小。 您似乎正在使用半双工模式(?) 仅发送数据。

    您可以尝试将模式设置为仅 TX 半双工。 将 TX FIFO 大小设置为32、将 RX FIFO 设置为0。 看看这是否有用。

    请忽略我的背对背评论。

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

    这完全是我只通过 SPI 接收数据的另一种方式。 然后通过以太网将接收到的数据重定向到计算机。 我已经尝试将 TX FIFO 大小设置为0、将 RX FIFO 大小设置为32/16。

    此致、

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

    你好、Lali、

    我现在尝试将 SPI DMA 与 CSL 驱动程序结合使用、但我仍然得到 RX_overflow 设置。 设置后、我无法再接收数据。

    /*包含所有必要的头文件*/
    #include "stdint.h"
    #include "mcspi.h"
    #include "hw_mcspi.h"
    #include "edma_event.h"
    #include "soc_am335x.h"
    #include "interrupt.h"
    
    #include "hw_event.h"
    
    #include "#include "include"
    
    
    //*
    内部宏定义 */
    ********* //#define
    MCSPI_TX_EVENT (EDMA3_CHA_MCSPI0_CH0_TX)
    //#define MCSPI_RX_EVENT (EDMA3_CHA_MCSPI0_CH0_RX)
    #define MCSPI_TX_EVENT (EDMA3_CHA_MCSPI1_CH0_TX)
    #define MCSPI_RX_EVENT (EDMA3_CHA_MCSPI1_CH0_RX)
    //#define MCSPI_TX0_REG (0x48130138u)
    #define MCSPI_TX0_REG (0x481A0138u)
    //#define MCSPI_RX0_REG (0x4803013Cu)
    #define MCSPI_RX0_REG (0x481A013Cu)
    #define MCSPI_IN_CLK (48000000u)
    #define MCSPI_OUT_FREQ (24000000u)
    #define MCSPI_CH_NUM (0U)
    #define EVT_QUEQUE_NUM (0U)
    #define dummy_ch_NUM (5U)
    #define MCSPISLV_MCSPI_regs SoC_SPI_1_regs
    #define MCSPI_CH_ZERO (0U)
    
    #define FIFORX DATALENGTH/2
    #define DATALENGTH 32
    #define FDAAENABLE (1U)
    
    
    
    #define MCSPI_SIDLEMODE_NO (((uint32_t) MCSPI_SysConfig_sIDLEMODE_NO \
    << MCSPI_SysConfig_sIDLEMODE_SHIFT)
    
    EDMA3CCPaRAMEntry 参数集;
    ********* //*
    本地函数原型 */
    ********* /
    静态空 McSpiTxEdmaParamSet (unsigned int tccNum、unsigned int chNum、
    volatile unsigned char * buffer、
    unsigned short buffLength);
    static void McSpiRxEdmaParamSet (unsigned int tccNum、unsigned int chNum、
    volatile unsigned char * buffer、
    无符号短 buffLength、
    unsigned int destBidxFlag);
    静态空回调(unsigned int tccNum、unsigned int status);
    静态空 McSPITransfer (unsigned short length);
    静态空 TxDummyPaRAMRequestEnable (void);
    静态空 Edma3HandlerIsError (void);
    静态空 Edma3ComplHandlerIsr (Confid);
    静态空
    静态空 EDMA3AINTCConfigure (void);
    静态空 EDMA3Initialize (void);
    静态空 McSPISetUp (void);
    
    静态空 testSPIEdma (void);
    
    / //*
    全局变量 */
    ********* /
    静态空(* CB_Fxn[EDMA3_NUM_TCC])(无符号 int TCC、无符号 int 状态);
    
    uint16_t rxBuffer[8192]__attribute__(对齐(256));
    
    uint16_t*
    
    
    无符号 rxBufferPtr =****Buffer;易失性 flagchar vrfyData[256];volatile ricatile trage****uintx
    = 0
    
    = 0;volatile rnatile rx uint8 = unsignatile rrrrrrrrrrrrrrrx = 0;volatile rx //*
    本地函数定义 */
    ********* //*
    
    
    **主函数。
    */
    int main (void)
    {
    testSPIEdma();
    while (1)
    {
    
    }
    }
    
    静态 void testSPIEdma()
    {
    /*启用 McSPI1模块的时钟。*/
    McSPI1ModuleClkConfig();
    /*对 SPI1实例执行引脚复用。*/
    McSPI1PinMuxSetup();
    /*初始化 EDMA3实例。*/
    EDMA3初始化();
    对于 SPI1、//请求针对 Tx 和 Rx 通道的 EDMA3CC。 *
    RequestEDMA3通道();
    /*设置 McSPI 实例。*/
    McSPISetUp();
    CB_Fxn[MCSPI_RX_EVENT]=回调(&B);
    /*为 EDMA 接收配置写入启用参数。*/
    McSpiRxEdmaParamSet (MCSPI_RX_EVENT、MCSPI_RX_EVENT、rxBuffer、DATALENGTH、TRUE);
    EDMA3SetPaRAM (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT、&ParamSet);
    /*启用 EDMA3传输。*/
    EDMA3ClrMissEvt (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT);
    EDMA3 EnableDmaEvt (SOC_EDMA30CC_0_regs、MCSPI_RX_EVENT);
    McSPITransfer (DATALENGTH);
    }/*
    
    
    **此函数用于配置 EDMA3通道控制器0
    的电源**和传输控制器0,在 AINTC 中记录 EDMA 中断。
    */
    静态空 EDMA3初始化(空)
    {
    /*为 EDMA 启用模块时钟*/
    EDMAModuleClkConfig();
    
    /* EDMA3初始化*/
    EDMA3Init (SOC_EDMA30CC_0_regs、EVT_QUEQUE_NUM);
    
    /*配置 AINTC 以接收 EDMA3中断*/
    EDMA3AINTCConfigure();
    }/*
    
    
    **此函数将在传输前使芯片选择线路有效,将
    **为 McSPI 外设的 Tx/Rx 启用 EDMA 事件,并
    在通信完成后使**芯片选择无效。
    */
    静态空 McSPITransfer (无符号短长度)
    {
    /*使用要传输的数据长度设置字节数字段。*/
    McSPIWordCountSet (SOC_SPI_1_regs、长度);
    
    /*为 McSPI 启用 Tx/Rx DMA 事件。 *
    McSPIDMAEnable (SOC_SPI_1_regs、(MCSPI_DMA_RX_EVENT)、
    MCSPI_CH_NUM);
    
    /*启用 McSPI 通道进行通信。*/
    McSPIChannelEnable (SOC_SPI_1_regs、MCSPI_CH_NUM);
    
    /*等待控制权从 ISR 返回。*/
    // while (flagRx =0)
    // ;
    ////
    flagTx = 0;
    // flagRx = 0;
    //
    //////*禁用 McSPI 通道进行通信。*//
    McSPIChannelDisable (SOC_SPI_1_regs、MCSPI_CH_NUM);
    }
    
    //
    ** EDMA3完成中断服务例程(ISR)。
    */
    static void Edma3ComplHandlerIsr (void)
    {
    unsigned int pendingIrqs;
    unsigned int isIPR = 0;
    unsigned int indexl;
    unsigned int cnt = 0;
    
    分度值= 1;
    EDMA3ClrIntr (SOC_EDMA30CC_0_regs、MCSPI_RX_EVENT);
    (* CB_Fxn[MCSPI_RX_EVENT])(MCSPI_RX_EVENT、EDMA3_Xfer_COMPLETE);
    }
    
    //* EDMA3错误处理程序*/
    静态空 Edma3ErrorHandlerIsr (void)
    {
    EDMA3ClrMissEvt (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT);
    
    /*禁用 McSPI 接收事件*/
    McSPIDMADisable (SOC_SPI_1_regs、MCSPI_DMA_RX_EVENT、MCSPI_CH_NUM);
    
    /*禁用 EDMA 传输*/
    EDMA3 DisableTransfer (SOC_EDMA30CC_0_regs、MCSPI_RX_EVENT、
    EDMA3_TRIG_MODE_EVENT);
    
    flagRx = 1;
    
    }/*
    
    
    **回叫功能。 这里我们禁用 McSPI
    **外设的 Tx/Rx DMA 事件。
    */
    静态空回调(unsigned int tccNum、unsigned int status)
    {
    
    if (tccNum == MCSPI_RX_EVENT)
    {
    flagRx = 1;
    //McSPIDMADisable (SOC_SPI_1_regs、MCSPI_DMA_RX_EVENT、MCSPI_CH_NUM);
    //McSPIChannelDisable (SOC_SPI_1_regs、MCSPI_CH_NUM);
    rxBufferPtr+=DATALENGTH;
    //McSpiRxEdmaParamSet (MCSPI_RX_EVENT、MCSPI_RX_EVENT、rxBufferPtr、DATALENGTH、TRUE);
    paramSet.destAddr =(unsigned int) rxBufferPtr;
    EDMA3SetPaRAM (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT、&ParamSet);
    EDMA3ClrMissEvt (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT);
    EDMA3 EnableDmaEvt (SOC_EDMA30CC_0_regs、MCSPI_RX_EVENT);
    McSPIWordCountSet (SOC_SPI_1_regs、DATALENGTH);
    
    //McSPIDMAEnable (SOC_SPI_1_regs、MCSPI_DMA_RX_EVENT、MCSPI_CH_NUM);
    //McSPIChannelEnable (SOC_SPI_1_regs、MCSPI_CH_NUM);
    /*禁用 McSPI 接收事件*/
    //McSPIDMADisable (SOC_SPI_1_regs、MCSPI_DMA_RX_EVENT、MCSPI_CH_NUM);
    }
    }
    
    /*
    **此函数用于设置 EDMA3的 PARAM 条目,以用于
    McSPI0实例的通道0的接收**事件。 相应的 EDMA3通道
    **也可用于接收。
    静态
    空 McSpiRxEdmaParamSet (unsigned int tccNum、unsigned int chNum、
    volatile unsigned char * buffer、
    无符号短 buffLength、
    unsigned int destBidxFlag)
    {
    
    
    unsigned char *p =(unsigned char *)&ParamSet;
    unsigned int index = 0;
    
    /*清理结构变量的内容。 *
    对于(index = 0;index < sizeof (ParamSet);index++)
    {
    P[索引]= 0;
    }
    
    /*用接收特定信息填写参数集。*/
    
    /* srcAddr 保存 SPI Rx FIFO 的地址。*/
    ParamSet.srcAddr =(unsigned int)(MCSPI_RX0_REG);
    
    /* destAddr 是名为 buffer 的内存位置的地址。*/
    paramSet.destAddr =(unsigned int)缓冲区;
    
    /* aCnt 保存数组中的字节数。*/
    ParamSet.aCnt = 2;
    
    /* bcnt 保存要传输的此类数组的数量。*/
    ParamSet.bCnt = FIFORX >> 1;
    
    /* ccnt 保存要传输的 aCnt*bcnt 字节的帧数。*/
    ParamSet.ccnt = DATALENGTH / ParamSet.bcnt;
    
    /*不应递增 srcBidx、因为它是一个 h/w 寄存器。*/
    ParamSet.srcBIdx = 0;
    
    if (true == destBidxFlag)
    {
    /*每个字节的 destBidx 应该递增。*/
    paramSet.destBIdx = ParamSet.aCnt;
    }
    其他
    {
    /*不应递增 destBidx。*/
    paramSet.destBIdx = 0;
    }
    
    /*同步传输模式。 *
    /*使用异步模式后,srCIdx 和 destCIdx 均设为零。*/
    ParamSet.srcCIdx = 0;
    /*TODO:rxtrig 或0*/
    paramSet.destCIdx = FIFORX;
    
    /*不使用 EDMA3中的链接传输。*/
    ParamSet.linkAddr = 0xFFFF;
    
    ParamSet.bCntReload = ParamSet.bCnt;
    
    ParamSet.opt &= 0xFFFFFFFCU;
    ParamSet.opt &= 0xFFFFFFU;
    ParamSet.op= 0x4U;
    ParamSet.opt &=(~EDMA3CC_opt_TCC);
    /*使用 tccNum.*/在选项中设置 TCC 字段
    ParamSet.opt |=((tccNum << EDMA3CC_OPT_TCC_SHIFT)和 EDMA3CC_OPT_TCC);
    
    
    /* EDMA3中断被启用并且中间中断被禁用。*/
    ParamSet.opt |=(1 <<EDMA3CC_OPT_TCINTEN 位移);
    
    }/*
    
    
    **此函数将 EDMA3通道分配给 McSPI0以进行传输和
    **接收。
    */
    静态 void RequestEDMA3通道(void)
    {
    //
    EDMA3RequestChannel (SOC_EDMA30CC_0_regs、EDMA3_CHANNEL_TYPE_DMA)\
    //请求 SPI 发送的 DMA 通道和 TCC MCSPI_TX_EVENT、MCSPI_TX_EVT_QUECE_NUM);
    /*请求 DMA 通道和 TCC 以进行 SPI 接收*/
    EDMA3RequestChannel (SOC_EDMA30CC_0_regs、EDMA3_CHANNEL_TYPE_DMA、
    MCSPI_RX_EVENT、
    MCSPI_RX_EVENT_EVT_QUEQUE_NUM);
    }
    
    /*
    **此函数将调用必要的 McSPI API,这些 API 将配置
    ** McSPI 控制器。
    */
    static void McSPISetUp (void)
    {
    /*重置 McSPI 实例。*/
    McSPIReset (SOC_SPI_1_regs);
    
    MCSPISysConfigSetup (SOC_SPI_1_regs、MCSPI_Clocks_OCP_ON_FUNC_ON、
    MCSPI_SIDLEMODE_NO、
    MCSPI_WAKEUP_DISABLE、
    MCSPI_AUTOIDLE_OFF);
    /*启用芯片选择引脚。*/
    McSPICSEnable (SOC_SPI_1_regs);
    
    /*启用主操作模式。*/
    /*从机模式启用*/
    //McSPIMasterModeEnable (SOC_SPI_1_regs);
    McSPISlaveModeEnable (SOC_SPI_1_regs);
    McSPIFODatManagementConfig (SOC_SPI_1_regs、FDAAENABLE);
    /*对主控模式执行必要的配置。*/
    MCSPIPinDirSet (SOC_SPI_1_regs、MCSPI_RX_ONLY _MODE、
    MCSPI_DATA_LINE_COMM_MODE_7、0);
    
    McSPITurboModeEnable (SOC_SPI_1_regs、MCSPI_CH_NUM);
    /*配置 McSPI 输出频率。 *
    McSPIClkConfig (SOC_SPI_1_regs、MCSPI_IN_CLK、MCSPI_OUT_FREQ、
    MCSPI_CH_NUM、
    MCSPI_CLK_MODE_0);
    
    /*配置字长。*/
    McSPIWordLengthSet (SOC_SPI_1_regs、MCSPI_WORD_LENGTH (16)、MCSPI_CH_NUM);
    
    /*将 SPIEN 的极性设置为低。*/
    McSPICSPPolarityConfig (SOC_SPI_1_regs、MCSPI_CS_POL_LOW、MCSPI_CH_NUM);
    
    /*启用 McSPI 的 Tx FIFO。*/
    McSPITxFIFOConfig (SOC_SPI_1_regs、MCSPI_TX_FIFO_DISABLE、MCSPI_CH_NUM);
    
    /*启用 McSPI 的 Rx FIFO。*/
    McSPIRxFIFOConfig (SOC_SPI_1_regs、MCSPI_RX_FIFO_ENABLE、MCSPI_CH_NUM);
    
    McSPIFIFOTrigLvlSet (SOC_SPI_1_regs、FIFORX、0、MCSPI_RX_ONLY _MODE);
    }/*
    
    
    **此函数将 AINTC 配置为接收 EDMA3中断。
    */
    static void EDMA3AINTCConfigure (void)
    {
    /*在 CPSR 中启用 IRQ。*/
    IntMasterIRQEnable();
    /*初始化 ARM 中断控制器。 *
    IntAINTCInit();
    
    /*注册 EDMA3通道控制器0传输完成中断。 *
    IntRegister (SYS_INT_EDMACOMPINT、Edma3ComplHandlerIsr);
    
    /*在 AINTC 中设置 EDMA3CC0完成中断的优先级。 *
    IntPrioritySet (SYS_INT_EDMACOMPINT、0、AINTC_HOSTINT_route _IRQ);
    
    /*在 AINTC 中启用 EDMA3CC0完成中断。 *
    IntSystemEnable (SYS_INT_EDMACOMPINT);
    
    /*注册 EDMA3通道控制器0错误中断。 *
    IntRegister (SYS_INT_EDMAERRINT、Edma3ErrorHandlerIsr);
    
    /*在 AINTC 中设置 EDMA3CC0错误中断的优先级。 *
    IntPrioritySet (SYS_INT_EDMAERRINT、0、AINTC_HOSTINT_route _IRQ);
    
    /*在 AINTC 中启用 EDMA3CC0错误中断。 *
    IntSystemEnable (SYS_INT_EDMAERRINT);
    }/*
    
    
    **这将配置虚拟传输的参数集。
    */
    static void TxDummyPaRAMConfEnable (void)
    {
    EDMA3CCPaRAMEntry DummyPaRAMSet;
    
    EDMA3GetPaRAM (SOC_EDMA30CC_0_regs、dummy_ch_NUM、&dummyPaRAMSet);
    
    dummyPaRAMSet.aCnt = 1;
    dummyPaRAMSet.bCnt = 0;
    dummyPaRAMSet.ccnt = 0;
    dummyPaRAMSet.srcAddr = 0;
    dummyPaRAMSet.destAddr = 0;
    dummyPaRAMSet.srcBIdx = 0;
    dummyPaRAMSet.destBIdx = 0;
    dummyPaRAMSet.srcCIdx = 0;
    dummyPaRAMSet.destCIdx = 0;
    dummyPaRAMSet.linkAddr = 0xFFFFu;
    dummyPaRAMSet.bCntReload = 0;
    dummyPaRAMSet.opt = 0;
    
    EDMA3SetPaRAM (SOC_EDMA30CC_0_regs、dummy_ch_NUM、&dummyPaRAMSet);
    }
    
    

    你有更新吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我在裸机 Starterware 基础上实施了 SPI DMA、现在我已经开始使用了。 我测试了作为具有24MHz 主时钟的从器件接收数百万数据、似乎可以正常工作。 我仍然会设置 RX_overflow 寄存器标志、但我现在确实忽略了这一点、因为我没有丢失任何数据。 如果您通过添加一个不能完全关闭驱动程序的 SPIDMA 传输函数来扩展 MCSPI 驱动程序以实现更高的吞吐量、那将是一种不错的选择。 在我的回调函数中、我仅执行此操作以重新启动传输。

    静态空回调(unsigned int tccNum、unsigned int status)


    if (tccNum == MCSPI_RX_EVENT)

    flagRx = 1;
    rxBufferPtr+=DATALENGTH;
    paramSet.destAddr =(unsigned int) rxBufferPtr;
    EDMA3SetPaRAM (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT、&ParamSet);
    EDMA3ClrMissEvt (SOC_EDMA30CC_0_reg、MCSPI_RX_EVENT);
    EDMA3 EnableDmaEvt (SOC_EDMA30CC_0_regs、MCSPI_RX_EVENT);
    McSPIWordCountSet (SOC_SPI_1_regs、DATALENGTH);