Reimplement Rtimer of Cooja mote as a microsecond resolution timer

This commit is contained in:
Yasuyuki Tanaka 2016-09-06 15:14:10 +02:00
parent 0201208664
commit 6d51c5f58e
8 changed files with 55 additions and 71 deletions

View file

@ -376,9 +376,6 @@ Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory(JNIEnv *env, jobject obj,
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj) Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
{ {
clock_time_t nextEtimer;
rtimer_clock_t nextRtimer;
simProcessRunValue = 0; simProcessRunValue = 0;
/* Let all simulation interfaces act first */ /* Let all simulation interfaces act first */
@ -403,21 +400,11 @@ Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
doActionsAfterTick(); doActionsAfterTick();
/* Do we have any pending timers */ /* Do we have any pending timers */
simEtimerPending = etimer_pending() || rtimer_arch_pending(); simEtimerPending = etimer_pending();
if(!simEtimerPending) {
return;
}
/* Save nearest expiration time */ /* Save nearest expiration time */
nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime; simEtimerNextExpirationTime = etimer_next_expiration_time();
nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime;
if(etimer_pending() && rtimer_arch_pending()) {
simNextExpirationTime = MIN(nextEtimer, nextRtimer);
} else if(etimer_pending()) {
simNextExpirationTime = nextEtimer;
} else if(rtimer_arch_pending()) {
simNextExpirationTime = nextRtimer;
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**

View file

@ -200,8 +200,8 @@ typedef unsigned short uip_stats_t;
#define CLOCK_CONF_SECOND 1000L #define CLOCK_CONF_SECOND 1000L
typedef unsigned long clock_time_t; typedef unsigned long clock_time_t;
typedef unsigned long rtimer_clock_t; typedef uint64_t rtimer_clock_t;
#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #define RTIMER_CLOCK_DIFF(a,b) ((int64_t)((a)-(b)))
#define RADIO_DELAY_BEFORE_TX 0 #define RADIO_DELAY_BEFORE_TX 0
#define RADIO_DELAY_BEFORE_RX 0 #define RADIO_DELAY_BEFORE_RX 0

View file

@ -452,9 +452,6 @@ Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory(JNIEnv *env, jobject obj,
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj) Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
{ {
clock_time_t nextEtimer;
rtimer_clock_t nextRtimer;
simProcessRunValue = 0; simProcessRunValue = 0;
/* Let all simulation interfaces act first */ /* Let all simulation interfaces act first */
@ -479,21 +476,11 @@ Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
doActionsAfterTick(); doActionsAfterTick();
/* Do we have any pending timers */ /* Do we have any pending timers */
simEtimerPending = etimer_pending() || rtimer_arch_pending(); simEtimerPending = etimer_pending();
if(!simEtimerPending) {
return;
}
/* Save nearest expiration time */ /* Save nearest expiration time */
nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime; simEtimerNextExpirationTime = etimer_next_expiration_time();
nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime;
if(etimer_pending() && rtimer_arch_pending()) {
simNextExpirationTime = MIN(nextEtimer, nextRtimer);
} else if(etimer_pending()) {
simNextExpirationTime = nextEtimer;
} else if(rtimer_arch_pending()) {
simNextExpirationTime = nextRtimer;
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**

View file

@ -40,7 +40,7 @@ char simDontFallAsleep = 0;
int simProcessRunValue; int simProcessRunValue;
int simEtimerPending; int simEtimerPending;
clock_time_t simNextExpirationTime; clock_time_t simEtimerNextExpirationTime;
void doActionsBeforeTick() { void doActionsBeforeTick() {
// Poll all interfaces to do their thing before the tick // Poll all interfaces to do their thing before the tick

View file

@ -42,7 +42,7 @@ struct simInterface {
// Variable for keeping the last process_run() return value // Variable for keeping the last process_run() return value
extern int simProcessRunValue; extern int simProcessRunValue;
extern int simEtimerPending; extern int simEtimerPending;
extern clock_time_t simNextExpirationTime; extern clock_time_t simEtimerNextExpirationTime;
extern clock_time_t simCurrentTime; extern clock_time_t simCurrentTime;
// Variable that when set to != 0, stops the mote from falling asleep next tick // Variable that when set to != 0, stops the mote from falling asleep next tick

View file

@ -48,46 +48,44 @@
#define PRINTF(...) #define PRINTF(...)
#endif #endif
extern clock_time_t simCurrentTime; /* COOJA */
int simRtimerPending;
static int pending_rtimer = 0; rtimer_clock_t simRtimerNextExpirationTime;
static rtimer_clock_t next_rtimer = 0; rtimer_clock_t simRtimerCurrentTicks;
static clock_time_t last_rtimer_now = 0;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
rtimer_arch_init(void) rtimer_arch_init(void)
{ {
next_rtimer = 0; simRtimerNextExpirationTime = 0;
last_rtimer_now = 0; simRtimerPending = 0;
pending_rtimer = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
rtimer_arch_schedule(rtimer_clock_t t) rtimer_arch_schedule(rtimer_clock_t t)
{ {
next_rtimer = t; simRtimerNextExpirationTime = t;
pending_rtimer = 1; simRtimerPending = 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
rtimer_clock_t rtimer_clock_t
rtimer_arch_next(void) rtimer_arch_next(void)
{ {
return next_rtimer; return simRtimerNextExpirationTime;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
rtimer_arch_pending(void) rtimer_arch_pending(void)
{ {
return pending_rtimer; return simRtimerPending;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
rtimer_arch_check(void) rtimer_arch_check(void)
{ {
if (simCurrentTime == next_rtimer) { if (simRtimerCurrentTicks == simRtimerNextExpirationTime) {
/* Execute rtimer */ /* Execute rtimer */
pending_rtimer = 0; simRtimerPending = 0;
rtimer_run_next(); rtimer_run_next();
return 1; return 1;
} }
@ -97,14 +95,7 @@ rtimer_arch_check(void)
rtimer_clock_t rtimer_clock_t
rtimer_arch_now(void) rtimer_arch_now(void)
{ {
if(last_rtimer_now == simCurrentTime) { return simRtimerCurrentTicks;
/* Yield to COOJA, to allow time to change */
simProcessRunValue = 1;
simNextExpirationTime = simCurrentTime + 1;
cooja_mt_yield();
}
last_rtimer_now = simCurrentTime;
return simCurrentTime;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -36,7 +36,10 @@
#include "contiki-conf.h" #include "contiki-conf.h"
#include "sys/clock.h" #include "sys/clock.h"
#define RTIMER_ARCH_SECOND CLOCK_CONF_SECOND #define RTIMER_ARCH_SECOND UINT64_C(1000000)
#define US_TO_RTIMERTICKS(US) (US)
#define RTIMERTICKS_TO_US(T) (T)
rtimer_clock_t rtimer_arch_now(void); rtimer_clock_t rtimer_arch_now(void);
int rtimer_arch_check(void); int rtimer_arch_check(void);

View file

@ -52,8 +52,11 @@ import org.contikios.cooja.mote.memory.VarMemory;
* Contiki variables: * Contiki variables:
* <ul> * <ul>
* <li>clock_time_t simCurrentTime * <li>clock_time_t simCurrentTime
* <li>clock_time_t simNextExpirationTime * <li>rtimer_clock_t simRtimerCurrentTicks
* <li>int simProcessRunValue * <li>clock_time_t simEtimerNextExpirationTime
* <li>rtimer_clock_t simEtimerNextExpirationTime
* <li>int simEtimerProcessRunValue
* <li>int simRtimerProcessRunValue
* <li>int simEtimerPending * <li>int simEtimerPending
* </ul> * </ul>
* *
@ -125,16 +128,24 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
public void doActionsBeforeTick() { public void doActionsBeforeTick() {
/* Update time */ /* Update time */
setTime(mote.getSimulation().getSimulationTime() + timeDrift); long currentSimulationTime = simulation.getSimulationTime();
setTime(currentSimulationTime + timeDrift);
moteMem.setInt64ValueOf("simRtimerCurrentTicks", currentSimulationTime);
} }
public void doActionsAfterTick() { public void doActionsAfterTick() {
long currentSimulationTime = mote.getSimulation().getSimulationTime();
/* Always schedule for Rtimer if anything pending */
if (moteMem.getIntValueOf("simRtimerPending") != 0) {
mote.scheduleNextWakeup(moteMem.getInt64ValueOf("simRtimerNextExpirationTime"));
}
/* Request next tick for remaining events / timers */ /* Request next tick for remaining events / timers */
int processRunValue = moteMem.getIntValueOf("simProcessRunValue"); int processRunValue = moteMem.getIntValueOf("simProcessRunValue");
if (processRunValue != 0) { if (processRunValue != 0) {
/* Handle next Contiki event in one millisecond */ /* Handle next Contiki event in one millisecond */
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND); mote.scheduleNextWakeup(currentSimulationTime + Simulation.MILLISECOND);
return; return;
} }
@ -144,15 +155,20 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
return; return;
} }
/* Request tick next wakeup time */ /* Request tick next wakeup time for Etimer */
int nextExpirationTime = moteMem.getIntValueOf("simNextExpirationTime"); long etimerNextExpirationTime = (long)moteMem.getInt32ValueOf("simEtimerNextExpirationTime") * Simulation.MILLISECOND;
if (nextExpirationTime <= 0) { long etimerTimeToNextExpiration = etimerNextExpirationTime - moteTime;
/*logger.warn("Event timer already expired, but has been delayed: " + nextExpirationTime);*/ if (etimerTimeToNextExpiration <= 0) {
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND); /* logger.warn(mote.getID() + ": Event timer already expired, but has been delayed: " + etimerTimeToNextExpiration); */
return; /* Wake up in one millisecond to handle a missed Etimer task
* which may be blocked by busy waiting such as one in
* radio_send(). Scheduling it in a shorter time than one
* millisecond, e.g., one microsecond, seems to be worthless and
* it would cause unnecessary CPU usage. */
mote.scheduleNextWakeup(currentSimulationTime + Simulation.MILLISECOND);
} else {
mote.scheduleNextWakeup(currentSimulationTime + etimerTimeToNextExpiration);
} }
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND*nextExpirationTime);
} }