OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5013|回复: 6

Linux驱动中固定周期执行某些操作的实现方案讨论

[复制链接]

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
发表于 2020-5-24 17:30:36 | 显示全部楼层 |阅读模式
5金钱
最近项目中需要实现一个SPI设备驱动,需要在驱动中以固定1ms的周期通过SPI把数据发送到SPI设备上。
我用的平台是I.MX6D(双核)、内核版本3.0.35,系统的节拍设置为1000Hz,驱动的具体实现已经完成了,但是遇到一些问题。

1.为了实现周期1ms的机制,我最开始使用的是延迟的工作队列来实现,但是过程中通过示波器测量发现
虽然延迟的工作队列设定执行周期是1ms,但是并不是严格的1ms去执行任务,总是会偶发的出现信号周期大于1ms或者小于1ms的情况(误差可达上百微秒),导致我通过SPI传送数据到设备上不是均匀的。

2.延迟的工作队列内部也是通过注册内核定时器来实现,于是我修改驱动,将延迟的工作队列替换成内核定时器,在定时器中断函数中去翻IO口测量周期,也观察到信号周期大于或者小于1ms的情况(误差也可达上百微秒)。

结合以上1、2点,我觉得内核定时器并不可靠,内核定时器本身的误差是造成延迟工作队列定时1ms执行不准的原因之一(还有其他原因,下面会讲到)。

3.为了排除内核定时器本身的误差,我又实现了一个内核高精度定时器,同样是在定时器中断中翻转IO口,通过示波器测量发现,高精度定时器可以将误差控制在20微秒以内,而且更稳定和精准,满足我的误差要求。

因此我修改驱动,采用工作队列+内核高精度定时器的方式,在定时器中断函数中去schedule我的工作队列,在工作队列中调用spi数据同步函数到设备上(同步数据前同样要操作IO口电平翻转),此时测量IO口发现,周期又不准了。
因此我推断可能是使用工作队列机制带来的问题,因为工作队列机制本身是可以休眠的,而同样的spi数据同步函数本身也可以引起休眠。
到这里可能有小伙伴会问为啥一开始就是用工作队列而不是软中断,或者tasklet?
因为,我要同步数据到SPI设备,spi数据同步函数只能用在进程上下文,不能用在中断上下文中,而软中断和tasklet都是处于中断上下文,这也是我前面为什么不直接在定时器中断函数调用SPI数据同步函数的原因。
综合以上,工作队列和SPI函数也是造成周期不准的原因。
为了实现周期性的同步数据到SPI设备,我目前只想到了定时器、工作队列这样的机制,但就是会存在以上的问题,目前找不到合适的机制来代替上面的实现方案,还请大家给点建议同时帮忙分析。
以上的分析如果有不对的地方,请大家指出。谢谢!

最佳答案

查看完整内容[请看2#楼]

你的目的时要求周期无延时(且精度要求到50us一下), 在进程中处理时无解的,嵌入式Linux本身就非实时系统,只要涉及内核切换的动作,都不保证时间的精确性,是随机的,特别是你精度要求还很高的情况,不符合实际,想实现实时,只能在中断上下文里面做,你只能自己实现SPI通讯收发函数满足中断里处理(这里有个思路:类似uboot的做法,在定时器中断里面实现无系统的SPI通讯,在提交到SPI驱动缓存中,由上位机去访问, 而不使用官方的sp ...
没有脑袋
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

400

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1746
金钱
1746
注册时间
2015-6-11
在线时间
308 小时
发表于 2020-5-24 17:30:37 | 显示全部楼层
你的目的时要求周期无延时(且精度要求到50us一下), 在进程中处理时无解的,嵌入式Linux本身就非实时系统,只要涉及内核切换的动作,都不保证时间的精确性,是随机的,特别是你精度要求还很高的情况,不符合实际,想实现实时,只能在中断上下文里面做,你只能自己实现SPI通讯收发函数满足中断里处理(这里有个思路:类似uboot的做法,在定时器中断里面实现无系统的SPI通讯,在提交到SPI驱动缓存中,由上位机去访问, 而不使用官方的spi_sync或者spi_async -- 这种思路因为堵塞中断,会降低系统的性能),
不过我还是建议你放弃这个时间精度需求,因为嵌入式Linux本身的目的是通用,开发方便,如果有实时性需求,就该选择单片机来做,而不是在非实时系统中去实现实时需求,如果需求不合理,应该去思考,提出自己的意见,至少你这个需求在我看来是违背开发原则的。
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165353
金钱
165353
注册时间
2010-12-1
在线时间
2108 小时
发表于 2020-5-25 01:02:21 | 显示全部楼层
帮顶
回复

使用道具 举报

2

主题

712

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2178
金钱
2178
注册时间
2018-8-27
在线时间
258 小时
发表于 2020-5-25 09:28:25 | 显示全部楼层
你这里只说是周期性向SPI从机设备发送数据,为啥还要用到工作队列?直接在定时器中断服务函数中发送不行吗?还是说这个过程占用时间比较长,不太适合全部有中断函数中进行处理?
森罗万象
回复

使用道具 举报

3

主题

400

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1746
金钱
1746
注册时间
2015-6-11
在线时间
308 小时
发表于 2020-5-25 10:28:51 | 显示全部楼层
xiaotaotao 发表于 2020-5-25 09:28
你这里只说是周期性向SPI从机设备发送数据,为啥还要用到工作队列?直接在定时器中断服务函数中发送不行吗 ...

nxp提供的SPI同步发送函数,SPI_Sync应该是内部有内核相关的休眠动作,如果放在中断上下文里面,应该直接无法执行,只能在进程上下文里面执行,这应该是问题原因
回复

使用道具 举报

82

主题

589

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1255
金钱
1255
注册时间
2017-11-18
在线时间
296 小时
 楼主| 发表于 2020-5-25 15:57:14 | 显示全部楼层
zc123 发表于 2020-5-25 08:34
你的目的时要求周期无延时(且精度要求到50us一下), 在进程中处理时无解的,嵌入式Linux本身就非实时系统, ...

是的  我前两个星期就觉得这样的要求不太可能实现,可惜的是我在项目中并没有话语权,尽管多次做出解释给出自己的见解,但我给的大部分理论都不被接收。我的领导并不懂Linux驱动,只懂单片机STM32,沟通起来并不是很简单的事情~~
没有脑袋
回复

使用道具 举报

17

主题

237

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1312
金钱
1312
注册时间
2017-3-1
在线时间
259 小时
发表于 2020-5-27 09:29:48 | 显示全部楼层
留下学习的脚步
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 12:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表