蜗窝科技

关于spin_lock是锁一个核还是所有核,gpio口模拟pwm怎么保持 时间准确并不被打断

蜗窝讨论区存档 · Linux kernel技术问答 · 楼主 cinmun · 2016-05-20 · 9 帖

本文是原「蜗窝讨论区」的历史存档(2016-05-20),来自版块「Linux kernel技术问答」,共 9 帖。讨论区已停止服务,此处仅供查阅。

cinmun · 2016-05-20 10:55

如题,楼主最近用gpio口模拟pwm载波,用延迟udelay,结果要保持不被打断,只能用spin_lock,但是要500ms的时间就太长了,系统整个被锁死, 后台播放的音乐就卡了,还有其他什么好方法,保持住gpio口高低循环,并且时间准确。

qdzhaozx · 2016-05-20 10:59

模拟pwm 建议用定时器timer中断来做

cinmun · 2016-05-20 11:01

没有多余的 timer 了 只能用io口来模拟

qdzhaozx 写道: 模拟pwm 建议用定时器timer中断来做

wowo · 2016-05-20 11:06

udelay的方法,应该是下下策吧? PWM的精度要求有多高?周期和占空比是什么量级的呢? 如果精度要求不高,可以用timer。如果精度要求高,系统有高精度timer吗?有的话,可以用hrtimer。

另外不需要多余的timer啊,和系统共用timer就可以了: include/linux/hrtimer.h include/linux/timer.h

qdzhaozx · 2016-05-20 11:10

同意! 看看片子上的Timer都怎么用的,共用同一个timer,还是用这个普通的io ,周期性的toggle即可!

wowo 写道: udelay的方法,应该是下下策吧? PWM的精度要求有多高?周期和占空比是什么量级的呢? 如果精度要求不高,可以用timer。如果精度要求高,系统有高精度timer吗?有的话,可以用hrtimer。

另外不需要多余的timer啊,和系统共用timer就可以了: include/linux/hrtimer.h include/linux/timer.h

linuxer · 2016-05-20 12:29

QQ群有若干相关的讨论,这里记录下来,如下:

【冒泡】维尼 其实我一直有一个疑问, spinlock自旋锁 是锁定一个核还是 所有的核都锁?


spinlock当然是锁所有核了

【活跃】showstopper 之前看资料说是spinlock关闭抢占和中断,锁所有核是什么意思


spinlock关闭抢占很正常啊,因为如果该CPU上的A和B两个进程都使用spinlock来保护临界区,如果不关闭抢占,那么在A的临界区内会发送B抢占A的执行的事件,这样,当B试图进入临界区的时候,岂不是要一直spin下去了吗? 至于中断,这从而说起啊,spinlock不会关闭中断的,本质上,spinlock和关闭本地中断是内核同步的两种工具,你可以单独使用其一,也可以组合使用,都是和你的临界区并发访问的特性有关的 锁所有核是什么意思?就是锁所有内核上的并发的意思,也就是说,如果有来个多个cpu core上运行的进程的并发访问,那么spinlock也是适合的。

【活跃】chinaLazy 我认为spinlock锁的本质不是核应该是总线


spinlock是一种内核同步手段,本质上和cpu core以及bus都是没有什么关系的,就是保护临界区不会被多个excution thread(可能是中断上下文,也可能是进程上下文,也可能是软中断上下文...)并发访问,只允许一个excution thread进入。

【冒泡】维尼 为什么是锁所有核呢 驱动程序只在一个核心运行 啊


驱动程序只在一个核心运行?你确定吗?驱动程序中有那么多上下文,怎么可能在一个CPU core上运行?例如:驱动的handler在哪个cpu core上执行?中断送达哪一个core就会在哪一个core上执行,如果你愿意,可以设定IRQ affinity,把中断分散送往各个core。而xxx_read这样的驱动函数,实际上属于进程上下文,各个cpu core上的进程都能够通过系统调用,从而执行驱动代码。

【冒泡】维尼 我现在用gpio口模拟 pwm载波 只能用spinlock来 保持不被间断 但是时间太长了 500多ms要


用spinlock来保护500ms的临界区,我也是醉了,可以考虑使用hrtimer

【冒泡】黑黑-Augus 2016/05/20 10:52:15 @showstopper 关闭本地中断是为了避免死锁吧


正解。当受保护的资源可能被中断上下文(hardirq)和进程上下文并发访问的时候,需要关闭本地中断。考虑下面的场景:在CPU CORE0上,在进程上下文中进入spinlock保护的临界区,这时候,如果不关闭本地中断,那么中断可以打断当前临界区的执行,从而执行interrupt handler,而在interupt handler中,获取spinlock并试图进入临界区,悲剧发生了,这时候该核永远的在中断上下文上spin起来......

【活跃】showstopper @黑黑-Augus 我的理解是,spin_lock为了当前临界区代码不被打断,所以不能有进程切换,这时候就需要关闭中断


"spin_lock为了当前临界区代码不被打断,所以不能有进程切换",其实禁止抢占也就是禁止了进程切换,和关闭中断无关的,如果临界区没有interrupt handler访问,单纯的spinlock就OK了,不需要disable local interrupt。

【活跃】chinaLazy @YIN spin_lock 的时候需要锁住内存总线,然后访问并修改数据,所以必须关闭中断,否则中断插入的话,嘿嘿,x86上是这样,其他的不知道,


x86上的确是有lock指令,它主要是把lock修饰的那条指令变成原子指令,所谓原子指令,其实就是中断也无法插入的,因此,spinlock不是一定要关闭中断的。

cinmun · 2016-05-20 14:00

us级别 我用开发板自带的pwm口 输出 也是比较要加上spinlock 才可以 要不然呢一段500us的pwm波形,会延迟到550左右

wowo 写道: udelay的方法,应该是下下策吧? PWM的精度要求有多高?周期和占空比是什么量级的呢? 如果精度要求不高,可以用timer。如果精度要求高,系统有高精度timer吗?有的话,可以用hrtimer。

另外不需要多余的timer啊,和系统共用timer就可以了: include/linux/hrtimer.h include/linux/timer.h

cinmun · 2016-05-20 17:33

我用了hrtimer 高精度定时器 结果还是会被打断,几十9ms的载波有时候会被拉低 没有载波(我用pwm口还不是gpio口)

wowo 写道: udelay的方法,应该是下下策吧? PWM的精度要求有多高?周期和占空比是什么量级的呢? 如果精度要求不高,可以用timer。如果精度要求高,系统有高精度timer吗?有的话,可以用hrtimer。

另外不需要多余的timer啊,和系统共用timer就可以了: include/linux/hrtimer.h include/linux/timer.h

wowo · 2016-05-20 17:39

cinmun 写道: 我用了hrtimer 高精度定时器 结果还是会被打断,几十9ms的载波有时候会被拉低 没有载波(我用pwm口还不是gpio口) wowo 写道: udelay的方法,应该是下下策吧? PWM的精度要求有多高?周期和占空比是什么量级的呢? 如果精度要求不高,可以用timer。如果精度要求高,系统有高精度timer吗?有的话,可以用hrtimer。

另外不需要多余的timer啊,和系统共用timer就可以了: include/linux/hrtimer.h include/linux/timer.h

不太可能啊,hrtimer的精度很高的,应该是us级别的。你在中断处理里面,把全局中断关了,拉完GPIO之后,再打开,应该不会有太大问题。 除非你们的系统太busy了,导致中断延时很高。