DMA 循环模式(CYCLIC)的疑问

岑西哲 2017-09-21 03:16:32
1 如果硬件FIFO只有1KB,正常情况下单次映射就映射512B即可,如果用了循环模式,是否可以映射大于1KB的DMA缓存,通知DMA控制器“当收取2K的时候再来告诉我处理”,就是由DMA控制器在底层循环接收?
2 假定DMA缓存4K,硬件FIFO是256Bytes,循环映射DMA中断控制在多少比较合理 ?
3 DMA循环模式,我看到资料上说是不间断的,如果4K大的缓存映射到了1K,DMA发起中断,上层接收到以后读取DMA缓存中的数据,此时DMA控制器还是在底层映射吗?还是等待本次中断结束后再接着映射?
4 DMA循环模式,我看到资料上说是不间断的,如果4K大的缓存映射到了1K,DMA发起中断,上层接收到以后读取DMA缓存中的数据后,DMA下次映射的结果是DMA BUFFER的1K地址开始还是从头开始?
...全文
2858 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
岑西哲 2017-09-25
  • 打赏
  • 举报
回复
谢谢你的建议~ 我测试一下看看吧~
岑西哲 2017-09-22
  • 打赏
  • 举报
回复
现在的问题是由于硬件FIFO太小了,只有256个字节,而我每次如果只能映射128个的话,速度太慢了; 目前采用上层轮询的方式,尽量多次读取,每次读取都是映射128个字节; DMA Cyclic的方式如果能只能DMA控制器底层自己去轮询映射的话,有可能会快一些? 也不知道DMA支不支持这样的需求,还望解答
Hello Worm 2017-09-22
  • 打赏
  • 举报
回复
Sorry,系统每天发生约25次这样的中断 ——> 笔误了,是每秒发生25次
Hello Worm 2017-09-22
  • 打赏
  • 举报
回复
这个影响并不是很大啊。我们可以这样算一下,多数情况,串口波特率115200bps,那么512字节相当于512*10/115200 = 44ms,也就是说系统每天发生约25次这样的中断,这个已经非常非常慢了。你可以每隔1秒用cat /proc/interrrupts看一下你的Linux中断数量,每秒超过1000次的都很多,25次几乎等于没有
岑西哲 2017-09-22
  • 打赏
  • 举报
回复
我看了串口的一些驱动,也是用的那种模式,难道说硬件FIFO如果是1K的话,那么无论何种映射方式,都必须小于1K的映射,这样对上层CPU调度影响也比较大吧
Hello Worm 2017-09-22
  • 打赏
  • 举报
回复
你可能还得再理解一下我写的这个过程。你的一些用词例如“终端”,“循环”都还比较模糊,单纯回答你说buffer size可以大于硬件FIFO size并不会帮助你多少。DMA的源端和目标端是可以分别独立设置是循环或者停止的,而引入DMA就好比饮料灌装线从一个喷口改为多个喷口,原来每次灌1瓶,现在每次可以灌10瓶,而Buffer RAM就好比底下的传送带上的空瓶,整个传送带要多长,你可以自己根据后道程序设置,并不一定和喷口数量一样。
Hello Worm 2017-09-22
  • 打赏
  • 举报
回复
单纯DMA Cyclic肯定无法解决你的问题,如果底层的代码你看不到或者改不了,估计你比较难以解决此问题。你可以从每秒的中断数开始查问题,按你18K的情况每秒中断仅有130次那个样子,确实不算特别多的,然后看一下你的中断处理是否足够快?可以先不加任何处理过程单纯每次进中断就count++然后返回,来看一下你的硬件到底能达到多块的速度,这个速度也差不多是你的硬件极限了,如果此时都达不到你说的要求,那就没辙了。
岑西哲 2017-09-22
  • 打赏
  • 举报
回复
十分感谢了你的回答,让我获益不少; 现在的难题就是硬件FIFO太小,我通过每次DMA映射128个字节的方法反复映射,就跟你之前说的一样,N个中断,但是每秒的速度还是上不来,18KB就是极限值了,但是根据另外一头设备的反馈,那个设备每秒可以发出35Mbit的数据,所以现在是接收的速度太慢了;也就是引出了是不是改用DMA cyclic(dmaengine_prep_dma_cyclic替换dmaengine_prep_slave_sg)的模式就可以加快效率的问题。 目前我只能修改完进行测试进行验证一下,目前通过以前的方案,速度根本无法提升…… 你有没有啥好的建议
岑西哲 2017-09-22
  • 打赏
  • 举报
回复
那我用循环的模式下,设定终端的Size是否可以大于时间硬件FIFO呢?
Hello Worm 2017-09-22
  • 打赏
  • 举报
回复
我理解你现在做的是通过DMA从FIFO搬数据到RAM。那么,当你设置好DMA后,它会自动去搬数据,每次搬完你指定大小的数据时,一般会有中断产生,你可以在中断中去处理(常见如通知读写函数,或者重新设置DMA的方式,例如你把接下来的数据拷贝放到另外一个RAM目标地址),所有这些设置都是非休眠的,几乎都是瞬间完成的)因此只要有数据,它就在不断的处理执行(甚至累计所有数据)。至于你上层何时读取和处理,那就是上层的问题了,上层来不及读取,当然会溢出。 综上,对于DMA传送,你需要设置的包括: 源地址,也就是你说的硬件FIFO地址,大小,是否循环 目标地址,同样也有类似的情况,但可以不用循环,而是不断累进(中断中改动目标地址),这样,硬件FIFO只有256字节,但我的RAM缓存可以设置很大如25600,这样例如通过100次中断我就可以得到这么多数据了。
Hello Worm 2017-09-21
  • 打赏
  • 举报
回复
一般是每次DMA传送完毕都会进中断,然后中断中可以去判断是否需要处理还是继续等待下一次DMA,甚至在中断中对DMA的原地址和目标地址进行改动。没有说让底层连续多次传送后再统一处理的,一般底层也不太支持这种操作。而所谓的循环模式应该是指数据传送到目标地址(也可能源地址)的最后区域时会复位当前目标地址,保证新数据能继续从目标地址的起始位置开始保存

1,317

社区成员

发帖
与我相关
我的任务
社区描述
主要是开发驱动技术
社区管理员
  • 驱动程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧