我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总。
内核支持两个不同的时钟。
内核还提供了许多变量,可用于将时钟使用的时间单位转换为标准时间单位(例如秒,毫秒,纳秒等),并在两种时钟时间单位之间进行转换。
大多数内核基于时间的服务都使用系统时钟,包括内核计时器对象和其他内核对象类型支持的超时。 为方便起见,内核的API允许以毫秒为单位指定持续时间,并自动将它们转换为相应的tick数。
硬件时钟可用于高精度的测量事务,因为它比内核系统时钟的精度更高。
系统时钟的tick计数来自硬件时钟的周期计数。内核计算出tick频率需要多少个硬件时钟周期,然后编程在多个硬件时钟周期后产生中断; 每个中断对应于一个tick。
注意:配置较小的时间间隔允许更细粒度的时序,但也会增加内核处理时钟中断所需的工作量,因为它们会更频繁地发生。 将滴答持续时间设置为零将禁用内核时钟及其相关服务。
使用内核API进行任何毫秒级别间隔的请求,都将发生最小延迟,实际上可能会比所请求的时间长的时间。
例如,当占用信号量时,要进行100 ms的占用请求,意味着内核不会在 100 ms过去之前终止操作以及报告故障。 但是,操作可能需要超过100毫秒才能完成,并且可能在附加时间内成功完成或者失败。
内核对象操作期间会产生附件时间,发生的附加时间量取决于以下因素。
此代码使用系统时钟来确定两个时间点之间经过的时间。
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);
此代码使用硬件时钟来确定两个时间点之间经过的时间。
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);
使用基于系统时钟的服务进行基于时间的处理,不需要高精度,如定时器对象或线程睡眠。
使用基于硬件时钟的服务进行基于时间的处理,这需要比系统时钟提供的精度更高的精度,例如忙等待)或细粒度时间测量。
注意:硬件时钟的高频率与32位数的大小紧密相关,意味着在进行长时间高精度测量时必须考虑计数器翻转的情况。
CONFIG_SYS_CLOCK_TICKS_PER_SEC
下列时钟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