zephyr笔记 2.2.1 内核时钟

1 前言

我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总

2 概念

内核支持两个不同的时钟。

  • 32位硬件时钟是一个高精度计数器,可以跟踪若干个周期时间,但这个周期不能指定单位。一个周期的持续时间取决于内核使用的电路板硬件,通常以纳秒为单位进行测量。

  • 64位系统时钟是一个计数器,用于跟踪自内核初始化以来已经过的tick数。tick的持续时间是可配置的,通常范围从1毫秒到100毫秒。

内核还提供了许多变量,可用于将时钟使用的时间单位转换为标准时间单位(例如秒,毫秒,纳秒等),并在两种时钟时间单位之间进行转换。

大多数内核基于时间的服务都使用系统时钟,包括内核计时器对象和其他内核对象类型支持的超时。 为方便起见,内核的API允许以毫秒为单位指定持续时间,并自动将它们转换为相应的tick数。

硬件时钟可用于高精度的测量事务,因为它比内核系统时钟的精度更高。

2.1 时钟限制

系统时钟的tick计数来自硬件时钟的周期计数。内核计算出tick频率需要多少个硬件时钟周期,然后编程在多个硬件时钟周期后产生中断; 每个中断对应于一个tick。

注意:配置较小的时间间隔允许更细粒度的时序,但也会增加内核处理时钟中断所需的工作量,因为它们会更频繁地发生。 将滴答持续时间设置为零将禁用内核时钟及其相关服务。

使用内核API进行任何毫秒级别间隔的请求,都将发生最小延迟,实际上可能会比所请求的时间长的时间。

例如,当占用信号量时,要进行100 ms的占用请求,意味着内核不会在 100 ms过去之前终止操作以及报告故障。 但是,操作可能需要超过100毫秒才能完成,并且可能在附加时间内成功完成或者失败。

内核对象操作期间会产生附件时间,发生的附加时间量取决于以下因素。

  • 从毫秒转换为tick时,通过四舍五入指定的时间间隔引入附加时间。 例如,如果使用10毫秒的时间间隔,则25毫秒的指定延迟将四舍五入至30毫秒。

  • 延迟时,只有等到下一个有效中断到来时才能开始进行有效地追踪,这样便引入了延迟。例如,如果正在使用 10 ms 的tick间隔,则 20 ms 的指定延迟要求内核等待3个时间片发生(而不是仅仅发生2个时间片),因为第一个tick可能发生在 0-10 ms之间,只有等第一个tick发生后,内核才能知道接下来的2个 tick 消耗 20ms。

3 操作

3.1 用正常精度测量时间

此代码使用系统时钟来确定两个时间点之间经过的时间。

s64_t time_stamp;
s64_t milliseconds_spent;

/* capture initial time stamp */
time_stamp = k_uptime_get();

/* do work for some (extended) period of time */
...

/* compute how long the work took (also updates the time stamp) */
milliseconds_spent = k_uptime_delta(&time_stamp);

3.2 高精度测量时间

此代码使用硬件时钟来确定两个时间点之间经过的时间。

u32_t start_time;
u32_t stop_time;
u32_t cycles_spent;
u32_t nanoseconds_spent;

/* capture initial time stamp */
start_time = k_cycle_get_32();

/* do work for some (short) period of time */
...

/* capture final time stamp */
stop_time = k_cycle_get_32();

/* compute how long the work took (assumes no counter rollover) */
cycles_spent = stop_time - start_time;
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(cycles_spent);

4 建议用法

使用基于系统时钟的服务进行基于时间的处理,不需要高精度,如定时器对象或线程睡眠

使用基于硬件时钟的服务进行基于时间的处理,这需要比系统时钟提供的精度更高的精度,例如忙等待)或细粒度时间测量。

注意:硬件时钟的高频率与32位数的大小紧密相关,意味着在进行长时间高精度测量时必须考虑计数器翻转的情况。

5 配置选项

CONFIG_SYS_CLOCK_TICKS_PER_SEC

6 API

下列时钟API,都在 kernel.h 中提供了:

k_uptime_get()
k_uptime_get_32()
k_uptime_delta()
k_uptime_delta_32()
k_cycle_get_32()
SYS_CLOCK_HW_CYCLES_TO_NS
K_NO_WAIT
K_MSEC
K_SECONDS
K_MINUTES
K_HOURS
K_FOREVER

End


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值