USART DMA通过TIME0超时接收数据帧这个功能虽然在数据手册上提过,但是官方demo不给,网上的代码要么不全要么驱动版本不一致,于是有这个坑
1. 基本框图
涉及到的模块:USART,AOS, DMA
其中,AOS模块不需要CPU的参与即可触发,触发源记为event,触发接口记为socket,socket会关联相关动作。
大坑注意:
1)图中的实线是数据手册明确说明的event和socket,需要配置,相关代码:
/* Enable peripheral circuit trigger function. */
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS,Enable);
/* Set DMA trigger source. */
DMA_SetTriggerSrc(DMA_UNIT, DMA_CH, DMA_TRG_SEL);
2)图中的虚线是隐藏的关联,不需要明确配置(也不能),数据手册中关于TIME0的这块并没有明确说明,这是实际调试中总结出来的,原理不一定对,但是可用,啊,
根据测试,配置USART的RTOE即可开启这两个虚线,并且他们的对应关系是固定的
USART1:Timer0 Unit1 A 通道
USART2:Timer0 Unit1 B 通道
USART3:Timer0 Unit2 A 通道
USART4:Timer0 Unit2 B 通道
3)TIME0有两个实例01和02,每个实例有两个通道,即1A, 1B, 2A, 2B,这4个通道共用一个socket ,通过HTSSR配置(这个寄存器在AOS里),在USART超时例子中用不到!!!并且不知道这个和图中的虚线功能的关系,有闲心可以测试
2. 具体实现和调试
1) 初始化TIME0,按模板开启就行
2) 初始化DMA,配置socket,参考DEMO中DMA的例子
3)初始化USART,复制粘贴没毛病
在MDK中调试的适合直接写寄存器来跑流程
如图,当用USART1时,
1)使能RE, RTOE,对应的TIME01A即关联到了(即图中的虚线使能),HSTAB和HCLEB使能,
2)配置的ctrl socket触发模式,此时除能CSTA,TIME01A未触发
3)通过写CRTOF清除RTOF标志位,准备就绪
4)通过上位机发送串口数据,此时会触发CNTAR运行,CSTA会变为1,当CNTAR运行到设定数值时,RTOF置位,此时手动清除CSTA和RTOF,即超时动作,在代码里需要开启RTOIE来启用中断从而执行这个动作(还有DMA复位等)。
5)原文档中有一句 “单元 1 的通道 A 的比较匹配中断(TMR0_U1_GCMA)仅在异步计数方式
(BCONR.SYNSA=1)时可用”,实际测试USART 超时中01A是可以用同步方式的,这句话可能仅指中断不可用,
3,其他
1)DMA源地址代码给出的是DR+2,
stcDmaInit.u32SrcAddr = ((uint32_t)(&USART_CH->DR)+2ul); /* Set source address. */
此处一大坑是,DR+2的值与DR的类型有关,如果DR是指针,实际数值是DR+2*4,加一个强制转换更好
改进:stcDmaInit.u32SrcAddr = ((uint32_t)((uint32_t)(&huart->DR)+2ul));
2)DMA重启问题
DMA重启后,需要经过关DMA→重新设置目的地址→开DMA流程
其中,为了不出现DMA内存溢出问题,需要对DMA接收数据长度进行限制,此时对于HC32460测试表明,其传输次数寄存器需要重新配置和载入,否则会出现异常
2)接收溢出等错误处理
HC460中UART一旦接收错误,如果不清除错误标志位,则后续接收均失败,因此错误处理是必须的。清除错误标志位时,还需要读一下接收数据寄存器,清空寄存器里面的数据以避免下一次接收失败。话说官方demo里没有这个操作,,不得不怀疑是不是压根就没测试接收溢出问题,,,