打印
[技术问答]

HC32F4A0 USART+DMA遇到的一个诡异问题

[复制链接]
400|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
eyesmall|  楼主 | 2025-3-30 13:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
发送长度为N的数据,概率性出现倒数第二个字节发两遍,最终导致虽然串口发出来的数据是N个,但是DMA剩余长度为1,最后一个字节发不出来,导致DMA发送完成状态始终无法置位,不知道有没有人遇到过。还有就是设置重载模式,始终没效果,长度为0时就停了。参考串口DMA例程,使用了链表,但是多通道使用时只有最后一个配置的通道才能正常工作,不适用链表不行吗?

使用特权

评论回复
沙发
eyesmall|  楼主 | 2025-3-30 19:49 | 只看该作者
官方例程串口DMA用的链表+reconfig,但是看例程reconfig都没有配置,链表的话多串口时之后最后配置的可以用

使用特权

评论回复
板凳
eyesmall|  楼主 | 2025-3-30 21:25 | 只看该作者
    DMA_StructInit(&stcDmaInit);
    stcDmaInit.u32IntEn = DMA_INT_DISABLE;
    stcDmaInit.u32BlockSize = 1UL;
    stcDmaInit.u32TransCount = 512;
    stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
    stcDmaInit.u32DestAddr = (uint32_t)DMARecBuf_USART4;
    stcDmaInit.u32SrcAddr = (uint32_t)(&CM_USART4->RDR);
    stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_FIX;
    stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_INC;
    DMA_Init(USART4_RX_DMA_UNIT, USART4_RX_DMA_CH, &stcDmaInit);

        pstcDmaRepeatInit.u32Mode=DMA_RPT_DEST;
        pstcDmaRepeatInit.u32DestCount=512;
        pstcDmaRepeatInit.u32SrcCount=0;
        DMA_RepeatInit(USART4_RX_DMA_UNIT, USART4_RX_DMA_CH, &pstcDmaRepeatInit);               
                       
        AOS_SetTriggerEventSrc(USART4_RX_DMA_TRIG_SEL, USART4_RX_DMA_TRIG_EVT_SRC);
                       
        DMA_Cmd(USART4_RX_DMA_UNIT, ENABLE);
        DMA_ChCmd(USART4_RX_DMA_UNIT, USART4_RX_DMA_CH, ENABLE);       
对着手册研究了半天,实在是搞不清错在哪了

使用特权

评论回复
地板
苏山人家| | 2025-3-31 09:01 | 只看该作者
链表虽然能够重设srcAddr.dstAddr,len,ctrl等寄存器,但多串口使用时trig源是不同的,所以没有办法多串口使用链表。
最简单方式再单次dma发送完成后重新设置trig源及各个寄存器,那和链表没啥区别。但也能减少dma使用。
另外这个芯片uart tx使用dma需要先关闭tx然后再打开才能引起dmatx

使用特权

评论回复
5
eyesmall|  楼主 | 2025-3-31 09:11 | 只看该作者
苏山人家 发表于 2025-3-31 09:01
链表虽然能够重设srcAddr.dstAddr,len,ctrl等寄存器,但多串口使用时trig源是不同的,所以没有办法多串口使 ...

其实我最早也发现了这些问题,使用repeat或是链表都有问题,最后只能用手动重置方案,接收完512字节后,进中断重置,但后来测试发现会频繁丢数据,开始以为是外部数据输入的问题,但后来使用链表接收数据都是完整的,所以想再次尝试文档里repeat模式,但是搞来搞去都不行,挂仿真一堆寄存器数据都是对的,但是计数到0之后还是不能自动重载512

使用特权

评论回复
6
eyesmall|  楼主 | 2025-3-31 09:16 | 只看该作者
苏山人家 发表于 2025-3-31 09:01
链表虽然能够重设srcAddr.dstAddr,len,ctrl等寄存器,但多串口使用时trig源是不同的,所以没有办法多串口使 ...

前面一共说了两个问题,第一个是DMA发送留一个字节发送不完的问题,第二个是DMA接收完指定长度后CNT无法自动重置的问题

使用特权

评论回复
7
苏山人家| | 2025-3-31 10:44 | 只看该作者
1.最后1byte发送2次这个没遇见,怀疑是你dmatx trig源问题建议使用完成触发试一下。
2.自动重置也需要触发源,的确很难理解,后来直接偷懒软件重置了。如果想用可以用链表做个环形也算自动重置了

使用特权

评论回复
8
eyesmall|  楼主 | 2025-3-31 12:14 | 只看该作者
苏山人家 发表于 2025-3-31 10:44
1.最后1byte发送2次这个没遇见,怀疑是你dmatx trig源问题建议使用完成触发试一下。
2.自动重置也需要触发 ...

1、第一个问题DMA发送确实诡异,因为发送出来的数据长度也是对的,但是检测到收到的数据没有最后一个字节,反而倒数第二个发了两遍。也就导致发送完成标志无法置位,最早发现这个问题就是因为使用了发送完成标志进行判断,确保下次发送不会覆盖当前发送中的数据。
2、第二个问题DMA接收,我最早也是偷懒用的软件重置,但是高速率下重置会导致接收到的数据不完整,最近有看串口有超时判断功能,正准备用超时+软件重置,结果发现只有4个串口支持该功能,这样会导致多个串口数据处理算法不一致,比如4个用超时,一个用链表,还有3个有问题,还不便于维护。并不能完全解决这个问题。还是希望找到一种所有串口都能用的通用的常规的解决方法
3、说到重置,看资料里DMA1和DMA2公用一个触发源,这样感觉每次重置会重置所有的CHx,显然不行

使用特权

评论回复
9
xch| | 2025-3-31 12:44 | 只看该作者
就发一个字节试试啥情况

使用特权

评论回复
10
eyesmall|  楼主 | 2025-3-31 13:40 | 只看该作者
xch 发表于 2025-3-31 12:44
就发一个字节试试啥情况

高频快速才有概率出,单字节估计费劲

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

162

帖子

0

粉丝