Reimplement Rtimer of Cooja mote as a microsecond resolution timer
This commit is contained in:
parent
0201208664
commit
6d51c5f58e
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue