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
Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
{
clock_time_t nextEtimer;
rtimer_clock_t nextRtimer;
simProcessRunValue = 0;
/* Let all simulation interfaces act first */
@ -403,21 +400,11 @@ Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
doActionsAfterTick();
/* Do we have any pending timers */
simEtimerPending = etimer_pending() || rtimer_arch_pending();
if(!simEtimerPending) {
return;
}
simEtimerPending = etimer_pending();
/* Save nearest expiration time */
nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime;
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;
}
simEtimerNextExpirationTime = etimer_next_expiration_time();
}
/*---------------------------------------------------------------------------*/
/**

View file

@ -200,8 +200,8 @@ typedef unsigned short uip_stats_t;
#define CLOCK_CONF_SECOND 1000L
typedef unsigned long clock_time_t;
typedef unsigned long rtimer_clock_t;
#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b)))
typedef uint64_t rtimer_clock_t;
#define RTIMER_CLOCK_DIFF(a,b) ((int64_t)((a)-(b)))
#define RADIO_DELAY_BEFORE_TX 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
Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
{
clock_time_t nextEtimer;
rtimer_clock_t nextRtimer;
simProcessRunValue = 0;
/* Let all simulation interfaces act first */
@ -479,21 +476,11 @@ Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj)
doActionsAfterTick();
/* Do we have any pending timers */
simEtimerPending = etimer_pending() || rtimer_arch_pending();
if(!simEtimerPending) {
return;
}
simEtimerPending = etimer_pending();
/* Save nearest expiration time */
nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime;
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;
}
simEtimerNextExpirationTime = etimer_next_expiration_time();
}
/*---------------------------------------------------------------------------*/
/**

View file

@ -40,7 +40,7 @@ char simDontFallAsleep = 0;
int simProcessRunValue;
int simEtimerPending;
clock_time_t simNextExpirationTime;
clock_time_t simEtimerNextExpirationTime;
void doActionsBeforeTick() {
// 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
extern int simProcessRunValue;
extern int simEtimerPending;
extern clock_time_t simNextExpirationTime;
extern clock_time_t simEtimerNextExpirationTime;
extern clock_time_t simCurrentTime;
// Variable that when set to != 0, stops the mote from falling asleep next tick

View file

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

View file

@ -36,7 +36,10 @@
#include "contiki-conf.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);
int rtimer_arch_check(void);

View file

@ -52,8 +52,11 @@ import org.contikios.cooja.mote.memory.VarMemory;
* Contiki variables:
* <ul>
* <li>clock_time_t simCurrentTime
* <li>clock_time_t simNextExpirationTime
* <li>int simProcessRunValue
* <li>rtimer_clock_t simRtimerCurrentTicks
* <li>clock_time_t simEtimerNextExpirationTime
* <li>rtimer_clock_t simEtimerNextExpirationTime
* <li>int simEtimerProcessRunValue
* <li>int simRtimerProcessRunValue
* <li>int simEtimerPending
* </ul>
*
@ -125,16 +128,24 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
public void doActionsBeforeTick() {
/* Update time */
setTime(mote.getSimulation().getSimulationTime() + timeDrift);
long currentSimulationTime = simulation.getSimulationTime();
setTime(currentSimulationTime + timeDrift);
moteMem.setInt64ValueOf("simRtimerCurrentTicks", currentSimulationTime);
}
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 */
int processRunValue = moteMem.getIntValueOf("simProcessRunValue");
if (processRunValue != 0) {
/* Handle next Contiki event in one millisecond */
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND);
mote.scheduleNextWakeup(currentSimulationTime + Simulation.MILLISECOND);
return;
}
@ -144,15 +155,20 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB
return;
}
/* Request tick next wakeup time */
int nextExpirationTime = moteMem.getIntValueOf("simNextExpirationTime");
if (nextExpirationTime <= 0) {
/*logger.warn("Event timer already expired, but has been delayed: " + nextExpirationTime);*/
mote.scheduleNextWakeup(simulation.getSimulationTime() + Simulation.MILLISECOND);
return;
/* Request tick next wakeup time for Etimer */
long etimerNextExpirationTime = (long)moteMem.getInt32ValueOf("simEtimerNextExpirationTime") * Simulation.MILLISECOND;
long etimerTimeToNextExpiration = etimerNextExpirationTime - moteTime;
if (etimerTimeToNextExpiration <= 0) {
/* logger.warn(mote.getID() + ": Event timer already expired, but has been delayed: " + etimerTimeToNextExpiration); */
/* 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);
}