linux内核中S3C6410 timer相关代码理解

发布时间:2024-09-25  

本文描述基于mini6410平台的time.c中的相关代码,主要描述下对部分代码的理解。


先贴上代码:


 1 /* we use the shifted arithmetic to work out the ratio of timer ticks

 2  * to usecs, as often the peripheral clock is not a nice even multiple

 3  * of 1MHz.

 4  *

 5  * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok

 6  * for the current HZ value of 200 without producing overflows.

 7  *

 8  * Original patch by Dimitry Andric, updated by Ben Dooks

 9 */

10 

11 /* timer_mask_usec_ticks

12  *

13  * given a clock and divisor, make the value to pass into timer_ticks_to_usec

14  * to scale the ticks into usecs

15 */

16 static inline unsigned long

17 timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)

18 {

19     unsigned long den = pclk / 1000;

20 

21     return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;

22 }


该函数主要的功能为换算出在某个时钟频率下,每个时钟周期所对应的微秒数,且该微秒数经过放大处理。


首先第19行代码将时钟频率由MHZ转换为KHZ,当然前提是pclk以MHZ为单位计算。


分析下一行代码前,先看下频率转换为微秒的计算公式:t = (10^6)/(pclk/scaler),上述公式表示在分频后的时钟频率下一个时钟周期对应的微秒数。显然上述公式可能出现小数部分,在计算机中我们用整型变量来保存数据时,为了不减小精度,一般会将数据放大处理,因此将上述公式放大一定的倍数,在得到最后结果前,再缩小相应的倍数得到最后结果。在这里将上述公式放大了2^16倍,得到公式:


t = (10^6)*(2^16)/(pclk/scaler),


对上述公式变量替换并推导:t = ((10^6)/1000)*(2^16)/((pclk/1000)/scaler)


   = ((10^3)<<16)/(den/scaler)


   = ((1000<<16)*scaler)/den。


    为了减小误差,对上述公式进行四舍五入则得到公式:


  ((1000<<16)*scaler)/den + (1/2) = ((1000<<16)*scaler)/den + (den/2den)


  = ((1000<<16)*scaler+den/2)/den


  = ((1000<<16)*scaler+(den>>1))/den。


      TIMER_USEC_SHIFT宏定义为16,由此第21行代码便不言而喻了。


关于第5、6行注释的理解:12MHZ转换为微秒为(10^6)/(12*10^6)=1/12=0.08333333333 将其放大保存在整型变量里,这里是说放大系数为2^15或2^14显得太低,精度不够。因此设置放大系数为2^16,并且2^16不会导致200HZ的频率上溢。200HZ频率表示5毫秒产生一个中断,假设时钟频率就是12M,则5毫秒需要12*(10^6)*(5/1000)=60000个时钟周期。((10^6)/(12*10^6))*(2^16)=5462(约等于), 5462*60000=0x13889C40,没有造成溢出。个人理解,如有错误之处,还请多多提点。


接下来再看另一段代码:


 1 /* timer_ticks_to_usec

 2  *

 3  * convert timer ticks to usec.

 4 */

 5 

 6 static inline unsigned long timer_ticks_to_usec(unsigned long ticks)

 7 {

 8     unsigned long res;

 9 

10     res = ticks * timer_usec_ticks;

11  

12     res += 1 << (TIMER_USEC_SHIFT - 4);    /* round up slightly */

13 

14     return res >> TIMER_USEC_SHIFT;

15 }


该函数的主要功能是将时钟周期数转换为微秒数,第10行代码中全局变量timer_usec_ticks为由timer_mask_usec_ticks函数返回得到的值。该值乘以具体时钟周期数便得到该时钟周期数对应的微秒数。后面第12行又加上了一个值,该值目的是进行向上取整处理,以提高精度。第14行代码右移处理便是将上面进行放大倍数处理后的值还原为实际的结果值。


1<<(TIMER_USEC_SHIFT - 4) = 2^12,  (2^12/2^16) 小于 1,因此起到向上取整的作用。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>