乘简 发表于 2024-6-14 10:31:32

关于串口DMA硬件改进建议。。。

本帖最后由 乘简 于 2024-6-24 09:26 编辑

首先,目前版本的硬件DMA用于做串口发送数据,我觉得没有任何问题,用起来很方便,可以满足我的任何需求。。。

但是用DMA做串口接收时,问题来了,如果要给这个硬件DMA打分的话,我只能打85分,因为在我看来功能是不全面的。。。理由如下:
1、当接收完1缓存数据(帧)后,需要手动重新开启接收,那么在这个时间段内,比如115200的波特率,那么接收1个字节需要1000000/115200*10=87us时间,那么在这个时间内来不及手动开启时又有串口数据发进来,这个数据就会丢失
    当接收完1帧数据,还没有开启下次接收的时候,完全可能被其它中断,或者其它占用时间多的后台程序消耗掉>=87us的时间,,从而导致数据丢失

2、如果接收完1帧数据后,立马开启下轮数据的接收,那么这时又正好接收到了串口数据,此时取出来的数据就会被新数据覆盖掉,导致收到的这帧数据不对。。

当然,我完全可以自己写1个非DMA的串口接收驱动,在中断中存进我自己的FIFO缓存中,然后再后台程序中慢慢处理,但那样还要DMA做什么?DMA不就是为了减少串口的中断次数而诞生的吗?

改进方案如下:
1、DMA_UR1R_CFG:再开1个标识位,比如B6:为0表示保持现有方案,为1表示以FIFO方式接收数据,就是循环接收数据,比如缓存区大小为255,那么接收到255后,再接到数据就会自动从0开始

2、需要增加1个影子寄存器,比如DMA_UR1R_RCV,与DMA_UR1R_DONE类似,用于记录用户取出的数据地址,也就是取数据指针

3、DMA_UR1R_DONE,这个寄存器不用清零,用于保存接收数据长度,也就是接收指针

4、增加1个8位的取出寄存器,比如DMA_UR1R_DAT,用户每次读取这个寄存器,表示取出1个字节,则硬件自动把DMA_UR1R_RCV+1,加满后,自动从0开始
    或者
    增加1个标志位,比如DMA_UR1R_STA:B4,从接收指针的位置取出数据后,标志位置1,则取出指针硬件自增1,然后该标志位自动置0

5、增加1个标识位,比如DMA_UR1R_STA:B3:1表示如果接收指针+1后==取出指针,表示缓存区满,无法再写入了,所以此位置1

6、增加1个标识位,比如DMA_UR1R_CR:B1,当B1有数据时,也就是说DMA_UR1R_DONE != DMA_UR1R_RCV时,此标志位为1,相等时为0

这样,这个DMA接收数据的时候,完全可以不开中断,在main(){while(1){}}中,这样写,while(DMA_UR1R_CR & 0x02);表示有数据,然后取出数据u8 c=DMA_UR1R_DAT,或u8 c=dma_ur1r_buffer;DMA_UR1R_STA|=0x08,因为取出数据,硬件会自增接收指针,进行数据处理即可,此时这个DMA才算是完整的,接收数据永远不需要停止,可以一直接收下去,用户只要在DMA缓存满之前把前面的数据取出来即可。

当然这个DMA也是可以开启中断的,比如可以设时间接收多少字节产生中断,定时中断,超时中断等附加功能。。。


神农鼎 发表于 2024-6-14 14:14:20

暂时软件开2个缓冲区来接收,方法参考下面





视频讲解:使用SPI_DMA读外部Flash+TFT_DMA双缓冲对TFT刷屏,不占CPU时间 - DMA: 支持4组串口,3组SPI,I2C,TFT-i8080/M6800,ADC 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)


下面是荣誉版主的另外一种风格

4组串口UART使用DMA收发 @STC32G,易用,高效,稳定 !精品实战代码 - DMA: 支持4组串口,3组SPI,I2C,TFT-i8080/M6800,ADC 国芯技术交流网站 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)


乘简 发表于 2024-6-14 15:31:05

神农鼎 发表于 2024-6-14 14:14
暂时软件开2个缓冲区来接收,方法参考下面




对于刷屏,启用双缓存技术,是没有任何问题的,对于串口接收数据:
1、哪怕启用双缓存,也有可能会丢数据,在1帧数据接收完后,这时DMA串口接收是自动停止了的,这时正好其它高优先级的中断来了,且占用了>=87us时间,在这期间串口接收的数据就会丢失。。。

2、串口接收数据,往往并不是1帧数据接收完才处理的,接收的数据有长有短的,比如处理modbus协议等,所以不能与LCM的DMA相提并论,所以哪怕启用双缓存,处理数据也会不及时。。。

当然,我只是提建议,而且这个方法也有可能并不是最优解,至于你们改不改,怎么改还是要看你们自己的。。。

不过不改的话,在我心目中这个串口DMA在接收数据这块,只能打85分,按我的建议改的话,至少90分吧,呵呵。。。


神农鼎 发表于 2024-6-14 15:40:05

要改就是 【DMA-特定外设】,一次设置双【DMA-特定外设】缓冲,自动切换,兹事体大

乘简 发表于 2024-6-14 15:49:54

神农鼎 发表于 2024-6-14 15:40
要改就是 DMA-外设,一次设置双缓冲,自动切换,兹事体大

看到 “兹事体大” 这4个字我就懂了。。。呵呵。。。

确实改硬件,成本应该不低,时间应该不会短,所带来的收益也就一般,因为不使用DMA,直接中断中接收,也能达到同样的效果。。。

乘简 发表于 2024-6-24 08:50:56

其实虽然目前的串口DMA发送模块,可以满足我任何需求,但如果发送模块也按照我提出的建议改进的话,就可以真正做到无感发送。。。

所谓的无感发送,就是说任何时候,直接发送数据就可以了,不用管上1个包(小于缓存区)数据有没有真正发送完成,下一包数据就可以直接发送(写入缓存中),因为有双指针,FIFO方式的缓存区,后台慢慢发,只要在写入缓存的时候检测到缓存满,则产生错误即可,其它的根本就不用考虑,如果真实现了这些功能,想想也是蛮爽的。。。
页: [1]
查看完整版本: 关于串口DMA硬件改进建议。。。