前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >zephyr笔记 2.2.2 定时器

zephyr笔记 2.2.2 定时器

作者头像
twowinter
发布2020-04-17 11:06:52
1.4K0
发布2020-04-17 11:06:52
举报
文章被收录于专栏:twowintertwowinter

1 前言

计时器是一个内核对象,它使用内核的系统时钟来度量时间的流逝。 当达到定时器的指定时间限制时,它可以执行应用程序定义的操作,或者它可以简单地记录到期并等待应用程序读取其状态。

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

2 概念

可以定义任意数量的定时器。每个定时器都由地址引用。

计时器具有以下关键属性:

  • duration,指定定时器到期前的持续时间,以毫秒为单位。它必须大于零。
  • period ,指定定时器到期后的时间间隔(以毫秒为单位)。它必须是非负的。零周期意味着定时器是一次性定时器,在一次到期后停止。 (例如,如果一个定时器的启动持续时间为200,周期为75,它将首先持续200ms,然后再75ms后重复。)
  • expiry function,每当计时器到期时执行一次到期函数。该功能由系统时钟中断处理程序执行。如果不需要到期函数,则可以指定NULL函数。
  • stop function,如果定时器在运行时过早停止,则执行停止功能。该函数由停止定时器的线程执行。如果不需要停止功能,则可以指定NULL功能。
  • status,状态值,指示自从状态值上次读取以来定时器已经过期的次数。

定时器必须在使用前初始化。这指定了其到期函数和停止函数值,将定时器的状态设置为零,并使定时器进入停止状态。

定时器通过指定持续时间和周期来启动。定时器的状态被重置为零,然后定时器进入运行状态并开始到期的倒计时。

当一个正在运行的定时器到期时,它的状态会增加,如果存在到期函数的话会执行到期函数; 如果一个线程正在等待定时器,它将被解除阻塞。 如果定时器的周期为零,则定时器进入停止状态; 否则定时器会以等于其周期的新持续时间重新启动。

如果需要,正在运行的计时器可以在倒计时期间中止。定时器的状态保持不变,然后定时器进入停止状态并执行其停止函数(如果存在)。如果一个线程正在等待定时器,它将被解除阻塞。试图停止不运行的计时器是允许的,但它对定时器没有影响,因为它已经停止。

如果需要,正在运行的定时器可以在倒数计时器中重新启动。定时器的状态重置为零,然后定时器使用调用者指定的新的持续时间和周期值开始倒计时。如果一个线程正在等待定时器,它将继续等待。

可以随时直接读取定时器的状态,以确定定时器自上次读取状态以来已经过了多少次。读定时器的状态会将其值重置为零。定时器到期之前剩余的时间量也可以读取;值为零表示定时器已停止。

线程可以通过与定时器同步来间接读取定时器的状态。这会阻塞线程,直到定时器的状态为非零(表示它至少已经过期)或定时器停止;如果定时器状态已经非零或定时器已经停止,则线程继续而不等待。同步操作返回定时器的状态并将其重置为零。

代码语言:javascript
复制
注意:由于读取状态(直接或间接)会改变其值,因此只有一个用户应该检查任何给定定时器的状态。 同样,一次只有一个线程应该与给定的定时器同步。ISR不允许与定时器同步,因为ISR不允许被阻塞。

3 定时器限制

由于定时器基于系统时钟,因此使用定时器时指定的延迟值为最小值。 (请参阅zephyr笔记 2.2.1 内核时钟中的时钟限制章节。)

4 操作

4.1 定义一个计时器

定时器使用 struct k_timer 类型的变量来定义。 它必须通过调用 k_timer_init() 来初始化。

以下代码定义并初始化一个计时器。

代码语言:javascript
复制
struct k_timer my_timer;
extern void my_expiry_function(struct k_timer *timer_id);

k_timer_init(&my_timer, my_expiry_function, NULL);

或者,可以通过调用K_TIMER_DEFINE在编译时定义和初始化计时器。

以下代码与上面的代码段具有相同的效果。

代码语言:javascript
复制
K_TIMER_DEFINE(my_timer, my_expiry_function, NULL);

4.2 使用定时器到期函数

以下代码使用计时器定期执行重要操作。由于所需工作不能在中断级完成,因此计时器的到期函数将工作项提交给系统工作队列,该工作队列的线程执行工作。

代码语言:javascript
复制
void my_work_handler(struct k_work *work)
{
    /* do the processing that needs to be done periodically */
    ...
}

K_WORK_DEFINE(my_work, my_work_handler);

void my_timer_handler(struct k_timer *dummy)
{
    k_work_submit(&my_work);
}

K_TIMER_DEFINE(my_timer, my_timer_handler, NULL);

...

/* start periodic timer that expires once every second */
k_timer_start(&my_timer, K_SECONDS(1), K_SECONDS(1));

4.3 读取计时器状态

以下代码直接读取计时器的状态以确定计时器是否已过期。

代码语言:javascript
复制
K_TIMER_DEFINE(my_status_timer, NULL, NULL);

...

/* start one shot timer that expires after 200 ms */
k_timer_start(&my_status_timer, K_MSEC(200), 0);

/* do work */
...

/* check timer status */
if (k_timer_status_get(&my_status_timer) > 0) {
    /* timer has expired */
} else if (k_timer_remaining_get(&my_status_timer) == 0) {
    /* timer was stopped (by someone else) before expiring */
} else {
    /* timer is still running */
}

4.4 使用定时器状态同步

以下代码执行定时器状态同步以允许线程执行有用的工作,同时确保一对协议操作按指定的时间间隔分隔。

代码语言:javascript
复制
K_TIMER_DEFINE(my_sync_timer, NULL, NULL);

...

/* do first protocol operation */
...

/* start one shot timer that expires after 500 ms */
k_timer_start(&my_sync_timer, K_MSEC(500), 0);

/* do other work */
...

/* ensure timer has expired (waiting for expiry, if necessary) */
k_timer_status_sync(&my_sync_timer);

/* do second protocol operation */
...
代码语言:javascript
复制
注意:如果线程没有其他工作要做,它可以简单地在两个协议操作之间休眠,而不使用定时器。

5 建议用法

使用定时器在指定的时间后启动异步操作。

使用计时器确定是否已经过了指定的时间量。

使用计时器执行其他工作,同时执行涉及时间限制的操作。

代码语言:javascript
复制
注意:如果一个线程在等待时间通过时没有其他工作要执行,它应该调用k_sleep() 。 如果线程需要测量执行操作所需的时间,它可以直接读取系统时钟或硬件时钟,而不是使用定时器。

6 配置选项

7 APIs

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

代码语言:javascript
复制
K_TIMER_DEFINE
k_timer_init()
k_timer_start()
k_timer_stop()
k_timer_status_get()
k_timer_status_sync()
k_timer_remaining_get()

End

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 前言
  • 2 概念
  • 3 定时器限制
  • 4 操作
    • 4.1 定义一个计时器
      • 4.2 使用定时器到期函数
        • 4.3 读取计时器状态
          • 4.4 使用定时器状态同步
          • 5 建议用法
          • 6 配置选项
          • 7 APIs
          • End
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档