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.
尊敬的TI工程师
您好,我在使用28377d的SPI的DMA模式时发现问题,请求您的帮助解答。
首先我在syscfg中将SPI与DMA配置如下图。
在board.c中生成的初始化部分对应代码如下:
void Board_init() { EALLOW; PinMux_init(); DMA_init(); SPI_init(); EDIS; } //***************************************************************************** // // PINMUX Configurations // //***************************************************************************** void PinMux_init() { // // PinMux for modules assigned to CPU1 // // // SPIA -> mySPI0 Pinmux // GPIO_setPinConfig(mySPI0_SPIPICO_PIN_CONFIG); GPIO_setPadConfig(mySPI0_SPIPICO_GPIO, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(mySPI0_SPIPICO_GPIO, GPIO_QUAL_ASYNC); GPIO_setPinConfig(mySPI0_SPIPOCI_PIN_CONFIG); GPIO_setPadConfig(mySPI0_SPIPOCI_GPIO, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(mySPI0_SPIPOCI_GPIO, GPIO_QUAL_ASYNC); GPIO_setPinConfig(mySPI0_SPICLK_PIN_CONFIG); GPIO_setPadConfig(mySPI0_SPICLK_GPIO, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(mySPI0_SPICLK_GPIO, GPIO_QUAL_ASYNC); GPIO_setPinConfig(mySPI0_SPIPTE_PIN_CONFIG); GPIO_setPadConfig(mySPI0_SPIPTE_GPIO, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(mySPI0_SPIPTE_GPIO, GPIO_QUAL_ASYNC); } //***************************************************************************** // // DMA Configurations // //***************************************************************************** void DMA_init(){ DMA_initController(); mySPI0_RX_DMA_init(); mySPI0_TX_DMA_init(); } void mySPI0_RX_DMA_init(){ DMA_setEmulationMode(DMA_EMULATION_STOP); DMA_configAddresses(mySPI0_RX_DMA_BASE, DualMCUCommSPI_destAddress, mySPI0_RX_DMA_ADDRESS); DMA_configBurst(mySPI0_RX_DMA_BASE, 1U, 0, 1); DMA_configTransfer(mySPI0_RX_DMA_BASE, 2U, 0, 1); DMA_configWrap(mySPI0_RX_DMA_BASE, 65535U, 0, 65535U, 0); DMA_configMode(mySPI0_RX_DMA_BASE, mySPI0_RX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT); DMA_enableTrigger(mySPI0_RX_DMA_BASE); DMA_stopChannel(mySPI0_RX_DMA_BASE); } void mySPI0_TX_DMA_init(){ DMA_setEmulationMode(DMA_EMULATION_STOP); DMA_configAddresses(mySPI0_TX_DMA_BASE, mySPI0_TX_DMA_ADDRESS, DualMCUCommSPI_srcAddress); DMA_configBurst(mySPI0_TX_DMA_BASE, 1U, 1, 0); DMA_configTransfer(mySPI0_TX_DMA_BASE, 2U, 1, 0); DMA_configWrap(mySPI0_TX_DMA_BASE, 65535U, 0, 65535U, 0); DMA_configMode(mySPI0_TX_DMA_BASE, mySPI0_TX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT); DMA_enableTrigger(mySPI0_TX_DMA_BASE); DMA_stopChannel(mySPI0_TX_DMA_BASE); } //***************************************************************************** // // SPI Configurations // //***************************************************************************** void SPI_init(){ mySPI0_init(); } void mySPI0_init(){ SPI_disableModule(mySPI0_BASE); SPI_setConfig(mySPI0_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1, SPI_MODE_CONTROLLER, mySPI0_BITRATE, mySPI0_DATAWIDTH); SPI_setPTESignalPolarity(mySPI0_BASE, SPI_PTE_ACTIVE_LOW); SPI_enableFIFO(mySPI0_BASE); SPI_disableLoopback(mySPI0_BASE); SPI_setEmulationMode(mySPI0_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT); SPI_enableModule(mySPI0_BASE); }
我在使用该SPI模块时发现,当我使用NonFIFO的primitive模式或pollingFIFO模式时,都能正确传输,但是当我用DMA模式时,传输故障,具体表现为:传输主机端完成发送接收动作后跳出该轮任务并判定传输失败,但从机却一直处在准备态,等待主机发起传输。
我把主机端的SPI应用函数放在下面这里:
typedef union SPI_ExchangeData { uint16_t data16[2]; // 16-bit representation uint32_t data32; // 32-bit representation } SPI_ExchangeData; SPI_ExchangeData gdataSendSPI[DualMCUCommSPI_BUFFER_SIZE_32BIT]; SPI_ExchangeData gdataReceiveSPI[DualMCUCommSPI_BUFFER_SIZE_32BIT]; const void *DualMCUCommSPI_destAddress = (const void*) gdataReceiveSPI; const void *DualMCUCommSPI_srcAddress = (const void*) gdataSendSPI; typedef enum { PRIMITIVE, POLLING, DMA, } TRANSFER_METHOD; void DualMCUCommSPI_transfer(TRANSFER_METHOD transferMethod) { switch(transferMethod) { case PRIMITIVE: { DualMCUCommSPI_transferPrimitive(); break; } case POLLING: { DualMCUCommSPI_transferPolling(); break; } case DMA: { DualMCUCommSPI_transferDMA(); break; } } } void DualMCUCommSPI_transferDMA(void) { DMA_startChannel(DualMCUCommSPI_TX_DMA_BASE); DMA_startChannel(DualMCUCommSPI_RX_DMA_BASE); } void DualMCUCommSPI_transferPolling(void) { SPI_pollingFIFOTransaction(DualMCUCommSPI_BASE, 16, (uint16_t *)&gdataSendSPI, (uint16_t *)&gdataReceiveSPI, 2, 0); } void DualMCUCommSPI_transferPrimitive(void) { SPI_writeDataNonBlocking(DualMCUCommSPI_BASE, gdataSendSPI[0].data16[0]); gdataReceiveSPI[0].data16[0] = SPI_readDataBlockingNonFIFO(DualMCUCommSPI_BASE); SPI_writeDataNonBlocking(DualMCUCommSPI_BASE, gdataSendSPI[0].data16[1]); gdataReceiveSPI[0].data16[1] = SPI_readDataBlockingNonFIFO(DualMCUCommSPI_BASE); }
SPI_DMA的方式我在F28388D上面曾验证测试通过,现在同样的调用方法在F28377D上却行不通,您帮我看看故障原因是DMA配置有误还是调用方式有误,除了开启TX和RX的DMA通道 还需要别的动作吗。
你好,
很抱歉回复延迟。浏览你的帖子,我有一个快速的问题——当你说传输主机完成了发送和接收操作时,你是说在失败之前有一个完整的通信,还是说主机从来没有真正与辅助设备通信,只是准备它?
如果是前者,请参阅设备TRM中关于连续模式的部分,并确保您正确地重新启用了通道。或者,还要确保所有SPI外围中断标志也被清除。
回答您的问题:主机从来没有真正与从机通信。
我观察到的现象是:从机先启动,从机的SPI_DMA一直在准备就绪状态,等待主机发起SPI_DMA任务,但主机的SPI任务已结束。
传输动作的关键部分如下:
DMA_startChannel(SPIA_TX_DMA_BASE); DMA_startChannel(SPIA_RX_DMA_BASE); while ((DMA_getTransferStatusFlag(SPIA_TX_DMA_BASE)) || (DMA_getTransferStatusFlag(SPIA_RX_DMA_BASE)));
主机执行完SPI_DMA启动通道后,已跳出状态忙等待,并已在执行后续操作,因此我确定主机已结束DMA任务,但由于从机的SPI一直等待,说明主机的SPI消息并未真正发送。我目前的疑点是F28377D是否支持DMA通道开启激活对应的SPI任务,意思是说,由于我用DMA状态作为任务是否完成的判据,有没有可能DMA启动了,但SPI没启动,主机看到DMA搬运完后跳出等待并认为SPI_DMA完成,实则DMA开启并未触发SPI收发。
很抱歉回复延迟。
你能用示波器观察SPI信号吗?
请在代码跳出while循环后发送DMA控制寄存器状态的屏幕截图。
验证FIFO级别是否设置为1?它必须与DMA的突发大小相匹配,该大小设置为1。