鉴于自己英语水平不高,在这里,将上一篇关于contiki 的timer的文章翻译为中文,让自己在学习的时候,更方便点。文中有许多不是很通顺的地方,将就吧。

Timers

Contiki系统提供了一套时钟库用于应用程序和系统本身。时钟库包含了检查时间超出、将系统从低功耗模式唤醒到预定时间,以及实时任务安排等功能。时钟也用于应用程序,让系统和其他一起工作,或者在恢复执行前进入低功耗模式一段时间。

The Contiki Timer Modules

Contiki有一个时钟模块和一套时钟:timer,stimer,ctimer,etimer和rtimer。不同的时钟有不同的用处:有的时钟提供了长运行时间低密度(时间间隔长),有的时钟提供了短运行时间和高密度(时间间隔短),有的时钟可以用在中断上下文(rtimer),而其他时钟则不行。

时钟模块提供了操作系统时间的功能,以及短时间阻塞CPU的功能。定时器库是实现时钟模块的功能的基础。

timer和stimer库提供了最简单形式的定时器,用于检查一段时间是否到期。应用程序需要问计时器,他们是否已经过期。然而两者的区别在于:timer使用系统嘀嗒,而stimer 使用秒,允许更长的时间。不同于其他timer的是,timer和stimer库可以从中断中安全的使用,这使得他们在底层的驱动中特别有用。

Etimer库提供事件时间,他能用于contiki进程在一段时间后的计划事件。他用于contiki的进程中,等待一段时间,在此时,其他的部分可以工作或进入低功耗模式。

Ctimer提供回调时间,他用于在一段时间之后,安排调用回调函数。就像事件定时器一样,他们是用来等待一些时间,而在这段时间内,系统其他的部分可以工作或进入低功耗模式。当时间到期之后,回调定时器调用函数,他在任何代码中都非常有用,以致没有一个想协议实现那样的显式的contiki进程。(这里我翻译的不是很好,原文:they are especially useful in any code that do not have an explicit Contiki process such as protocol implementations)在其他方面,使用的回调定时器在Rime协议栈处理通信超时。

Rtimer库提供实时任务调度。Rtimer库抢占任何运行着的contiki进程,让实时任务在预定的时间里执行。实时任务用在关键代码处理时间里,例如X-MAC实现收音机开启或关闭这种没有延时的情况下。

The Clock Module

时钟模块提供操作系统时间的功能。

Contiki时钟模块的API接口所示如下:clock_time()函数以时钟嘀嗒的形式返回当前系统时间。每秒时钟嘀嗒的数是和平台相关的,通常被指定为常数CLOCK_SECOND。系统时间被指定为和平台相关的类型clock_time_t,在大多数情况下这是一个有限的无符号值,运行时会变很大。时钟模块也提供clock_seconds()函数,以秒的形式获得系统时间,其值为一个无符号的长整型数,这个时间值会变的很大,直到他增加到最大,(在MSP430平台上为136年),然后系统重新开始,时间也从零开始。

时钟模块提供两个函数阻塞CPU:clock_delay(),阻塞CPU一个指定的延迟,clock_wait(),阻塞CPU一个指定的时钟嘀嗒。这些函数通常只用于底层驱动程序,在有必要等待很短的时间,但并不放弃控制CPU的情况。

函数clock_init()由系统启动,初始化时钟模块的时候调用。

时钟模块API:

clock_time_t clock_time():获得系统时间。

unsigned long clock_seconds() :以秒的形式获得系统时间。

void clock_delay(unsigned int delay):CPU延时。

void clock_wait(int delay):CPU延时一定数量的系统嘀嗒。

void clock_init(void):初始化时钟模块。

CLOCK_SECOND:每秒系统嘀嗒数。

Porting the Clock Module

时钟模块与平台相关,他的应用在clock.c文件里面。时钟模块处理系统时间,他的实现通常需要适时检查事件计时器是否到时,然后通知etimer库处理。

The Timer Library

Contiki时钟库提供设置、重置、重启时钟的函数,并检查一个时钟是否到期。一个应用程序

需要“手动”地检查定时器是否到期,而不是自动完成的。在时钟模块中,时钟库使用clock_timer()获得当前的系统时间。

定时器被声明为struct类型,所有访问定时器都是经过指针指向被声明的定时器。

Contiki定时器库的API如下所示。定时器由timer_set()完成初始化,设置定时器从当前时间到指定时间的延迟,而且他还存储了定时器的时间间隔。Timer_reset()可以从之前的到期时间重置定时器,timer_restart()从当前时间重新启动定时器。Timer_reset()和timer_restart()都是调用timer_set(),用时间间隔设置定时器。这些函数的区别是:timer_reset()用完全相同的时间间隔设置定时器延时,而timer_restart()从当前时间设置时间间隔,使时间推移。

Timer_expired()函数用来检查定时器是否到期,timer_remaining()获得一个定时器到期的剩余时间。如果定时器已经过期,他的返回值未知的。

Timer库可以从中断中安全的使用。下面的代码显示了一个简单的例子:一个定时器如何在中断中检测超时。

Timer库API:

void timer_set(struct timer *t, clock_time_t interval) :启动定时器。

void timer_reset(struct timer *t):从以前到期时间重新启动定时器。

void timer_restart(struct timer *t):从当前时间重启定时器。

int timer_expired(struct timer *t) :检查定时器是否到期。

clock_time_t timer_remaining(struct timer *t):获得剩余时间。

一个例子展示了一个定时器如何检测超时:

static struct timer rxtimer;

void init(void) {

timer_set(&rxtimer, CLOCK_SECOND / 2);

}

interrupt(UART1RX_VECTOR)

uart1_rx_interrupt(void)

{

if(timer_expired(&rxtimer)) {

/* Timeout */

/* ... */

}

timer_restart(&rxtimer);

/* ... */

}

The Stimer Library

Contiki Stimer 库提供的定时机制类似于timer库,但是他的时间使用是秒,允许更长的到期时间,stimer库在时钟模块中用clock_seconds()以秒的形式获得当前的系统时间。

Contiki stimer库的API如下所示,他非常类似于timer的库。不同的是,他以秒为单位,而timer是以系统嘀嗒为单位。

Stimer库可以从中断中安全的使用。

Stimer库的API:

void stimer_set(struct stimer *t, unsigned long interval) :启动timer。

void stimer_reset(struct stimer *t):从到期时间中重启timer。

void stimer_restart(struct stimer *t):从当前时间重启timer。

nt stimer_expired(struct stimer *t):检查时间是否到期。

unsigned long stimer_remaining(struct stimer *t):获得剩余时间。

The Etimer Library

Contiki etimer库提供了一个定时器机制,产生定时事件。当事件时间到期时,事件定时器将向进程标示PROCESS_EVENT_TIMER来设置定时器。在时钟模块中,Etimer库使用clock_time()获得系统当前时间。

事件定时器声明为struct etimer类型,所有访问事件定时器都需要通过指针来指向被声明的etimer时间。

Contiki etimer库的API 如下所示。如同前面的那些定时器,事件定时器总是调用etimer_set()初始化,设置定时器从当前时间开始到指定时间的延时。etimer_reset() 可以从之前的到期时间启动定时器。Etimer_restart()从当前时间重启定时器,他们都使用相同的时间间隔,且最初都是由etimer_set()设置。etimer_reset()和etimer_restart()的区别在于:前者的时间从以前的到期时间,而后者的时间从当前时间开始,从而允许时间推移。一个事件定时器可以被etimer_stop()停止,这意味着etimer立即过期,而不会发布一个定时器事件。Etimer_expired()用来检查一个etimer时间是否过期。

注意:定时器事件被发送到contiki进程用来调度事件定时器。(太绕了,暂时这么理解吧)如果一个事件定时器在回调函数或者其他的contiki进程被设置, PROCESS_CONTEXT_BEGIN() 和PROCESS_CONTEXT_END()可以被用来临时改变进程上下文。在processes中有更多关于进程管理的信息。

下面是一个简单的例子:如何用etimer每秒安排process运行一次。

Etimer库不能从中断中安全使用。

Etimer库的API:

void etimer_set(struct etimer *t, clock_time_t interval) :启动定时器。

void etimer_reset(struct etimer *t) :从以前到期时间重启定时器。

void etimer_restart(struct etimer *t) :从当前时间重启定时器。

void etimer_stop(struct etimer *t):停止定时器。

int etimer_expired(struct etimer *t):检查时间是否到期。

int etimer_pending() :检查是否有非过期的事件计时器。

clock_time_t etimer_next_expiration_time():得到下一个事件定时器过期时间。

void etimer_request_poll() :通知etimer库,系统时间已经改变。

设置一个事件定时器,让process每秒执行一次。

PROCESS_THREAD(example_process, ev, data)

{

static struct etimer et;

PROCESS_BEGIN();

/* Delay 1 second */

etimer_set(&et, CLOCK_SECOND);

while(1) {

PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));

/* Reset the etimer to trig again in 1 second */

etimer_reset(&et);

/* ... */

}

PROCESS_END();

}

Porting the Etimer Library

Etimer库实现的核心是/sys/etimer.c,与平台无关,但需要回调etimer_request_poll()来处理事件定时器。这允许事件定时器到期时,从低功耗模式唤醒。Etimer库提供三种功能:

etimer_pending() 检查是否有任何非过期事件定时器。

etimer_next_expiration_time()得到下一个事件定时器过期时间。

etimer_request_poll() 通知etimer库,系统时间已经改变,一个etimer已经过期。这个函数从中断调用是安全的。

时钟模块处理系统时间之后,通常还要回调etimer库。(这句也不太懂,原文The implementation of the clock module usually also handles the callbacks to the etimer library since the module already handles the system time)可以通过定期调用etimer_request_poll()简单地实现,或者利用etime_next_expiration_time(),或者在需要时通知etimer库。

The Ctimer Library

Contiki ctimer库提供了一个定时器机制,当回调时间过期时,调用指定的函数。在时钟模块中Ctimer库使用clock_timer()获得当前的系统时间。

Contiki ctimer库的API如下所示,他和etimer的库很像。区别在于ctimer_set()需要一个回调函数指针和数据指针作为参数。当ctimer到期时,他将数据指针作为参数调用回调函数。下面的代码展示了ctimer如何安排回调函数每秒调用一次。

注意:尽管这个回调定时器指定回调函数,但是ctimer安排进程上下文的回调。除非你确定回调定时器如何工作,否则不采取任何特定的进程上下文回调。

Ctimer库从中断中使用不是安全的。

Ctimer库的API:

void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr):启动定时器。

void ctimer_reset(struct ctimer *t) :从以前到期的时间重启定时器。

void ctimer_restart(struct ctimer *t) :从当前时间重启定时器。

void ctimer_stop(struct ctimer *t) :停止定时器。

int ctimer_expired(struct ctimer *t) :检查定时器是否过期。

设置一个ctimer,每秒调用一次函数。

static void

callback(void *ptr)

{

ctimer_reset(&timer);

/* ... */

}

void

init(void)

{

ctimer_set(&timer, CLOCK_SECOND, callback, NULL);

}

Porting the Ctimer Library

Ctimer库的实现使用etimer库,不需要近一步移植。

The Rtimer Library

Contiki rtimer库提供了实时任务调度和执行(可预测执行时间)。Rtimer使用自己的时钟模块调度,允许更高的时钟分辨率。RTIMER_SECOND()函数以嘀嗒的形式获取当前系统时间,RTIMER_SECOND指定每秒的时钟节拍数。

不像其他的contiki定时器库,实时任务抢占正常执行的进程,立即执行任务。在实时任务中能做什么是有约束的,因为大多数函数不处理具有优先权的任务。中断安全函数例如asprocess_poll()在实时任务中总是安全的,但是任何可能的冲突与正常执行必须是同步的。

实时任务可以使用函数RTIMER_TIME(struct rtimer *t)在任务被执行的最后一次检索所需的执行时间。

这里没有例子,这里的文档解释的是从2007年以前的API,是误导。

Porting the Rtimer Library

Rtimer库实现的核心是/sys/rtimer.c,与平台无关,取决于rtime-arch.c处理平台的相关功能,如调度等。下面三个功能在移植rtimer库是需要实现。

rtimer_arch_init()被rtimer库调用,初始化rtimer代码。

rtimer_arch_now()用来获取当前的系统实时时间。

rtimer_arch_schedule()需要一个参数---唤醒时间,请求唤醒回调。

除了这三个函数,rtimer架构代码需要定义RTIMER_ARCH_SECOND作为每秒的滴答数,rtimer_clock_t数据类型用于rtimer时间,这些都是在rtimer-arch.h文件中声明的。

Rtimer库与平台相关的函数:

RTIMER_ARCH_SECOND:每秒的滴答数。

void rtimer_arch_init(void):初始化rtimer。

rtimer_clock_t rtimer_arch_now():获取当前时间。

int rtimer_arch_schedule(rtimer_clock_t wakeup_time):安排一个rtimer_run_next()调用。

Conclusions

Contiki包含一组定时器库,应用于contiki核心模块和应用程序。定时器库用来检测超时、安排处理事件和函数回调来让系统处理一些其他事情,或者进入低功耗模式一段时间,在这之后恢复执行。

[置顶] STM32移植contiki进阶之三(中):timer 中文版的更多相关文章

  1. 【转】hurry_liu 大神STM32移植contiki入门之一:系统介绍和开发环境搭建

    前言: 由于项目的原因,需要在LPC1788(STM32 cortex-M3)上面跑contiki. 之前没有涉及到contiki,不知其为何物.不过这个不是难事,做IT的,每每遇到新事物,都不会处理 ...

  2. [置顶] 我的Android进阶之旅------>如何将Android源码导入Eclipse中来查看(非常实用)

    Android源码下载完成的目录结构如如所示: step1:将.classpath文件拷贝到源代码的根目录 Android源码支持多种IDE,如果是针对APP层做开发的话,建议大家使用Eclipse开 ...

  3. [置顶] 我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书

    Android应用开发接入各种SDK时会发现,有很多SDK是需要靠package name和的证书指纹SHA1码来识别的,如百度地图SDK.这样如果使用默认自动生成的debug的话就会给开发调试工作带 ...

  4. [置顶] 我的Android进阶之旅------>介绍一款集录制与剪辑为一体的屏幕GIF 动画制作工具 GifCam

    由于上一篇文章:我的Android进阶之旅------>Android之动画之Frame Animation实例 中展示的是Frame动画效果,但是之前我是将图片截取下来,不好说明确切的动画过程 ...

  5. [置顶] 【玩转cocos2d-x之三十】点九图和输入框的使用

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/17297721 登录界面一个帐号/密码输入框或者主角命名框是少不了的.这节就来 ...

  6. [置顶] STM32的ADC1采集多条通道,可以不使用DMA功能吗?

    类似的问题 为什么我采集5条通道的电压,而采集到的值却都是第一条的呢? 我什么时候需要使用DMA功能? Ⅰ关于ADC的一些知识 STM32的ADC是一种12位逐次逼近型的模拟数字转换器.它有多达18条 ...

  7. [置顶] STM32 输入捕获的脉冲宽度及频率计算

    输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...

  8. [置顶] Ruby,Scala和JavaScript中的函数式编程(一)

    函数式编程(英语:Functional programming)或者函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象.函数编程语言最重要的 ...

  9. [置顶] LOAD语句:利用MSSQL中的xp_cmdshell功能,将指定文件夹下的指定文件,生成mysql的LOAD语句

    LOAD语句:利用MSSQL中的xp_cmdshell功能,将指定文件夹下的指定文件,生成mysql的LOAD语句 declare @sql varchar(4000), @dirpath varch ...

随机推荐

  1. 左右TextView旋转门问题

    最近由于旋转门问题的一个客户找我,当在字符25更多的时候是不是走了,后来,我在重现的问题,发现问题如下面: 问题1.人物25几个月之内可以去. 问题2.在人物25个月,虽然比屏幕宽度,不去 问题3.屏 ...

  2. Android SDK Manager 无法更新SDK

    Android SDK Manager 被墙后无法更新SDK 下载sdk时抛出错误:Failed to fetch URL http://dl-ssl.google.com/ 參考例如以下博客: ht ...

  3. Qt - 与众不同的电子时钟

     Qt的电子时钟是个老掉牙的demo了,但是利用lcdNumber显示的样子非常老土(下图第一个显示效果),一看就知道是从qt帮助文档里摘出来的example,毫无新意. 美化一下系统时钟,抛开固有控 ...

  4. python实现websocket服务器,可以在web实时显示远程服务器日志

    一.开始的话 使用python简单的实现websocket服务器,可以在浏览器上实时显示远程服务器的日志信息. 之前做了一个web版的发布系统,但没实现在线看日志,每次发布版本后,都需要登录到服务器上 ...

  5. Android Studio使用教程(一)

    今年的Google全球开发者大会虽然没有新的Android系统和设备,但是还是推出了一些不错的产品,Android Studio就是其中之一.这个基于Intellij IDEA开发的Android I ...

  6. Vi操作技巧

    Vi操作技巧: :nu    显示当前所在行的行号 :set nu    显示全部行号 :set nonu        取消显示行号 /字符串    查询字符串,按n查询下一个,按N查询上一个 持续 ...

  7. DateBox( 日期输入框) 组件

    本节课重点了解 EasyUI 中 DateBox(日期输入框)组件的使用方法,这个组件依赖于 Combo(自定义下拉框)和 Calendar(日历). 一. 加载方式//class 加载方式<i ...

  8. 路由器密码破解工具 Hydra 7.5

    之前只在 Browser 中保存了路由管理密码,无奈升级时管理的密码丢失了,又不想重新设置,所以尝试破解登录密码. 使用破解工具 Hydra 7.5. # hydra -l username -x : ...

  9. Android material design support library -- CollapsingToolbarLayout简介

    本文是codetrick上material design support library教程的第三篇,主要讲的是CollapsingToolbarLayout的概念和应用方法. 原文链接:Materi ...

  10. <display:table>属性解释

    参考官方网站:http://www.displaytag.org/1.2/displaytag/tagreference.html 所有属性: cellpadding,cellspacing,clas ...