⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trickletimerimplp.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
// $Id: TrickleTimerImplP.nc,v 1.5 2007/07/30 00:42:00 scipio Exp $/* * "Copyright (c) 2006 Stanford University. All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose, without fee, and without written * agreement is hereby granted, provided that the above copyright * notice, the following two paragraphs and the author appear in all * copies of this software. *  * IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY * HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS." *//* * Module that provides a service instance of trickle timers. For * details on the working of the parameters, please refer to Levis et * al., "A Self-Regulating Algorithm for Code Maintenance and * Propagation in Wireless Sensor Networks," NSDI 2004. * * @param l Lower bound of the time period in seconds. * @param h Upper bound of the time period in seconds. * @param k Redundancy constant. * @param count How many timers to provide. * * @author Philip Levis * @author Gilman Tolle * @date   Jan 7 2006 */ #include <Timer.h>generic module TrickleTimerImplP(uint16_t low,				 uint16_t high,				 uint8_t k,				 uint8_t count,				 uint8_t scale) {  provides {    interface Init;    interface TrickleTimer[uint8_t id];  }  uses {    interface Timer<TMilli>;    interface BitVector as Pending;    interface BitVector as Changed;    interface Random;    interface Leds;  }}implementation {  typedef struct {    uint16_t period;    uint32_t time;    uint32_t remainder;    uint8_t count;  } trickle_t;  trickle_t trickles[count];    void adjustTimer();  void generateTime(uint8_t id);    command error_t Init.init() {    int i;    for (i = 0; i < count; i++) {      trickles[i].period = high;      trickles[i].count = 0;      trickles[i].time = 0;      trickles[i].remainder = 0;    }    atomic {      call Pending.clearAll();      call Changed.clearAll();    }    return SUCCESS;  }  /**   * Start a trickle timer. Reset the counter to 0.   */  command error_t TrickleTimer.start[uint8_t id]() {    if (trickles[id].time != 0) {      return EBUSY;    }    trickles[id].time = 0;    trickles[id].remainder = 0;    trickles[id].count = 0;    generateTime(id);    atomic {      call Changed.set(id);    }    adjustTimer();    dbg("Trickle", "Starting trickle timer %hhu @ %s\n", id, sim_time_string());    return SUCCESS;  }  /**   * Stop the trickle timer. This call sets the timer period to H.   */  command void TrickleTimer.stop[uint8_t id]() {    trickles[id].time = 0;    trickles[id].period = high;    adjustTimer();    dbg("Trickle", "Stopping trickle timer %hhu @ %s\n", id, sim_time_string());  }  /**   * Reset the timer period to L. If called while the timer is running,   * then a new interval (of length L) begins immediately.   */  command void TrickleTimer.reset[uint8_t id]() {    trickles[id].period = low;    trickles[id].count = 0;    if (trickles[id].time != 0) {      dbg("Trickle", "Resetting running trickle timer %hhu @ %s\n", id, sim_time_string());      atomic {	call Changed.set(id);      }      trickles[id].time = 0;      trickles[id].remainder = 0;      generateTime(id);      adjustTimer();    } else {      dbg("Trickle", "Resetting  trickle timer %hhu @ %s\n", id, sim_time_string());    }  }  /**   * Increment the counter C. When an interval ends, C is set to 0.   */  command void TrickleTimer.incrementCounter[uint8_t id]() {    trickles[id].count++;  }  task void timerTask() {    uint8_t i;    for (i = 0; i < count; i++) {      bool fire = FALSE;      atomic {	if (call Pending.get(i)) {	  call Pending.clear(i);	  fire = TRUE;	}      }      if (fire) {	dbg("Trickle", "Firing trickle timer %hhu @ %s\n", i, sim_time_string());	signal TrickleTimer.fired[i]();	post timerTask();	return;      }    }  }    /**   * The trickle timer has fired. Signaled if C &gt; K.   */  event void Timer.fired() {    uint8_t i;    uint32_t dt = call Timer.getdt();    for (i = 0; i < count; i++) {      uint32_t remaining = trickles[i].time;      if (remaining != 0) {	remaining -= dt;	if (remaining == 0) {	  if (trickles[i].count < k) {	    atomic {	      call Pending.set(i);	    }	    post timerTask();	  }	  generateTime(i);	    	  /* Note that this logic is not the exact trickle algorithm.	   * Rather than C being reset at the beginning of an interval,	   * it is being reset at a firing point. This means that the	   * listening period, rather than of length tau/2, is in the	   * range [tau/2, tau]. 	   */	  trickles[i].count = 0;	}	else {	  trickles[i].time = remaining;	}      }    }    adjustTimer();  }  // This is where all of the work is done!  void adjustTimer() {    uint8_t i;    uint32_t lowest = 0;    bool set = FALSE;    // How much time has elapsed on the current timer    // since it was scheduled? This value is needed because    // the time remaining of a running timer is its time    // value minus time elapsed.    uint32_t elapsed = (call Timer.getNow() - call Timer.gett0());	    for (i = 0; i < count; i++) {      uint32_t timeRemaining = trickles[i].time;      if (timeRemaining != 0) {	atomic {	  if (!call Changed.get(i)) {	    call Changed.clear(i);	    timeRemaining -= elapsed;	  }	}	if (!set) {	  lowest = timeRemaining;	  set = TRUE;	}	else if (timeRemaining < lowest) {	  lowest = timeRemaining;	}      }    }    if (set) {      uint32_t timerVal = lowest;      timerVal = timerVal;      dbg("Trickle", "Starting time with time %u.\n", timerVal);      call Timer.startOneShot(timerVal);    }    else {      call Timer.stop();    }  }  /* Generate a new firing time for a timer. if the timer was already   * running (time != 0), then double the period.   */  void generateTime(uint8_t id) {    uint32_t newTime;    uint16_t rval;        if (trickles[id].time != 0) {      trickles[id].period *= 2;      if (trickles[id].period > high) {	trickles[id].period = high;      }    }        trickles[id].time = trickles[id].remainder;        newTime = trickles[id].period;    newTime = newTime << (scale - 1);    rval = call Random.rand16() % (trickles[id].period << (scale - 1));    newTime += rval;        trickles[id].remainder = (trickles[id].period << scale) - newTime;    trickles[id].time += newTime;    dbg("Trickle,TrickleTimes", "Generated time for %hhu with period %hu (%u) is %u (%i + %hu)\n", id, trickles[id].period, (uint32_t)trickles[id].period << scale, trickles[id].time, (trickles[id].period << (scale - 1)), rval);  } default event void TrickleTimer.fired[uint8_t id]() {   return; }}  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -