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.
我正在使用散聚模式将 SPI 传感器与 DMA 连接。 我在这里一定会错过一些东西。
为了从传感器 FIFO 中提取192个字节、我填充了一个任务表、每个任务表都是 DMA_ControlTable 类型的元素。 此类表如下所示;其中385个条目、需要大约6 KB、但我有足够的内存:
/* SPI 读取 DMA 序列*/ DMA_ControlTable SpiAccReadoutSEQ[N_of _ACC_DMA_tasks];
该序列倾向于重复相同的任务、只需更改几个参数;因此我编写了以下代码以快速初始化任务列表:
// SPI 读取任务 DMA_ControlTable SendAccReadoutAddr = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&AccOutputAddr、 UDMA_DST_INC_NONE、&SPI_Module_Address->TXBUF、 UDMA_ARB_1、(UDMA_MODE_MEM_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable SendFirstDummyByte = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&dummyTx、 UDMA_DST_INC_NONE、&SPI_Module_Address->TXBUF、 UDMA_ARB_1、(UDMA_MODE_PER_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable SendDummyByte = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&dummyTx、 UDMA_DST_INC_NONE、&SPI_Module_Address->TXBUF、 UDMA_ARB_1、(UDMA_MODE_MEM_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable 检索字节 FromAcc = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&SPI_Module_Address->RXBUF、 UDMA_DST_INC_NONE、&AccDataBuffer[0]、 UDMA_ARB_1、(UDMA_MODE_PER_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable 检索 LastByteFromAcc = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&SPI_Module_Address->RXBUF、 UDMA_DST_INC_NONE、&AccDataBuffer[ACC_DATA_Buffer_LEN - 1]、 UDMA_ARB_1、UDMA_MODE_BASIC); SpiAccReadoutSEQ[0]= SendAccReadoutAddr; SpiAccReadoutSEQ[1]= SendFirstDummyByte; SpiAccReadoutSEQ[2]=检索字节从 Acc; 对于(I = 3;I < N_of _ACC_DMA_tasks;I += 2) { SpiAccReadoutSEQ[i]= SendDummyByte; if (i = N_of _acc_dma_tasks - 2) 中断; SpiAccReadoutSEQ[i+1]=检索字节从 Acc; SpiAccReadoutSEQ[i+1].dstEndAddr =&AccDataBuffer[(I-1)/2]; } SpiAccReadoutseq[N_of _ACC_DMA_tasks - 1]=获取 LastByteFromAcc;
DMA 的配置如下:
/* DMA 控制表*/ #if defined (__TI_Compiler_version__) #pragma DATA_ALIGN (DmaControlTable,1024) #Elif defined (__IAR_SYSTEMS_ICC__) #pragma DATA_ALIGNing=1024 #Elif defined (__GNUC__) __(aligned ((aligned (__IAR_systems_cus))))__dmaControlTable_241024_ad_ad_(dirt_arm_en_en_ador_en_en_en_(#elift_(_status_(1024 )
//启用 DMA DMA_enableModule(); //分配控制表 DMA_setControlBase (DmaControlTable); //配置 DMA 传输 DMA_setChannelControl (DMA_Wired_UART_TX_CH|UDMA_PRI_SELECT、UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_ARB_NONE | UDMA_INC_1); DMA_setChannelControl (DMA_Wired_UART_RX_CH|UDMA_PRI_SELECT、UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_ARB_8 | UDMA_INC_1); DMA_setChannelControl (DMA_OPTIC_UART_TX_CH|UDMA_PRI_SELECT、UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_ARB_NONE | UDMA_INC_1); DMA_setChannelControl (DMA_OPTIC_UART_RX_CH|UDMA_PRI_SELECT、UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_ARC_8 | UDMA_INC_1); DMA_setChannelControl (DMA_append_packet_ch|UDMA_PRI_SELECT、UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_ARB_8 | UDMA_INC_1024); //分配通道 dma_assignChannel (dma_optical_uart_TX_CH); DMA_assignChannel (DMA_wired_UART_TX_CH); dma_assignChannel (dma_optical_uart_RX_CH); DMA_assignChannel (DMA_wired_UART_RX_CH); DMA_assignChannel (DMA_SPI_TX_CH); DMA_assignChannel (DMA_SPI_RX_CH); dma_assignChannel (dma_append_packet_CH); //清除 IFG 寄存器 DMA_Channel->INT0_CLRFLG = 0xFFFFFFFF; //将中断分配给特定的 DMA ISR DMA_assignInterrupt (INT_DMA_SPI、DMA_SPI_RX_CH_NUM); //在启用前清除特定的 DMA 中断标志 DMA_clearInterruptFlag (DMA_SPI_RX_CH 和0x0F); //启用 SPI DMA 中断 DMA_enableInterrupt (INT_DMA_SPI);
void FetchInertialData (SpiDeviceHandle *句柄) { //超时计数器 volatile uint16_t Timeout; //在开始数据传输之前,等待一些时间 超时= handle->CsInterval_T; while (--Timeout); //预载建立时间 超时= handle->setup_T; //清除 SPI Rx 中断标志 Handle->SpiModuleAddress->IFG &=~SPI_Receive_interrupt_FLAG; //降低 CS GPIO_setOutputLowOnPin (handle->CsPort、handle->CsPin); //等待建立时间 while (--Timeout); //在散聚模式下执行数据提取 if (handle =&AccSpiHandle) DMA_setChannelScatterGather (DMA_SPI_RX_CH、N_of _ACC_DMA_tasks、SpiAccReadoutSeq、0); DMA_enableChannel (DMA_SPI_RX_CH_NUM); DMA_requestSoftwareTransfer (DMA_SPI_RX_CH_NUM); }
SPI 外设工作正常、可在启动时读取和写入传感器设置。 当我尝试通过 DMA 获取外部 FIFO 内容时、会出现问题:MOSI 和 MISO 不移动、并且在示波器上对 SCK 脉冲进行计数、我只看到10字节的传输尝试。 DMA_INT1正确触发、显然太早。 我怀疑触发器有问题、有些任务只是重叠、但我现在看不出原因。
是否有线索?
您好 Chris、
让我检查一下我是否掌握了散聚触发器背后的概念:
任务列表长度有何限制?
查看我发布的跟踪、可以清楚地看到软件触发器实际上会触发某种操作(SCLK 运行很长时间并且输入了 DMA ISR)。 我之所以选择软件触发器、是因为我无法通过手动驱动中断标志来看到任何效果、这是启动自动模式存储器到存储器 DMA 传输的典型方法、因为任务加载就是这样。 我重新组织了任务列表、并根据上面的四个点更正了代码、但我仍然无法检索数据、数据传输似乎甚至没有开始。
让我们来回顾一下我要做的事情、我一定犯了一些愚蠢的错误、这些错误会一直隐藏在明暗之中。
#define ACC_DATA_buffer_LEN inertial_FIFO_DEPTH * accumor_active_Axs * inertial_data_size /* DMA 控制表*/ #if defined (__TI_Compiler_version__) #pragma DATA_ALIGN (dma_CONTRAL_ACT_REFERENCE Table、1024) #Elif defined (__Seq_systems_ma_ic_) #if (_accordinatured_dma_dma_dma_trador_dma_dma_tras_tras_tras_ination_ (#_dma_dma_trador_dma_dma_dma_dma_deltas_dma_dma_dma_dma_dma_dma_dma_dma_tagc)* (#define)* 24) /*与 DMA 相关的存储器位置和常数*/ const uint8_t dummyTx = 0x00; volatile uint8_t dummyRx; /*传感器输出地址*/ const uint8_t AccReadOutputAddr = LIS3DSH_OUT_X_L_ADDR |(1 << 7);
#define DMA_SPI_RX_CH DMA_CH5_EUSCIB1RX1 #define DMA_SPI_RX_INT_FLAG DMA_INT0_SRCFG_CH5 #define DMA_SPI_RX_CH_NUM DMA_CHANNEL_5 //启用 DMA DMA_enableModule (); //分配控制表 DMA_setControlBase (DmaControlTable); //分配通道 //[...] DMA_assignChannel (DMA_SPI_RX_CH);
#define INT_DMA_SPIINT_DMA_INT1 //清除 IFG 寄存器 DMA_Channel->INT0_CLRFLG = 0xFFFFFFFF; //将中断分配给特定的 DMA ISR DMA_enableInterrupt (INT_DMA_SPI、DMA_SPI_RX_CH_NUM); //在启用 CH_clearInterrupt (INT_DMA_INT_INT_ENABLETE)之前清除特定的 DMA 中断标志; // 启用中断(INT_AMA_INT_INT_INT_INT_INT_INT_INT_INT_INT_Interrupt (INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_CONTINT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_INT_ // main() IDLE 例程 while (1) {PCM_gotoLPM0InterruptSafe() ; }
#define N_OV_ACC_DMA_Tasks 2 * inertial_FIFO_DEPTH * accorize_active_Axs * inertial_data_size + 3 SpiAccReadoutSeq[0]= SendAccReadoutAddr; SpiAccoutSeq[1]= ClearRxIfg; for (i = 2;i < N_OV_ACC_DMA_tases - 1) SpiAccReadoutSEQ[i]= SendDummyByte; SpiAccReadoutSEQ[i+1]=检索字节从 Acc; SpiAccReadoutSEQ[i+1].dstEndAddr =&AccDataBuffer[(I-2)/2]; } SpiReadoutSEQ[N_of _ACC_DMA_tases - 1]= DummyMemMove;
// SPI 读取任务 DMA_ControlTable SendAccReadoutAddr = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&AccReadOutputAddr、 UDMA_DST_INC_NONE、&SPI_Module_Address->TXBUF、 UDMA_ARB_1、(UDMA_MODE_MEM_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable ClearRxIfg = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&SPI_Module_Address->RXBUF、 UDMA_DST_INC_NONE、&dummyRx、 UDMA_ARB_1、(UDMA_MODE_PER_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable SendDummyByte = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&dummyTx、 UDMA_DST_INC_NONE、&SPI_Module_Address->TXBUF、 UDMA_ARB_1、(UDMA_MODE_MEM_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable 检索字节 FromAcc = DMA_TaskStructEntry (1、UDMA_SIZE_8、 UDMA_SRC_INC_NONE、&SPI_Module_Address->RXBUF、 UDMA_DST_INC_NONE、&AccDataBuffer[0]、 UDMA_ARB_1、(UDMA_MODE_PER_SP散 射_收集+ UDMA_MODE_ALT_SELECT); DMA_ControlTable DummyMemMove = DMA_TaskStructEntry (1、UDMA_SIZE、 UDMA_SRC_INC_NONE、&dummyTx、 UDMA_DST_INC_NONE、&dummyRx、 UDMA_ARB_1、UDMA_MODE_BASIC);
#define SPI_RECEIVE_INTERRUPT_FLAG EUSCI_B_IFG_RXIFG void FetchInertialData (SpiDeviceHandle *句柄) { //超时计数器 volatile uint16_t Timeout; //在开始数据传输之前,等待一些时间 超时= handle->CsInterval_T; while (--Timeout); //预载建立时间 超时= handle->setup_T; //降低 CS GPIO_setOutputLowOnPin (handle->CsPort、handle->CsPin); //等待建立时间 while (--Timeout); //在散聚模式下执行数据提取 if (handle =&AccSpiHandle) DMA_setChannelScatterGather (DMA_SPI_RX_CH、N_of _ACC_DMA_tasks、SpiAccReadoutSeq、0); DMA_enableChannel (DMA_SPI_RX_CH_NUM); handle->SpiModuleAddress->IFG |= SPI_Receive_interrupt_FLAG; //dma_requestSoftwareTransfer (dma_spi_RX_ch_NUM); }
我想您已经准确地描述了散聚触发。 我认为、查看 TRM 中的图表也很有帮助。
任务数的限制为256。 这意味着主设备实际上被设置为1024、执行4次传输(从任务列表到备用数据结构) 256次。
在表/通道分配中、您选择了 DMA_CH5_EUSCIB1RX1。 这是一个无效的 SPI 通道。 RX1/TX1、RX2/TX2和 RX3/TX3只适用于 I2C 从地址 UCBxI2COA1、UCBxI2COA2和 UCBxI2COA3。 仅适用于 UART 和 SPI、RX0/TX0适用。
希望这有所帮助、
Chris
非常感谢!
我不会在一百万年后发现这个问题、手册中记录了 SPI/UART 和 I2C DMA 触发器之间的区别在哪里?
尊敬的 Chris:
我知道我可以直接在试验电路板上进行测试、但您可以通过最快、最可靠的方式为我提供这些信息:
对于 SPI 模式中使用的 UCAx 外设、DMA 通道分配是否有任何限制?
在这种情况下、如果没有 I2C 选项、则 UART 和 SPI 的 DMA 触发器是相同的、对吧?
在我的新系统设计中、我需要更多的串行链路、因此我不能像我以前一直在做的那样仅依赖 UCB SPI 外设。
非常感谢和问候