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

发布者:WanderlustSoul最新更新时间:2024-09-25 来源: elecfans关键字:linux内核  S3C6410  timer 手机看文章 扫描二维码
随时随地手机看文章

本文描述基于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,因此起到向上取整的作用。


关键字:linux内核  S3C6410  timer 引用地址:linux内核中S3C6410 timer相关代码理解

上一篇:ARM11 S3C6410 硬件浮点(VFP)实现
下一篇:玩转S3C6410之一 交叉工具链制作(gcc4.5.1-armv6-vfp)

推荐阅读最新更新时间:2024-11-12 11:35

工程师笔记|STM32G4 Advanced Timer Break 功能
1、引言 在使用 STM32 的 Advanced Timer 用于工业控制,比如电机驱动,电源应用等诸多应用场合,除了 PWM 波互补输出功能外,break 功能,或者叫做刹车功能/断路功能基本都会涉及到,正确的使用这个功能是此类应用中必备的,本文将针对 break 功能做细致说明,方便PWM 驱动使用者更好去应用 break 功能。 2、Break基本功能说明 Break 功能主要用于快速硬件保护功能,功率驱动往往使用 Advanced Timer(如TIM1,TIM8)的 PWM 波进行外部驱动,进行功率开关控制,当出现了过流,过压的使用情况下,需要快速关闭外部输出,达到保护功率电路的目的,如果不能快速关断,可能
[单片机]
6410中断控制详解
S3C6410的中断主要改进是. 增加中断向量控制器,这样在S3C2440里需要用软件来跳转的中断处理机制,在S3C6410完全由硬件来跳转。你只要把ISR地址是存在连续向量寄存器空间,而不是象S3C2440自行分配空间自行管理。 换句话说,在S3C2440下是由CPU触发IRQ/FIQ异常,由异常处理函数里再查找相关中断寄存器来跳到指定的ISR,而可以全部由S3C6410的VIC硬件来自动处理。 这个大大简化中断处理编程。 另一个是外部中断加入滤波电路,这样原来需要软件去毛刺的地方均可以采用硬件来进行滤波了,这样大大简化外部中断处理。 S3C6410 中断操作 -----------------------
[单片机]
ARM Linux (S3C6410架构/2.6.35内核)的内存映射(三)
这里记录一下Linux内核做二级内存映射的过程,以中断向量表的映射过程为例。 在S3C6410架构下,Linux采用的是粗粒度小页内存管理方式,即内存段(section)的大小为1M,而页(page)的大小为4K。在第一级内存映射中,每一个PGD项覆盖1M的内存区域;如果有二级内存映射的话,每一个PTE项覆盖4K的内存区域。 下面我们来看一下二级内存映射表的设计。如果段的大小是1M而页的大小是4K的话,那么每一张二级映射表即页表中就需要有1M/4K=256个表项。而不论是PGD还是PTE,每一个表项的大小是4字节,即一个长整形数的大小。一张页表的大小为256*4=1024/1K字节,所以,页表的大小与页的大小并不能对并,一张4K大
[单片机]
s3c6410在linux下的WATCHDOG TIMER(看门狗定时器)驱动(1)
还是先说下整体结构,又要说到大家很熟悉的平台设备了,同样看门狗定时器也是作为平台设备存在的,但与以前的不同的地方是,看门狗定时器是一种混杂设备,先介绍下混杂设备。 1、混杂设备 1.1、混杂设备并没有明确的定义。它的主设备号是10,不同的设备用次设备号区分。混杂设备用结构体miscdevice表示,源码如下: struct miscdevice { int minor; 次设备号 const char *name; 设备名 const struct file_operations *fops;设备的操作函数,与字符设备相同 struct list_head list; 链接混杂设备的链表 struct device *
[单片机]
Linux下s3c6410的GPIO操作(7)
没想到一个小小的GPIO操作函数,竟然写了七篇博客,这应该算是最后一篇了。 1、s3c6410的GPIO操作函数主要涉及到三个文件,如下所示: arch/arm/plat-s3c64xx/gpiolib.c linux/arch/arm/plat-s3c/gpio.c linux/arch/arm/plat-s3c/gpio-config.c 这三个文件中的很多函数都已经讲到了,可以说基本上都讲了,当然,下面这两个函数没讲: int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) { struct s3c_gpio_chip *chip =s
[单片机]
基于tiny4412的Linux内核移植 ---- 調試方法
平臺 Linux-4.4.4 uboot使用的是友善自帶的(爲了支持uImage和設備樹做了稍許修改) 概述 這篇博客主要用於匯總一下調試方法。 正文 1. dnw下載 目前我將uboot燒寫到SD卡中,然後使用dnw將kernel、根文件系統以及設備樹鏡像下載到內存中,爲了提高效率,可以使用下面的方法: 在uboot中添加環境變量: setenv dnw_up 'dnw 0x40600000; dnw 0x41000000; dnw 0x42000000; bootm 0x40600000 0x41000000 0x42000000' 進入uboot終端後,執行如下命令: run d
[单片机]
S3C6410移植u-boot-2010.3(1)成功编译的开始
  参考连接:http://wenku.baidu.com/view/ae78a00390c69ec3d5bb75ce.html?st=1   链接上已经指明了我之前一直2013.01版本uboot产生错误的原因,2010.3版本到2010.6版本是uboot的一个分界,而2010.3版本的uboot是最接近samsung定制的s3c-u-boot-1.1.6版本uboot的一个版本号,所以在此选择版本2010.3   1、download the uboot from ftp http://ftp.denx.de/pub/u-boot/ download u-boot-2010.03.tar.bz2   2、为
[单片机]
基于S3C6410处理器和Linux的家居监控运动目标检测系统
选用ARM11(S3C6410)处理器作为硬件平台,嵌入式Linux操作系统作为软件平台,综合运动图像检测的背景差分法和帧间差分法为算法,并与GSM模块相结合,设计并实现了一种应用于家居环境或私人办公室无人值守的运动目标检测系统。提出了系统设计的总体方案,并详细介绍了系统软硬件平台的设计流程,最后对系统进行了测试。 随着社会的发展和科技的进步,人们的安防意识越来越强,而计算机网络技术,通信技术,和数字视频编码技术的日益成熟,使基于计算机的多媒体视频监控系统成为可能。但是传统的视频监控系统因十分复杂,功耗和成本较高且需要值守,而无法应用于诸如家居或私人办公室等场所,为此,本文设计了一种以ARM11为核心处理器,嵌入式Linux为
[单片机]
基于<font color='red'>S3C6410</font>处理器和Linux的家居监控运动目标检测系统
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved