四、callback timer 回调计时器(ctimer)
Callback timer(回调计时器)
Contiki system
ctimer模块提供了一个计时器机制(机制)调用指定的C函数ctimer什么时候到期。
Files
file ctimer.c
ctimer实现
file ctimer.h
ctimer的头文件
Functions
Initialize the callback timer library.
初始化回调计时器库。
void ctimer_set (struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
//Set a callback timer.
//设置ctimer
void ctimer_reset (struct ctimer *c)
//Reset a callback timer with the same interval as was previously set.
//重置一个ctimer,其间隔与前面设置的相同。
void ctimer_restart (struct ctimer *c)
//Restart a callback timer from the current point in time.
//从当前时间点重新启动一个ctimer。
void ctimer_stop (struct ctimer *c)
//Stop a pending callback timer.
//停止挂起的ctimer。
int ctimer_expired (struct ctimer *c)
//Check if a callback timer has expired(过期).
//检查是否一个回调计时器过期了
Detailed Description
ctimer模块提供了一个计时器机制调用指定的C函数ctimer什么时候到期。
Function Documentation
int ctimer_expired ( struct ctimer * c )
//检查ctimer是否已过期。
参数:
c 指向ctimer的指针
Returns:
0 正常
非0 过期
此函数测试ctimer是否已过期,并根据其状态返回true或false。
void ctimer_init ( void )
//初始化ctimer。
此函数初始化回调计时器库,并应从系统引导代码中调用。
void ctimer_reset ( struct ctimer * c )
//重置一个ctimer,其间隔与前面设置的相同。
参数:
c 指向ctimer的指针
此函数使用与ctimer_set()函数给定的回调计时器相同的间隔重置回调计时器。间隔的起始点是回调计时器最后过期的确切时间。因此,与ctimer_restart()函数不同,此函数将使计时器随时间保持稳定。
间隔的起始点是回调计时器上次过期的确切时间。因此,此函数将导致计时器随着时间的推移而稳定,
void ctimer_restart ( struct ctimer * c )
//从当前时间点重新启动一个ctimer。
// 同间隔立即重启
Parameters:
c 指向ctimer的指针
此函数使用与ctimer_set()函数相同的间隔重新启动ctimer。ctimer将在当前时间启动。
Note:
一个周期运行的定时器将漂移如果这个函数是用来重置它。对于周期性计时器,可以使用ctimer_reset()函数。
void ctimer_set ( struct ctimer * c,
clock_time_t t,
void(*)(void *) f,
void * ptr
)
//设置ctimer
参数:
c 指向ctimer的指针
t 计时器到期前的时间间隔。
f 定时器过期时要调用的函数。
ptr 将作为回调函数的参数提供的不透明指针。
此函数用于设置将来某个时间的回调计时器。当回调计时器过期时,将使用ptr作为参数调用回调函数f。
void ctimer_stop ( struct ctimer * c )
//停止等待(挂起的)回调计时器。
// 调用stop后定时器将会过期,不会调用回调函数
参数:
c 指向挂起的ctimer指针
此函数将停止之前使用ctimer_set()、ctimer_reset()或ctimer_restart()设置的回调计时器。调用此函数后,回调计时器将过期,不会调用回调函数。
下面是etimer.c的源文件
/**
00002 * \addtogroup etimer
00003 * @{
00004 */
00005
00006 /**
00007 * \file
00008 * Event timer library implementation.
00009 * \author
00010 * Adam Dunkels <adam@sics.se>
00011 */
00012
00013 /*
00014 * Copyright (c) 2004, Swedish Institute of Computer Science.
00015 * All rights reserved.
00016 *
00017 * Redistribution and use in source and binary forms, with or without
00018 * modification, are permitted provided that the following conditions
00019 * are met:
00020 * 1. Redistributions of source code must retain the above copyright
00021 * notice, this list of conditions and the following disclaimer.
00022 * 2. Redistributions in binary form must reproduce the above copyright
00023 * notice, this list of conditions and the following disclaimer in the
00024 * documentation and/or other materials provided with the distribution.
00025 * 3. Neither the name of the Institute nor the names of its contributors
00026 * may be used to endorse or promote products derived from this software
00027 * without specific prior written permission.
00028 *
00029 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00030 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00031 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00032 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00033 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00034 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00035 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00036 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00037 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00038 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00039 * SUCH DAMAGE.
00040 *
00041 * This file is part of the Contiki operating system.
00042 *
00043 * Author: Adam Dunkels <adam@sics.se>
00044 *
00045 * $Id: etimer.c,v 1.3 2007/10/07 19:59:27 joxe Exp $
00046 */
00047
00048 #include "contiki-conf.h"
00049
00050 #include "sys/etimer.h"
00051 #include "sys/process.h"
00052
00053 static struct etimer *timerlist;
00054 static clock_time_t next_expiration; //expiration 截止日期
00055
00056 PROCESS(etimer_process, "Event timer");
00057 /*---------------------------------------------------------------------------*/
00058 static void
00059 update_time(void)
00060 {
00061 clock_time_t tdist;
00062 clock_time_t now;
00063 struct etimer *t;
00064
00065 if (timerlist == NULL) {
00066 next_expiration = 0;
00067 } else {
00068 now = clock_time();
00069 t = timerlist;
00070 /* Must calculate distance to next time into account due to wraps(包装) */
00071 tdist = t->timer.start + t->timer.interval - now;
00072 for(t = t->next; t != NULL; t = t->next) {
00073 if(t->timer.start + t->timer.interval - now < tdist) {
00074 tdist = t->timer.start + t->timer.interval - now;
00075 }
00076 }
00077 next_expiration = now + tdist;
00078 }
00079 }
00080 /*---------------------------------------------------------------------------*/
00081 PROCESS_THREAD(etimer_process, ev, data)
00082 {
00083 struct etimer *t, *u;
00084
00085 PROCESS_BEGIN();
00086
00087 timerlist = NULL;
00088
00089 while(1) {
00090 PROCESS_YIELD(); //生成当前正在运行的进程。
00091
00092 if(ev == PROCESS_EVENT_EXITED) {
00093 struct process *p = data;
00094
00095 while(timerlist != NULL && timerlist->p == p) {
00096 timerlist = timerlist->next;
00097 }
00098
00099 if(timerlist != NULL) {
00100 t = timerlist;
00101 while(t->next != NULL) {
00102 if(t->next->p == p) {
00103 t->next = t->next->next;
00104 } else
00105 t = t->next;
00106 }
00107 }
00108 continue;
00109 } else if(ev != PROCESS_EVENT_POLL) {
00110 continue;
00111 }
00112
00113 again:
00114
00115 u = NULL;
00116
00117 for(t = timerlist; t != NULL; t = t->next) {
00118 if(timer_expired(&t->timer)) {
00119 if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) {
00120
00121 /* Reset the process ID of the event timer, to signal that the
00122 etimer has expired. This is later checked in the
00123 etimer_expired() function. */
00124 t->p = PROCESS_NONE;
00125 if(u != NULL) {
00126 u->next = t->next;
00127 } else {
00128 timerlist = t->next;
00129 }
00130 t->next = NULL;
00131 update_time();
00132 goto again;
00133 } else {
00134 etimer_request_poll();
00135 }
00136 }
00137 u = t;
00138 }
00139
00140 }
00141
00142 PROCESS_END();
00143 }
00144 /*---------------------------------------------------------------------------*/
00145 void
00146 etimer_request_poll(void)
00147 {
00148 process_poll(&etimer_process);
00149 }
00150 /*---------------------------------------------------------------------------*/
00151 static void
00152 add_timer(struct etimer *timer)
00153 {
00154 struct etimer *t;
00155
00156 etimer_request_poll();
00157
00158 if(timer->p != PROCESS_NONE) {
00159 /* Timer not on list. */
00160
00161 for(t = timerlist; t != NULL; t = t->next) {
00162 if(t == timer) {
00163 /* Timer already on list, bail out. */
00164 update_time();
00165 return;
00166 }
00167 }
00168 }
00169
00170 timer->p = PROCESS_CURRENT();
00171 timer->next = timerlist;
00172 timerlist = timer;
00173
00174 update_time();
00175 }
00176 /*---------------------------------------------------------------------------*/
00177 void
00178 etimer_set(struct etimer *et, clock_time_t interval)
00179 {
00180 timer_set(&et->timer, interval);
00181 add_timer(et);
00182 }
00183 /*---------------------------------------------------------------------------*/
00184 void
00185 etimer_reset(struct etimer *et)
00186 {
00187 timer_reset(&et->timer);
00188 add_timer(et);
00189 }
00190 /*---------------------------------------------------------------------------*/
00191 void
00192 etimer_restart(struct etimer *et)
00193 {
00194 timer_restart(&et->timer);
00195 add_timer(et);
00196 }
00197 /*---------------------------------------------------------------------------*/
00198 void
00199 etimer_adjust(struct etimer *et, int timediff)
00200 {
00201 et->timer.start += timediff;
00202 update_time();
00203 }
00204 /*---------------------------------------------------------------------------*/
00205 int
00206 etimer_expired(struct etimer *et)
00207 {
00208 return et->p == PROCESS_NONE;
00209 }
00210 /*---------------------------------------------------------------------------*/
00211 clock_time_t
00212 etimer_expiration_time(struct etimer *et)
00213 {
00214 return et->timer.start + et->timer.interval;
00215 }
00216 /*---------------------------------------------------------------------------*/
00217 clock_time_t
00218 etimer_start_time(struct etimer *et)
00219 {
00220 return et->timer.start;
00221 }
00222 /*---------------------------------------------------------------------------*/
00223 int
00224 etimer_pending(void)
00225 {
00226 return timerlist != NULL;
00227 }
00228 /*---------------------------------------------------------------------------*/
00229 clock_time_t
00230 etimer_next_expiration_time(void)
00231 {
00232 return etimer_pending() ? next_expiration : 0;
00233 }
00234 /*---------------------------------------------------------------------------*/
00235 void
00236 etimer_stop(struct etimer *et)
00237 {
00238 struct etimer *t;
00239
00240 /* First check if et is the first event timer on the list. */
00241 if(et == timerlist) {
00242 timerlist = timerlist->next;
00243 update_time();
00244 } else {
00245 /* Else walk through the list and try to find the item before the
00246 et timer. */
00247 for(t = timerlist; t != NULL && t->next != et; t = t->next);
00248
00249 if(t != NULL) {
00250 /* We've found the item before the event timer that we are about
00251 to remove. We point the items next pointer to the event after
00252 the removed item. */
00253 t->next = et->next;
00254
00255 update_time();
00256 }
00257 }
00258
00259 /* Remove the next pointer from the item to be removed. */
00260 et->next = NULL;
00261 /* Set the timer as expired */
00262 et->p = PROCESS_NONE;
00263 }
00264 /*---------------------------------------------------------------------------*/
00265 /** @} */
五、event timer 事件计时器(etimer)
etimer提供了一种方法来生成的事件。
Data Structures
struct etimer
A timer. More...
Files
file etimer.c
etimer库的实现
file etimer.h
etimer库的头文件
Functions called from application programs
void etimer_set (struct etimer *et, clock_time_t interval)
//Set an event timer.
//设置etimer
void etimer_reset (struct etimer *et)
//Reset an event timer with the same interval as was previously set.
//重置etimer,其间隔与前面设置的相同。
void etimer_restart (struct etimer *et)
//Restart an event timer from the current point in time.
//从当前时间点重新启动etimer。
void etimer_adjust (struct etimer *et, int td)
//Adjust the expiration time for an event timer.
//调整etimer的过期时间。
int etimer_expired (struct etimer *et)
// Check if an event timer has expired.
//检查etimer是否已过期。
clock_time_t etimer_expiration_time (struct etimer *et)
//Get the expiration time for the event timer.
//获取etimer的过期时间。
clock_time_t etimer_start_time (struct etimer *et)
//Get the start time for the event timer.
//获取etimer的开始时间。
void etimer_stop (struct etimer *et)
//Stop a pending event timer.
//停止挂起的事件计时器。
Functions called from timer interrupts, by the system
由系统从定时器中断中调用的函数
void etimer_request_poll (void)
//Make the event timer aware that the clock has changed.
//使etimer知道时钟已更改。
int etimer_pending (void)
//Check if there are any non-expired event timers.
//检查是否有任何未过期的etimer。
clock_time_t etimer_next_expiration_time (void)
//Get next event timer expiration time.
//获取下一个etimer过期时间。
Detailed Description
事件计时器提供了生成定时事件的方法。
事件计时器将向在事件计时器过期时设置计时器的进程发送事件。
事件计时器被声明为struct etimer,所有对事件计时器的访问都是通过指向声明的事件计时器的指针来完成的。
See also:
Simple timer library
Clock library (used by the timer library)
Function Documentation
void etimer_adjust ( struct etimer * et,
int td
)
//调整etimer的过期时间。
参数:
et 指向etimer的指针
td 用来调整到期时间的时差。
此函数用于调整事件计时器到期的时间。它可以用于同步周期性计时器,而不需要重新启动计时器或更改计时器间隔。
Note:
这个功能应该只用于小的调整。对于较大的调整,可以使用etimer_set()。
除非使用etimer_reset()函数,否则周期性计时器将会偏移。
clock_time_t etimer_expiration_time ( struct etimer * et )
//获取etimer的过期时间。
Parameters:
et 指向etimer的指针
Returns:
事件计时器的过期时间。
此函数返回事件计时器的过期时间。
CCIF int etimer_expired ( struct etimer * et )
//检查事件计时器是否已过期。
Parameters:
et 指向etimer的指针
Returns:
如果计时器已过期,则为非零,否则为零。
此函数测试事件计时器是否已过期,并根据其状态返回true或false。
clock_time_t etimer_next_expiration_time ( void )
//获取下一个事件计时器过期时间。
Returns:
所有挂起事件计时器的下一次过期时间。如果没有等待事件计时器,这个函数将返回0。
此函数将返回所有挂起事件计时器的下一个过期时间。
int etimer_pending ( void )
//检查是否有任何未过期的事件计时器。
Returns:
如果有活动事件计时器,则为真;如果没有活动计时器,则为假。
此函数检查是否有活动事件计时器未过期。
void etimer_request_poll ( void )
//使事件计时器知道时钟已更改。
此函数用于通知事件计时器模块系统时钟已更新。通常,当时钟滴答响时,会从定时器中断处理程序调用此函数。
CCIF void etimer_reset ( struct etimer * et )
//重置事件计时器,其间隔与前面设置的相同。
Parameters:
et 指向etimer的指针
此函数使用etimer_set()函数为事件计时器指定的相同间隔重置事件计时器。间隔的起始点是事件计时器最后过期的确切时间。因此,与etimer_restart()函数不同,此函数将使计时器随时间保持稳定。
void etimer_restart ( struct etimer * et )
//从当前时间点重新启动事件计时器。
Parameters:
et 指向etimer的指针
该函数使用与etimer_set()函数相同的间隔重新启动事件计时器。事件计时器将在当前时间启动。
Note:
如果使用此函数重置,则周期计时器将偏移。对于周期性计时器,可以使用etimer_reset()函数。
CCIF void etimer_set ( struct etimer * et,
clock_time_t interval
//Set an etimer
)
Parameters:
et 指向etimer的指针
interval 计时器到期前的时间间隔。
此函数用于设置将来某个时间的事件计时器。当事件计时器过期时,事件PROCESS_EVENT_TIMER将被发送到调用etimer_set()函数的进程。
clock_time_t etimer_start_time ( struct etimer * et )
//获取事件计时器的开始时间。
Parameters:
et 指向etimer的指针
Returns:
事件计时器的启动时间。
此函数返回事件计时器的开始时间(上一次设置计时器时的时间)。
void etimer_stop ( struct etimer * et )
//停止挂起的事件计时器。
Parameters:
et 指向挂起事件计时器的指针。
此函数将停止先前使用etimer_set()或etimer_reset()设置的事件计时器。调用此函数后,事件计时器在过期时将不发出任何事件。
实例宣布 暂时分析etimer用法
/*
* Copyright (c) 2009, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* $Id: example-announcement.c,v 1.3 2011/01/07 23:23:31 nvt-se Exp $
*/
/**
* \file
* Example code that uses the annuncement module
* \author
* Adam Dunkels <adam@sics.se>
*/
#include "contiki.h"
#include "net/rime.h"
#include "net/rime/announcement.h"
#include <stdio.h>
#if CONTIKI_TARGET_NETSIM
#include "ether.h"
#endif
/*---------------------------------------------------------------------------*/
PROCESS(example_announcement_process, "Example announcement process");
AUTOSTART_PROCESSES(&example_announcement_process);
/*---------------------------------------------------------------------------*/
static void
received_announcement(struct announcement *a, const rimeaddr_t *from,
uint16_t id, uint16_t value)
{
/* We set our own announced value to one plus that of our neighbor. */
//我们将自己的值设置为1加上邻居的值。
announcement_set_value(a, value + 1);
printf("Got announcement from %d.%d, id %d, value %d, our new value is %d\n",
from->u8[0], from->u8[1], id, value, value + 1);
#if CONTIKI_TARGET_NETSIM
{
char buf[8];
sprintf(buf, "%d", value + 1);
ether_set_text(buf);
}
#endif
}
static struct announcement example_announcement;
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_announcement_process, ev, data)
{
PROCESS_EXITHANDLER(announcement_remove(&example_announcement);)
PROCESS_BEGIN();
/* Register an announcement with ID 128. We provide the
'received_announcement' function pointer so that this function
will be called when a announcements from neighbors are heard. */
announcement_register(&example_announcement,
128,
received_announcement);
/* Set the lowest eight bytes of the Rime address as the value. */
announcement_set_value(&example_announcement, rimeaddr_node_addr.u8[0]);
while(1) {
static struct etimer et;
/* Listen for announcements every ten seconds. */
//每十秒监听一次
etimer_set(&et, CLOCK_SECOND * 10);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
announcement_listen(1);
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/