单片机/MCU论坛
直播中

萧蔼晨

7年用户 925经验值
私信 关注
[问答]

在psco6上使用DMA将阵列传输到SPI外围设备,为什么无法启动第二个描述符?

你好。我正在尝试在 psco6 (CY8CKIT-062-BT-WIFI) 上使用 DMA 将阵列传输到 SPI 外围设备。
数组长度是一个很大的任意数字,不适合 2D 传输。比方说 643 字节。
我的想法是将其分成两个描述符并将它们链接起来。即第一个描述符传输 10x64 字节,第二个描述符传输 3 字节。(我不确定是否有其他方法。)
我遇到的问题是它无法启动第二个描述符。这是我正在尝试使用的代码:
#define txDma_ENABLED 1U#define txDma_HW DW0#define txDma_CHANNEL 2U#define txDma_IRQ cpuss_interrupts_dw0_2_IRQn/* Interrupt priority for TXDMA */#define TXDMA_INTERRUPT_PRIORITY (7u)volatile bool tx_dma_done = false;cy_stc_dma_descriptor_t txDma_Descriptor_1 = {    .ctl = 0UL,    .src=0UL,    .dst = 0UL,    .xCtl = 0UL,    .yCtl = 0UL,    .nextPtr = 0UL,};cy_stc_dma_descriptor_t txDma_Descriptor_0 = {    .ctl = 0UL,    .src=0UL,    .dst = 0UL,    .xCtl = 0UL,    .yCtl = 0UL,    .nextPtr = 0UL,};const cy_stc_dma_descriptor_config_t txDma_Descriptor_0_config = {    .retrigger = CY_DMA_RETRIG_IM,    .interruptType = CY_DMA_DESCR_CHAIN,    .triggerOutType = CY_DMA_1ELEMENT,    .channelState = CY_DMA_CHANNEL_DISABLED,    .triggerInType = CY_DMA_1ELEMENT,    .dataSize = CY_DMA_BYTE,    .srcTransferSize = CY_DMA_TRANSFER_SIZE_DATA,    .dstTransferSize = CY_DMA_TRANSFER_SIZE_WORD,    .descriptorType = CY_DMA_2D_TRANSFER,    .srcAddress = NULL,    .dstAddress = NULL,    .srcXincrement = 1,    .dstXincrement = 0,    .xCount = 1,    .srcYincrement = 0,    .dstYincrement = 0,    .yCount = 1,    .nextDescriptor = 0UL,};const cy_stc_dma_channel_config_t txDma_channelConfig = {    .descriptor =  txDma_Descriptor_0,    .preemptable = false,    .priority = 3,    .enable = false,    .bufferable = false,};const uint8_t small_buffer[10]={0xA1,0xB2,0xC3};uint32_t configure_tx_dma(uint8_t* tx_buffer){     cy_en_dma_status_t dma_init_status;     const cy_stc_sysint_t intTxDma_cfg =     {         .intrsrc=txDma_IRQ,         .intrPriority = 7u     };     /* Initialize descriptor */     dma_init_status = Cy_DMA_Descriptor_Init( txDma_Descriptor_0,  txDma_Descriptor_0_config);     Cy_DMA_Descriptor_SetXloopSrcIncrement( txDma_Descriptor_0, 1);     Cy_DMA_Descriptor_SetYloopSrcIncrement( txDma_Descriptor_0, 64);     Cy_DMA_Descriptor_SetXloopDataCount( txDma_Descriptor_0, 64);     Cy_DMA_Descriptor_SetYloopDataCount( txDma_Descriptor_0, 10);     Cy_DMA_Descriptor_SetNextDescriptor( txDma_Descriptor_0,  txDma_Descriptor_1);     dma_init_status = Cy_DMA_Descriptor_Init( txDma_Descriptor_1,  txDma_Descriptor_0_config);     Cy_DMA_Descriptor_SetXloopSrcIncrement( txDma_Descriptor_1, 1);     Cy_DMA_Descriptor_SetYloopSrcIncrement( txDma_Descriptor_1, 3);     Cy_DMA_Descriptor_SetXloopDataCount( txDma_Descriptor_1, 3);     Cy_DMA_Descriptor_SetYloopDataCount( txDma_Descriptor_1, 1);     Cy_DMA_Descriptor_SetNextDescriptor( txDma_Descriptor_1, 0UL);     if (dma_init_status!=CY_DMA_SUCCESS)     {         return INIT_FAILURE;     }     dma_init_status = Cy_DMA_Channel_Init(txDma_HW, txDma_CHANNEL,  txDma_channelConfig);     if (dma_init_status!=CY_DMA_SUCCESS)     {         return INIT_FAILURE;     }     /* Set source and destination for descriptor 1 */     Cy_DMA_Descriptor_SetSrcAddress( txDma_Descriptor_0, tx_buffer);     Cy_DMA_Descriptor_SetDstAddress( txDma_Descriptor_0, (void *) SCB6->TX_FIFO_WR);     Cy_DMA_Descriptor_SetSrcAddress( txDma_Descriptor_1, small_buffer);     Cy_DMA_Descriptor_SetDstAddress( txDma_Descriptor_1, (void *) SCB6->TX_FIFO_WR);      /* Initialize and enable the interrupt from TxDma */     Cy_SysInt_Init( intTxDma_cfg,  tx_dma_complete);     NVIC_EnableIRQ((IRQn_Type)intTxDma_cfg.intrSrc);      /* Enable DMA interrupt source. */     Cy_DMA_Channel_SetInterruptMask(txDma_HW, txDma_CHANNEL, CY_DMA_INTR_MASK);     /* Enable DMA block to start descriptor execution process */     Cy_DMA_Enable(txDma_HW);     return INIT_SUCCESS;}void tx_dma_complete(void){     /* Check tx DMA status */     if ((CY_DMA_INTR_CAUSE_COMPLETION    != Cy_DMA_Channel_GetStatus(txDma_HW, txDma_CHANNEL))            (CY_DMA_INTR_CAUSE_CURR_PTR_NULL != Cy_DMA_Channel_GetStatus(txDma_HW, txDma_CHANNEL)))     {         /* DMA error occurred while TX operations */         //handle_error();     }     tx_dma_done = true;     /* Clear tx DMA interrupt */     Cy_DMA_Channel_ClearInterrupt(txDma_HW, txDma_CHANNEL);}void spi_dma_transfer(){    Cy_DMA_Channel_SetDescriptor(txDma_HW, txDma_CHANNEL, txDma_Descriptor_0);    Cy_DMA_Channel_Enable(txDma_HW, txDma_CHANNEL);}

回帖(1)

王玉兰

2024-1-18 17:01:54
您好!关于无法启动第二个描述符的问题,可能有几个原因导致:

1. 描述符链配置问题:请确保第一个描述符的链结束符(bit[15])设置为0,而第二个描述符的链结束符设置为1。

2. 描述符的有效性问题:请确保每个描述符的有效位(bit[31])都被设置为1,以确保DMA引擎可以正确处理它们。

3. DMA配置问题:请确保正确配置了DMA引擎相关的寄存器,包括描述符地址、描述符数目和DMA通道。

此外,您还可以尝试使用中断方式来处理每个描述符的传输完成事件,以便及时处理第二个描述符的传输。

对于您提到的不适合2D传输的问题,您可以尝试使用多个描述符来传输数据,如您所示的将数组分成两个描述符。另外,您还可以使用循环模式来重复传输同一个描述符,从而实现大数组的传输。

最后,如果您提供更多的代码和错误消息,我可以帮助您更好地理解问题并给出更具体的建议。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分