diff --git a/tos/chips/cc2420/lpl/DefaultLplC.nc b/tos/chips/cc2420/lpl/DefaultLplC.nc index b18b08a5ff..27fa975359 100644 --- a/tos/chips/cc2420/lpl/DefaultLplC.nc +++ b/tos/chips/cc2420/lpl/DefaultLplC.nc @@ -79,11 +79,7 @@ implementation { SubReceive = DefaultLplP.SubReceive; SubSend = DefaultLplP.SubSend; - - MainC.SoftwareInit -> DefaultLplP; - - - DefaultLplP.SplitControlState -> PowerCycleC.SplitControlState; + DefaultLplP.SubControlState -> PowerCycleC.SplitControlState; DefaultLplP.RadioPowerState -> PowerCycleC.RadioPowerState; DefaultLplP.SendState -> SendStateC; DefaultLplP.OffTimer -> OffTimerC; diff --git a/tos/chips/cc2420/lpl/DefaultLplP.nc b/tos/chips/cc2420/lpl/DefaultLplP.nc index 4c5c63b489..47517baf4c 100644 --- a/tos/chips/cc2420/lpl/DefaultLplP.nc +++ b/tos/chips/cc2420/lpl/DefaultLplP.nc @@ -38,6 +38,7 @@ * and performing receive detections. * * @author David Moss + * @author Marcin K Szczodrak - preventing Lpl getting stuck after shutdown */ #include "Lpl.h" @@ -46,7 +47,6 @@ module DefaultLplP { provides { - interface Init; interface LowPowerListening; interface Send; interface Receive; @@ -63,7 +63,7 @@ module DefaultLplP { interface PacketAcknowledgements; interface State as SendState; interface State as RadioPowerState; - interface State as SplitControlState; + interface State as SubControlState; interface Timer as OffTimer; interface Timer as SendDoneTimer; interface Random; @@ -80,9 +80,6 @@ implementation { /** The length of the current send message */ uint8_t currentSendLen; - /** TRUE if the radio is duty cycling and not always on */ - bool dutyCycling; - /** * Radio Power State */ @@ -114,12 +111,6 @@ implementation { void initializeSend(); void startOffTimer(); - /***************** Init Commands ***************/ - command error_t Init.init() { - dutyCycling = FALSE; - return SUCCESS; - } - /***************** LowPowerListening Commands ***************/ /** * Set this this node's radio wakeup interval, in milliseconds. @@ -167,7 +158,8 @@ implementation { * signal receive() more than once for that message. */ command error_t Send.send(message_t *msg, uint8_t len) { - if(call SplitControlState.getState() == S_OFF) { + if(call SubControlState.isState(S_OFF) || + call SubControlState.isState(S_TURNING_OFF)) { // Everything is off right now, start SplitControl and try again return EOFF; } @@ -190,7 +182,6 @@ implementation { return SUCCESS; } - return EBUSY; } @@ -265,6 +256,17 @@ implementation { } event void SubControl.stopDone(error_t error) { + /* This check distinguishes the LPL sleep interval from + * the whole AM radio stack stop + */ + if(call SubControlState.isState(S_OFF) || + call SubControlState.isState(S_TURNING_OFF)) { + call OffTimer.stop(); + call SendDoneTimer.stop(); + call SendState.toIdle(); + return; + } + if(!error) { if(call SendState.getState() == S_LPL_FIRST_MESSAGE @@ -281,11 +283,23 @@ implementation { /***************** SubSend Events ***************/ event void SubSend.sendDone(message_t* msg, error_t error) { - + /* Prevent resending routine when the radio AM + * is getting completely turned off + */ + if(call SubControlState.isState(S_OFF) || + call SubControlState.isState(S_TURNING_OFF)) { + signal Send.sendDone(msg, error); + return; + } + switch(call SendState.getState()) { case S_LPL_SENDING: if(call SendDoneTimer.isRunning()) { - if(!call PacketAcknowledgements.wasAcked(msg)) { + if(call PowerCycle.getSleepInterval() > 0 && + !call PacketAcknowledgements.wasAcked(msg)) { + /* Continue resending when duty-cycling and when last + * message was not acknowledged. + */ post resend(); return; } @@ -302,7 +316,6 @@ implementation { default: break; } - call SendState.toIdle(); call SendDoneTimer.stop(); startOffTimer(); @@ -329,9 +342,9 @@ implementation { * Only stop the radio if the radio is supposed to be off permanently * or if the duty cycle is on and our sleep interval is not 0 */ - if(call SplitControlState.getState() == S_OFF - || (call PowerCycle.getSleepInterval() > 0 - && call SplitControlState.getState() != S_OFF + if(call SubControlState.getState() == S_OFF + || (call PowerCycle.getSleepInterval() > 0 + && call SubControlState.getState() != S_OFF && call SendState.getState() == S_LPL_NOT_SENDING)) { post stopRadio(); } @@ -368,6 +381,10 @@ implementation { } task void resend() { + if(call SubControlState.isState(S_OFF) || + call SubControlState.isState(S_TURNING_OFF)) { + return; + } if(call Resend.resend(TRUE) != SUCCESS) { post resend(); } @@ -389,8 +406,8 @@ implementation { /***************** Functions ***************/ void initializeSend() { - if(call LowPowerListening.getRemoteWakeupInterval(currentSendMsg) - > ONE_MESSAGE) { + if(call PowerCycle.getSleepInterval() > 0 && + call LowPowerListening.getRemoteWakeupInterval(currentSendMsg) > ONE_MESSAGE) { if((call CC2420PacketBody.getHeader(currentSendMsg))->dest == IEEE154_BROADCAST_ADDR) { call PacketAcknowledgements.noAck(currentSendMsg); @@ -408,7 +425,9 @@ implementation { void startOffTimer() { - call OffTimer.startOneShot(call SystemLowPowerListening.getDelayAfterReceive()); + if (call PowerCycle.getSleepInterval() > 0) { + call OffTimer.startOneShot(call SystemLowPowerListening.getDelayAfterReceive()); + } } }