NXP EDMA学习(3):Scatter/Gather模式之串口循环缓冲区的实现

在实际应用中,循环缓冲区的使用十分广泛,如果DMA每次接收一定字节然后再在中断中写入自己定义的循环缓冲区,这样又失去了使用DMA的意义。所以硬件上的循环缓冲区的实现非常重要。大部分芯片支持DMA循环模式,而NXP的eDMA则可以通过Scatter/Gather模式来实现硬件循环缓冲区。

文章目录

  • 1 TCD Pool初始化
  • 2 eDMA回调函数
  • 3 获取缓冲区接收长度

1 TCD Pool初始化

硬件循环缓冲区的代码与上一节大体相同,只不过增加了一个tcdPool,在前面的初始化完成后,无需调用UART_ReceiveEDMA,而是执行下面的函数来启动硬件循环缓冲区:

__attribute__((aligned(ALIGN))) uint8_t g_ringBuffer[256];
__attribute__((section("DataQuickAccess"))) __attribute__((aligned(sizeof(edma_tcd_t)))) edma_tcd_t tcdMemoryPoolPtr[1];
/* Start ring buffer configuration. */
static void EXAMPLE_StartRingBufferEDMA(void)
{edma_transfer_config_t xferConfig;/* 添加tcdPool到edma结构体中 */EDMA_InstallTCDMemory(&g_uartRxEdmaHandle, tcdMemoryPoolPtr, 1U);/* 参考上一节博客的分析 */EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(UART0), sizeof(uint8_t), g_ringBuffer,sizeof(uint8_t), sizeof(uint8_t), 256, kEDMA_PeripheralToMemory);/* 开始传输:设置可以被加载到TCD内存中的TCD的数量 */g_uartRxEdmaHandle.tcdUsed = 1U;/* 表示下一个加载到tcd内存池的索引 */g_uartRxEdmaHandle.tail    = 0U;/* 初始化自己声明的tcd内存池中的寄存器为0,但该函数会使能CSR.DREQ=1,表示主循环结束后关闭DMA请求 */EDMA_TcdReset(&g_uartRxEdmaHandle.tcdPool[0U]);/* 将在EDMA_PrepareTransfer中设置到的参数应用到tcdPool中* 由于使能了Scatter/Gather模式,理论上不能在每次主循环结束后关闭DMA请求,故在此函数中清除DREQ位*/EDMA_TcdSetTransferConfig(&g_uartRxEdmaHandle.tcdPool[0U], &xferConfig, tcdMemoryPoolPtr);/* 打开主循环完成中断,为了计算收到数据的字节数 */g_uartRxEdmaHandle.tcdPool[0U].CSR |= DMA_CSR_INTMAJOR_MASK;/* 将tcdPool中的TCD内容加载到DMA通道对应的TCD内存中 */EDMA_InstallTCD(DMA0, UART_RX_DMA_CHANNEL, &g_uartRxEdmaHandle.tcdPool[0U]);/* 开始eDMA传输 */EDMA_StartTransfer(&am


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部