x210-2023-04-18

发布时间 2023-04-18 16:06:50作者: migui

1、在定时器选值过程中,为了尽量减少公式记忆加快直觉判断,算出来2014Hz说明要数2014次就可以得到1s,算出来625000Hz说明要数625000次就可以得到1s,但是这里625000Hz一般不会按s来使用,而是按us使用,所以通过看到625000Hz时要能直接得到大概是多少us才行,625000Hz=0.625MHz,也就是数0.625次就可以得到1us,但是定时器不可能只数0.几次,最少也要1次,所以这里要能得到定时器数够1次耗时多长,也就是0.625次*2=1.25次,此时能满足至少1次的要求了,同时也可以得出定时器数够至少1次需要耗时1us*2=2us;上面只是加快了根据Hz数直接得到s/us的直觉判断,但是定时器还有一个关键因素,那就是分频系数,定时单位为s为什么通常直接选最大分频?定时us为什么通常直接选最小分频?一般估算时只是代入分频系数能够算到一个频率值,但是对于得到的频率值无法知道是更偏向s还是更偏向us,譬如上面2014Hz、625000Hz,值越小越偏向s值越大越偏向us这样记忆?时间一长记忆容易出错以及混乱,但是有一个普遍直觉是,频率越快时间越短,所以频率数值更大的625000Hz其定时单位更偏向us,也就是可以通过频率值数字的大小直接推测大概单位;如果这时分频系数都选好之后算出来定时器的(参考)频率为66000Hz(即0.066MHz),要满足至少一次的要求,则要0.066*100,目的是将第一个6剥离出来,但是还不够,因为需要接近1次所以除以6,即0.066*100/6=6.6/6=1.1次,于是按上面最开始的思路可以得出定时器数够至少1次需要耗时为1us*(100/6)≈1us*(16)=16us,这时如果给出初始值和重装载值为1000(次),那就很容易得到定时器总的耗时时间大约为16us*1000=16000us=16ms,这些计算里如果纯脑力计算不依靠纸笔的话,相对麻烦的也只是算100/6了,想要全部通过心算完成的话是可以接受的,但是这里要说的是另一个问题,因为有些场合并不是要定时器这段总的耗时时间,而是要这段总耗时时间对应的频率,譬如蜂鸣器这种以频率为指标的器件(至于为什么要的是频率,是因为大部分定时器同时具有PWM输出功能,如果单纯用作定时器功能,那么只有当倒计时为0之后触发定时器中断,而用作PWM输出时,一般还需要设置极性和比较值,极性最重要的一点是负责初始输出电平是高还是低,但是只有当计数值递减到和比较值相同时才翻转电平,翻转电平是芯片自动完成的,假如在初始值和重装载值为1000次的情况下,设定了比较值为500,那么高低电平的比例为1:1,即高电平数500次:低电平数500次,或者低电平数500次:高电平数500次,所以这里也看出如果不设定极性就会得到两种情况,但是总的来说,这1000次就构成了方波的一个周期,而通过这一个周期的总耗时就能反映频率,为什么?因为频率是指一秒内有多少个重复的周期,这也就是在问一秒内有多少个16ms,那不就刚好是在求频率吗?1s/16ms),回到原问题,先拿上面2014Hz为例,由于数够2014次就可以得到1s,所以每数一次需要耗时(1/2014)s,如果给出的初始值和重装载值也为1000次,那么总共耗时为(1000/2014)s,但是时间和频率是倒数关系,所以得到该段总耗时对应的频率为(2014/1000)Hz=2.14Hz,通过推算的过程得到最有利用价值的结论是,总耗时对应的频率可以通过定时器频率直接除以计数值(也就是上面提的初始值和重装载值)而快速得到,简单点说也就是将计数值直接作为分母进行计算,就可以快速估算总耗时对应的频率值,例如上面定时器频率为66000Hz、计数值为1000次的情况下,这1000次数完所对应的频率值就是66000/1000=66Hz。

2、按键事件发生后,一般会在read接口(驱动层)中使用copy_to_user()上报按键键值数据到用户空间,如果应用层通过一直开着read来等待按键事件发生,这明显是不应该的,但是应用层又不知道底层什么时候会发生按键事件,所以这时就需要有一个东西来控制同步,在32按键中断中一般会使用一个flag,进入中断置一,然后应用程序main中轮询该flag是否被置位了,如果还没置位那就去干其它事情先,到了linux这,实现相同机制的这个东西就是等待队列,用等待队列来解决“应用层通过一直开着read来等待按键事件发生”这个问题需要考虑到应用层read也是具有一定程度的随机性的,也就是你不能限制用户在应用层使用read的时机,所以这也就说明了应用层read很可能就read一次,而不是像32那样的main可以一直轮询标志位flag,所以在应用层第一次read时,驱动层相应的read接口在开头处就需要做好等待队列的准备,即调用wait_event_interruptible(),这样一来,应用层即使只read一次而且在读的那一时刻还没有碰上key中断发生,在往后的时间里也不用担心错过中断了。

3、在使用source insight的search下的replace...虽然可以方便快速地对框架代码按照新工程名称一键替换所有变量以及自定义函数名称,但是也容易出现某些非必要的替换,例如下图头文件的platform_device.h被替换成了platform_driver.h导致编译出错。

 4、在《第十二天 01 platform之pwm实现》的0:35:53中所用DEFINE_RES_MEM()在2.6.35版本kernel下查找过但不存在,但是由于思路是一致的,只是resource数组元素内容被DEFINE_RES_MEM()平替了,所以还是可以按照.start、.end、.flags逐个赋值这种相对原始的方式进行实现。