0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

数据处理时为什么要从DMA缓存空间中获取?

GReq_mcu168 来源:玩转单片机 作者:玩转单片机 2020-06-24 11:28 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

笔记中最后得出一个串口接收的总结“空闲中断 + DMA + 队列 + 内存管理 + 定时控制”。因为空闲中断的误触发,导致我们不得不使用定时器来达到接收完整一帧的效果,这样一来,就会导致一些问题:1、数据吞吐率低,发送方需要延时一段时间后才能发送下一帧;2、响应不及时,因为有延时,必然导致接收方回复慢。3、空间利用率不高,如果一个短帧到来,会导致整帧缓存空间(这个空间大小一般是最大帧长)无法使用。

今天鱼鹰自己对自己进行一次升级,改用“空闲中断 + 循环DMA + 无锁队列”的方式进行最为高效的接收方式(无锁队列以后有时间再写,这次的重点不在这)。这种接收方式鱼鹰在接触了循环队列后就开始思考了,那个时候工作没多久,然后一位前辈使用的就是空闲中断 + DMA 的方式接收,也算是惊到鱼鹰了。后来鱼鹰在想,循环队列的优势显而易见,而DMA在设置为循环模式时,天然就是一个循环队列,我是否能将循环队列和DMA相结合,实现一个循环缓存空间呢?具体当时是如何思考的鱼鹰已不记得了,只知道当时利用KEIL模拟功能貌似是实现了想要的效果,但是在实际测试过程中应该是出现了问题,所以导致这个想法搁置了。这个实现代码鱼鹰会一并上传到公众号,让各位道友参考一二,自认为自己符合条件的自行获取就是了。直到最近看到头条一位读者的评论,鱼鹰的心思才又活泛起来了,通过评论交流,终于理解了其中是如何实现的,也想到了如何将其和无锁队列相结合,也就有了这一次笔记的分享。

实习时初次接触空闲中断时,用的接收方式是 空闲中断 + 串口接收中断,这个算是 V1.0版。后来正式工作后接触到的是 “空闲中断 + DMA”这个是V2.0,后来鱼鹰在此基础上进行改进,加入了队列,加入了定时器,算V2.5好了。这次效率更高,而且空间利用率也高,中断处理简单到到极致,定为V3.0。可能很多人在之前的笔记中根本无法真正理解鱼鹰的本意,因为这份笔记太长,如果没有一定的经验根本无法体会,尽管有一份参考代码放在后台供各位道友进行参考,但是因为那份代码只解决了一个定时器控制问题,注释也不详尽,还是鱼鹰的初次思考,所以相信很多人看到这份代码都是云里雾里的,还是无法实现其中的细节。那么今天鱼鹰就来简单描述其中的关键细节实现:

串口接收实现V1.01、初始化时开启串口的接收中断和空闲中断2、串口中断处理时,每接收一个字节存入缓存空间(注意控制越界问题)3、一旦空闲中断来了,停止接收,设置标志位,通知上层已完成一帧数据的接收,上层负责数据的处理工作。当然为了防止误触发,也可以使用定时器进行进一步控制,也可以在此基础上加入缓存队列。

串口接收实现V2.01、初始化时开启串口的空闲中断,并且初始化为正常DMA。2、触发空闲中断时,通知上层接收完成并且将其拷贝到一个缓存中供上层使用,然后重新启动DMA进行下一次的接收,因为帧与帧之间有空闲时间,只要保证这段时间大于中断处理时间,那么接收一般不会出现问题。这里有一个关键点就是,如何获取这次接收的数据长度:

Rev_Size = DMA_Set_Size - CNDTR

Rev_Size 是实际接收的长度,DMA_Set_Size是初始化DMA时设置的缓存大小,这个大小一般大于等于一帧数据的最大长度,并且最好是它的2倍以上,这样极端情况下不容易被下一帧数据所覆盖(怕中断处理不及时导致覆盖了之前已接收的数据)。而 CNDTR就是 DMA 寄存器中记录目前剩余需要接收的大小,当它为 0 时表示接收完成,DMA自动关闭。好好理解一下,实现起来不难。 串口接收实现V3.0

1、初始化时开启串口的空闲中断,并且初始化为循环DMA。2、触发空闲中断时,更新索引,这个索引表示当前写入索引值,用于上层判断缓存空间已写入的数据(鱼鹰前面写了关于循环FIFO的笔记,可自行查看,如果不懂这个,下面的你理解不了,数据结构系列文章之队列 FIFO)。3、如果加入无锁FIFO,更新in索引值。数据处理时只要从DMA缓存空间中获取即可。

现在我们来分析一下更细节的东西1、缓存大小?2、如何获取数据?3、好处?4、隐患,缺点?缓存大小可以根据需要设置,这个需要看你数据处理的延迟时间。比如说发送者10 ms发送一帧数据,你的数据处理正常时候10 ms处理一次,但有时候CPU 负担重,你的数据处理优先级较低,那么可能20 ms才会处理,那么缓存空间必然需要大于两帧数据才行,这个空间需要测试后才能确定,而且需要留有一定的富余才行。那么如何获取数据?通过学习循环FIFO的知识我们知道,循环FIFO由两个变量in和out进行数据管理,如果我们的in可以根据DMA剩余量进行更新,那么就可以根据in和out之间的关系知道目前缓存空间里面到底有多少未处理的数据了。那么如何更新呢?鱼鹰就不藏私了,直接在此说明,不过加入无锁FIFO的就自己从参考代码中获取了,这个其实都差不多。

In = DMA_Set_Size - CNDTR(CNDTR永远不会是0)

数据处理时为什么要从DMA缓存空间中获取?

是不是很惊讶,是不是不可思议,你和终极接收方式只差一层窗户纸?当年鱼鹰为了更新这个值,用了老长一段代码实现:

数据处理时为什么要从DMA缓存空间中获取?

而现在再看这个代码,已经忘记当初是咋想的了,但是这个式子确实可以更新in的值,即上面的offset,只是当初想的有点复杂了。简单来说,就是先通过CNTR和之前的 offset 获取目前的接收的长度(这个应该是受V2.0版本影响),然后根据长度更新目前的offset。但是通过读者的评论,发现根本不需要这样麻烦。只要有了in的值,然后又有out,那么获取队列中的数据也就不难了。

其实如果说采用循环DMA只是减少了中断的代码,让中断处理时间更短,那么鱼鹰还是会选择以前的V2.0的接收方式,毕竟这种方式实现了帧隔离,但是读者的一个评论提醒了我,那就是这种方式不需要重新启动DMA。这意味着什么?意味着高效,意味着DMA持续工作,意味着不存在因为DMA的短暂关闭而导致数据丢失。这就是鱼鹰接下来要说的优点:1、中断代码及其简单,像上面那种只是更新in的话只需要三条代码即可完成。2、不需要重启DMA3、因为不需要重启DMA,也就减少了这段时间串口数据的丢失4、数据吞吐量可以达到最大化,每帧数据只需间隔一个空闲时间即可继续发送。最大程度的利用了串口的接收能力,而且不用担心数据丢失,这对于快速数据的接收是非常有好处的。5、就算你不想数据帧之间出现空闲间隔时间,你也可以通过一个定时器定时更新in的值。6、即使在串口中断更新in的值时DMA又在接收数据,也不会出现问题,这个原理和无锁FIFO一样。7、不需要定时控制,防止空闲中断的误触发。8、即使因为中断体系短暂关闭,而导致空闲中断不能及时处理,也不会影响DMA在后台自动接收数据。 优点很多,缺点也有,下面就来唠叨唠叨缺点:1、因为所有数据都在一个缓存中,无法实现帧与帧之间的硬性隔离,所以必须通过数据本身确定一帧数据,对于数据的处理难道较高,这一点目前鱼鹰采用状态机处理,但是总感觉效率较低,后期看看能不能升个级啥的。2、因为无法实现帧隔离,所以一旦因为硬件干扰啥的导致多或少接收一个字节数据,又或者数据接收错误,那么再从缓存中得到一帧完整数据就比较耗时了,所以状态机一定要有自恢复机制,能够继续处理后续的数据帧。3、一旦数据处理比较慢,而剩余缓存空间不够大,那么未处理的数据将自动被DMA接收的新数据所覆盖,所以缓存大小一定要有富余。4、一次发送的数据大于或等于缓存空间,那么in的值就有问题,所以发送者发送的一帧数据一定不能大于或等于缓存空间,切记这一点。 上面的第3点可以通过处理来提醒用户缓存不够(有些无法情况无法发觉),这个鱼鹰在代码中做了处理,各位可参考。而第四点一般不会出现,这是在设计DMA缓存时就会考虑的。
责任编辑:pj

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 缓存
    +关注

    关注

    1

    文章

    248

    浏览量

    27822
  • dma
    dma
    +关注

    关注

    3

    文章

    582

    浏览量

    106282
  • 数据处理
    +关注

    关注

    0

    文章

    655

    浏览量

    30082
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    云端数据处理专利技术:重塑数字时代的算力基石

    一、云端数据处理:数字经济的核心引擎在数字化浪潮席卷全球的今天,每天产生的数据量呈指数级增长。从智能终端的实时传感数据,到企业的业务运营数据,再到科研领域的海量实验
    的头像 发表于 04-07 11:20 1539次阅读
    云端<b class='flag-5'>数据处理</b>专利技术:重塑数字时代的算力基石

    C语言的缓冲区(缓存)详解

    缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的
    发表于 01-14 07:30

    海光3350便携机主板:大数据处理利器

    随着企业数字化转型加速,大数据处理需求从固定机房向移动场景延伸。无论是金融机构外出调研、科研团队野外数据采集,还是个人创作者处理海量素材,便携设备的性能成为关键。海光便携机主板凭借独特的技术优势,正成为大
    的头像 发表于 12-26 11:15 718次阅读

    MCU数据采集模块的数据处理和分析能力如何?

    MCU数据采集模块的数据处理和分析能力如何?在现代化结构物安全监测领域,MCU数据采集模块扮演着至关重要的角色。它不仅仅是数据的“搬运工”,更是具备初步
    的头像 发表于 12-02 16:03 561次阅读
    MCU<b class='flag-5'>数据</b>采集模块的<b class='flag-5'>数据处理</b>和分析能力如何?

    内存与数据处理优化艺术

    事务数量,更好地利用CPU缓存。测试表明,在处理大量数据(如20MB)时,这种优化可能带来数倍的性能提升。
    发表于 11-14 07:46

    AG32 内置的CPLD 的DMA功能如何实现?

    dma 读取》中的样例代码包含两部分: 1、MCU端实现 •配置DMA读取功能 •为便于测试,MCU会向CPLD的另一个地址写入测试数据 2、CPLD端实现 •对MCU写入的数据
    发表于 10-31 15:42

    串口DMA发送有缓存吗?

    串口DMA发送有缓存吗, 我是从ringbuffer取出来,放到申请的缓存里,启动串口DMA发送,然后就释放了。暂时没发现什么问题。 用的drv_usart.c是这个版本
    发表于 10-10 06:14

    串口DMA接收数据包丢失怎么解决?

    RTT串口DMA接收数据,超过缓冲区后为什么会吞掉一个数据包呢,不能每次处理完后清除缓冲区数据吗,感觉接收的
    发表于 09-29 07:50

    M483SIDAE SD控制器,无法使用DMA读取从SDHC获取正确的数据,怎么解决?

    1、至于M483SIDAE SD控制器,我们无法使用DMA读取从SDHC获取正确的数据 对于SD接口,我们只使用SD0,所以我们连接SD0_DAT0~3和SD0_CMD,SD0_CLK到SD插槽,但
    发表于 08-28 06:21

    如何利用 AI 算法优化碳化硅衬底 TTV 厚度测量数据处理

    摘要 本文聚焦碳化硅衬底 TTV 厚度测量数据处理环节,针对传统方法的局限性,探讨 AI 算法在数据降噪、误差校正、特征提取等方面的应用,为提升数据处理效率与测量准确性提供新的技术思路。 引言 在
    的头像 发表于 08-25 14:06 767次阅读
    如何利用 AI 算法优化碳化硅衬底 TTV 厚度测量<b class='flag-5'>数据处理</b>

    AG32:dma在cpld中的使用

    \\\\7.cpld中配合实现mcu的dma读取 在这个样例中,展示了两部分代码: mcu中,配置dma读取;为了测试,mcu会在另一地址给cpld写数据; cpld中,会对mcu写进来的数据
    发表于 08-12 09:22

    电商API的实时数据处理

      在现代电商平台中,API(应用程序接口)扮演着核心角色,它连接用户、商家和后台系统,实现数据的高效交换。随着电商业务规模的扩大,实时数据处理变得至关重要——它要求系统在毫秒级内响应API请求
    的头像 发表于 07-23 15:39 701次阅读
    电商API的实时<b class='flag-5'>数据处理</b>

    抖音电商 API 接口和传统电商接口,直播数据处理谁更快?

    ​ 在直播电商蓬勃发展的今天,数据处理速度成为平台竞争力的关键。抖音电商作为新兴力量,其API接口针对直播场景进行了优化,而传统电商接口则基于通用模型设计。本文将逐步分析两者的数据处理速度差异,帮助
    的头像 发表于 07-09 15:39 849次阅读
    抖音电商 API 接口和传统电商接口,直播<b class='flag-5'>数据处理</b>谁更快?

    请问如何增大usb3.0从设备fifo接口固件中的写dma缓存大小?

    现有的固件是默认的,分别配置了2个1KB的缓存给读和写的dma。我想要多分配一点缓存给写dma,比如分配4kB给写dma。请教一下该如何修改
    发表于 05-14 08:13

    有没有上位机获取DMA状态的API?

    我想在发送数据之前,查看DMA的状态。或者在接受数据之前获取DMA的状态。
    发表于 05-13 08:28