contiki学习笔记(五)ctimer和etimer

四、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();
}
/*---------------------------------------------------------------------------*/

版权声明:本文为qq_39549987原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。