[IMX6DL]do_gettimeofday()的精度分析
2016-04-14 16:30
651 查看
Platform: IMX6DL
OS: Android 4.4
Kernel branch: 3.0.35
网上有很多不同版本说 do_gettimeofday()精度是ms,有的又说是us,那么正确答案到底是什么呢?
还有,系统的tick只有ms的精度,如果是us精度,那么它又是如何做到的呢?
先看do_gettimeofday()源代码:
do_gettimeofday -> //timekeeping.c
getnstimeofday ->
timekeeping_get_ns //先获取ns,再转换成us.
timerkeeper是什么?
可以把timerkeeper看成时间的管理者~
timekeeper.clock是什么?
系统有很多种clock,例如jiffies, RTC, OSC等,不同时钟源的精度不一样,
这也就导致最终得到的时间精度不一样,到这里大概知道系统的us以及ns精度是如何来的了,继续往下分析。
timekeeper.clock的初始化在哪里完成的?
开机有:
start_kernel -> //main.c
timekeeping_init -> //timekeeping.c
clocksource_default_clock -> //jiffies.c
对应的read()实现就是jiffies_read()了!
当系统没有其他的clock source可选时,就会使用默认jiffies作为clock source, 所以它的精度只能到ms级。
那么当有更高精度的clock source时如何替换呢,答案如下:
mx6_tek_timer_init -> //board-mx6-tek.c
mx6_clocks_init(32768, 24000000, 0, 0); -> //clock.c 注意第一个参数是RTC,为32.768KHz, 第二个参数是osc,为24MHz.
oscillator_reference = osc;
mxc_timer_init(&gpt_clk[0], timer_base, MXC_INT_GPT); -> //time.c 注意第一个参数,一会会说到
mxc_clocksource_init ->
c = clk_get_rate(timer_clk); //获取对应的clock,如果获取不到,会获取parent对应的clock,依次向上获取。
clocksource_mmio_init ->
clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
clocksource_mmio_readl_up); -> //c为clock,clocksource_mmio_readl_up()为read()函数。
clocksource_register_hz
__clocksource_register_scale ->
clocksource_select -> //系统可能会同时多个clock source, 找到最佳
timekeeping_notify ->
change_clocksource ->
old = timekeeper.clock; //这里就会替换原有的clock source,本例是替换jiffies
也就是说timer_clk变量对应的是&gpt_clk[0],对应的parent为osc_clk
而oscillator_reference的值就是osc,为24000000Hz,能达到ns精度, 也就是说do_gettimeofday()的精度能达到us级了!
24MHz的OSC硬件图如下:
参考:
http://blog.csdn.net/droidphone/article/details/7989566
OS: Android 4.4
Kernel branch: 3.0.35
网上有很多不同版本说 do_gettimeofday()精度是ms,有的又说是us,那么正确答案到底是什么呢?
还有,系统的tick只有ms的精度,如果是us精度,那么它又是如何做到的呢?
先看do_gettimeofday()源代码:
do_gettimeofday -> //timekeeping.c
getnstimeofday ->
timekeeping_get_ns //先获取ns,再转换成us.
static inline s64 timekeeping_get_ns(void) { cycle_t cycle_now, cycle_delta; struct clocksource *clock; /* read clocksource: */ clock = timekeeper.clock; /*读取当前时间*/ cycle_now = clock->read(clock); /*计算上一次和现在的时间差。*/ /* calculate the delta since the last update_wall_time: */ cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; /* return delta convert to nanoseconds using ntp adjusted mult. */ return clocksource_cyc2ns(cycle_delta, timekeeper.mult, timekeeper.shift); }
timerkeeper是什么?
可以把timerkeeper看成时间的管理者~
timekeeper.clock是什么?
系统有很多种clock,例如jiffies, RTC, OSC等,不同时钟源的精度不一样,
这也就导致最终得到的时间精度不一样,到这里大概知道系统的us以及ns精度是如何来的了,继续往下分析。
timekeeper.clock的初始化在哪里完成的?
开机有:
start_kernel -> //main.c
timekeeping_init -> //timekeeping.c
clocksource_default_clock -> //jiffies.c
struct clocksource * __init __weak clocksource_default_clock(void) { return &clocksource_jiffies; } struct clocksource clocksource_jiffies = { .name = "jiffies", .rating = 1, /* lowest valid rating*/ .read = jiffies_read, .mask = 0xffffffff, /*32bits*/ .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ .shift = JIFFIES_SHIFT, };
对应的read()实现就是jiffies_read()了!
static cycle_t jiffies_read(struct clocksource *cs) { return (cycle_t) jiffies; }
当系统没有其他的clock source可选时,就会使用默认jiffies作为clock source, 所以它的精度只能到ms级。
那么当有更高精度的clock source时如何替换呢,答案如下:
mx6_tek_timer_init -> //board-mx6-tek.c
mx6_clocks_init(32768, 24000000, 0, 0); -> //clock.c 注意第一个参数是RTC,为32.768KHz, 第二个参数是osc,为24MHz.
oscillator_reference = osc;
mxc_timer_init(&gpt_clk[0], timer_base, MXC_INT_GPT); -> //time.c 注意第一个参数,一会会说到
mxc_clocksource_init ->
c = clk_get_rate(timer_clk); //获取对应的clock,如果获取不到,会获取parent对应的clock,依次向上获取。
clocksource_mmio_init ->
clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
clocksource_mmio_readl_up); -> //c为clock,clocksource_mmio_readl_up()为read()函数。
clocksource_register_hz
__clocksource_register_scale ->
clocksource_select -> //系统可能会同时多个clock source, 找到最佳
timekeeping_notify ->
change_clocksource ->
old = timekeeper.clock; //这里就会替换原有的clock source,本例是替换jiffies
也就是说timer_clk变量对应的是&gpt_clk[0],对应的parent为osc_clk
static struct clk gpt_clk[] = { { __INIT_CLK_DEBUG(gpt_clk) .parent = &osc_clk, ...... }; static struct clk osc_clk = { __INIT_CLK_DEBUG(osc_clk) .get_rate = get_oscillator_reference_clock_rate, }; static unsigned long get_oscillator_reference_clock_rate(struct clk *clk) { return oscillator_reference; }
而oscillator_reference的值就是osc,为24000000Hz,能达到ns精度, 也就是说do_gettimeofday()的精度能达到us级了!
24MHz的OSC硬件图如下:
参考:
http://blog.csdn.net/droidphone/article/details/7989566
相关文章推荐
- Mybatis中oracle、mysql、db2、sql server的like模糊查询
- spark.streaming.concurrentJobs参数分析
- 添加删除用户
- Asp.net Session保存到Redis: 使用 RedisSessionStateProvider
- Angluar中Controller之间通信方法
- 8种交换
- vb14
- 范范(10)
- 二叉排序树(BST)创建,删除,查找操作
- 详解JSP中的语句对象Statement操作MySQL的使用实例
- mysql登录报错提示:ERROR 1045 (28000)的解决方法
- 通过Android源代码分析startActivity()过程(下)
- 使用virtualbox设置双网卡,桥接+内部网络
- C++中map、set、hash_map、hash_set、unordered_map、unordered_set通俗辨析
- 利用反射取得类中属性(引用及非引用数据类型)及设置该类实例化对象的属性值
- Ajax例子,views返回,html接收数据
- HTML5 五子棋 - JS/Canvas 游戏
- 树结点的简单练习
- 二叉排序树(BST)创建,删除,查找操作
- URL链接中文参数乱码的若干处理方法