From: janhauer Date: Tue, 25 Nov 2008 09:35:08 +0000 (+0000) Subject: + modified radio driver (PHY) interfaces: CSMA-CA algorithm is now pushed to radio... X-Git-Tag: rc_6_tinyos_2_1_1~562 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=82c215ff867ea7ef4fa748fb72b686c32ffb25e1 + modified radio driver (PHY) interfaces: CSMA-CA algorithm is now pushed to radio driver + adapted CC2420 driver + renamed CsmaP -> FrameDispatchP + provided workaround for a problem with virtualized alarms (sometimes they seem to fire 2s too late) + updated placeholder components + updated debug information --- diff --git a/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc b/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc index 7688a55e..edeebfe6 100644 --- a/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc +++ b/tos/chips/cc2420_tkn154/CC2420AsyncSplitControl.nc @@ -73,57 +73,33 @@ */ /** - * An async version of the SplitControl interface. + * This interface is a mixture of a SplitControl/AsyncStdControl interface. * @author Jan Hauer */ interface CC2420AsyncSplitControl { /** - * Start this component and all of its subcomponents. Return - * values of SUCCESS will always result in a startDone() - * event being signalled. + * Start this component and all of its subcomponents. * - * @return SUCCESS if the device is already in the process of - * starting or the device was off and the device is now ready to turn - * on. After receiving this return value, you should expect a - * startDone event in the near future.
- * EBUSY if the component is in the middle of powering down - * i.e. a stop() command has been called, - * and a stopDone() event is pending
- * EALREADY if the device is already on
+ * @return SUCCESS if the component was started successfully.
* FAIL Otherwise */ async command error_t start(); - /** - * Notify caller that the component has been started and is ready to - * receive other commands. - * - * @param error -- SUCCESS if the component was successfully - * turned on, FAIL otherwise - */ - async event void startDone(error_t error); - /** - * Start this component and all of its subcomponents. Return - * values of SUCCESS will always result in a startDone() - * event being signalled. + * Stop this component and all of its subcomponents - iff this command + * succeeds then stopDone will signal the result of the stop + * operation. * - * @return SUCCESS if the device is already in the process of - * stopping or the device was on and the device is now ready to turn - * off. After receiving this return value, you should expect a - * stopDone event in the near future.
- * EBUSY if the component is in the middle of powering up - * i.e. a start() command has been called, - * and a startDone() event is pending
- * EALREADY if the device is already off
- * FAIL Otherwise + * @return SUCCESS Stop operation was started, stopDone will be signalled + * FAIL Otherwise (stopDone will not be signalled) */ async command error_t stop(); /** - * Notify caller that the component has been stopped. + * Notify caller that the component has been stopped. This event + * completes the stop() operation. * * @param error -- SUCCESS if the component was successfully * turned off, FAIL otherwise diff --git a/tos/chips/cc2420_tkn154/CC2420ControlP.nc b/tos/chips/cc2420_tkn154/CC2420ControlP.nc index 64e4adf8..6b8eac0d 100644 --- a/tos/chips/cc2420_tkn154/CC2420ControlP.nc +++ b/tos/chips/cc2420_tkn154/CC2420ControlP.nc @@ -33,7 +33,7 @@ * @author Jonathan Hui * @author David Moss * @author Urs Hunkeler (ReadRssi implementation) - * @author Jan Hauer (support for promiscuous mode) + * @author Jan Hauer * @version $Revision$ $Date$ */ @@ -53,6 +53,7 @@ module CC2420ControlP { uses interface GeneralIO as RSTN; uses interface GeneralIO as VREN; uses interface GpioInterrupt as InterruptCCA; + uses interface GeneralIO as FIFO; uses interface CC2420Ram as IEEEADR; uses interface CC2420Register as FSCTRL; @@ -62,11 +63,14 @@ module CC2420ControlP { uses interface CC2420Register as MDMCTRL1; uses interface CC2420Register as RXCTRL1; uses interface CC2420Register as RSSI; + uses interface CC2420Register as RXFIFO_REGISTER; + uses interface CC2420Strobe as SNOP; uses interface CC2420Strobe as SRXON; uses interface CC2420Strobe as SRFOFF; uses interface CC2420Strobe as SXOSCOFF; uses interface CC2420Strobe as SXOSCON; - uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set + uses interface CC2420Strobe as SACKPEND; + uses interface CC2420Strobe as SFLUSHRX; uses interface CC2420Register as TXCTRL; uses interface AMPacket; @@ -122,6 +126,12 @@ implementation { } /***************** Resource Commands ****************/ + /* This module never actively requests the SPI resource, + * instead the caller MUST request the SPI through this module + * before it calls any of the provided commands and it must + * release it afterwards (the caller can call multiple + * commands in this module before it releases the SPI, though). + */ async command error_t Resource.immediateRequest() { error_t error = call SpiResource.immediateRequest(); if ( error == SUCCESS ) { @@ -145,6 +155,11 @@ implementation { } } + event void SpiResource.granted() { +/* call CSN.clr();*/ + signal Resource.granted(); + } + void switchToUnbufferedMode() { uint16_t mdmctrol1; @@ -179,7 +194,7 @@ implementation { m_state = S_VREG_STARTING; } call VREN.set(); - call StartupAlarm.start( CC2420_TIME_VREN * 2 ); // JH: a 15.4 symbol is about two 32khz ticks + call StartupAlarm.start( CC2420_TIME_VREN * 2 ); // JH: changed from 32khz jiffies return SUCCESS; } @@ -241,32 +256,52 @@ implementation { async command error_t CC2420Power.rxOn() { atomic { - if ( m_state != S_XOSC_STARTED ) { + if ( !call SpiResource.isOwner() ) return FAIL; - } call CSN.set(); call CSN.clr(); call SRXON.strobe(); - call SACKPEND.strobe(); // JH: ACKs have the pending bit set + call SACKPEND.strobe(); // JH: ACKs need the pending bit set call CSN.set(); } return SUCCESS; } async command error_t CC2420Power.rfOff() { - atomic { - if ( m_state != S_XOSC_STARTED ) { + atomic { + if ( !call SpiResource.isOwner() ) return FAIL; - } call CSN.set(); call CSN.clr(); - call SACKPEND.strobe(); // JH: ACKs have the pending bit set call SRFOFF.strobe(); call CSN.set(); } return SUCCESS; } + async command error_t CC2420Power.flushRxFifo() + { + uint16_t dummy; + atomic { + if ( !call SpiResource.isOwner() ) + return FAIL; + if ( call FIFO.get() ){ // check if there is something in the RXFIFO + // SFLUSHRX: "Flush the RX FIFO buffer and reset the demodulator. + // Always read at least one byte from the RXFIFO before + // issuing the SFLUSHRX command strobe" (CC2420 Datasheet) + call CSN.clr(); + call RXFIFO_REGISTER.read(&dummy); // reading 1 byte would be enough... + call CSN.set(); + call CSN.clr(); + // "SFLUSHRX command strobe should be issued twice to ensure + // that the SFD pin goes back to its idle state." (CC2420 Datasheet) + call SFLUSHRX.strobe(); + call SFLUSHRX.strobe(); + call CSN.set(); + } + } + return SUCCESS; + } /***************** CC2420Config Commands ****************/ command uint8_t CC2420Config.getChannel() { @@ -367,13 +402,11 @@ implementation { * Sync must be called to commit software parameters configured on * the microcontroller (through the CC2420Config interface) to the * CC2420 radio chip. - * ASSUMPTION: caller owns the SPI, radio will be switched off ! */ async command error_t CC2420Config.sync() { atomic { - if ( m_state != S_XOSC_STARTED ) { + if ( !call SpiResource.isOwner() ) return FAIL; - } if (m_needsSync){ call CSN.set(); call CSN.clr(); @@ -396,29 +429,30 @@ implementation { /***************** ReadRssi Commands ****************/ async command error_t CC2420Power.rssi(int8_t *rssi) { - // we are owner of the Spi ! uint16_t data; cc2420_status_t status; - call CSN.clr(); - status = call RSSI.read(&data); - call CSN.set(); - if ((status & 0x02)){ - *rssi = (data & 0x00FF); - return SUCCESS; - } else - return FAIL; - } - - event void SpiResource.granted() { -/* call CSN.clr();*/ - signal Resource.granted(); + atomic { + if ( !call SpiResource.isOwner() ) + return FAIL; + call CSN.set(); + call CSN.clr(); + status = call RSSI.read(&data); + call CSN.set(); + if ((status & 0x02)){ + *rssi = (data & 0x00FF); + return SUCCESS; + } else + return FAIL; + } } - - /***************** StartupAlarm Events ****************/ async event void StartupAlarm.fired() { if ( m_state == S_VREG_STARTING ) { + cc2420_status_t status; + do { + status = call SNOP.strobe(); + } while (!(status & CC2420_STATUS_XOSC16M_STABLE)); m_state = S_VREG_STARTED; call RSTN.clr(); call RSTN.set(); diff --git a/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc b/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc index 76f8568e..83aa7d31 100644 --- a/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc +++ b/tos/chips/cc2420_tkn154/CC2420ControlTransmitC.nc @@ -86,6 +86,7 @@ implementation { CC2420ControlP.CSN -> Pins.CSN; CC2420ControlP.RSTN -> Pins.RSTN; CC2420ControlP.VREN -> Pins.VREN; + CC2420ControlP.FIFO -> Pins.FIFO; components HplCC2420InterruptsC as Interrupts; CC2420ControlP.InterruptCCA -> Interrupts.InterruptCCA; @@ -106,7 +107,10 @@ implementation { CC2420ControlP.TXCTRL -> Spi.TXCTRL; CC2420ControlP.IEEEADR -> Spi.IEEEADR; CC2420ControlP.RXCTRL1 -> Spi.RXCTRL1; + CC2420ControlP.SFLUSHRX-> Spi.SFLUSHRX; CC2420ControlP.RSSI -> Spi.RSSI; + CC2420ControlP.RXFIFO_REGISTER -> Spi.RXFIFO_REGISTER; + CC2420ControlP.SNOP -> Spi.SNOP; // CC2420TransmitC components CC2420TransmitP; diff --git a/tos/chips/cc2420_tkn154/CC2420Power.nc b/tos/chips/cc2420_tkn154/CC2420Power.nc index a213f31d..9d62b049 100644 --- a/tos/chips/cc2420_tkn154/CC2420Power.nc +++ b/tos/chips/cc2420_tkn154/CC2420Power.nc @@ -102,4 +102,12 @@ interface CC2420Power { * @return SUCCESS if RSSI was read successfulyy, FAIL otherwise. */ async command error_t rssi(int8_t *rssi); + + /** + * Flush the RXFIFO if it is not empty. + * Radio SHOULD be disabled (off) when calling this command. + * + * @return SUCCESS if fifo was flushed (or it was empty), FAIL otherwise. + */ + async command error_t flushRxFifo(); } diff --git a/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc b/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc index 04860924..4824d540 100644 --- a/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc +++ b/tos/chips/cc2420_tkn154/CC2420ReceiveP.nc @@ -42,7 +42,6 @@ module CC2420ReceiveP { provides interface CC2420AsyncSplitControl as AsyncSplitControl; provides interface CC2420Receive; provides interface CC2420Rx; -/* provides interface ReceiveIndicator as PacketIndicator;*/ uses interface GeneralIO as CSN; uses interface GeneralIO as FIFO; @@ -54,13 +53,12 @@ module CC2420ReceiveP { uses interface CC2420Strobe as SACK; uses interface CC2420Strobe as SFLUSHRX; uses interface CC2420Strobe as SRXON; - uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set + uses interface CC2420Strobe as SACKPEND; uses interface CC2420Register as MDMCTRL1; uses interface ReferenceTime; uses interface FrameUtility; uses interface CC2420Config; -/* uses interface CC2420Packet;*/ -/* uses interface CC2420PacketBody;*/ + uses interface CC2420Ram as RXFIFO_RAM; uses interface Leds; } @@ -70,7 +68,6 @@ implementation { typedef enum { S_STOPPED, S_STARTING, - S_STARTING_FLUSHRX, S_STARTED, S_RX_LENGTH, S_RX_FCF, @@ -125,7 +122,6 @@ implementation { void flush(); void switchToUnbufferedMode(); void switchToBufferedMode(); - void startingSpiReserved(); void continueStart(); void continueStop(); task void stopContinueTask(); @@ -139,79 +135,48 @@ implementation { return SUCCESS; } - /***************** AsyncSplitControl **************** - * IMPORTANT: when AsyncSplitControl.start is called, - * the radio MUST be off ! + /***************** AsyncSplitControl ****************/ + /* NOTE: AsyncSplitControl does not switch the state of the radio + * hardware (i.e. it does not put the radio in Rx mode, this has to + * be done by the caller through a separate interface/component). + */ + + /** + * AsyncSplitControl.start should be called before radio + * is switched to Rx mode (or at least early enough before + * a packet has been received, i.e. before FIFOP changes) */ async command error_t AsyncSplitControl.start() { atomic { + if ( !call FIFO.get() && !call FIFOP.get() ){ + // RXFIFO has some data (remember: FIFOP is inverted) + // the problem is that this messses up the timestamping + // so why don't we flush here ourselves? + // because we don't own the SPI... + return FAIL; + } if (m_state != S_STOPPED){ call Leds.led0On(); return FAIL; - } else { - m_state = S_STARTING; - if (call SpiResource.isOwner()){ - call Leds.led0On(); // internal error (debug) ! - startingSpiReserved(); - } - if (call SpiResource.immediateRequest() == SUCCESS) - startingSpiReserved(); - else - call SpiResource.request(); } - } - return SUCCESS; - } - - void startingSpiReserved() - { - atomic { - if (!call FIFOP.get() || call FIFO.get()){ // FIFOP is inverted - // there is something in RXFIFO: flush it out - // the datasheet says at least one byte should - // be read before flushing - m_state = S_STARTING_FLUSHRX; - call CSN.set(); - call CSN.clr(); - call RXFIFO.beginRead( &m_dummy, 1 ); // will continue in continueFlushStart() - return; - } - } - continueStart(); - } - - - void continueFlushStart() - { - atomic { - call CSN.set(); - call CSN.clr(); - call SFLUSHRX.strobe(); - call SFLUSHRX.strobe(); - call CSN.set(); - } - continueStart(); - } - - void continueStart() - { - // RXFIFO is empty - if (!call FIFOP.get() || call FIFO.get()){ - call Leds.led0On(); - } - atomic { reset_state(); m_state = S_STARTED; + call InterruptFIFOP.enableFallingEdge(); // ready! } - call SpiResource.release(); - call InterruptFIFOP.enableFallingEdge(); - signal AsyncSplitControl.startDone(SUCCESS); + return SUCCESS; } - /***************** AsyncSplitControl **************** + /* AsyncSplitControl.stop: + * * IMPORTANT: when AsyncSplitControl.stop is called, - * the radio MUST NOT be off ! + * then either + * 1) the radio MUST still be in RxMode + * 2) it was never put in RxMode after + * AsyncSplitControl.start() was called + * + * => The radio may be switched off only *after* the + * stopDone() event was signalled. */ async command error_t AsyncSplitControl.stop() { @@ -222,9 +187,9 @@ implementation { m_stop = TRUE; call InterruptFIFOP.disable(); if (!receivingPacket) - continueStop(); - // else stopContinueTask will be posted after - // current Rx operation is finished, because m_stop is set + continueStop(); // it is safe to stop now + // else continueStop will be called after + // current Rx operation is finished } } return SUCCESS; @@ -233,6 +198,9 @@ implementation { void continueStop() { atomic { + if (!m_stop){ + return; + } m_stop = FALSE; m_state = S_STOPPED; } @@ -241,9 +209,8 @@ implementation { task void stopContinueTask() { - if (receivingPacket){ + if (receivingPacket) call Leds.led0On(); - } call SpiResource.release(); // may fail atomic m_state = S_STOPPED; signal AsyncSplitControl.stopDone(SUCCESS); @@ -314,10 +281,10 @@ implementation { atomic { switch (m_state) { - case S_STARTING: startingSpiReserved(); break; - case S_STARTING_FLUSHRX: // fall through - case S_STOPPED: call Leds.led0On(); - call SpiResource.release(); break; + case S_STOPPED: // this should never happen! + call Leds.led0On(); + call SpiResource.release(); + break; default: receive(); } } @@ -471,8 +438,6 @@ implementation { waitForNextPacket(); break; - case S_STARTING_FLUSHRX: continueFlushStart(); break; - default: atomic receivingPacket = FALSE; call CSN.set(); @@ -538,8 +503,7 @@ implementation { */ void beginReceive() { atomic { - if ( m_state == S_STOPPED){ - call Leds.led0On(); + if (m_state == S_STOPPED || m_stop){ return; } m_state = S_RX_LENGTH; @@ -591,11 +555,11 @@ implementation { */ void waitForNextPacket() { atomic { - receivingPacket = FALSE; if ( m_state == S_STOPPED) { call SpiResource.release(); return; } + receivingPacket = FALSE; if (m_stop){ continueStop(); return; diff --git a/tos/chips/cc2420_tkn154/CC2420SpiC.nc b/tos/chips/cc2420_tkn154/CC2420SpiC.nc new file mode 100644 index 00000000..7b7676c3 --- /dev/null +++ b/tos/chips/cc2420_tkn154/CC2420SpiC.nc @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2005-2006 Arch Rock Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * - Neither the name of the Arch Rock Corporation nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE + */ + +/** + * Implementation of basic SPI primitives for the ChipCon CC2420 radio. + * + * Jan Hauer: this component currently shadows + * tinyos-2.x/tos/chips/cc2420/spi/CC2420SpiC.nc because the latter + * does not (yet) provide access to the RXFIFO via the CC2420Register + * interface. As soon as it does, this file should be removed. + * + * @author Jonathan Hui + * @version $Revision$ $Date$ + */ + +generic configuration CC2420SpiC() { + + provides interface Resource; + provides interface ChipSpiResource; + + // commands + provides interface CC2420Strobe as SNOP; + provides interface CC2420Strobe as SXOSCON; + provides interface CC2420Strobe as STXCAL; + provides interface CC2420Strobe as SRXON; + provides interface CC2420Strobe as STXON; + provides interface CC2420Strobe as STXONCCA; + provides interface CC2420Strobe as SRFOFF; + provides interface CC2420Strobe as SXOSCOFF; + provides interface CC2420Strobe as SFLUSHRX; + provides interface CC2420Strobe as SFLUSHTX; + provides interface CC2420Strobe as SACK; + provides interface CC2420Strobe as SACKPEND; + provides interface CC2420Strobe as SRXDEC; + provides interface CC2420Strobe as STXENC; + provides interface CC2420Strobe as SAES; + + // registers + provides interface CC2420Register as MAIN; + provides interface CC2420Register as MDMCTRL0; + provides interface CC2420Register as MDMCTRL1; + provides interface CC2420Register as RSSI; + provides interface CC2420Register as SYNCWORD; + provides interface CC2420Register as TXCTRL; + provides interface CC2420Register as RXCTRL0; + provides interface CC2420Register as RXCTRL1; + provides interface CC2420Register as FSCTRL; + provides interface CC2420Register as SECCTRL0; + provides interface CC2420Register as SECCTRL1; + provides interface CC2420Register as BATTMON; + provides interface CC2420Register as IOCFG0; + provides interface CC2420Register as IOCFG1; + provides interface CC2420Register as MANFIDL; + provides interface CC2420Register as MANFIDH; + provides interface CC2420Register as FSMTC; + provides interface CC2420Register as MANAND; + provides interface CC2420Register as MANOR; + provides interface CC2420Register as AGCCTRL; + provides interface CC2420Register as RXFIFO_REGISTER; + + // ram + provides interface CC2420Ram as IEEEADR; + provides interface CC2420Ram as PANID; + provides interface CC2420Ram as SHORTADR; + provides interface CC2420Ram as TXFIFO_RAM; + + // fifos + provides interface CC2420Fifo as RXFIFO; + provides interface CC2420Fifo as TXFIFO; + +} + +implementation { + + enum { + CLIENT_ID = unique( "CC2420Spi.Resource" ), + }; + + components HplCC2420PinsC as Pins; + components CC2420SpiWireC as Spi; + + ChipSpiResource = Spi.ChipSpiResource; + Resource = Spi.Resource[ CLIENT_ID ]; + + // commands + SNOP = Spi.Strobe[ CC2420_SNOP ]; + SXOSCON = Spi.Strobe[ CC2420_SXOSCON ]; + STXCAL = Spi.Strobe[ CC2420_STXCAL ]; + SRXON = Spi.Strobe[ CC2420_SRXON ]; + STXON = Spi.Strobe[ CC2420_STXON ]; + STXONCCA = Spi.Strobe[ CC2420_STXONCCA ]; + SRFOFF = Spi.Strobe[ CC2420_SRFOFF ]; + SXOSCOFF = Spi.Strobe[ CC2420_SXOSCOFF ]; + SFLUSHRX = Spi.Strobe[ CC2420_SFLUSHRX ]; + SFLUSHTX = Spi.Strobe[ CC2420_SFLUSHTX ]; + SACK = Spi.Strobe[ CC2420_SACK ]; + SACKPEND = Spi.Strobe[ CC2420_SACKPEND ]; + SRXDEC = Spi.Strobe[ CC2420_SRXDEC ]; + STXENC = Spi.Strobe[ CC2420_STXENC ]; + SAES = Spi.Strobe[ CC2420_SAES ]; + + // registers + MAIN = Spi.Reg[ CC2420_MAIN ]; + MDMCTRL0 = Spi.Reg[ CC2420_MDMCTRL0 ]; + MDMCTRL1 = Spi.Reg[ CC2420_MDMCTRL1 ]; + RSSI = Spi.Reg[ CC2420_RSSI ]; + SYNCWORD = Spi.Reg[ CC2420_SYNCWORD ]; + TXCTRL = Spi.Reg[ CC2420_TXCTRL ]; + RXCTRL0 = Spi.Reg[ CC2420_RXCTRL0 ]; + RXCTRL1 = Spi.Reg[ CC2420_RXCTRL1 ]; + FSCTRL = Spi.Reg[ CC2420_FSCTRL ]; + SECCTRL0 = Spi.Reg[ CC2420_SECCTRL0 ]; + SECCTRL1 = Spi.Reg[ CC2420_SECCTRL1 ]; + BATTMON = Spi.Reg[ CC2420_BATTMON ]; + IOCFG0 = Spi.Reg[ CC2420_IOCFG0 ]; + IOCFG1 = Spi.Reg[ CC2420_IOCFG1 ]; + MANFIDL = Spi.Reg[ CC2420_MANFIDL ]; + MANFIDH = Spi.Reg[ CC2420_MANFIDH ]; + FSMTC = Spi.Reg[ CC2420_FSMTC ]; + MANAND = Spi.Reg[ CC2420_MANAND ]; + MANOR = Spi.Reg[ CC2420_MANOR ]; + AGCCTRL = Spi.Reg[ CC2420_AGCCTRL ]; + RXFIFO_REGISTER = Spi.Reg[ CC2420_RXFIFO ]; + + // ram + IEEEADR = Spi.Ram[ CC2420_RAM_IEEEADR ]; + PANID = Spi.Ram[ CC2420_RAM_PANID ]; + SHORTADR = Spi.Ram[ CC2420_RAM_SHORTADR ]; + TXFIFO_RAM = Spi.Ram[ CC2420_RAM_TXFIFO ]; + + // fifos + RXFIFO = Spi.Fifo[ CC2420_RXFIFO ]; + TXFIFO = Spi.Fifo[ CC2420_TXFIFO ]; + +} + diff --git a/tos/chips/cc2420_tkn154/CC2420TKN154P.nc b/tos/chips/cc2420_tkn154/CC2420TKN154P.nc index 2546253e..73e0a7d7 100644 --- a/tos/chips/cc2420_tkn154/CC2420TKN154P.nc +++ b/tos/chips/cc2420_tkn154/CC2420TKN154P.nc @@ -78,26 +78,30 @@ module CC2420TKN154P S_RESERVE_RX_SPI, S_RX_PREPARED, + S_RX_WAIT, S_RECEIVING, S_OFF_PENDING, S_LOAD_TXFIFO, S_TX_LOADED, + S_TX_WAIT, S_TX_ACTIVE, S_TX_CANCEL, S_TX_DONE, } m_state_t; norace m_state_t m_state = S_STOPPED; - norace ieee154_txframe_t *m_txdata; + norace ieee154_txframe_t *m_txframe; norace error_t m_txError; norace ieee154_reftime_t m_txReferenceTime; norace bool m_ackFramePending; uint32_t m_edDuration; bool m_pibUpdated; - uint8_t m_numCCA; + norace uint8_t m_numCCA; ieee154_reftime_t *m_t0Tx; - uint32_t m_dtTx; + uint32_t m_dtMax; + uint32_t m_dt; + norace ieee154_csma_t *m_csmaParams; norace uint8_t m_txLockOnCCAFail; norace bool m_rxAfterTx = FALSE; @@ -112,34 +116,20 @@ module CC2420TKN154P void rxSpiReserved(); void txSpiReserved(); void txDoneSpiReserved(); - void signalTxDone(); void finishTx(); void stopContinue(); void offSpiReserved(); void offStopRxDone(); - void continueTxPrepare(); + uint16_t generateRandomBackoff(uint8_t BE); + void randomDelayUnslottedCsmaCa(); + void randomDelaySlottedCsmaCa(bool resume, uint16_t remainingBackoff); + void sendDone(ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error); - /******************************/ - /* StdControl Operations */ - /******************************/ - - /****************************************/ - /* TelosB Pin connection (debug) */ - /* */ - /* R1 = P6.6 = ADC6, R2 = P6.7 = ADC7 */ - /* S1 = P2.3 = GIO2, S2 = P2.6 = GIO3 */ - /* R1 is at 6pin-expansion pin 1, */ - /* R2 is at 6pin-expansion pin 2, */ - /****************************************/ +/* ----------------------- StdControl Operations ----------------------- */ command error_t SplitControl.start() { - // debug - //P6SEL &= ~0xC0; // debug PIN: 6.6, 6.7, set to I/O function - //P6DIR |= 0xC0; // output - //P6OUT &= ~0xC0; // low - atomic { if (m_state == S_RADIO_OFF) return EALREADY; @@ -166,6 +156,7 @@ module CC2420TKN154P { // default configuration (addresses, etc) has been written call CC2420Power.rfOff(); + call CC2420Power.flushRxFifo(); call CC2420Tx.unlockChipSpi(); post startDoneTask(); } @@ -203,10 +194,9 @@ module CC2420TKN154P m_state = S_STOPPING; } if (m_state != S_STOPPING) - post stopTask(); // this will not happen, because the caller has switched radio off + post stopTask(); // spin - this should not happen, because the caller has switched radio off else - if (call RxControl.stop() == EALREADY) - stopContinue(); + stopContinue(); } void stopContinue() @@ -219,19 +209,28 @@ module CC2420TKN154P // we own the SPI bus atomic { call CC2420Power.rfOff(); - call CC2420Tx.unlockChipSpi(); - call TxControl.stop(); + call CC2420Power.flushRxFifo(); call CC2420Power.stopOscillator(); call CC2420Power.stopVReg(); + call CC2420Tx.unlockChipSpi(); call SpiResource.release(); m_state = S_STOPPED; signal SplitControl.stopDone(SUCCESS); } } - /*********************************/ - /* PIB Updates */ - /*********************************/ + uint16_t generateRandomBackoff(uint8_t BE) + { + // return random number from [0,(2^BE) - 1] (uniform distr.) + uint16_t res = call Random.rand16(); + uint16_t mask = 0xFFFF; + mask <<= BE; + mask = ~mask; + res &= mask; + return res; + } + +/* ----------------------- PIB Updates ----------------------- */ // input: power in dBm, output: PA_LEVEL parameter for cc2420 TXCTRL register uint8_t dBmToPA_LEVEL(int dBm) @@ -292,9 +291,7 @@ module CC2420TKN154P call CC2420Config.setPromiscuousMode(val); } - /*********************************/ - /* Energy Detection */ - /*********************************/ +/* ----------------------- Energy Detection ----------------------- */ command error_t EnergyDetection.start(uint32_t duration) { @@ -319,7 +316,7 @@ module CC2420TKN154P call CC2420Power.rxOn(); // reading an RSSI value over SPI will usually almost // take as much time as 8 symbols, i.e. there's - // no point using an Alarm here (but maybe a BusyWait?) + // no point using an Alarm here (but maybe a busy wait?) while (!call TimeCalc.hasExpired(start, m_edDuration)){ if (call CC2420Power.rssi(&value) != SUCCESS) continue; @@ -331,21 +328,33 @@ module CC2420TKN154P if (maxEnergy > -128) maxEnergy -= 45; call CC2420Power.rfOff(); + call CC2420Power.flushRxFifo(); m_state = S_RADIO_OFF; call SpiResource.release(); signal EnergyDetection.done(SUCCESS, maxEnergy); } - /****************************************/ - /* Transceiver Off */ - /****************************************/ +/* ----------------------- Transceiver Off ----------------------- */ + + task void spinOffTask() + { + uint8_t i; + call Leds.led2On(); call Leds.led1On(); + for (i=0; i<65500U; i++) ; + call Leds.led2Off(); call Leds.led1Off(); + for (i=0; i<65500U; i++) ; + call RadioOff.off(); + } async command error_t RadioOff.off() { atomic { if (m_state == S_RADIO_OFF) return EALREADY; - else if (m_state != S_RECEIVING && m_state != S_TX_LOADED && m_state != S_RX_PREPARED) + if (m_state == S_RX_WAIT || m_state == S_TX_WAIT){ + post spinOffTask(); + return SUCCESS; + } else if (m_state != S_RECEIVING && m_state != S_TX_LOADED && m_state != S_RX_PREPARED) return FAIL; m_state = S_OFF_PENDING; } @@ -367,7 +376,7 @@ module CC2420TKN154P { call TxControl.stop(); call CC2420Power.rfOff(); - call CC2420Config.sync(); // put any PIB updates into operation + call CC2420Power.flushRxFifo(); call CC2420Tx.unlockChipSpi(); call SpiResource.release(); m_state = S_RADIO_OFF; @@ -379,9 +388,7 @@ module CC2420TKN154P return m_state == S_RADIO_OFF; } - /****************************************/ - /* Receive Operations */ - /****************************************/ +/* ----------------------- Receive Operations ----------------------- */ async command error_t RadioRx.prepare() { @@ -392,26 +399,24 @@ module CC2420TKN154P return FAIL; m_state = S_RESERVE_RX_SPI; } - if (call RxControl.start() != SUCCESS){ // will trigger rxStartRxDone() + if (call RxControl.start() != SUCCESS){ m_state = S_RADIO_OFF; call Leds.led0On(); return FAIL; + } else { + if (call SpiResource.immediateRequest() == SUCCESS) // will trigger rxSpiReserved() + rxSpiReserved(); + else + call SpiResource.request(); } return SUCCESS; } - void rxStartRxDone() - { - if (call SpiResource.immediateRequest() == SUCCESS) // will trigger rxSpiReserved() - rxSpiReserved(); - else - call SpiResource.request(); - } - void rxSpiReserved() { call CC2420Config.sync(); // put PIB changes into operation - call TxControl.start(); // for timestamping + call TxControl.stop(); + call TxControl.start(); // for timestamping (SFD interrupt) m_state = S_RX_PREPARED; signal RadioRx.prepareDone(); // keep owning the SPI } @@ -428,8 +433,9 @@ module CC2420TKN154P call Leds.led0On(); return FAIL; } - if (t0 != NULL && dt) - call ReliableWait.waitRx(t0, dt); + m_state = S_RX_WAIT; + if (t0 != NULL) + call ReliableWait.waitRx(t0, dt); // will signal waitRxDone() in time else signal ReliableWait.waitRxDone(); } @@ -447,12 +453,12 @@ module CC2420TKN154P call SpiResource.release(); } - event message_t* CC2420Rx.received(message_t *data, ieee154_reftime_t *timestamp) + event message_t* CC2420Rx.received(message_t *frame, ieee154_reftime_t *timestamp) { if (m_state == S_RECEIVING) - return signal RadioRx.received(data, timestamp); + return signal RadioRx.received(frame, timestamp); else - return data; + return frame; } async command bool RadioRx.isReceiving() @@ -460,40 +466,28 @@ module CC2420TKN154P return m_state == S_RECEIVING; } - /******************************/ - /* Transmit Operations */ - /******************************/ +/* ----------------------- Transmit Operations ----------------------- */ async command error_t RadioTx.load(ieee154_txframe_t *frame) { - bool startRxControl; atomic { if (m_state != S_RADIO_OFF && m_state != S_TX_LOADED) return FAIL; - startRxControl = (m_state == S_RADIO_OFF); - m_txdata = frame; + m_txframe = frame; m_state = S_LOAD_TXFIFO; } - if (!startRxControl) - continueTxPrepare(); - else if (call RxControl.start() != SUCCESS) // will trigger continueTxPrepare() - call Leds.led0On(); - return SUCCESS; - } - - void continueTxPrepare() - { - if (call SpiResource.immediateRequest() == SUCCESS) + if (call SpiResource.isOwner() || call SpiResource.immediateRequest() == SUCCESS) txSpiReserved(); else call SpiResource.request(); // will trigger txSpiReserved() + return SUCCESS; } void txSpiReserved() { call CC2420Config.sync(); call TxControl.start(); - if (call CC2420Tx.loadTXFIFO(m_txdata) != SUCCESS) + if (call CC2420Tx.loadTXFIFO(m_txframe) != SUCCESS) call Leds.led0On(); } @@ -508,80 +502,228 @@ module CC2420TKN154P async command ieee154_txframe_t* RadioTx.getLoadedFrame() { if (m_state == S_TX_LOADED) - return m_txdata; + return m_txframe; else return NULL; } - async command error_t RadioTx.transmit(ieee154_reftime_t *t0, uint32_t dt, uint8_t numCCA, bool ackRequest) + async command error_t RadioTx.transmit(ieee154_reftime_t *t0, uint32_t dt) + { + // transmit without CCA + atomic { + if (m_state != S_TX_LOADED) + return FAIL; + m_numCCA = 0; + m_state = S_TX_WAIT; + if (t0 != NULL) + call ReliableWait.waitTx(t0, dt); // will signal waitTxDone() in time + else + signal ReliableWait.waitTxDone(); + } + return SUCCESS; + } + + void checkEnableRxForACK() + { + // the packet is currently being transmitted, check if we need the receive logic ready + bool ackRequest = (m_txframe->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST) ? TRUE : FALSE; + if (ackRequest){ + // ATTENTION: here the SpiResource is released if ACK is expected + // (so Rx part of the driver can take over) + call SpiResource.release(); + if (call RxControl.start() != SUCCESS) + call Leds.led0On(); + } + } + + async event void ReliableWait.waitTxDone() { + atomic { + m_state = S_TX_ACTIVE; + if (call CC2420Tx.send(FALSE) == SUCCESS) // transmit without CCA, this must succeed + checkEnableRxForACK(); + else + call Leds.led0On(); + } + } + + async command error_t RadioTx.transmitUnslottedCsmaCa(ieee154_csma_t *csmaParams) + { + // transmit with single CCA atomic { if (m_state != S_TX_LOADED) return FAIL; - m_numCCA = numCCA; - m_t0Tx = t0; - m_dtTx = dt; - if (numCCA){ - // for CCA we need to be in Rx mode - call CC2420Power.rxOn(); - call ReliableWait.busyWait(20); // turnaround + CCA valid time - if (numCCA == 2){ - // first CCA is done in software (8 symbols after backoff boundary) - if (t0 != NULL){ - call ReliableWait.waitCCA(t0, dt-IEEE154_aUnitBackoffPeriod-12); - return SUCCESS; - } + m_csmaParams = csmaParams; + m_numCCA = 1; + randomDelayUnslottedCsmaCa(); + } + return SUCCESS; + } + + void randomDelayUnslottedCsmaCa() + { + // wait random delay (unslotted CSMA-CA) + uint16_t dtTx = generateRandomBackoff(m_csmaParams->BE) * 20; + call ReferenceTime.getNow(m_t0Tx, 0); + m_state = S_TX_WAIT; + call ReliableWait.waitBackoff(m_t0Tx, dtTx); + } + + void waitBackoffUnslottedCsmaCaDone() + { + int8_t dummy; + atomic { + // CC2420 needs to be in an Rx state for STXONCCA strobe + // note: the receive logic of the CC2420 driver is not yet started, + // i.e. we will not (yet) receive any packets + call CC2420Power.rxOn(); + m_state = S_TX_ACTIVE; + // wait for CC2420 Rx to calibrate + CCA valid time + while (call CC2420Power.rssi(&dummy) != SUCCESS) + ; + // call ReliableWait.busyWait(40); + // transmit with single CCA (STXONCCA strobe) + if (call CC2420Tx.send(TRUE) == SUCCESS){ + checkEnableRxForACK(); + } else { + // channel is busy + call CC2420Power.rfOff(); + call CC2420Power.flushRxFifo(); // we might have (accidentally) caught something during CCA + m_state = S_TX_LOADED; + m_csmaParams->NB += 1; + if (m_csmaParams->NB > m_csmaParams->macMaxCsmaBackoffs){ + // CSMA-CA failure, note: we keep owning the SPI, + // our state is back to S_TX_LOADED, the MAC may try to retransmit + signal RadioTx.transmitUnslottedCsmaCaDone(m_txframe, FALSE, m_csmaParams, FAIL); + } else { + // next iteration of unslotted CSMA-CA + m_csmaParams->BE += 1; + if (m_csmaParams->BE > m_csmaParams->macMaxBE) + m_csmaParams->BE = m_csmaParams->macMaxBE; + randomDelayUnslottedCsmaCa(); } } - signal ReliableWait.waitCCADone(); + } + } + + async command error_t RadioTx.transmitSlottedCsmaCa(ieee154_reftime_t *slot0Time, uint32_t dtMax, + bool resume, uint16_t remainingBackoff, ieee154_csma_t *csmaParams) + { + // slotted CSMA-CA requires very exact timing (transmission on + // 320 us backoff boundary), even if we have a sufficiently precise and + // accurate clock the CC2420 is not the right radio for + // this task because it is accessed over SPI. The code below relies on + // platform-specific busy-wait functions that must be adjusted + // (through measurements) such that they meet the timing constraints + atomic { + if (m_state != S_TX_LOADED) + return FAIL; + m_csmaParams = csmaParams; + m_numCCA = 2; + m_t0Tx = slot0Time; + m_dtMax = dtMax; + randomDelaySlottedCsmaCa(resume, remainingBackoff); } return SUCCESS; } - async event void ReliableWait.waitCCADone() + void randomDelaySlottedCsmaCa(bool resume, uint16_t remainingBackoff) { - bool cca = call CC2420Tx.cca(); - if (m_numCCA == 2 && !cca){ - // channel is busy - ieee154_reftime_t now; - call ReferenceTime.getNow(&now, IEEE154_aUnitBackoffPeriod+12); - memcpy(&m_txReferenceTime, &now, sizeof(ieee154_reftime_t)); - m_ackFramePending = FALSE; - m_txError = EBUSY; - signalTxDone(); - return; - } else { - // the second CCA (or first CCA if there's only one) is done in hardware... - uint16_t offset = 0; - if (m_numCCA) - offset = 12; - if (m_t0Tx) - call ReliableWait.waitTx(m_t0Tx, m_dtTx-offset); + uint16_t dtTx; + atomic { + dtTx = call TimeCalc.timeElapsed(call ReferenceTime.toLocalTime(m_t0Tx), call LocalTime.get()); + dtTx += (20 - (dtTx % 20)); // round to backoff boundary + if (resume) + dtTx += remainingBackoff; else - signal ReliableWait.waitTxDone(); + dtTx = dtTx + (generateRandomBackoff(m_csmaParams->BE) * 20); + dtTx += 40; // two backoff periods for the two CCA, the actual tx is scheduled for = m_t0Tx + dtTx + if (dtTx > m_dtMax){ + uint16_t remaining = dtTx - m_dtMax; + if (remaining >= 40) + remaining -= 40; // substract the two CCA (they don't count for the backoff) + else + remaining = 0; + signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, NULL, FALSE, remaining, m_csmaParams, ERETRY); + } else { + m_state = S_TX_WAIT; + call ReliableWait.waitBackoff(m_t0Tx, dtTx); + } } } - async event void ReliableWait.waitTxDone() + void waitBackoffSlottedCsmaCaDone() + { + bool cca; + uint16_t dtTx=0; + int8_t dummy; + atomic { + // CC2420 needs to be in an Rx state for STXONCCA strobe + // note: the receive logic of the CC2420 driver is not yet started, + // i.e. we will not (yet) receive any packets + call CC2420Power.rxOn(); + m_state = S_TX_ACTIVE; + // wait for CC2420 Rx to calibrate + CCA valid time + while (call CC2420Power.rssi(&dummy) != SUCCESS) + ; + // perform CCA on slot boundary (or rather 8 symbols after) + call ReliableWait.busyWaitSlotBoundaryCCA(m_t0Tx, &dtTx); // platform-specific implementation + cca = call CC2420Tx.cca(); + if (cca && dtTx <= m_dtMax){ + // Tx in following slot (STXONCCA) + call ReliableWait.busyWaitSlotBoundaryTx(m_t0Tx, dtTx+20); // platform-specific implementation + if (call CC2420Tx.send(TRUE) == SUCCESS){ + checkEnableRxForACK(); + return; + } else + cca = FALSE; + } + // did not transmit the frame + call CC2420Power.rfOff(); + call CC2420Power.flushRxFifo(); // we might have (accidentally) caught something + m_state = S_TX_LOADED; + if (dtTx > m_dtMax) + // frame didn't fit into remaining CAP, this can only + // be because we couldn't meet the time-constraints + // (in principle the frame should have fitted) + signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, NULL, FALSE, 0, m_csmaParams, ERETRY); + else { + // CCA failed + m_csmaParams->NB += 1; + if (m_csmaParams->NB > m_csmaParams->macMaxCsmaBackoffs){ + // CSMA-CA failure, note: we keep owning the SPI + signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, NULL, FALSE, 0, m_csmaParams, FAIL); + } else { + // next iteration of slotted CSMA-CA + m_csmaParams->BE += 1; + if (m_csmaParams->BE > m_csmaParams->macMaxBE) + m_csmaParams->BE = m_csmaParams->macMaxBE; + randomDelaySlottedCsmaCa(FALSE, 0); + } + } + } + } + + async event void ReliableWait.waitBackoffDone() { - m_state = S_TX_ACTIVE; - call CC2420Tx.send(m_numCCA>0); // go (with or without CCA) ! + if (m_numCCA == 1) + waitBackoffUnslottedCsmaCaDone(); + else + waitBackoffSlottedCsmaCaDone(); } - async event void CC2420Tx.transmissionStarted( ieee154_txframe_t *data ) + async event void CC2420Tx.transmissionStarted( ieee154_txframe_t *frame ) { - uint8_t frameType = data->header->mhr[0] & FC1_FRAMETYPE_MASK; - uint8_t token = data->headerLen; - signal Timestamp.transmissionStarted(frameType, data->handle, data->payload, token); + uint8_t frameType = frame->header->mhr[0] & FC1_FRAMETYPE_MASK; + uint8_t token = frame->headerLen; + signal Timestamp.transmissionStarted(frameType, frame->handle, frame->payload, token); } - async event void CC2420Tx.transmittedSFD(uint32_t time, ieee154_txframe_t *data) + async event void CC2420Tx.transmittedSFD(uint32_t time, ieee154_txframe_t *frame) { - uint8_t frameType = data->header->mhr[0] & FC1_FRAMETYPE_MASK; - uint8_t token = data->headerLen; - signal Timestamp.transmittedSFD(time, frameType, data->handle, data->payload, token); - // ATTENTION: here we release the SPI, so we can receive a possible ACK - call SpiResource.release(); + uint8_t frameType = frame->header->mhr[0] & FC1_FRAMETYPE_MASK; + uint8_t token = frame->headerLen; + signal Timestamp.transmittedSFD(time, frameType, frame->handle, frame->payload, token); } async command void Timestamp.modifyMACPayload(uint8_t token, uint8_t offset, uint8_t* buf, uint8_t len ) @@ -593,15 +735,18 @@ module CC2420TKN154P async event void CC2420Tx.sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error) { - memcpy(&m_txReferenceTime, referenceTime, sizeof(ieee154_reftime_t)); - m_ackFramePending = ackPendingFlag; - m_txError = error; - if (error == EBUSY) // CCA failure, i.e. didn't transmit - signalTxDone(); - else - // reset radio + if (!call SpiResource.isOwner()){ + // this can only happen if an ack was requested and we gave up the SPI + bool wasAckRequested = (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST) ? TRUE : FALSE; + if (!wasAckRequested) + call Leds.led0On(); // internal error! + memcpy(&m_txReferenceTime, referenceTime, sizeof(ieee154_reftime_t)); + m_ackFramePending = ackPendingFlag; + m_txError = error; if (call RxControl.stop() != SUCCESS) // will trigger txDoneRxControlStopped() call Leds.led0On(); + } else + sendDone(referenceTime, ackPendingFlag, error); } void txDoneRxControlStopped() @@ -615,37 +760,43 @@ module CC2420TKN154P void txDoneSpiReserved() { - // switch radio off - call CC2420Power.rfOff(); - call TxControl.stop(); - call SpiResource.release(); // for RxControl.start to succeed - if (m_txError == SUCCESS) - signalTxDone(); - else { - call TxControl.start(); - call RxControl.start(); // will trigger txDoneRxControlStarted() - } + sendDone(&m_txReferenceTime, m_ackFramePending, m_txError); } - void txDoneRxControlStarted() + void sendDone(ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error) { - m_state = S_TX_DONE; - call SpiResource.request(); // will trigger signalTxDone() - } - - void signalTxDone() - { - // radio is off, Rx component is started, radio is loaded, we own the SPI - if (m_txError == SUCCESS) + uint8_t numCCA = m_numCCA; + // transmission complete, we're owning the SPI, Rx logic is disabled + call CC2420Power.rfOff(); + call CC2420Power.flushRxFifo(); + switch (error) + { + case SUCCESS: + m_state = S_RADIO_OFF; + break; + case ENOACK: + m_state = S_TX_LOADED; + break; + default: + call Leds.led0On(); // internal error! + break; + } + if (error == SUCCESS){ + call CC2420Tx.unlockChipSpi(); + call TxControl.stop(); + call SpiResource.release(); m_state = S_RADIO_OFF; - else + } else m_state = S_TX_LOADED; - signal RadioTx.transmitDone(m_txdata, &m_txReferenceTime, m_ackFramePending, m_txError); + if (numCCA == 0) + signal RadioTx.transmitDone(m_txframe, referenceTime); + else if (numCCA == 1) + signal RadioTx.transmitUnslottedCsmaCaDone(m_txframe, ackPendingFlag, m_csmaParams, error); + else + signal RadioTx.transmitSlottedCsmaCaDone(m_txframe, referenceTime, ackPendingFlag, 0, m_csmaParams, error); } - /*************/ - /* RxControl */ - /*************/ +/* ----------------------- RxControl ----------------------- */ async event void RxControl.stopDone(error_t error) { @@ -659,7 +810,6 @@ module CC2420TKN154P switch (m_state) { case S_OFF_PENDING: offStopRxDone(); break; - case S_RX_PREPARED: rxStartRxDone(); break; case S_TX_ACTIVE: txDoneRxControlStopped(); break; case S_STOPPING: stopContinue(); break; default: // huh ? @@ -667,21 +817,7 @@ module CC2420TKN154P } } - async event void RxControl.startDone(error_t error) - { - switch (m_state) - { - case S_RESERVE_RX_SPI: rxStartRxDone(); break; - case S_LOAD_TXFIFO: continueTxPrepare(); break; - case S_TX_ACTIVE: txDoneRxControlStarted(); break; - default: // huh ? - call Leds.led0On(); break; - } - } - - /***********************/ - /* SPI Bus Arbitration */ - /***********************/ +/* ----------------------- SPI Bus Arbitration ----------------------- */ event void SpiResource.granted() { @@ -693,7 +829,6 @@ module CC2420TKN154P case S_LOAD_TXFIFO: txSpiReserved(); break; case S_TX_ACTIVE: txDoneSpiReserved(); break; case S_STOPPING: stopReserved(); break; - case S_TX_DONE: signalTxDone(); break; case S_OFF_PENDING: offSpiReserved(); break; default: // huh ? call Leds.led0On(); break; diff --git a/tos/chips/cc2420_tkn154/CC2420TransmitP.nc b/tos/chips/cc2420_tkn154/CC2420TransmitP.nc index d746c854..87388ce9 100644 --- a/tos/chips/cc2420_tkn154/CC2420TransmitP.nc +++ b/tos/chips/cc2420_tkn154/CC2420TransmitP.nc @@ -34,6 +34,14 @@ * @author David Moss * @author Jung Il Choi Initial SACK implementation * @author Jan Hauer + * + * IMPORTANT: this module does not use the SPI Resource interface, + * instead the caller must take care of the resource arbitration + * (i.e. the caller must own the resource before calling commands + * like CC2420Tx.loadTXFIFO()) + * Note: on TelosB there seems to be a problem if BackoffAlarm + * is virtualized - i.e. BackoffAlarm should be a dedicated Alarm. + * * @version $Revision$ $Date$ */ @@ -45,21 +53,13 @@ module CC2420TransmitP { provides interface Init; provides interface AsyncStdControl; -/* interface CC2420Transmit;*/ provides interface CC2420Tx; -/* provides interface RadioBackoff;*/ -/* provides interface RadioTimeStamping as TimeStamp;*/ -/* provides interface ReceiveIndicator as EnergyIndicator;*/ -/* provides interface ReceiveIndicator as ByteIndicator;*/ - -/* uses interface Alarm as BackoffAlarm;*/ uses interface Alarm as BackoffAlarm; uses interface GpioCapture as CaptureSFD; uses interface GeneralIO as CCA; uses interface GeneralIO as CSN; uses interface GeneralIO as SFD; -/* uses interface Resource as SpiResource;*/ uses interface ChipSpiResource; uses interface CC2420Fifo as TXFIFO; uses interface CC2420Ram as TXFIFO_RAM; @@ -71,7 +71,7 @@ module CC2420TransmitP { uses interface CC2420Strobe as SRXON; uses interface CC2420Strobe as SRFOFF; uses interface CC2420Strobe as SFLUSHRX; - uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set + uses interface CC2420Strobe as SACKPEND; uses interface CC2420Register as MDMCTRL1; uses interface CaptureTime; uses interface ReferenceTime; @@ -86,25 +86,21 @@ implementation { S_STOPPED, S_STARTED, S_LOAD, - S_SAMPLE_CCA, - S_BEGIN_TRANSMIT, + S_READY_TX, S_SFD, S_EFD, S_ACK_WAIT, - S_CANCEL, } cc2420_transmit_state_t; - // This specifies how many jiffies the stack should wait after a + // This specifies how many symbols the stack should wait after a // TXACTIVE to receive an SFD interrupt before assuming something is // wrong and aborting the send. There seems to be a condition // on the micaZ where the SFD interrupt is never handled. enum { - CC2420_ABORT_PERIOD = 320 + CC2420_ABORT_PERIOD = 320*3, }; -/* norace message_t *m_msg;*/ - norace ieee154_txframe_t *m_data; - norace uint8_t m_txFrameLen; + norace ieee154_txframe_t *m_frame; ieee154_reftime_t m_timestamp; cc2420_transmit_state_t m_state = S_STOPPED; @@ -119,27 +115,16 @@ implementation { /** Let the CC2420 driver keep a lock on the SPI while waiting for an ack */ norace bool abortSpiRelease; - /** Total CCA checks that showed no activity before the NoAck LPL send */ - norace int8_t totalCcaChecks; - /** The initial backoff period */ norace uint16_t myInitialBackoff; /** The congestion backoff period */ norace uint16_t myCongestionBackoff; + norace uint32_t alarmStartTime; /***************** Prototypes ****************/ - error_t load( ieee154_txframe_t *data ); - error_t resend( bool cca ); - void loadTXFIFO(); - void attemptSend(bool cca); - void congestionBackoff(); - error_t acquireSpiResource(); - error_t releaseSpiResource(); -/* void signalDone( error_t err );*/ void signalDone( bool ackFramePending, error_t err ); -/* void cancelTx();*/ /***************** Init Commands *****************/ command error_t Init.init() { @@ -166,81 +151,90 @@ implementation { m_state = S_STOPPED; call BackoffAlarm.stop(); call CaptureSFD.disable(); -/* call SpiResource.release(); // REMOVE*/ call CSN.set(); } return SUCCESS; } - /**************** Send Commands ****************/ + /**************** Load/Send Commands ****************/ -/* async command error_t Send.send( message_t* p_msg, bool useCca ) {*/ - async command error_t CC2420Tx.loadTXFIFO(ieee154_txframe_t *data) { - return load( data); - } - - async command void CC2420Tx.send(bool cca) + async command error_t CC2420Tx.loadTXFIFO(ieee154_txframe_t *data) { - attemptSend(cca); - } - - async command bool CC2420Tx.cca() - { - return call CCA.get(); - } - - async command error_t CC2420Tx.modify( uint8_t offset, uint8_t* buf, - uint8_t len ) { - call CSN.set(); - call CSN.clr(); - call TXFIFO_RAM.write( offset, buf, len ); - call CSN.set(); + atomic { + if ( m_state != S_STARTED ) + return FAIL; + m_state = S_LOAD; + m_frame = data; + m_frame->header->length = m_frame->headerLen + m_frame->payloadLen + 2; // 2 for CRC + call CSN.set(); + call CSN.clr(); + call SFLUSHTX.strobe(); // flush out anything that was in TXFIFO + call CSN.set(); + call CSN.clr(); + call TXFIFO.write( &(m_frame->header->length), 1 ); + } return SUCCESS; - } - - async command void CC2420Tx.lockChipSpi() + } + + async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error) { - abortSpiRelease = TRUE; + atomic { + call CSN.set(); + if (tx_buf == &(m_frame->header->length)){ + call CSN.clr(); + call TXFIFO.write( m_frame->header->mhr, m_frame->headerLen ); + return; + } else if (tx_buf == m_frame->header->mhr) { + call CSN.clr(); + call TXFIFO.write( m_frame->payload, m_frame->payloadLen ); + return; + } + } + m_state = S_READY_TX; + signal CC2420Tx.loadTXFIFODone(m_frame, error); } - async command void CC2420Tx.unlockChipSpi() + + async command error_t CC2420Tx.send(bool cca) { - abortSpiRelease = FALSE; - } + cc2420_status_t status; + bool congestion = TRUE; - /***************** Indicator Commands ****************/ -/* command bool EnergyIndicator.isReceiving() {*/ -/* return !(call CCA.get());*/ -/* }*/ -/* */ -/* command bool ByteIndicator.isReceiving() {*/ -/* bool high;*/ -/* atomic high = sfdHigh;*/ -/* return high;*/ -/* }*/ - + atomic { + if (m_state != S_READY_TX) + return EOFF; + call CSN.set(); + call CSN.clr(); - /***************** RadioBackoff Commands ****************/ - /** - * Must be called within a requestInitialBackoff event - * @param backoffTime the amount of time in some unspecified units to backoff - */ -/* async command void RadioBackoff.setInitialBackoff(uint16_t backoffTime) {*/ -/* myInitialBackoff = backoffTime + 1;*/ -/* }*/ - - /** - * Must be called within a requestCongestionBackoff event - * @param backoffTime the amount of time in some unspecified units to backoff - */ -/* async command void RadioBackoff.setCongestionBackoff(uint16_t backoffTime) {*/ -/* myCongestionBackoff = backoffTime + 1;*/ -/* }*/ - -/* async command void RadioBackoff.setCca(bool useCca) {*/ -/* }*/ - - + // DEBUG + //P2OUT |= 0x40; // P2.6 high + status = cca ? call STXONCCA.strobe() : call STXON.strobe(); + //status = call STXON.strobe(); + //U0TXBUF = 0x04; // strobe STXON + //while (!(IFG1 & URXIFG0)); + //status = U0RXBUF; + //call CSN.set(); + + if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) { + status = call SNOP.strobe(); + if ( status & CC2420_STATUS_TX_ACTIVE ) { + congestion = FALSE; + } + } + + call CSN.set(); + // DEBUG: on telosb SFD is connected to Pin P4.1 + //if (!congestion) {while (!(P4IN & 0x02)) ; P6OUT &= ~0x80;} + + if (congestion){ + return FAIL; // channel busy + } else { + m_state = S_SFD; + call BackoffAlarm.start(CC2420_ABORT_PERIOD); + return SUCCESS; + } + } + } /** * The CaptureSFD event is actually an interrupt from the capture pin @@ -256,33 +250,18 @@ implementation { * would have picked up and executed had our microcontroller been fast enough. */ async event void CaptureSFD.captured( uint16_t time ) { - // "time" is from TimerB capture, which is sourced by SMCLK (1MHz) //P2OUT &= ~0x40; // debug: P2.6 low - uint32_t localTime; atomic { switch( m_state ) { case S_SFD: m_state = S_EFD; sfdHigh = TRUE; - call CaptureTime.convert(time, &m_timestamp, -8); // -8 for the preamble call CaptureSFD.captureFallingEdge(); -/* signal TimeStamp.transmittedSFD( time, m_msg );*/ - localTime = call ReferenceTime.toLocalTime(&m_timestamp); - signal CC2420Tx.transmittedSFD(localTime, m_data ); - //if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) { - //if ( (m_data->header)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) { - // This is an ack packet, don't release the chip's SPI bus lock. - //} - releaseSpiResource(); + // timestamp denotes time of first bit (chip) of PPDU on the channel + call CaptureTime.convert(time, &m_timestamp, -10); // offset: -10 for 5 bytes (preamble+SFD) + m_frame->metadata->timestamp = call ReferenceTime.toLocalTime(&m_timestamp); call BackoffAlarm.stop(); - m_data->metadata->timestamp = localTime; - - -/* if ( ( ( (call CC2420PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) {*/ -/* (call CC2420PacketBody.getMetadata( m_msg ))->time = time;*/ -/* }*/ - if ( call SFD.get() ) { break; } @@ -291,11 +270,15 @@ implementation { case S_EFD: sfdHigh = FALSE; call CaptureSFD.captureRisingEdge(); - -/* if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {*/ - if ( (m_data->header->mhr)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) { + signal CC2420Tx.transmissionStarted(m_frame); + if ( (m_frame->header->mhr)[0] & ( 1 << IEEE154_FCF_ACK_REQ ) ) { + // wait for the ACK m_state = S_ACK_WAIT; - call BackoffAlarm.start( 200 ); // we need to have *completely* received the ACK + alarmStartTime = call BackoffAlarm.getNow(); + // we need to have *completely* received the ACK, 32+22 symbols + // should theroretically be enough, but there can be delays in + // servicing the FIFOP interrupt, so we use 100 symbols here + call BackoffAlarm.start( 100 ); } else { signalDone(FALSE, SUCCESS); } @@ -309,8 +292,7 @@ implementation { if ( !m_receiving ) { sfdHigh = TRUE; call CaptureSFD.captureFallingEdge(); -/* signal TimeStamp.receivedSFD( time );*/ - call CaptureTime.convert(time, &m_timestamp, -8); + call CaptureTime.convert(time, &m_timestamp, -10); call CC2420Receive.sfd( &m_timestamp ); m_receiving = TRUE; m_prev_time = time; @@ -318,13 +300,13 @@ implementation { // wait for the next interrupt before moving on return; } + // if we move on, then the timestamp will be invalid! } sfdHigh = FALSE; call CaptureSFD.captureRisingEdge(); m_receiving = FALSE; -/* if ( time - m_prev_time < 10 ) {*/ -#ifdef PIERCEBOARD_ENABLED +#ifdef TKN154_PIERCEBOARD if ( time - m_prev_time < 10*30 ) { #else if ( time - m_prev_time < 10 ) { @@ -336,8 +318,31 @@ implementation { } } } + + async command bool CC2420Tx.cca() + { + return call CCA.get(); + } + + async command error_t CC2420Tx.modify( uint8_t offset, uint8_t* buf, uint8_t len ) + { + call CSN.set(); + call CSN.clr(); + call TXFIFO_RAM.write( offset, buf, len ); + call CSN.set(); + return SUCCESS; + } + + async command void CC2420Tx.lockChipSpi() + { + abortSpiRelease = TRUE; + } + + async command void CC2420Tx.unlockChipSpi() + { + abortSpiRelease = FALSE; + } - /***************** ChipSpiResource Events ****************/ async event void ChipSpiResource.releasing() { if(abortSpiRelease) { call ChipSpiResource.abortRelease(); @@ -351,392 +356,54 @@ implementation { * our send is complete. */ async event void CC2420Receive.receive( uint8_t type, message_t *ackFrame ){ -/* async event void CC2420Receive.receive( uint8_t type, message_t* ack_msg ) {*/ -/* cc2420_header_t* ack_header;*/ -/* cc2420_header_t* msg_header;*/ -/* cc2420_metadata_t* msg_metadata;*/ -/* uint8_t* ack_buf;*/ -/* uint8_t length;*/ - atomic { if ( type == IEEE154_TYPE_ACK ) { - - /* ack_header = call CC2420PacketBody.getHeader( ack_msg );*/ - /* msg_header = call CC2420PacketBody.getHeader( m_msg );*/ - - /* if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) {*/ if ( m_state == S_ACK_WAIT && - m_data->header->mhr[2] == ((ieee154_header_t*) ackFrame->header)->mhr[2] ) { // compare seqno + m_frame->header->mhr[2] == ((ieee154_header_t*) ackFrame->header)->mhr[2] ) { // compare seqno call BackoffAlarm.stop(); - - /* msg_metadata = call CC2420PacketBody.getMetadata( m_msg );*/ - /* ack_buf = (uint8_t *) ack_header;*/ - /* length = ack_header->length;*/ - /* */ - /* msg_metadata->ack = TRUE;*/ - /* msg_metadata->rssi = ack_buf[ length - 1 ];*/ - /* msg_metadata->lqi = ack_buf[ length ] & 0x7f;*/ signalDone(( ((ieee154_header_t*) ackFrame->header)->mhr[0] & 0x10) ? TRUE: FALSE, SUCCESS); } } } } - - /***************** SpiResource Events ****************/ - /* - event void SpiResource.granted() { - uint8_t cur_state; - - atomic { - cur_state = m_state; - } - - switch( cur_state ) { - case S_LOAD: - loadTXFIFO(); - break; - - case S_BEGIN_TRANSMIT: - attemptSend(); - break; - - case S_CANCEL: - cancelTx(); - break; - - default: - releaseSpiResource(); - break; - } - } - */ - /***************** TXFIFO Events ****************/ - /** - * The TXFIFO is used to load packets into the transmit buffer on the - * chip - */ - async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, - error_t error ) { - - call CSN.set(); - - if (tx_buf == &m_txFrameLen){ - // until here: 1.65 ms - call CSN.clr(); - call TXFIFO.write( m_data->header->mhr, m_data->headerLen ); - return; - } else if (tx_buf == m_data->header->mhr) { - // until here: 2.2 ms - call CSN.clr(); - call TXFIFO.write( m_data->payload, m_data->payloadLen ); - return; - } - // until here: 4.6 ms (no DMA on USART0) - // until here: 3.3 ms (with DMA on USART0) - // P2OUT &= ~0x40; // P2.1 low - -/* if ( m_state == S_CANCEL ) {*/ -/* atomic {*/ -/* call CSN.clr();*/ -/* call SFLUSHTX.strobe();*/ -/* call CSN.set();*/ -/* }*/ -/* releaseSpiResource();*/ -/* m_state = S_STARTED;*/ - -/* } else if ( !m_cca ) {*/ -/* } else {*/ - m_state = S_BEGIN_TRANSMIT; - releaseSpiResource(); - signal CC2420Tx.loadTXFIFODone(m_data, error); -/* attemptSend();*/ -/* }*/ - -/* } else {*/ -/* releaseSpiResource();*/ -/* atomic {*/ -/* if (m_state == S_LOAD_CANCEL) {*/ -/* m_state = S_CCA_CANCEL;*/ -/* } else {*/ -/* m_state = S_SAMPLE_CCA;*/ -/* }*/ -/* }*/ -/* signal CC2420Tx.loadTXFIFODone(m_data, error);*/ - -/* signal RadioBackoff.requestInitialBackoff(m_msg);*/ -/* call BackoffAlarm.start(myInitialBackoff);*/ -/* }*/ - } - - - async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, - error_t error ) { - } - - - /***************** Timer Events ****************/ - /** - * The backoff timer is mainly used to wait for a moment before trying - * to send a packet again. But we also use it to timeout the wait for - * an acknowledgement, and timeout the wait for an SFD interrupt when - * we should have gotten one. - */ async event void BackoffAlarm.fired() { atomic { switch( m_state ) { - - case S_SAMPLE_CCA : - // sample CCA and wait a little longer if free, just in case we - // sampled during the ack turn-around window - if ( call CCA.get() ) { - m_state = S_BEGIN_TRANSMIT; - call BackoffAlarm.start( CC2420_TIME_ACK_TURNAROUND ); - - } else { - congestionBackoff(); - } - break; - - case S_BEGIN_TRANSMIT: - case S_CANCEL: - // should never happen - call Leds.led0On(); -/* if ( acquireSpiResource() == SUCCESS ) {*/ -/* attemptSend();*/ -/* }*/ - break; - - case S_ACK_WAIT: -/* signalDone( SUCCESS );*/ - signalDone( FALSE, FAIL ); - break; - - case S_SFD: - // We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD - // jiffies. Assume something is wrong. - atomic { - call CSN.set(); - call CSN.clr(); - call SFLUSHTX.strobe(); - call CSN.set(); - } - signalDone( FALSE, ERETRY ); - releaseSpiResource(); - //call CaptureSFD.captureRisingEdge(); - break; - - default: - break; - } - } - } - - /***************** Functions ****************/ - /** - * Set up a message to be sent. First load it into the outbound tx buffer - * on the chip, then attempt to send it. - * @param *p_msg Pointer to the message that needs to be sent - * @param cca TRUE if this transmit should use clear channel assessment - */ - error_t load( ieee154_txframe_t *data) { - atomic { - if (m_state == S_CANCEL) { - return ECANCEL; - } - - if ( m_state != S_STARTED ) { - return FAIL; - } - - m_state = S_LOAD; -/* m_msg = p_msg;*/ - m_data = data; - totalCcaChecks = 0; - } - - if ( acquireSpiResource() == SUCCESS ) { - loadTXFIFO(); - } - - return SUCCESS; - } - - /** - * Resend a packet that already exists in the outbound tx buffer on the - * chip - * @param cca TRUE if this transmit should use clear channel assessment - */ -/* error_t resend( bool cca ) {*/ - -/* atomic {*/ -/* if (m_state == S_LOAD_CANCEL*/ -/* || m_state == S_CCA_CANCEL*/ -/* || m_state == S_TX_CANCEL) {*/ -/* return ECANCEL;*/ -/* }*/ -/* */ -/* if ( m_state != S_STARTED ) {*/ -/* return FAIL;*/ -/* }*/ -/* */ -/* m_cca = cca;*/ -/* m_state = cca ? S_SAMPLE_CCA : S_BEGIN_TRANSMIT;*/ -/* totalCcaChecks = 0;*/ -/* }*/ -/* */ -/* if(m_cca) {*/ -/* signal RadioBackoff.requestInitialBackoff(m_msg);*/ -/* call BackoffAlarm.start( myInitialBackoff );*/ -/* */ -/* } else if ( acquireSpiResource() == SUCCESS ) {*/ -/* attemptSend();*/ -/* }*/ -/* */ -/* return SUCCESS;*/ -/* }*/ - - /** - * Attempt to send the packet we have loaded into the tx buffer on - * the radio chip. The STXONCCA will send the packet immediately if - * the channel is clear. If we're not concerned about whether or not - * the channel is clear (i.e. m_cca == FALSE), then STXON will send the - * packet without checking for a clear channel. - * - * If the packet didn't get sent, then congestion == TRUE. In that case, - * we reset the backoff timer and try again in a moment. - * - * If the packet got sent, we should expect an SFD interrupt to take - * over, signifying the packet is getting sent. - */ - void attemptSend(bool cca) { - uint8_t status; - bool congestion = TRUE; - atomic { - call CSN.set(); - call CSN.clr(); + case S_SFD: + case S_EFD: // fall through + // We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD + // jiffies. Assume something is wrong. + atomic { + call CSN.set(); + call CSN.clr(); + call SFLUSHTX.strobe(); + call CSN.set(); + } + signalDone( FALSE, ERETRY ); + break; - // STXONCCA costs about ? symbols, i.e. attemptSend should be called - // ? symbols, before the actual CCA - //P2OUT |= 0x40; // P2.6 high - status = cca ? call STXONCCA.strobe() : call STXON.strobe(); - //status = call STXON.strobe(); - //U0TXBUF = 0x04; // strobe STXON - //while (!(IFG1 & URXIFG0)); - //status = U0RXBUF; - //call CSN.set(); + case S_ACK_WAIT: + /* signalDone( SUCCESS );*/ + signalDone( FALSE, ENOACK ); + break; - if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) { - status = call SNOP.strobe(); - if ( status & CC2420_STATUS_TX_ACTIVE ) { - congestion = FALSE; - } - } - - call CSN.set(); - // debug: on telosb SFD is connected to Pin P4.1 - if (!congestion) {while (!(P4IN & 0x02)) ; P6OUT &= ~0x80;} - if (congestion){ - call ReferenceTime.getNow(&m_timestamp, 0); - m_state = S_BEGIN_TRANSMIT; // don't use a state S_SAMPLE_CCA - releaseSpiResource(); - signal CC2420Tx.sendDone(m_data, &m_timestamp, FALSE, EBUSY); // waiting for the next send() - } else { - m_state = S_SFD; // wait for an ACK - signal CC2420Tx.transmissionStarted(m_data); - call BackoffAlarm.start(CC2420_ABORT_PERIOD*3); + default: + break; } - return; // we still own the SPI, either we wait for an ACK or resend is going to be called soon } - -/* if ( congestion ) {*/ -/* totalCcaChecks = 0;*/ -/* releaseSpiResource();*/ -/* congestionBackoff();*/ -/* } else {*/ -/* call BackoffAlarm.start(CC2420_ABORT_PERIOD);*/ -/* }*/ } - - /** - * Congestion Backoff - */ - void congestionBackoff() { - atomic { -/* signal RadioBackoff.requestCongestionBackoff(m_msg);*/ - call BackoffAlarm.start(myCongestionBackoff); - } - } - - error_t acquireSpiResource() { - return SUCCESS; - /* - error_t error = call SpiResource.immediateRequest(); - if ( error != SUCCESS ) { - call SpiResource.request(); - } - return error; - */ - } - - error_t releaseSpiResource() { - //call SpiResource.release(); - return SUCCESS; - } - - - /** - * Setup the packet transmission power and load the tx fifo buffer on - * the chip with our outbound packet. - * - * Warning: the tx_power metadata might not be initialized and - * could be a value other than 0 on boot. Verification is needed here - * to make sure the value won't overstep its bounds in the TXCTRL register - * and is transmitting at max power by default. - * - * It should be possible to manually calculate the packet's CRC here and - * tack it onto the end of the header + payload when loading into the TXFIFO, - * so the continuous modulation low power listening strategy will continually - * deliver valid packets. This would increase receive reliability for - * mobile nodes and lossy connections. The crcByte() function should use - * the same CRC polynomial as the CC2420's AUTOCRC functionality. - */ - void loadTXFIFO() { -/* cc2420_header_t* header = call CC2420PacketBody.getHeader( m_msg );*/ -/* uint8_t tx_power = (call CC2420PacketBody.getMetadata( m_msg ))->tx_power;*/ - m_txFrameLen = m_data->headerLen + m_data->payloadLen + 2; -/* if ( !tx_power ) {*/ -/* tx_power = CC2420_DEF_RFPOWER;*/ -/* }*/ - call CSN.set(); - call CSN.clr(); - call SFLUSHTX.strobe(); // flush out anything that was in there - call CSN.set(); - call CSN.clr(); - -/* call TXFIFO.write( (uint8_t*)header, header->length - 1);*/ - call TXFIFO.write( &m_txFrameLen, 1 ); - - } - void signalDone( bool ackFramePending, error_t err ) { atomic m_state = S_STARTED; - signal CC2420Tx.sendDone( m_data, &m_timestamp, ackFramePending, err ); + signal CC2420Tx.sendDone( m_frame, &m_timestamp, ackFramePending, err ); call ChipSpiResource.attemptRelease(); -/* signal Send.sendDone( m_msg, err );*/ } - - /***************** Tasks ****************/ - - /***************** Defaults ****************/ -/* default async event void TimeStamp.transmittedSFD( uint16_t time, message_t* p_msg ) {*/ -/* }*/ - -/* default async event void TimeStamp.receivedSFD( uint16_t time ) {*/ -/* }*/ + async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, + error_t error ) { + } } diff --git a/tos/chips/cc2420_tkn154/CC2420Tx.nc b/tos/chips/cc2420_tkn154/CC2420Tx.nc index 53e1fc9f..8d7fe923 100644 --- a/tos/chips/cc2420_tkn154/CC2420Tx.nc +++ b/tos/chips/cc2420_tkn154/CC2420Tx.nc @@ -40,7 +40,7 @@ interface CC2420Tx { async command error_t loadTXFIFO(ieee154_txframe_t *data); async event void loadTXFIFODone(ieee154_txframe_t *data, error_t error ); - async command void send(bool cca); + async command error_t send(bool cca); async event void sendDone(ieee154_txframe_t *frame, ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error); diff --git a/tos/chips/cc2420_tkn154/ReliableWait.nc b/tos/chips/cc2420_tkn154/ReliableWait.nc index 02140b11..0ac64324 100644 --- a/tos/chips/cc2420_tkn154/ReliableWait.nc +++ b/tos/chips/cc2420_tkn154/ReliableWait.nc @@ -32,18 +32,14 @@ */ interface ReliableWait { - async command void busyWait(uint16_t dt); - - /* - * The following command/event pairs are platform-specific - * busy-waits. - */ - async command void waitRx(ieee154_reftime_t *t0, uint16_t dt); async event void waitRxDone(); - async command void waitCCA(ieee154_reftime_t *t0, uint16_t dt); - async event void waitCCADone(); async command void waitTx(ieee154_reftime_t *t0, uint16_t dt); async event void waitTxDone(); + async command void waitBackoff(ieee154_reftime_t *t0, uint16_t dt); + async event void waitBackoffDone(); + + async command void busyWaitSlotBoundaryCCA(ieee154_reftime_t *t0, uint16_t *dt); + async command void busyWaitSlotBoundaryTx(ieee154_reftime_t *t0, uint16_t dt); } diff --git a/tos/lib/mac/tkn154/AssociateP.nc b/tos/lib/mac/tkn154/AssociateP.nc index c420f320..57409419 100644 --- a/tos/lib/mac/tkn154/AssociateP.nc +++ b/tos/lib/mac/tkn154/AssociateP.nc @@ -152,7 +152,7 @@ implementation call TxControlPool.put(txControl); } } - call Debug.log(LEVEL_INFO, AssociateP_REQUEST, status, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, AssociateP_REQUEST, status, 0, 0); return status; } @@ -165,10 +165,10 @@ implementation signal MLME_ASSOCIATE.confirm(0xFFFF, status, 0); } else { call ResponseTimeout.startOneShot(call MLME_GET.macResponseWaitTime()*IEEE154_aBaseSuperframeDuration); - call Debug.log(LEVEL_INFO, AssociateP_SETTIMER, + call Debug.log(DEBUG_LEVEL_INFO, AssociateP_SETTIMER, call MLME_GET.macResponseWaitTime()*IEEE154_aBaseSuperframeDuration, 0, 0); } - call Debug.log(LEVEL_INFO, AssociateP_TXDONE, status, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, AssociateP_TXDONE, status, 0, 0); } event void ResponseTimeout.fired() @@ -202,7 +202,7 @@ implementation event void DataRequest.pollDone() { if (m_associationOngoing){ - call Debug.log(LEVEL_INFO, AssociateP_POLL_DONE, m_payloadAssocRequest[0], m_assocRespStatus, 0); + call Debug.log(DEBUG_LEVEL_INFO, AssociateP_POLL_DONE, m_payloadAssocRequest[0], m_assocRespStatus, 0); call ResponseTimeout.stop(); m_associationOngoing = FALSE; signal MLME_ASSOCIATE.confirm(m_shortAddress, m_assocRespStatus, 0); diff --git a/tos/lib/mac/tkn154/BeaconSynchronizeP.nc b/tos/lib/mac/tkn154/BeaconSynchronizeP.nc index c4c570c5..eadfc4bc 100644 --- a/tos/lib/mac/tkn154/BeaconSynchronizeP.nc +++ b/tos/lib/mac/tkn154/BeaconSynchronizeP.nc @@ -105,7 +105,6 @@ implementation bool m_internalRequest = FALSE; norace uint8_t m_numBeaconsLost; - uint8_t m_coordAddress[8]; message_t m_beaconBuffer; norace message_t *m_beaconBufferPtr = &m_beaconBuffer; norace bool m_beaconSwapBufferReady = TRUE; @@ -161,7 +160,7 @@ implementation (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !call IsBeaconEnabledPAN.getNow()) return IEEE154_INVALID_PARAMETER; - call Debug.log(LEVEL_INFO,SyncP_REQUEST, logicalChannel, channelPage, trackBeacon); + call Debug.log(DEBUG_LEVEL_INFO,0, logicalChannel, channelPage, trackBeacon); if (!trackBeacon && m_tracking){ // stop tracking after next received beacon m_stopTracking = TRUE; @@ -171,7 +170,7 @@ implementation m_updateTrackBeacon = trackBeacon; m_internalRequest = FALSE; m_updatePending = TRUE; - call Debug.log(LEVEL_INFO,SyncP_RESOURCE_REQUEST, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO,1, 0, 0, 0); atomic { // if we are tracking then we'll get the Token automatically, // otherwise request it now @@ -185,7 +184,8 @@ implementation event void FindBeacon.notify( bool val ) { - if (!m_tracking && !m_updatePending){ + call Debug.log(DEBUG_LEVEL_IMPORTANT,20, m_tracking, m_updatePending, 0); + if (!m_tracking && !m_updatePending && !call Token.isOwner()){ // find a single beacon now (treat this like a user request) m_updateLogicalChannel = call MLME_GET.phyCurrentChannel(); m_updateTrackBeacon = FALSE; @@ -197,7 +197,7 @@ implementation event void Token.granted() { - call Debug.log(LEVEL_INFO,SyncP_GOT_RESOURCE, m_lastBeaconRxTime+m_beaconInterval, + call Debug.log(DEBUG_LEVEL_INFO,2, m_lastBeaconRxTime+m_beaconInterval, m_beaconInterval, (m_updatePending<<1)+m_tracking); if (m_updatePending){ m_state = S_FIRST_SCAN; @@ -210,7 +210,7 @@ implementation m_beaconInterval = ((uint32_t) 1 << m_beaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; m_dt = m_beaconInterval; m_numBeaconsLost = IEEE154_aMaxLostBeacons; // will be reset when beacon is received - call Debug.log(LEVEL_INFO,SyncP_UPDATING, call MLME_GET.macCoordShortAddress(), + call Debug.log(DEBUG_LEVEL_INFO,3, call MLME_GET.macCoordShortAddress(), call MLME_GET.macPANId(), m_updateLogicalChannel); } getNextBeacon(); @@ -225,23 +225,24 @@ implementation m_state = S_PREPARE; if (!m_tracking){ // nothing to do, just give up the token - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO,4, 0, 0, 0); call Token.release(); return; } while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)){ // missed a beacon! missed = TRUE; - call Debug.log(LEVEL_INFO,SyncP_BEACON_MISSED_1, m_lastBeaconRxTime, m_dt, missed); + call Debug.log(DEBUG_LEVEL_IMPORTANT,5, m_lastBeaconRxTime, m_dt, missed); m_dt += m_beaconInterval; m_numBeaconsLost++; } if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){ + call Debug.log(DEBUG_LEVEL_IMPORTANT,19, m_numBeaconsLost, m_dt, missed); post processBeaconTask(); return; } if (missed){ call Token.request(); - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, m_lastBeaconRxTime, m_dt, missed); + call Debug.log(DEBUG_LEVEL_IMPORTANT,6, m_lastBeaconRxTime, m_dt, missed); call Token.release(); return; } @@ -272,17 +273,15 @@ implementation async event void TrackAlarm.fired() { - call Debug.log(LEVEL_IMPORTANT,SyncP_TRACK_ALARM, m_state,m_lastBeaconRxTime,m_dt); - atomic { - switch (m_state) - { - case S_PREPARE: - call BeaconRx.prepare(); - break; - case S_RADIO_OFF: - call RadioOff.off(); - break; - } + call Debug.log(DEBUG_LEVEL_INFO,7, m_state,m_lastBeaconRxTime,m_dt); + switch (m_state) + { + case S_PREPARE: + call BeaconRx.prepare(); + break; + case S_RADIO_OFF: + call RadioOff.off(); + break; } } @@ -299,9 +298,10 @@ implementation } else { m_state = S_RADIO_OFF; result = call BeaconRx.receive(&m_lastBeaconRxRefTime, m_dt-RX_LAG); - call Debug.log(LEVEL_IMPORTANT,SyncP_RX_ON, m_lastBeaconRxTime, call TrackAlarm.getNow(), m_dt+RX_DURATION); + //__nesc_enable_interrupt(); + call Debug.log(DEBUG_LEVEL_INFO,8, m_lastBeaconRxTime, 0,(m_lastBeaconRxTime+m_dt) - call TrackAlarm.getNow()); if (result != SUCCESS) - call Debug.log(LEVEL_IMPORTANT,SyncP_RADIO_BUSY, result, 0, 0); + call Debug.log(DEBUG_LEVEL_CRITICAL,9, result, 0, 0); call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + RX_DURATION); } } @@ -309,20 +309,23 @@ implementation event message_t* BeaconRx.received(message_t *frame, ieee154_reftime_t *timestamp) { uint8_t *mhr = MHR(frame); - call Debug.log(LEVEL_INFO,SyncP_RX_PACKET,*((nxle_uint32_t*) &mhr[MHR_INDEX_ADDRESS]), + call Debug.log(DEBUG_LEVEL_INFO,10,*((nxle_uint32_t*) &mhr[MHR_INDEX_ADDRESS]), mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK,mhr[MHR_INDEX_SEQNO]); if (!m_beaconSwapBufferReady || !call FrameUtility.isBeaconFromCoord(frame)) { - call Debug.log(LEVEL_IMPORTANT,SyncP_RX_GARBAGE, m_beaconSwapBufferReady, 0, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT,11, m_beaconSwapBufferReady, 0, 0); return frame; } else { + error_t resultOff; message_t *tmp = m_beaconBufferPtr; call TrackAlarm.stop(); m_beaconSwapBufferReady = FALSE; m_beaconBufferPtr = frame; - if (timestamp != NULL) + resultOff = call RadioOff.off(); + if (timestamp != NULL){ memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_reftime_t)); - call RadioOff.off(); + call Debug.log(DEBUG_LEVEL_INFO,23,0, 0, resultOff); + } return tmp; } } @@ -331,10 +334,14 @@ implementation { if (m_state == S_FIRST_SCAN) call BeaconRx.prepare(); - else if (m_state == S_PREPARE) - call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY); - else + else if (m_state == S_PREPARE){ + if (!call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY)) + call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt - IEEE154_RADIO_RX_PREPARE_DELAY); + else + signal TrackAlarm.fired(); + } else { post processBeaconTask(); + } } task void processBeaconTask() @@ -342,17 +349,22 @@ implementation // valid beacon timestamp is pre-condition for slotted CSMA-CA if (m_beaconSwapBufferReady || !call Frame.isTimestampValid(m_beaconBufferPtr)){ // missed a beacon! + if (!m_beaconSwapBufferReady) + call Debug.log(DEBUG_LEVEL_IMPORTANT, 21,m_numBeaconsLost,m_beaconSwapBufferReady,m_lastBeaconRxTime); + else + call Debug.log(DEBUG_LEVEL_IMPORTANT, 12,m_numBeaconsLost,m_beaconSwapBufferReady,m_lastBeaconRxTime); m_sfSlotDuration = 0; // CAP len will be 0 m_numBeaconsLost++; m_dt += m_beaconInterval; - call Debug.log(LEVEL_IMPORTANT, SyncP_BEACON_MISSED_3,m_numBeaconsLost,0,m_lastBeaconRxTime); + m_beaconSwapBufferReady = TRUE; if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons){ m_tracking = FALSE; - call Debug.log(LEVEL_IMPORTANT, SyncP_LOST_SYNC,0,0,0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, 13,m_internalRequest,0,0); call Leds.led2Off(); - if (m_internalRequest) + if (m_internalRequest){ call TokenToCap.transfer(); - else + return; + } else signal MLME_SYNC_LOSS.indication( IEEE154_BEACON_LOSS, call MLME_GET.macPANId(), @@ -362,7 +374,7 @@ implementation ); } else call Token.request(); // make another request again (before giving the token up) - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO,14, 0, 0, 0); call Token.release(); } else { // got the beacon! @@ -379,7 +391,7 @@ implementation uint8_t gtsFieldLength; uint32_t timestamp = call Frame.getTimestamp(m_beaconBufferPtr); - call Debug.log(LEVEL_INFO, SyncP_BEACON_RX, m_lastBeaconRxTime, timestamp, mhr[2]); + call Debug.log(DEBUG_LEVEL_INFO, 15, m_lastBeaconRxTime, timestamp, mhr[2]); m_numGtsSlots = (payload[2] & 7); gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0); m_lastBeaconRxTime = timestamp; @@ -395,7 +407,7 @@ implementation m_BLELen += call MLME_GET.macMinLIFSPeriod(); else m_BLELen += call MLME_GET.macMinSIFSPeriod(); - m_BLELen += call MLME_GET.macBattLifeExtPeriods(); + m_BLELen = m_BLELen + call MLME_GET.macBattLifeExtPeriods() * 20; } else m_BLELen = 0; m_broadcastPending = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE; @@ -403,12 +415,12 @@ implementation m_dt = m_beaconInterval = ((uint32_t) 1 << coordBeaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; if (m_stopTracking){ m_tracking = FALSE; - call Debug.log(LEVEL_INFO,SyncP_RELEASE_RESOURCE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO,16, 0, 0, 0); if (m_updatePending) // there is already a new request pending... call Token.request(); call Token.release(); } else { - call Debug.log(LEVEL_INFO,SyncP_TRANSFER_RESOURCE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO,17, 0, 0, 0); call TokenToCap.transfer(); // borrow Token to CAP/CFP module, we'll get it back afterwards } @@ -435,7 +447,7 @@ implementation call DataRequest.poll(CoordAddrMode, CoordPANId, CoordAddress, SrcAddrMode); } // Beacon Tracking: update state - call Debug.log(LEVEL_INFO, SyncP_NEXT_RX_TIME, 0, timestamp, m_beaconInterval); + call Debug.log(DEBUG_LEVEL_INFO, 18, m_lastBeaconRxTime, m_beaconInterval, 0); m_numBeaconsLost = 0; // TODO: check PAN ID conflict here? if (!autoRequest || beaconPayloadSize) diff --git a/tos/lib/mac/tkn154/BeaconTransmitP.nc b/tos/lib/mac/tkn154/BeaconTransmitP.nc index b3b04dbd..04ef7641 100644 --- a/tos/lib/mac/tkn154/BeaconTransmitP.nc +++ b/tos/lib/mac/tkn154/BeaconTransmitP.nc @@ -238,7 +238,7 @@ implementation status = IEEE154_SUCCESS; if (panCoordinator) startTime = 0; // start immediately - call Debug.log(LEVEL_INFO, StartP_REQUEST, logicalChannel, beaconOrder, superframeOrder); + call Debug.log(DEBUG_LEVEL_INFO, 0, logicalChannel, beaconOrder, superframeOrder); if (beaconOrder == 15){ // beaconless PAN superframeOrder = 15; @@ -394,7 +394,7 @@ implementation event void Token.granted() { call Debug.flush(); - call Debug.log(LEVEL_INFO, StartP_GOT_RESOURCE, m_lastBeaconTxTime, m_beaconInterval, m_requests); + call Debug.log(DEBUG_LEVEL_INFO, 1, m_lastBeaconTxTime, m_beaconInterval, m_requests); if (m_requests & REQUEST_REALIGNMENT_DONE_PENDING){ // unlikely to occur: we have not yet received a done() // event after sending out a realignment frame @@ -404,7 +404,7 @@ implementation if (m_requests & REQUEST_UPDATE_SF){ m_requests &= ~REQUEST_UPDATE_SF; continueStartRequest(); - call Debug.log(LEVEL_INFO, StartP_UPDATE_STATE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, 2, 0, 0, 0); } if (call RadioOff.isOff()) prepareNextBeaconTransmission(); @@ -433,7 +433,7 @@ implementation if (m_txState == S_TX_LOCKED){ // have not had time to finish processing the last sent beacon post grantedTask(); - call Debug.log(LEVEL_CRITICAL, StartP_OWNER_TOO_FAST, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, 3, 0, 0, 0); return; } else if (m_beaconOrder == 15){ call Token.release(); @@ -463,8 +463,8 @@ implementation // the usual case: next beacon tx time = last time + BI m_dt = m_beaconInterval; } - while (call TimeCalc.hasExpired(m_lastBeaconTxTime, m_dt)){ // missed sending a beacon - call Debug.log(LEVEL_INFO, StartP_SKIPPED_BEACON, m_lastBeaconTxTime, m_dt, 0); + while (call TimeCalc.hasExpired(m_lastBeaconTxTime, m_dt)){ // skipped a beacon + call Debug.log(DEBUG_LEVEL_IMPORTANT, 4, m_lastBeaconTxTime, m_dt, 0); m_dt += m_beaconInterval; } if (m_dt < IEEE154_RADIO_TX_PREPARE_DELAY) @@ -489,12 +489,12 @@ implementation else m_beaconFrame.header->mhr[MHR_INDEX_FC1] &= ~FC1_FRAME_PENDING; m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = m_bsn; // update beacon seqno - call Debug.log(LEVEL_INFO, StartP_PREPARE_TX, 0, m_lastBeaconTxTime, 0); + call Debug.log(DEBUG_LEVEL_INFO, 5, 0, m_lastBeaconTxTime, 0); call BeaconTx.load(&m_beaconFrame); break; case S_TX_LOCKED: - call Debug.log(LEVEL_INFO, StartP_TRANSMIT, m_lastBeaconTxTime, m_dt, ((uint32_t)m_lastBeaconTxRefTime)); - call BeaconTx.transmit(&m_lastBeaconTxRefTime, m_dt, 0, FALSE); + call Debug.log(DEBUG_LEVEL_INFO, 6, m_lastBeaconTxTime, m_dt, 0); + call BeaconTx.transmit(&m_lastBeaconTxRefTime, m_dt); break; } } @@ -503,25 +503,23 @@ implementation async event void BeaconTx.loadDone() { atomic { - call Debug.log(LEVEL_INFO, StartP_PREPARE_TXDONE, 0, m_lastBeaconTxTime, 0); + call Debug.log(DEBUG_LEVEL_INFO, 7, 0, m_lastBeaconTxTime, 0); if (m_txOneBeaconImmediately){ m_txOneBeaconImmediately = FALSE; - call BeaconTx.transmit(0, 0, 0, FALSE); // now! + call BeaconTx.transmit(NULL, 0); // now! } else call BeaconTxAlarm.startAt(m_lastBeaconTxTime, m_dt - IEEE154_RADIO_TX_SEND_DELAY); } } - - async event void BeaconTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool pendingFlag, error_t error) + async event void BeaconTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime) { // Coord CAP has just started... uint8_t gtsFieldLength; // Sec. 7.5.1.1: "start of slot 0 is defined as the point at which // the first symbol of the beacon PPDU is transmitted" - call Debug.log(LEVEL_INFO, StartP_BEACON_TRANSMITTED, frame->metadata->timestamp, m_lastBeaconTxTime, m_dt); + call Debug.log(DEBUG_LEVEL_INFO, 8, frame->metadata->timestamp, m_lastBeaconTxTime, m_dt); m_lastBeaconTxTime = frame->metadata->timestamp; - memcpy(&m_lastBeaconTxRefTime, referenceTime, sizeof(ieee154_reftime_t)); + memcpy(&m_lastBeaconTxRefTime, txTime, sizeof(ieee154_reftime_t)); m_numGtsSlots = (frame->payload[2] & 0x07); gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0); m_finalCAPSlot = (frame->payload[1] & 0x0F); @@ -534,12 +532,12 @@ implementation if (frame->payload[1] & 0x10){ // BLE is active; calculate the time offset from slot0 m_BLELen = IEEE154_SHR_DURATION + - (frame->headerLen + frame->payloadLen) * IEEE154_SYMBOLS_PER_OCTET; - if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize) + (frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET; + if (frame->headerLen + frame->payloadLen + 2 > IEEE154_aMaxSIFSFrameSize) m_BLELen += IEEE154_MIN_LIFS_PERIOD; else m_BLELen += IEEE154_MIN_SIFS_PERIOD; - m_BLELen += m_battLifeExtPeriods; + m_BLELen = m_BLELen + m_battLifeExtPeriods * 20; } else m_BLELen = 0; call TokenToBroadcast.transfer(); // borrow Token to Broadcast/CAP/CFP module, we'll get it back afterwards @@ -658,7 +656,7 @@ implementation atomic { if (m_txState == S_TX_LOCKED) { - call Debug.log(LEVEL_INFO, StartP_BEACON_UPDATE, 0, 0, m_txState); + call Debug.log(DEBUG_LEVEL_IMPORTANT, 10, 0, 0, m_txState); return; // too late ! } if (m_payloadState & MODIFIED_PENDING_ADDR_FIELD){ @@ -696,7 +694,7 @@ implementation atomic { if (m_txState == S_TX_LOCKED) { - call Debug.log(LEVEL_INFO, StartP_BEACON_UPDATE_2, 0, 0, m_txState); + call Debug.log(DEBUG_LEVEL_INFO, 11, 0, 0, m_txState); return; // too late ! } if (m_payloadState & MODIFIED_BEACON_PAYLOAD){ @@ -815,6 +813,11 @@ implementation async command uint32_t SfSlotDuration.getNow() { return m_sfSlotDuration; } async command uint8_t FinalCapSlot.getNow() { return m_finalCAPSlot; } async command uint8_t NumGtsSlots.getNow() { return m_numGtsSlots; } + async event void BeaconTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result){} + async event void BeaconTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result){} + default event void MLME_START.confirm ( ieee154_status_t status diff --git a/tos/lib/mac/tkn154/CsmaP.nc b/tos/lib/mac/tkn154/CsmaP.nc deleted file mode 100644 index 4567accf..00000000 --- a/tos/lib/mac/tkn154/CsmaP.nc +++ /dev/null @@ -1,735 +0,0 @@ -/* - * Copyright (c) 2008, Technische Universitaet Berlin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the Technische Universitaet Berlin nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - Revision ------------------------------------------------------------- - * $Revision$ - * $Date$ - * @author Jan Hauer - * ======================================================================== - */ - -#include "TKN154_PHY.h" -#include "TKN154_MAC.h" - -/** - * This module implements the slotted and unslotted CSMA-CA algorithm. - * Unslotted CSMA-CA is used in nonbeacon-enabled PANs, slotted CSMA-CA is used - * in beacon-enabled PANs. In a beacon-enabled PAN this module is responsible - * for channel access during the contention access period (CAP). It does - * slightly different things depending on whether it is the CAP for an outgoing - * superframe (superframeDirection = OUTGOING_SUPERFRAME), i.e. the CAP from - * the perspective of a coordinator after it has transmitted its own beacon; or - * for an incoming superframe (superframeDirection = INCOMING_SUPERFRAME), i.e. - * the CAP from the perspective of a device after it has received a beacon from - * its coordinator; for example, in the CAP a coordinator will usually listen for - * incoming frames from the devices, and a device will usually switch the radio - * off unless it has a frame to transmit. In nonbeacon-enabled PANs the - * superframeDirection parameter is ignored. - */ - -generic module CsmaP(uint8_t superframeDirection) -{ - provides - { - interface Init as Reset; - interface FrameTx as FrameTx; - interface FrameRx as FrameRx[uint8_t frameType]; - interface FrameExtracted as FrameExtracted[uint8_t frameType]; - interface FrameTxNow as BroadcastTx; - interface Notify as WasRxEnabled; - interface Notify as FindBeacon; - } - uses - { - interface Random; - interface Alarm as CapEndAlarm; - interface Alarm as BLEAlarm; - interface Alarm as IndirectTxWaitAlarm; - interface Alarm as BroadcastAlarm; - interface Resource as Token; - interface GetNow as IsTokenRequested; - interface ResourceTransfer as TokenToCfp; - interface ResourceTransferred as TokenTransferred; - interface GetNow as CapStart; - interface GetNow as CapStartRefTime; - interface GetNow as CapLen; - interface GetNow as IsBLEActive; - interface GetNow as BLELen; - interface GetNow as IsRxBroadcastPending; - interface GetNow as IsRxEnableActive; - interface Notify as RxEnableStateChange; - interface GetNow as IsTrackingBeacons; - interface FrameUtility; - interface RadioTx; - interface RadioRx; - interface RadioOff; - interface GetNow as IsBeaconEnabledPAN; - interface MLME_GET; - interface MLME_SET; - interface Ieee802154Debug as Debug; - interface TimeCalc; - interface Leds; - interface SetNow as FrameBackup; - interface GetNow as FrameRestore; - } -} -implementation -{ - typedef enum { - SWITCH_OFF, - LOAD_TX, - PREPARE_RX, - DO_NOTHING, - WAIT_FOR_TXDONE, - } next_state_t; - - typedef enum { - INDIRECT_TX_ALARM, - BROADCAST_ALARM, - NO_ALARM, - } rx_alarm_t; - - enum { - COORD_ROLE = (superframeDirection == OUTGOING_SUPERFRAME), - DEVICE_ROLE = !COORD_ROLE, - }; - - norace bool m_lock; - norace ieee154_txframe_t *m_currentFrame; - norace ieee154_txframe_t *m_bcastFrame; - norace ieee154_txframe_t *m_lastFrame; - norace ieee154_macMaxBE_t m_BE; - norace ieee154_macMaxBE_t m_NB; - norace ieee154_macMaxBE_t m_numCCA; - norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs; - norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries; - norace ieee154_macMaxBE_t m_macMaxBE; - norace ieee154_macMinBE_t m_macMinBE; - norace uint16_t m_backoff; - norace uint16_t m_backoffElapsed; - norace ieee154_status_t m_result; - norace uint32_t m_transactionTime; - norace bool m_indirectTxPending = FALSE; - norace bool m_broadcastRxPending; - norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime; - - uint16_t generateRandomBackoff(uint8_t BE); - void stopAllAlarms(); - next_state_t tryReceive(rx_alarm_t alarmType); - next_state_t tryTransmit(); - next_state_t trySwitchOff(); - void backupCurrentFrame(); - void restoreFrameFromBackup(); - void updateState(); - void setCurrentFrame(ieee154_txframe_t *frame); - void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error); - task void signalTxDoneTask(); - task void setupTxBroadcastTask(); - task void wasRxEnabledTask(); - - command error_t Reset.init() - { - if (m_currentFrame) - signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW); - if (m_lastFrame) - signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW); - if (m_bcastFrame) - signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW); - m_currentFrame = m_lastFrame = m_bcastFrame = NULL; - stopAllAlarms(); - return SUCCESS; - } - - async event void TokenTransferred.transferred() - { - // we got the token, i.e. CAP has just started - uint32_t actualCapLen = call CapLen.getNow(); - if (!call IsBeaconEnabledPAN.getNow()){ - call Leds.led0On(); // internal error! - call TokenToCfp.transfer(); - call Debug.log(LEVEL_IMPORTANT, CapP_INTERNAL_ERROR, 0,0,0); - } else if (DEVICE_ROLE && actualCapLen == 0){ - // very rare case: - // this can only happen, if we're on a beacon-enabled PAN, not tracking beacons, - // and searched but didn't find a beacon for aBaseSuperframeDuration*(2n+1) symbols - // -> transmit current frame using unslotted CSMA-CA - m_numCCA = 1; - updateState(); - return; - } else if (actualCapLen < IEEE154_RADIO_GUARD_TIME){ - call Debug.log(LEVEL_IMPORTANT, CapP_TOO_SHORT, superframeDirection, actualCapLen, IEEE154_RADIO_GUARD_TIME); - call TokenToCfp.transfer(); - return; - } else { - actualCapLen -= IEEE154_RADIO_GUARD_TIME; - if (DEVICE_ROLE) - m_broadcastRxPending = call IsRxBroadcastPending.getNow(); - else { - // COORD_ROLE - if (m_bcastFrame != NULL) { - // we have to transmit a broadcast frame immediately; this - // (possibly) requires a backup of the previously active frame - // and a reinitializing the CSMA parameters -> will do it - // in task context and then continue - m_lock = TRUE; - post setupTxBroadcastTask(); - } - } - call CapEndAlarm.startAt(call CapStart.getNow(), actualCapLen); - if (call IsBLEActive.getNow()) - call BLEAlarm.startAt(call CapStart.getNow(), call BLELen.getNow()); - call Debug.log(LEVEL_IMPORTANT, CapP_SET_CAP_END, call CapStart.getNow(), - actualCapLen, call CapStart.getNow()+ actualCapLen); - } - updateState(); - } - - command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) - { - if (m_currentFrame != NULL) - return IEEE154_TRANSACTION_OVERFLOW; - else { - setCurrentFrame(frame); - if (!call IsBeaconEnabledPAN.getNow()){ - call Token.request(); // prepare for unslotted CSMA-CA - } else { - // a beacon must be found before transmitting in a beacon-enabled PAN - if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()){ - signal FindBeacon.notify(TRUE); - // we'll receive the Token at latest after aBaseSuperframeDuration*(2n+1) symbols; - // if the beacon was not found, then we'll send the frame using unslotted CSMA-CA - } - updateState(); - } - return IEEE154_SUCCESS; - } - } - - task void setupTxBroadcastTask() - { - ieee154_macDSN_t tmp; - ieee154_txframe_t *oldFrame = m_currentFrame; - if (COORD_ROLE){ - if (m_bcastFrame != NULL){ - // broadcasts should be transmitted *immediately* after the beacon, - // which may interrupt a pending transmit operation from the previous - // CAP; back up the last active frame configuration (may be none) - // and restore it after the broadcast frame has been transmitted; - // do this through interfaces and don't wire them for DEVICE_ROLE, - // so we don't waste the RAM of devices - backupCurrentFrame(); - setCurrentFrame(m_bcastFrame); - if (oldFrame){ - // now the sequence number are out of order... swap them back - tmp = m_bcastFrame->header->mhr[MHR_INDEX_SEQNO]; - m_bcastFrame->header->mhr[MHR_INDEX_SEQNO] = - oldFrame->header->mhr[MHR_INDEX_SEQNO]; - oldFrame->header->mhr[MHR_INDEX_SEQNO] = tmp; - } - } - } - m_lock = FALSE; - updateState(); - } - - void setCurrentFrame(ieee154_txframe_t *frame) - { - ieee154_macDSN_t dsn = call MLME_GET.macDSN(); - frame->header->mhr[MHR_INDEX_SEQNO] = dsn++; - call MLME_SET.macDSN(dsn); - m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs(); - m_macMaxFrameRetries = call MLME_GET.macMaxFrameRetries(); - m_macMaxBE = call MLME_GET.macMaxBE(); - m_macMinBE = call MLME_GET.macMinBE(); - if (call MLME_GET.macBattLifeExt() && m_macMinBE > 2) - m_macMinBE = 2; - m_BE = m_macMinBE; - if (call IsBeaconEnabledPAN.getNow()) - m_numCCA = 2; - else - m_numCCA = 1; - m_NB = 0; - m_transactionTime = IEEE154_SHR_DURATION + - (frame->headerLen + frame->payloadLen) * IEEE154_SYMBOLS_PER_OCTET; - if (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST) - m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod + - 11 * IEEE154_SYMBOLS_PER_OCTET); - if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize) - m_transactionTime += call MLME_GET.macMinLIFSPeriod(); - else - m_transactionTime += call MLME_GET.macMinSIFSPeriod(); - m_backoff = generateRandomBackoff(m_BE) * IEEE154_aUnitBackoffPeriod; // initial backoff - m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime(); - m_backoffElapsed = 0; - m_currentFrame = frame; - } - - uint16_t generateRandomBackoff(uint8_t BE) - { - // return random number from [0,(2^BE) - 1] (uniform distr.) - uint16_t res = call Random.rand16(); - uint16_t mask = 0xFFFF; - mask <<= BE; - mask = ~mask; - res &= mask; - return res; - } - - void stopAllAlarms() - { - call CapEndAlarm.stop(); - if (DEVICE_ROLE){ - call IndirectTxWaitAlarm.stop(); - call BroadcastAlarm.stop(); - } - call BLEAlarm.stop(); - } - - /** - * The updateState() function is called whenever some event happened that - * might require a state change; it implements a lock mechanism (m_lock) to - * prevent race conditions. Whenever the lock is set a "done"-event (from a - * RadioTx/RadioRx/RadioOff interface) is pending and will "soon" unset the - * lock (and then updateState() will called again). The updateState() - * function decides about the next state by checking a list of possible - * current states ordered by priority, e.g. it first always checks whether - * the CAP is still active. Calling this function more than necessary can do - * no harm, but it SHOULD be called whenever an event happened that might - * lead to a state change. - */ - - void updateState() - { - error_t result = SUCCESS; - next_state_t next; - atomic { - // long atomics are bad... but in this block, once the - // current state has been determined only one branch will - // be taken (no loops, etc.) - if (m_lock || !call Token.isOwner()) - return; - m_lock = TRUE; // lock - - // Check 1: for beacon-enabled PANs, has the CAP finished? - if (call IsBeaconEnabledPAN.getNow() - && (COORD_ROLE || call IsTrackingBeacons.getNow()) // FALSE only if device could't find a beacon - && (call TimeCalc.hasExpired(call CapStart.getNow(), call CapLen.getNow()-IEEE154_RADIO_GUARD_TIME) || - !call CapEndAlarm.isRunning())){ - if (call RadioOff.isOff()) { - stopAllAlarms(); // may still fire, locked through isOwner() - if (DEVICE_ROLE && m_indirectTxPending) - signal IndirectTxWaitAlarm.fired(); - m_broadcastRxPending = FALSE; - if (COORD_ROLE && m_bcastFrame){ - // didn't manage to transmit a broadcast - restoreFrameFromBackup(); - signalTxBroadcastDone(m_bcastFrame, IEEE154_CHANNEL_ACCESS_FAILURE); - m_bcastFrame = NULL; - } - m_lock = FALSE; // unlock - call TokenToCfp.transfer(); - return; - } else - next = SWITCH_OFF; - } - - // Check 2: should a broadcast frame be received/transmitted immediately - // at the start of CAP? - else if (DEVICE_ROLE && m_broadcastRxPending){ - // receive a broadcast from coordinator - next = tryReceive(BROADCAST_ALARM); - } else if (COORD_ROLE && m_bcastFrame){ - next = tryTransmit(); - } - - // Check 3: was an indirect transmission successfully started - // and are we now waiting for a frame from the coordinator? - else if (DEVICE_ROLE && m_indirectTxPending) { - next = tryReceive(INDIRECT_TX_ALARM); - } - - // Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending? - else if (call IsTokenRequested.getNow() && call IsBeaconEnabledPAN.getNow()) { - if (call RadioOff.isOff()) { - stopAllAlarms(); // may still fire, but is locked through isOwner() - // nothing more to do... just release the Token - m_lock = FALSE; // unlock - call TokenToCfp.transfer(); - return; - } else - next = SWITCH_OFF; - } - - // Check 5: is battery life extension (BLE) active and - // has the BLE period expired? - else if (call IsBLEActive.getNow() && - call TimeCalc.hasExpired(call CapStart.getNow(), call BLELen.getNow()) && - !call IsRxEnableActive.getNow()) { - next = trySwitchOff(); - } - - // Check 6: is there a frame ready to transmit? - else if (m_currentFrame != NULL) { - next = tryTransmit(); - } - - // Check 7: should we be in receive mode? - else if (COORD_ROLE || call IsRxEnableActive.getNow()) { - next = tryReceive(NO_ALARM); - if (next == DO_NOTHING && call IsRxEnableActive.getNow()){ - // this means there is an active MLME_RX_ENABLE.request - // and the radio was just switched to Rx mode - signal - // a notify event to inform the next higher layer - post wasRxEnabledTask(); - } - } - - // Check 8: just make sure the radio is switched off - else { - next = trySwitchOff(); - if (next == DO_NOTHING && - (!call IsBeaconEnabledPAN.getNow() || (DEVICE_ROLE && call CapLen.getNow() == 0))){ - // nothing more to do... just release the Token - stopAllAlarms(); // may still fire, but is locked through isOwner() - m_lock = FALSE; // unlock - call Token.release(); - return; - } - } - - // if there is nothing to do, then we must clear the lock - if (next == DO_NOTHING) - m_lock = FALSE; - } // atomic - // put next state in operation (possibly keeping the lock) - switch (next) - { - case SWITCH_OFF: result = call RadioOff.off(); break; - case LOAD_TX: result = call RadioTx.load(m_currentFrame); break; - case PREPARE_RX: result = call RadioRx.prepare(); break; - case WAIT_FOR_TXDONE: break; - case DO_NOTHING: break; - } - if (result != SUCCESS) - call Leds.led0On(); // internal error: could not update state !!! - } - - next_state_t tryTransmit() - { - // tries to transmit m_currentFrame using the configuration stored - // in other module variables (m_backoff, etc.) - next_state_t next; - if (call RadioTx.getLoadedFrame() == m_currentFrame){ - // the frame is already loaded -> transmit it now - if (m_numCCA == 1){ - // unslotted CSMA-CA - call RadioTx.transmit(NULL, m_backoff, m_numCCA, m_currentFrame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST ? TRUE : FALSE); - next = WAIT_FOR_TXDONE; // this will NOT clear the lock - } else { - // slotted CSMA-CA - uint32_t capLen = call CapLen.getNow(), capStart = call CapStart.getNow(); - uint32_t elapsed, totalTime; - totalTime = IEEE154_RADIO_TX_SEND_DELAY + - m_backoff - m_backoffElapsed + m_transactionTime + IEEE154_RADIO_GUARD_TIME; - if (totalTime > capLen) - totalTime = capLen; // CAP is too short - elapsed = call TimeCalc.timeElapsed(capStart, call CapEndAlarm.getNow()); - elapsed += (20 - (elapsed % 20)); // round to backoff boundary - if (!call TimeCalc.hasExpired(capStart, capLen - totalTime)){ - call RadioTx.transmit(call CapStartRefTime.getNow(), - elapsed + IEEE154_RADIO_TX_SEND_DELAY + m_backoff - m_backoffElapsed, - m_numCCA, - m_currentFrame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST ? TRUE : FALSE); - next = WAIT_FOR_TXDONE; // this will NOT clear the lock - } else { - // frame does not fit in remaing portion of the CAP - if (elapsed < call CapLen.getNow()){ - m_backoffElapsed += call CapLen.getNow() - elapsed; - if (m_backoffElapsed > m_backoff) - m_backoffElapsed = m_backoff; - } - next = SWITCH_OFF; - } - } - } else { - // the frame to transmit has not yet been loaded -> load it now - if (!call RadioOff.isOff()) - next = SWITCH_OFF; - else { - if (m_lastFrame){ - // the done event for the previous frame has not yet been - // signalled to the upper layer -> wait - next = DO_NOTHING; - } else - next = LOAD_TX; - } - } - return next; - } - - next_state_t tryReceive(rx_alarm_t alarmType) - { - next_state_t next; - if (call RadioRx.isReceiving()){ - next = DO_NOTHING; - } else if (call RadioRx.isPrepared()){ - call RadioRx.receive(NULL, 0); - switch (alarmType) - { - case INDIRECT_TX_ALARM: call IndirectTxWaitAlarm.start(m_macMaxFrameTotalWaitTime); break; - case BROADCAST_ALARM: call BroadcastAlarm.start(m_macMaxFrameTotalWaitTime); break; - case NO_ALARM: break; - } - next = DO_NOTHING; - } else if (call RadioOff.isOff()) - next = PREPARE_RX; - else - next = SWITCH_OFF; - return next; - } - - next_state_t trySwitchOff() - { - next_state_t next; - if (call RadioOff.isOff()) - next = DO_NOTHING; - else - next = SWITCH_OFF; - return next; - } - - async event void RadioTx.loadDone(){ m_lock = FALSE; updateState();} - async event void RadioOff.offDone(){ m_lock = FALSE; updateState();} - async event void RadioRx.prepareDone(){ m_lock = FALSE; updateState();} - - async event void CapEndAlarm.fired(){ - call Debug.log(LEVEL_IMPORTANT, CapP_CAP_END_FIRED, superframeDirection, 0, 0); - updateState(); - } - async event void BLEAlarm.fired(){ updateState();} - event void RxEnableStateChange.notify(bool whatever){ updateState();} - async event void BroadcastAlarm.fired(){ m_broadcastRxPending = FALSE; updateState();} - - async event void IndirectTxWaitAlarm.fired() - { - atomic { - if (m_indirectTxPending){ - m_indirectTxPending = FALSE; - post signalTxDoneTask(); - } - } - } - - async event void RadioTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error) - { - bool retry = FALSE; - switch (error) - { - case SUCCESS: - m_result = IEEE154_SUCCESS; - if (DEVICE_ROLE && frame->payload[0] == CMD_FRAME_DATA_REQUEST && - ((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD){ - // just transmitted a data request frame - m_result = IEEE154_NO_DATA; // pessimistic - if (ackPendingFlag){ - // the coordinator has data for us; switch to Rx - // to complete the indirect transmission - m_indirectTxPending = TRUE; - m_lastFrame = m_currentFrame; - m_currentFrame = NULL; - if (call RadioRx.prepare() != SUCCESS) // SHOULD succeed - call RadioOff.off(); - return; - } - } - break; - case EBUSY: - // we're following the SDL Spec in IEEE 802.15.4-2003 Annex D - m_result = IEEE154_CHANNEL_ACCESS_FAILURE; - m_NB += 1; - if (m_NB < m_macMaxCSMABackoffs){ - m_BE += 1; - if (m_BE > m_macMaxBE) - m_BE = m_macMaxBE; - retry = TRUE; - } - break; - case ENOACK: - // we're following the SDL Spec in IEEE 802.15.4-2003 Annex D - m_result = IEEE154_NO_ACK; - m_NB += 1; - // shouldn't the next check be (m_NB-1 < m_macMaxFrameRetries)? but - // on the other hand, NB is used for CHANNEL_ACCESS_FAILURE and NO_ACK, - // i.e. m_NB does not tell us much about past retransmissions anyway... - if (m_NB < m_macMaxFrameRetries){ - m_BE = m_macMinBE; - retry = TRUE; - } - break; - default: break; - } - if (retry){ - m_backoff = generateRandomBackoff(m_BE) * IEEE154_aUnitBackoffPeriod; // next backoff - m_backoffElapsed = 0; - } else if (COORD_ROLE && frame == m_bcastFrame){ - // signal result of broadcast transmissions immediately - restoreFrameFromBackup(); - signalTxBroadcastDone(m_bcastFrame, m_result); - m_bcastFrame = NULL; - } else { - m_lastFrame = m_currentFrame; - m_currentFrame = NULL; - post signalTxDoneTask(); - } - m_lock = FALSE; - updateState(); - } - - task void signalTxDoneTask() - { - ieee154_txframe_t *lastFrame = m_lastFrame; - m_lastFrame = NULL; // only now can a next transmission begin - m_indirectTxPending = FALSE; - if (lastFrame) - signal FrameTx.transmitDone(lastFrame, m_result); - updateState(); - } - - event message_t* RadioRx.received(message_t* frame, ieee154_reftime_t *timestamp) - { - // received a frame during CAP - find out frame type and - // signal it to corresponding client component - uint8_t *payload = (uint8_t *) frame->data; - uint8_t *mhr = MHR(frame); - uint8_t frameType = mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK; - if (frameType == FC1_FRAMETYPE_CMD) - frameType += payload[0]; - atomic { - if (DEVICE_ROLE && m_indirectTxPending){ - message_t* frameBuf; - call IndirectTxWaitAlarm.stop(); - // TODO: check! - //if (frame->payloadLen) - // is this frame from our coordinator? hmm... we cannot say - // with certainty, because we might only know either the - // coordinator extended or short address (and the frame could - // have been sent with the other addressing mode) ?? - m_result = IEEE154_SUCCESS; - frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); - signal IndirectTxWaitAlarm.fired(); - return frameBuf; - } else - return signal FrameRx.received[frameType](frame); - } - } - - void backupCurrentFrame() - { - ieee154_cap_frame_backup_t backup = {m_currentFrame, m_BE, m_macMaxCSMABackoffs, - m_macMaxBE, m_macMinBE, m_NB, m_backoff, m_backoffElapsed, m_transactionTime}; - call FrameBackup.setNow(&backup); - } - - void restoreFrameFromBackup() - { - ieee154_cap_frame_backup_t *backup = call FrameRestore.getNow(); - if (backup != NULL){ - m_currentFrame = backup->frame; - m_BE = backup->BE; - m_macMaxCSMABackoffs = backup->allowedBackoffs; - m_macMaxBE = backup->macMaxBE; - m_macMinBE = backup->macMinBE; - m_NB = backup->NB; - m_backoff = backup->backoff; - m_backoffElapsed = backup->backoffElapsed; - m_transactionTime = backup->transactionTime; - } - } - - async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) - { - // if this command is called then it is (MUST be) called - // only just before the token is transferred to this component - // and it is then be called only once per CAP (max. one broadcast - // is allowed after a beacon transmission) - atomic { - if (!call Token.isOwner() && m_bcastFrame == NULL){ - m_bcastFrame = frame; - return IEEE154_SUCCESS; - } else { - call Leds.led0On(); - return IEEE154_TRANSACTION_OVERFLOW; - } - } - } - - void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error) - { - signal BroadcastTx.transmitNowDone(frame, error); - } - - task void wasRxEnabledTask() - { - signal WasRxEnabled.notify(TRUE); - } - - bool isUnslottedCSMA_CA() - { - return (m_numCCA == 1); - } - - event void Token.granted() - { - // the current frame should be transmitted using unslotted CSMA-CA - updateState(); - } - - default event void FrameTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status){} - default event message_t* FrameRx.received[uint8_t client](message_t* data){return data;} - default async command bool IsRxEnableActive.getNow(){return FALSE;} - - default async command void IndirectTxWaitAlarm.start(uint32_t dt){call Leds.led0On();} - default async command void IndirectTxWaitAlarm.stop(){call Leds.led0On();} - default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();} - - default async command void BroadcastAlarm.start(uint32_t dt){call Leds.led0On();} - default async command void BroadcastAlarm.stop(){call Leds.led0On();} - default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();} - - default async command bool IsRxBroadcastPending.getNow(){ return FALSE;} - default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status){} - default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame){return msg;} - default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val ){return FAIL;} - default async command ieee154_cap_frame_backup_t* FrameRestore.getNow(){return NULL;} - - command error_t WasRxEnabled.enable(){return FAIL;} - command error_t WasRxEnabled.disable(){return FAIL;} - command error_t FindBeacon.enable(){return FAIL;} - command error_t FindBeacon.disable(){return FAIL;} -} diff --git a/tos/lib/mac/tkn154/CsmaQueueP.nc b/tos/lib/mac/tkn154/CsmaQueueP.nc deleted file mode 100644 index f89c762a..00000000 --- a/tos/lib/mac/tkn154/CsmaQueueP.nc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2008, Technische Universitaet Berlin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the Technische Universitaet Berlin nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - Revision ------------------------------------------------------------- - * $Revision$ - * $Date$ - * @author Jan Hauer - * ======================================================================== - */ -#include "TKN154_MAC.h" -generic module CsmaQueueP() { - provides - { - interface Init as Reset; - interface FrameTx[uint8_t client]; - interface FrameRx as FrameExtracted[uint8_t client]; - interface Purge; - } uses { - interface Queue; - interface FrameTx as FrameTxCsma; - interface FrameRx as SubFrameExtracted; - } -} -implementation -{ - task void txTask(); - bool m_busy; - uint8_t m_client; - - command error_t Reset.init() - { - while (call Queue.size()){ - ieee154_txframe_t *txFrame = call Queue.dequeue(); - signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_OVERFLOW); - } - m_busy = FALSE; - return SUCCESS; - } - - command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame) - { - txFrame->client = client; - if (call Queue.enqueue(txFrame) != SUCCESS) - return IEEE154_TRANSACTION_OVERFLOW; - else { - post txTask(); - return IEEE154_SUCCESS; - } - } - - task void txTask() - { - if (!m_busy && call Queue.size()){ - ieee154_txframe_t *txFrame = call Queue.head(); - if (txFrame->headerLen == 0){ - // was purged - call Queue.dequeue(); - signal Purge.purgeDone(txFrame, IEEE154_SUCCESS); - post txTask(); - } - m_client = txFrame->client; - if (call FrameTxCsma.transmit(txFrame) == IEEE154_SUCCESS){ - m_busy = TRUE; - } - } - } - - event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) - { - call Queue.dequeue(); - m_busy = FALSE; - signal FrameTx.transmitDone[txFrame->client](txFrame, status); - post txTask(); - } - - event message_t* SubFrameExtracted.received(message_t* frame) - { - // this event is signalled when a frame has been received - // in response to a data request command frame. The transmitDone - // event will be signalled later - return signal FrameExtracted.received[m_client](frame); - } - - default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){} - - command ieee154_status_t Purge.purge(uint8_t msduHandle) - { - uint8_t qSize = call Queue.size(), i; - if (qSize > 1){ - for (i=0; iheader->mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_DATA) && - txFrame->handle == msduHandle){ - txFrame->headerLen = 0; // mark as invalid - return IEEE154_SUCCESS; - } - } - } - return IEEE154_INVALID_HANDLE; - } - - default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status){} -} diff --git a/tos/lib/mac/tkn154/DisassociateP.nc b/tos/lib/mac/tkn154/DisassociateP.nc index 5eddab18..a229f50a 100644 --- a/tos/lib/mac/tkn154/DisassociateP.nc +++ b/tos/lib/mac/tkn154/DisassociateP.nc @@ -142,7 +142,7 @@ implementation call TxControlPool.put(txControl); } } - call Debug.log(LEVEL_INFO, DISSASSOCIATE_REQUEST, status, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, DISSASSOCIATE_REQUEST, status, 0, 0); return status; } @@ -158,7 +158,7 @@ implementation call FrameUtility.convertToNative(&DeviceAddress.extendedAddress, &mhr[srcAddrOffset]); call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) data->header - offsetof(ieee154_txcontrol_t, header))); call TxFramePool.put(data); - call Debug.log(LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 2, 0); + call Debug.log(DEBUG_LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 2, 0); m_disAssociationOngoing = FALSE; signal MLME_DISASSOCIATE.confirm(status, DeviceAddrMode, DevicePANID, DeviceAddress); } @@ -176,10 +176,10 @@ implementation uint16_t DevicePANID = *((nxle_uint16_t*) (&(mhr[MHR_INDEX_ADDRESS]))); ieee154_address_t DeviceAddress; call FrameUtility.convertToNative(&DeviceAddress.extendedAddress, &mhr[dstAddrOffset]); - call Debug.log(LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 1, 0); + call Debug.log(DEBUG_LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 1, 0); call TxControlPool.put((ieee154_txcontrol_t*) ((uint8_t*) data->header - offsetof(ieee154_txcontrol_t, header))); call TxFramePool.put(data); - call Debug.log(LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 2, 0); + call Debug.log(DEBUG_LEVEL_INFO, DISSASSOCIATE_TXDONE, status, 2, 0); m_disAssociationOngoing = FALSE; signal MLME_DISASSOCIATE.confirm(status, DeviceAddrMode, DevicePANID, DeviceAddress); } @@ -205,7 +205,7 @@ implementation { // received a disassociation notification from the device ieee154_address_t address; - call Debug.log(LEVEL_INFO, DISSASSOCIATE_RX, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, DISSASSOCIATE_RX, 0, 0, 0); if (call Frame.getSrcAddrMode(frame) == ADDR_MODE_EXTENDED_ADDRESS && call Frame.getSrcAddr(frame, &address) == SUCCESS) signal MLME_DISASSOCIATE.indication(address.extendedAddress, frame->data[1], NULL); diff --git a/tos/lib/mac/tkn154/FrameDispatchP.nc b/tos/lib/mac/tkn154/FrameDispatchP.nc new file mode 100644 index 00000000..ad8b693e --- /dev/null +++ b/tos/lib/mac/tkn154/FrameDispatchP.nc @@ -0,0 +1,770 @@ +/* + * Copyright (c) 2008, Technische Universitaet Berlin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the Technische Universitaet Berlin nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * - Revision ------------------------------------------------------------- + * $Revision$ + * $Date$ + * @author Jan Hauer + * ======================================================================== + */ + +#include "TKN154_PHY.h" +#include "TKN154_MAC.h" + + +/** + * This module is responsible for preparing the transmission/reception of DATA + * and COMMAND frames in the contention access period (CAP, slotted CSMA-CA) or + * in a nonbeacon-enabled PAN (unslotted CSMA-CA). It prepares the relevant + * parameters of the CSMA-CA algorithm (NB, BE, etc.), but it does not implement + * the CSMA-CA algorithm (the CSMA-CA algorithm is implemented in the radio + * driver). + * + * In a beacon-enabled this module does slightly different things depending on + * whether it is the CAP for an outgoing superframe (superframeDirection = + * OUTGOING_SUPERFRAME), i.e. the CAP from the perspective of a coordinator + * after it has transmitted its own beacon; or for an incoming superframe + * (superframeDirection = INCOMING_SUPERFRAME), i.e. the CAP from the + * perspective of a device after it has received a beacon from its coordinator. + * For example, in the CAP a coordinator will usually listen for incoming + * frames from the devices, and a device will usually switch the radio off + * unless it has a frame to transmit. In nonbeacon-enabled PANs the + * superframeDirection parameter is ignored. + */ + +generic module FrameDispatchP(uint8_t superframeDirection) +{ + provides + { + interface Init as Reset; + interface FrameTx as FrameTx; + interface FrameRx as FrameRx[uint8_t frameType]; + interface FrameExtracted as FrameExtracted[uint8_t frameType]; + interface FrameTxNow as BroadcastTx; + interface Notify as WasRxEnabled; + interface Notify as FindBeacon; + } + uses + { + interface Alarm as CapEndAlarm; + interface Alarm as BLEAlarm; + interface Alarm as IndirectTxWaitAlarm; + interface Alarm as BroadcastAlarm; + interface Resource as Token; + interface GetNow as IsTokenRequested; + interface ResourceTransfer as TokenToCfp; + interface ResourceTransferred as TokenTransferred; + interface GetNow as CapStart; + interface GetNow as CapStartRefTime; + interface GetNow as CapLen; + interface GetNow as IsBLEActive; + interface GetNow as BLELen; + interface GetNow as IsRxBroadcastPending; + interface GetNow as IsRxEnableActive; + interface Get as GetIndirectTxFrame; + interface Notify as RxEnableStateChange; + interface GetNow as IsTrackingBeacons; + interface FrameUtility; + interface RadioTx; + interface RadioRx; + interface RadioOff; + interface GetNow as IsBeaconEnabledPAN; + interface MLME_GET; + interface MLME_SET; + interface Ieee802154Debug as Debug; + interface TimeCalc; + interface Leds; + interface SetNow as FrameBackup; + interface GetNow as FrameRestore; + } +} +implementation +{ + typedef enum { + SWITCH_OFF, + LOAD_TX, + PREPARE_RX, + DO_NOTHING, + WAIT_FOR_TXDONE, + } next_state_t; + + typedef enum { + INDIRECT_TX_ALARM, + BROADCAST_ALARM, + NO_ALARM, + } rx_alarm_t; + + enum { + COORD_ROLE = (superframeDirection == OUTGOING_SUPERFRAME), + DEVICE_ROLE = !COORD_ROLE, + }; + + norace bool m_lock; + norace ieee154_txframe_t *m_currentFrame; + norace ieee154_txframe_t *m_bcastFrame; + norace ieee154_txframe_t *m_lastFrame; + + norace ieee154_csma_t m_csmaParams; + norace bool m_resume; + norace uint16_t m_remainingBackoff; + norace ieee154_macMaxBE_t m_BE; + norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs; + norace ieee154_macMaxBE_t m_macMaxBE; + norace bool m_slottedCsma; + norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries; + norace ieee154_status_t m_result; + norace uint32_t m_transactionTime; + norace bool m_indirectTxPending = FALSE; + norace bool m_broadcastRxPending; + norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime; + + +#ifdef TKN154_SERIAL_DEBUG +#define DEBUG_NEXT_BUFFER_SIZE 12 + norace uint8_t dbgHistory[DEBUG_NEXT_BUFFER_SIZE]; + norace uint8_t dbgHistoryIndex; + void dbgHistoryReset(){dbgHistoryIndex=0; memset(dbgHistory, 0xFF, DEBUG_NEXT_BUFFER_SIZE);} + void dbgHistoryAdd(uint8_t nextState) + { + dbgHistory[dbgHistoryIndex] = nextState; + dbgHistoryIndex = (dbgHistoryIndex+1) % DEBUG_NEXT_BUFFER_SIZE; + } + void dbgHistoryFlush() + { + uint8_t i,k=dbgHistoryIndex; + uint32_t s1=0xFFFFFFFF,s2=0xFFFFFFFF,s3=0xFFFFFFFF; + for (i=0; i<4; i++){ s1 = s1 << 8; s1 |= dbgHistory[k]; k = (k+1) % DEBUG_NEXT_BUFFER_SIZE;} + for (i=0; i<4; i++){ s2 = s2 << 8; s2 |= dbgHistory[k]; k = (k+1) % DEBUG_NEXT_BUFFER_SIZE;} + for (i=0; i<4; i++){ s3 = s3 << 8; s3 |= dbgHistory[k]; k = (k+1) % DEBUG_NEXT_BUFFER_SIZE;} + call Debug.log(DEBUG_LEVEL_INFO, 12, s1,s2,s3); + } +#else + void dbgHistoryReset(){} + void dbgHistoryAdd(uint8_t nextState){} + void dbgHistoryFlush(){} +#endif + + void stopAllAlarms(); + next_state_t tryReceive(rx_alarm_t alarmType); + next_state_t tryTransmit(); + next_state_t trySwitchOff(); + void backupCurrentFrame(); + void restoreFrameFromBackup(); + void updateState(); + void setCurrentFrame(ieee154_txframe_t *frame); + void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error); + void transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result); + task void signalTxDoneTask(); + task void setupTxBroadcastTask(); + task void wasRxEnabledTask(); + + command error_t Reset.init() + { + if (m_currentFrame) + signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW); + if (m_lastFrame) + signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW); + if (m_bcastFrame) + signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW); + m_currentFrame = m_lastFrame = m_bcastFrame = NULL; + stopAllAlarms(); + return SUCCESS; + } + + async event void TokenTransferred.transferred() + { + // we got the token, i.e. CAP has just started + uint32_t actualCapLen = call CapLen.getNow(); + dbgHistoryReset(); + if (!call IsBeaconEnabledPAN.getNow()){ + call Leds.led0On(); // internal error! + call TokenToCfp.transfer(); + call Debug.log(DEBUG_LEVEL_IMPORTANT, 0, 0,0,0); + } else if (DEVICE_ROLE && actualCapLen == 0){ + // very rare case: + // this can only happen, if we're on a beacon-enabled PAN, not tracking beacons, + // and searched but didn't find a beacon for aBaseSuperframeDuration*(2n+1) symbols + // -> transmit current frame using unslotted CSMA-CA + m_slottedCsma = FALSE; + updateState(); + return; + } else if (actualCapLen < IEEE154_ACTIVE_PERIOD_GUARD_TIME){ + call Debug.log(DEBUG_LEVEL_IMPORTANT, 1, superframeDirection, actualCapLen, IEEE154_ACTIVE_PERIOD_GUARD_TIME); + call TokenToCfp.transfer(); + return; + } else { + actualCapLen -= IEEE154_ACTIVE_PERIOD_GUARD_TIME; + if (DEVICE_ROLE) + m_broadcastRxPending = call IsRxBroadcastPending.getNow(); + else { + // COORD_ROLE + if (m_bcastFrame != NULL) { + // we have to transmit a broadcast frame immediately; this + // (possibly) requires a backup of the previously active frame + // and a reinitializing the CSMA parameters -> will do it + // in task context and then continue + m_lock = TRUE; + post setupTxBroadcastTask(); + call Debug.log(DEBUG_LEVEL_INFO, 7, 0,0,0); + } + } + call CapEndAlarm.startAt(call CapStart.getNow(), actualCapLen); + if (call IsBLEActive.getNow()) + call BLEAlarm.startAt(call CapStart.getNow(), call BLELen.getNow()); + call Debug.log(DEBUG_LEVEL_INFO, 2, call CapStart.getNow(), + actualCapLen, call CapStart.getNow()+ actualCapLen); + } + updateState(); + } + + command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) + { + //call Debug.log(DEBUG_LEVEL_INFO, 4, m_lock, call Token.isOwner(), m_currentFrame == NULL); + if (m_currentFrame != NULL){ + call Debug.log(DEBUG_LEVEL_IMPORTANT, 5, 0,0,0); + return IEEE154_TRANSACTION_OVERFLOW; + } else { + setCurrentFrame(frame); + if (!call IsBeaconEnabledPAN.getNow()){ + call Token.request(); // prepare for unslotted CSMA-CA + } else { + // a beacon must be found before transmitting in a beacon-enabled PAN + if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()){ + signal FindBeacon.notify(TRUE); + // we'll receive the Token at latest after aBaseSuperframeDuration*(2n+1) symbols; + // if the beacon was not found, then we'll send the frame using unslotted CSMA-CA + } + updateState(); + } + return IEEE154_SUCCESS; + } + } + + task void setupTxBroadcastTask() + { + ieee154_macDSN_t tmp; + ieee154_txframe_t *oldFrame = m_currentFrame; + if (COORD_ROLE){ + if (m_bcastFrame != NULL){ + // broadcasts should be transmitted *immediately* after the beacon, + // which may interrupt a pending transmit operation from the previous + // CAP; back up the last active frame configuration (may be none) + // and restore it after the broadcast frame has been transmitted; + // do this through interfaces and don't wire them for DEVICE_ROLE, + // so we don't waste the RAM of devices + backupCurrentFrame(); + setCurrentFrame(m_bcastFrame); + if (oldFrame){ + // now the sequence number are out of order... swap them back + tmp = m_bcastFrame->header->mhr[MHR_INDEX_SEQNO]; + m_bcastFrame->header->mhr[MHR_INDEX_SEQNO] = + oldFrame->header->mhr[MHR_INDEX_SEQNO]; + oldFrame->header->mhr[MHR_INDEX_SEQNO] = tmp; + } + } + } + m_lock = FALSE; + updateState(); + } + + void setCurrentFrame(ieee154_txframe_t *frame) + { + ieee154_macDSN_t dsn = call MLME_GET.macDSN(); + frame->header->mhr[MHR_INDEX_SEQNO] = dsn++; + call MLME_SET.macDSN(dsn); + m_csmaParams.NB = 0; + m_csmaParams.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs(); + m_csmaParams.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE(); + m_csmaParams.BE = call MLME_GET.macMinBE(); + if (call MLME_GET.macBattLifeExt() && m_csmaParams.BE > 2) + m_csmaParams.BE = 2; + m_BE = m_csmaParams.BE; + if (COORD_ROLE && call GetIndirectTxFrame.get() == frame) + m_macMaxFrameRetries = 0; // this is an indirect transmissions (never retransmit) + else + m_macMaxFrameRetries = call MLME_GET.macMaxFrameRetries(); + m_slottedCsma = call IsBeaconEnabledPAN.getNow(); + m_transactionTime = IEEE154_SHR_DURATION + + (frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET; // extra 2 for CRC + if (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST) + m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod + + 11 * IEEE154_SYMBOLS_PER_OCTET); // 11 byte for the ACK PPDU + //if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize) + // m_transactionTime += call MLME_GET.macMinLIFSPeriod(); + //else + // m_transactionTime += call MLME_GET.macMinSIFSPeriod(); + m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime(); + m_currentFrame = frame; + } + + void stopAllAlarms() + { + call CapEndAlarm.stop(); + if (DEVICE_ROLE){ + call IndirectTxWaitAlarm.stop(); + call BroadcastAlarm.stop(); + } + call BLEAlarm.stop(); + } + + /** + * The updateState() function is called whenever some event happened that + * might require a state change; it implements a lock mechanism (m_lock) to + * prevent race conditions. Whenever the lock is set a "done"-event (from a + * RadioTx/RadioRx/RadioOff interface) is pending and will "soon" unset the + * lock (and then updateState() will called again). The updateState() + * function decides about the next state by checking a list of possible + * current states ordered by priority, e.g. it first always checks whether + * the CAP is still active. Calling this function more than necessary can do + * no harm, but it SHOULD be called whenever an event happened that might + * lead to a state change. + */ + + void updateState() + { + error_t result = SUCCESS; + next_state_t next; + atomic { + // long atomics are bad... but in this block, once the + // current state has been determined only one branch will + // be taken (no loops, etc.) + if (m_lock || !call Token.isOwner()) + return; + m_lock = TRUE; // lock + + // Check 1: for beacon-enabled PANs, has the CAP finished? + if (call IsBeaconEnabledPAN.getNow() + && (COORD_ROLE || call IsTrackingBeacons.getNow()) // FALSE only if device could't find a beacon + && (call TimeCalc.hasExpired(call CapStart.getNow(), call CapLen.getNow()-IEEE154_ACTIVE_PERIOD_GUARD_TIME) || + !call CapEndAlarm.isRunning())){ + if (call RadioOff.isOff()) { + stopAllAlarms(); // may still fire, locked through isOwner() + if (DEVICE_ROLE && m_indirectTxPending) + signal IndirectTxWaitAlarm.fired(); + m_broadcastRxPending = FALSE; + if (COORD_ROLE && m_bcastFrame){ + // didn't manage to transmit a broadcast + restoreFrameFromBackup(); + signalTxBroadcastDone(m_bcastFrame, IEEE154_CHANNEL_ACCESS_FAILURE); + m_bcastFrame = NULL; + } + m_lock = FALSE; // unlock + call TokenToCfp.transfer(); + call Debug.log(DEBUG_LEVEL_INFO, 8, 0,0,0); + dbgHistoryFlush(); + return; + } else + next = SWITCH_OFF; + } + + // Check 2: should a broadcast frame be received/transmitted immediately + // at the start of CAP? + else if (DEVICE_ROLE && m_broadcastRxPending){ + // receive a broadcast from coordinator + next = tryReceive(BROADCAST_ALARM); + } else if (COORD_ROLE && m_bcastFrame){ + next = tryTransmit(); + } + + // Check 3: was an indirect transmission successfully started + // and are we now waiting for a frame from the coordinator? + else if (DEVICE_ROLE && m_indirectTxPending) { + next = tryReceive(INDIRECT_TX_ALARM); + } + + // Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending? + else if (call IsTokenRequested.getNow() && call IsBeaconEnabledPAN.getNow()) { + if (call RadioOff.isOff()) { + stopAllAlarms(); // may still fire, but is locked through isOwner() + // nothing more to do... just release the Token + m_lock = FALSE; // unlock + call TokenToCfp.transfer(); + call Debug.log(DEBUG_LEVEL_INFO, 9, call IsTokenRequested.getNow(),0,0); + dbgHistoryFlush(); + return; + } else + next = SWITCH_OFF; + } + + // Check 5: is battery life extension (BLE) active and + // has the BLE period expired? + else if (call IsBLEActive.getNow() && + call TimeCalc.hasExpired(call CapStart.getNow(), call BLELen.getNow()) && + !call IsRxEnableActive.getNow()) { + next = trySwitchOff(); + } + + // Check 6: is there a frame ready to transmit? + else if (m_currentFrame != NULL) { + next = tryTransmit(); + } + + // Check 7: should we be in receive mode? + else if (COORD_ROLE || call IsRxEnableActive.getNow()) { + next = tryReceive(NO_ALARM); + if (next == DO_NOTHING && call IsRxEnableActive.getNow()){ + // this means there is an active MLME_RX_ENABLE.request + // and the radio was just switched to Rx mode - signal + // a notify event to inform the next higher layer + post wasRxEnabledTask(); + } + } + + // Check 8: just make sure the radio is switched off + else { + next = trySwitchOff(); + if (next == DO_NOTHING && + (!call IsBeaconEnabledPAN.getNow() || (DEVICE_ROLE && call CapLen.getNow() == 0))){ + // nothing more to do... just release the Token + stopAllAlarms(); // may still fire, but is locked through isOwner() + m_lock = FALSE; // unlock + call Debug.log(DEBUG_LEVEL_INFO, 10, 0,0,0); + dbgHistoryFlush(); + call Token.release(); + return; + } + } + + // if there is nothing to do, then we must clear the lock + if (next == DO_NOTHING) + m_lock = FALSE; + } // atomic + dbgHistoryAdd(next); + // put next state in operation (possibly keeping the lock) + switch (next) + { + case SWITCH_OFF: result = call RadioOff.off(); break; + case LOAD_TX: result = call RadioTx.load(m_currentFrame); break; + case PREPARE_RX: result = call RadioRx.prepare(); break; + case WAIT_FOR_TXDONE: break; + case DO_NOTHING: break; + } + if (result != SUCCESS) + call Leds.led0On(); // internal error: could not update state !!! + } + + next_state_t tryTransmit() + { + // tries to transmit m_currentFrame using the either slotted or unslotted csma-ca + next_state_t next; + if (call RadioTx.getLoadedFrame() == m_currentFrame){ + // the frame is already loaded -> transmit it now + if (!m_slottedCsma){ + // unslotted CSMA-CA + call RadioTx.transmitUnslottedCsmaCa(&m_csmaParams); + next = WAIT_FOR_TXDONE; // this will NOT clear the lock + } else { + // slotted CSMA-CA + uint32_t dtMax = call CapLen.getNow() - m_transactionTime - IEEE154_ACTIVE_PERIOD_GUARD_TIME; + if (dtMax > call CapLen.getNow()) + dtMax = 0; + if (call IsBLEActive.getNow()){ + // battery life extension + uint16_t bleLen = call BLELen.getNow(); + if (bleLen < dtMax) + dtMax = bleLen; + } + if (call TimeCalc.hasExpired(call CapStart.getNow() - 60, dtMax)) // 60 is for enabling Rx + 2 CCA + next = SWITCH_OFF; // frame doesn't possibly fit in the remaining CAP + else { + call RadioTx.transmitSlottedCsmaCa(call CapStartRefTime.getNow(), + dtMax, m_resume, m_remainingBackoff, &m_csmaParams); + //call Debug.log(DEBUG_LEVEL_INFO, 13, call CapStart.getNow(), dtMax, m_resume); + next = WAIT_FOR_TXDONE; // this will NOT clear the lock + } + } + } else { + // the frame to transmit has not yet been loaded -> load it now + if (!call RadioOff.isOff()) + next = SWITCH_OFF; + else { + if (m_lastFrame){ + // the done event for the previous frame has not yet been + // signalled to the upper layer -> wait + next = DO_NOTHING; + } else + next = LOAD_TX; + } + } + return next; + } + + next_state_t tryReceive(rx_alarm_t alarmType) + { + next_state_t next; + if (call RadioRx.isReceiving()){ + next = DO_NOTHING; + } else if (call RadioRx.isPrepared()){ + call RadioRx.receive(NULL, 0); + switch (alarmType) + { + case INDIRECT_TX_ALARM: call IndirectTxWaitAlarm.start(m_macMaxFrameTotalWaitTime); break; + case BROADCAST_ALARM: call BroadcastAlarm.start(m_macMaxFrameTotalWaitTime); break; + case NO_ALARM: break; + } + next = DO_NOTHING; + } else if (call RadioOff.isOff()) + next = PREPARE_RX; + else + next = SWITCH_OFF; + return next; + } + + next_state_t trySwitchOff() + { + next_state_t next; + if (call RadioOff.isOff()) + next = DO_NOTHING; + else + next = SWITCH_OFF; + return next; + } + + async event void RadioTx.loadDone(){ m_lock = FALSE; updateState();} + async event void RadioOff.offDone(){ m_lock = FALSE; updateState();} + async event void RadioRx.prepareDone(){ m_lock = FALSE; updateState();} + + async event void CapEndAlarm.fired(){ + call Debug.log(DEBUG_LEVEL_IMPORTANT, 3, superframeDirection, 0, 0); + updateState(); + } + async event void BLEAlarm.fired(){ updateState();} + event void RxEnableStateChange.notify(bool whatever){ updateState();} + async event void BroadcastAlarm.fired(){ m_broadcastRxPending = FALSE; updateState();} + + async event void IndirectTxWaitAlarm.fired() + { + atomic { + if (m_indirectTxPending){ + m_indirectTxPending = FALSE; + post signalTxDoneTask(); + } + } + } + + async event void RadioTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result) + { + transmitDone(frame, NULL, ackPendingFlag, csmaParams, result); + } + + async event void RadioTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result) + { + if (result == ERETRY){ + m_resume = TRUE; + m_remainingBackoff = remainingBackoff; + } else + m_resume = FALSE; + transmitDone(frame, txTime, ackPendingFlag, csmaParams, result); + } + + void transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result) + { + bool done = TRUE; + //call Debug.log(DEBUG_LEVEL_INFO, 11, result,0,0); + switch (result) + { + case SUCCESS: + // frame was successfully transmitted, if ACK was requested + // then a matching ACK was successfully received also + m_result = IEEE154_SUCCESS; + if (DEVICE_ROLE && frame->payload[0] == CMD_FRAME_DATA_REQUEST && + ((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD){ + // this was a data request frame + m_result = IEEE154_NO_DATA; // pessimistic + if (ackPendingFlag){ + // the coordinator has data for us; switch to Rx + // to complete the indirect transmission + m_indirectTxPending = TRUE; + m_lastFrame = m_currentFrame; + m_currentFrame = NULL; + if (call RadioRx.prepare() != SUCCESS) // SHOULD succeed + call RadioOff.off(); + return; + } + } + break; + case FAIL: + // CSMA-CA algorithm failed: frame was not transmitted, + // because channel was never idle (including backoff attempts) + m_result = IEEE154_CHANNEL_ACCESS_FAILURE; + break; + case ENOACK: + // frame was transmitted, but we didn't receive an ACK (and + // the AckRequest flag was set in the frame header) + // note: coordinator never retransmits an indirect transmission (see above) + if (m_macMaxFrameRetries > 0) { + // retransmit: reinitialize CSMA-CA parameters + done = FALSE; + m_csmaParams.NB = 0; + m_csmaParams.macMaxCsmaBackoffs = m_macMaxCSMABackoffs; + m_csmaParams.macMaxBE = m_macMaxBE; + m_csmaParams.BE = m_BE; + m_macMaxFrameRetries -= 1; + } else + m_result = IEEE154_NO_ACK; + break; + case ERETRY: + // frame was not transmitted, because the transaction does not + // fit in the remaining CAP (in beacon-enabled PANs only) + done = FALSE; + break; + default: + break; + } + if (COORD_ROLE && frame == m_bcastFrame){ + // always signal result of broadcast transmissions immediately + restoreFrameFromBackup(); + signalTxBroadcastDone(m_bcastFrame, (!done) ? IEEE154_CHANNEL_ACCESS_FAILURE : m_result); + m_bcastFrame = NULL; + } else if (done) { + m_lastFrame = m_currentFrame; + m_currentFrame = NULL; + post signalTxDoneTask(); + } + m_lock = FALSE; + updateState(); + } + + task void signalTxDoneTask() + { + ieee154_txframe_t *lastFrame = m_lastFrame; + m_lastFrame = NULL; // only now can a next transmission begin + m_indirectTxPending = FALSE; + if (lastFrame) + signal FrameTx.transmitDone(lastFrame, m_result); + updateState(); + } + + event message_t* RadioRx.received(message_t* frame, ieee154_reftime_t *timestamp) + { + // received a frame during CAP - find out frame type and + // signal it to corresponding client component + uint8_t *payload = (uint8_t *) frame->data; + uint8_t *mhr = MHR(frame); + uint8_t frameType = mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK; + if (frameType == FC1_FRAMETYPE_CMD) + frameType += payload[0]; + atomic { + if (DEVICE_ROLE && m_indirectTxPending){ + message_t* frameBuf; + call IndirectTxWaitAlarm.stop(); + // TODO: check! + //if (frame->payloadLen) + // is this frame from our coordinator? hmm... we cannot say + // with certainty, because we might only know either the + // coordinator extended or short address (and the frame could + // have been sent with the other addressing mode) ?? + m_result = IEEE154_SUCCESS; + frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); + signal IndirectTxWaitAlarm.fired(); + return frameBuf; + } else + return signal FrameRx.received[frameType](frame); + } + } + + void backupCurrentFrame() + { + ieee154_cap_frame_backup_t backup = {m_currentFrame, m_csmaParams, m_transactionTime}; + call FrameBackup.setNow(&backup); + } + + void restoreFrameFromBackup() + { + ieee154_cap_frame_backup_t *backup = call FrameRestore.getNow(); + if (backup != NULL){ + m_currentFrame = backup->frame; + memcpy(&m_csmaParams, &backup->csmaParams, sizeof(ieee154_csma_t)); + m_transactionTime = backup->transactionTime; + } + } + + async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) + { + // if this command is called then it is (MUST be) called + // only just before the token is transferred to this component + // and it is then be called only once per CAP (max. one broadcast + // is allowed after a beacon transmission) + atomic { + if (!call Token.isOwner() && m_bcastFrame == NULL){ + m_bcastFrame = frame; + return IEEE154_SUCCESS; + } else { + call Leds.led0On(); + return IEEE154_TRANSACTION_OVERFLOW; + } + } + } + + void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error) + { + signal BroadcastTx.transmitNowDone(frame, error); + } + + task void wasRxEnabledTask() + { + signal WasRxEnabled.notify(TRUE); + } + + event void Token.granted() + { + // the current frame should be transmitted using unslotted CSMA-CA + dbgHistoryReset(); + call Debug.log(DEBUG_LEVEL_INFO, 6, 0,0,0); + updateState(); + } + + async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime){} + + default event void FrameTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status){} + default event message_t* FrameRx.received[uint8_t client](message_t* data){return data;} + default async command bool IsRxEnableActive.getNow(){return FALSE;} + + default async command void IndirectTxWaitAlarm.start(uint32_t dt){call Leds.led0On();} + default async command void IndirectTxWaitAlarm.stop(){call Leds.led0On();} + default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();} + + default async command void BroadcastAlarm.start(uint32_t dt){call Leds.led0On();} + default async command void BroadcastAlarm.stop(){call Leds.led0On();} + default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();} + + default async command bool IsRxBroadcastPending.getNow(){ return FALSE;} + default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status){} + default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame){return msg;} + default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val ){return FAIL;} + default async command ieee154_cap_frame_backup_t* FrameRestore.getNow(){return NULL;} + + command error_t WasRxEnabled.enable(){return FAIL;} + command error_t WasRxEnabled.disable(){return FAIL;} + command error_t FindBeacon.enable(){return FAIL;} + command error_t FindBeacon.disable(){return FAIL;} +} diff --git a/tos/lib/mac/tkn154/FrameDispatchQueueP.nc b/tos/lib/mac/tkn154/FrameDispatchQueueP.nc new file mode 100644 index 00000000..4e34605f --- /dev/null +++ b/tos/lib/mac/tkn154/FrameDispatchQueueP.nc @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2008, Technische Universitaet Berlin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the Technische Universitaet Berlin nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * - Revision ------------------------------------------------------------- + * $Revision$ + * $Date$ + * @author Jan Hauer + * ======================================================================== + */ +#include "TKN154_MAC.h" +generic module FrameDispatchQueueP() { + provides + { + interface Init as Reset; + interface FrameTx[uint8_t client]; + interface FrameRx as FrameExtracted[uint8_t client]; + interface Purge; + } uses { + interface Queue; + interface FrameTx as FrameTxCsma; + interface FrameRx as SubFrameExtracted; + } +} +implementation +{ + task void txTask(); + bool m_busy; + uint8_t m_client; + + command error_t Reset.init() + { + while (call Queue.size()){ + ieee154_txframe_t *txFrame = call Queue.dequeue(); + signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_OVERFLOW); + } + m_busy = FALSE; + return SUCCESS; + } + + command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame) + { + txFrame->client = client; + if (call Queue.enqueue(txFrame) != SUCCESS) + return IEEE154_TRANSACTION_OVERFLOW; + else { + post txTask(); + return IEEE154_SUCCESS; + } + } + + task void txTask() + { + if (!m_busy && call Queue.size()){ + ieee154_txframe_t *txFrame = call Queue.head(); + if (txFrame->headerLen == 0){ + // was purged + call Queue.dequeue(); + signal Purge.purgeDone(txFrame, IEEE154_SUCCESS); + post txTask(); + } + m_client = txFrame->client; + if (call FrameTxCsma.transmit(txFrame) == IEEE154_SUCCESS){ + m_busy = TRUE; + } + } + } + + event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) + { + call Queue.dequeue(); + m_busy = FALSE; + signal FrameTx.transmitDone[txFrame->client](txFrame, status); + post txTask(); + } + + event message_t* SubFrameExtracted.received(message_t* frame) + { + // this event is signalled when a frame has been received + // in response to a data request command frame. The transmitDone + // event will be signalled later + return signal FrameExtracted.received[m_client](frame); + } + + default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){} + + command ieee154_status_t Purge.purge(uint8_t msduHandle) + { + uint8_t qSize = call Queue.size(), i; + if (qSize > 1){ + for (i=0; iheader->mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_DATA) && + txFrame->handle == msduHandle){ + txFrame->headerLen = 0; // mark as invalid + return IEEE154_SUCCESS; + } + } + } + return IEEE154_INVALID_HANDLE; + } + + default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status){} +} diff --git a/tos/lib/mac/tkn154/IndirectTxP.nc b/tos/lib/mac/tkn154/IndirectTxP.nc index cf654ce6..d17ac67f 100644 --- a/tos/lib/mac/tkn154/IndirectTxP.nc +++ b/tos/lib/mac/tkn154/IndirectTxP.nc @@ -41,6 +41,7 @@ module IndirectTxP interface FrameTx[uint8_t client]; interface WriteBeaconField as PendingAddrWrite; interface Notify as PendingAddrSpecUpdated; + interface Get as GetIndirectTxFrame; interface Purge; } uses @@ -129,7 +130,7 @@ implementation for (j=0; j<8; j++) pendingAddrField[1 + 2*m_numShortPending + i*8 + j] = longAdrPtr[i][j]; pendingAddrField[0] = m_numShortPending | (m_numExtPending << 4); - call Debug.log(LEVEL_INFO, IndirectTxP_BEACON_ASSEMBLY, len,0,0); + call Debug.log(DEBUG_LEVEL_INFO, IndirectTxP_BEACON_ASSEMBLY, len,0,0); return len; } @@ -143,7 +144,7 @@ implementation // send a frame through indirect transmission uint8_t i; if (m_numTableEntries >= NUM_MAX_PENDING){ - call Debug.log(LEVEL_IMPORTANT, IndirectTxP_OVERFLOW, 0,0,0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, IndirectTxP_OVERFLOW, 0,0,0); return IEEE154_TRANSACTION_OVERFLOW; } txFrame->client = client; @@ -159,7 +160,7 @@ implementation m_numExtPending++; if (!call IndirectTxTimeout.isRunning()) call IndirectTxTimeout.startOneShot(getPersistenceTime()); - call Debug.log(LEVEL_INFO, IndirectTxP_NOTIFIED, 0,0,0); + call Debug.log(DEBUG_LEVEL_INFO, IndirectTxP_NOTIFIED, 0,0,0); signal PendingAddrSpecUpdated.notify(TRUE); return IEEE154_SUCCESS; } @@ -203,7 +204,7 @@ implementation } } } - call Debug.log(LEVEL_INFO, IndirectTxP_REQUESTED, NUM_MAX_PENDING-i,i,*src); + call Debug.log(DEBUG_LEVEL_INFO, IndirectTxP_REQUESTED, NUM_MAX_PENDING-i,i,*src); if (i != NUM_MAX_PENDING){ // found a matching frame, mark it for transmission m_txFrameTable[i]->client |= SEND_THIS_FRAME; @@ -219,16 +220,16 @@ implementation // iterate over the queued frames and transmit them in the CAP // (if they are marked for transmission) uint8_t i; - if (!m_pendingTxFrame && m_numTableEntries){ + if (m_pendingTxFrame == NULL && m_numTableEntries){ for (i=0; iclient & SEND_THIS_FRAME)){ // TODO: set frame pending bit, if there's more data for this destination m_pendingTxFrame = m_txFrameTable[i]; m_client = m_txFrameTable[i]->client; if (call CoordCapTx.transmit(m_txFrameTable[i]) == IEEE154_SUCCESS){ - call Debug.log(LEVEL_INFO, IndirectTxP_SEND_NOW, 0,0,0); + call Debug.log(DEBUG_LEVEL_INFO, IndirectTxP_SEND_NOW, 0,0,0); } else { - m_pendingTxFrame = 0; + m_pendingTxFrame = NULL; post tryCoordCapTxTask(); } return; // done - wait for txDone @@ -275,7 +276,7 @@ implementation event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { uint8_t i; - // TODO: if CSMA-CA algorithm failed, then frame shall remain in transaction queue + // TODO: if CSMA-CA algorithm failed, then frame shall still remain in transaction queue for (i=0; iclient](txFrame, status); post tryCoordCapTxTask(); - call Debug.log(LEVEL_INFO, IndirectTxP_SEND_DONE, status,m_numTableEntries,0); + call Debug.log(DEBUG_LEVEL_INFO, IndirectTxP_SEND_DONE, status,m_numTableEntries,0); } + command ieee154_txframe_t* GetIndirectTxFrame.get(){ return m_pendingTxFrame;} command error_t PendingAddrSpecUpdated.enable(){return FAIL;} command error_t PendingAddrSpecUpdated.disable(){return FAIL;} default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){} diff --git a/tos/lib/mac/tkn154/PollP.nc b/tos/lib/mac/tkn154/PollP.nc index df20b2a8..26972788 100644 --- a/tos/lib/mac/tkn154/PollP.nc +++ b/tos/lib/mac/tkn154/PollP.nc @@ -111,7 +111,7 @@ implementation if ((txStatus = call PollTx.transmit(txFrame)) != IEEE154_SUCCESS){ call TxFramePool.put(txFrame); call TxControlPool.put(txControl); - call Debug.log(LEVEL_IMPORTANT, PollP_ALLOC_FAIL1, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, PollP_ALLOC_FAIL1, 0, 0, 0); } else m_numPending++; } @@ -124,8 +124,8 @@ implementation ieee154_txframe_t *txFrame; ieee154_txcontrol_t *txControl; ieee154_status_t status = IEEE154_TRANSACTION_OVERFLOW; - call Debug.log(LEVEL_INFO, PollP_INTERNAL_POLL, CoordAddrMode, client, m_numPending); - if (client == SYNC_CLIENT && m_numPending != 0){ + call Debug.log(DEBUG_LEVEL_INFO, PollP_INTERNAL_POLL, CoordAddrMode, client, m_numPending); + if (client == SYNC_POLL_CLIENT && m_numPending != 0){ // no point in auto-requesting if user request is pending signal DataRequest.pollDone[client](); return IEEE154_SUCCESS; @@ -141,7 +141,7 @@ implementation if ((status = call PollTx.transmit(txFrame)) != IEEE154_SUCCESS){ call TxControlPool.put(txControl); call TxFramePool.put(txFrame); - call Debug.log(LEVEL_IMPORTANT, PollP_ALLOC_FAIL2, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, PollP_ALLOC_FAIL2, 0, 0, 0); } else m_numPending++; } @@ -188,23 +188,23 @@ implementation event message_t* DataExtracted.received(message_t* frame, ieee154_txframe_t *txFrame) { if (!txFrame){ - call Debug.log(LEVEL_CRITICAL, PollP_INTERNAL_ERROR, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_CRITICAL, PollP_INTERNAL_ERROR, 0, 0, 0); return frame; } else - call Debug.log(LEVEL_INFO, PollP_SUCCESS, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, PollP_SUCCESS, 0, 0, 0); if (txFrame->handle == HANDLE_MLME_POLL_REQUEST) signal MLME_POLL.confirm(IEEE154_SUCCESS); else signal DataRequest.pollDone[txFrame->handle](); txFrame->handle = HANDLE_MLME_POLL_SUCCESS; // mark as processed // TODO: check if pending bit is set (then initiate another POLL) - call Debug.log(LEVEL_IMPORTANT, PollP_RX, txFrame->handle, 0, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, PollP_RX, txFrame->handle, 0, 0); return signal DataRx.received(frame); } event void PollTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { - call Debug.log(LEVEL_IMPORTANT, PollP_TXDONE, status, txFrame->handle, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, PollP_TXDONE, status, txFrame->handle, 0); m_numPending--; if (txFrame->handle != HANDLE_MLME_POLL_SUCCESS){ // didn't receive a DATA frame from the coordinator diff --git a/tos/lib/mac/tkn154/PromiscuousModeP.nc b/tos/lib/mac/tkn154/PromiscuousModeP.nc index 4cba26cd..8261c7d8 100644 --- a/tos/lib/mac/tkn154/PromiscuousModeP.nc +++ b/tos/lib/mac/tkn154/PromiscuousModeP.nc @@ -81,7 +81,7 @@ implementation return FAIL; m_promiscuousState = S_STARTING; call Token.request(); - call Debug.log(LEVEL_INFO, EnableRxP_PROMISCUOUS_REQUEST, m_promiscuousState, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, EnableRxP_PROMISCUOUS_REQUEST, m_promiscuousState, 0, 0); call Debug.flush(); return SUCCESS; } @@ -96,7 +96,7 @@ implementation if (call PromiscuousRx.prepare() != IEEE154_SUCCESS){ m_promiscuousState = S_IDLE; call Token.release(); - call Debug.log(LEVEL_IMPORTANT, EnableRxP_RADIORX_ERROR, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_IMPORTANT, EnableRxP_RADIORX_ERROR, 0, 0, 0); signal PromiscuousMode.startDone(FAIL); } } @@ -115,7 +115,7 @@ implementation m_promiscuousState = S_STARTED; call PromiscuousRx.receive(NULL, 0); signal PromiscuousMode.startDone(SUCCESS); - call Debug.log(LEVEL_INFO, EnableRxP_PROMISCUOUS_ON, m_promiscuousState, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, EnableRxP_PROMISCUOUS_ON, m_promiscuousState, 0, 0); } event message_t* PromiscuousRx.received(message_t *frame, ieee154_reftime_t *timestamp) @@ -151,7 +151,7 @@ implementation call RadioPromiscuousMode.set(FALSE); call Token.release(); signal PromiscuousMode.stopDone(SUCCESS); - call Debug.log(LEVEL_INFO, EnableRxP_PROMISCUOUS_OFF, m_promiscuousState, 0, 0); + call Debug.log(DEBUG_LEVEL_INFO, EnableRxP_PROMISCUOUS_OFF, m_promiscuousState, 0, 0); } default event void PromiscuousMode.startDone(error_t error){} diff --git a/tos/lib/mac/tkn154/RadioControlImplP.nc b/tos/lib/mac/tkn154/RadioControlImplP.nc index 189d8761..ae0b7041 100644 --- a/tos/lib/mac/tkn154/RadioControlImplP.nc +++ b/tos/lib/mac/tkn154/RadioControlImplP.nc @@ -142,22 +142,54 @@ implementation } } + async command error_t MacTx.transmit[uint8_t client](ieee154_reftime_t *t0, uint32_t dt) + { + if (client == call ArbiterInfo.userId()) + return call PhyTx.transmit(t0, dt); + else { + call Leds.led0On(); + return IEEE154_TRANSACTION_OVERFLOW; + } + } + + async event void PhyTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime) + { + signal MacTx.transmitDone[call ArbiterInfo.userId()](frame, txTime); + } - async command error_t MacTx.transmit[uint8_t client](ieee154_reftime_t *referenceTime, - uint32_t timeOffset, uint8_t numCCA, bool ackRequest) + async command error_t MacTx.transmitUnslottedCsmaCa[uint8_t client](ieee154_csma_t *csmaParams) { if (client == call ArbiterInfo.userId()) - return call PhyTx.transmit(referenceTime, timeOffset, numCCA, ackRequest); + return call PhyTx.transmitUnslottedCsmaCa(csmaParams); else { call Leds.led0On(); return IEEE154_TRANSACTION_OVERFLOW; } } - async event void PhyTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error) + async event void PhyTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result) { - signal MacTx.transmitDone[call ArbiterInfo.userId()](frame, referenceTime, ackPendingFlag, error); + signal MacTx.transmitUnslottedCsmaCaDone[call ArbiterInfo.userId()]( + frame, ackPendingFlag, csmaParams, result); + } + + async command error_t MacTx.transmitSlottedCsmaCa[uint8_t client](ieee154_reftime_t *slot0Time, uint32_t dtMax, + bool resume, uint16_t remainingBackoff, ieee154_csma_t *csmaParams) + { + if (client == call ArbiterInfo.userId()) + return call PhyTx.transmitSlottedCsmaCa(slot0Time, dtMax, resume, remainingBackoff, csmaParams); + else { + call Leds.led0On(); + return IEEE154_TRANSACTION_OVERFLOW; + } + } + + async event void PhyTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result) + { + signal MacTx.transmitSlottedCsmaCaDone[call ArbiterInfo.userId()]( + frame, txTime, ackPendingFlag, remainingBackoff, csmaParams, result); } /* ----------------------- RadioOff ----------------------- */ @@ -190,24 +222,34 @@ implementation default async event void MacTx.loadDone[uint8_t client]() { - call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_PREPARE_TX_DONE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_CRITICAL, 0, 0, 0, 0); } - default async event void MacTx.transmitDone[uint8_t client](ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error) + default async event void MacTx.transmitDone[uint8_t client](ieee154_txframe_t *frame, ieee154_reftime_t *txTime) { - call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_TX_DONE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_CRITICAL, 1, 0, 0, 0); } default async event void MacRx.prepareDone[uint8_t client]() { - call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_PREPARE_RX_DONE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_CRITICAL, 2, 0, 0, 0); } default event message_t* MacRx.received[uint8_t client](message_t *frame, ieee154_reftime_t *timestamp) { - call Debug.log(LEVEL_INFO, RadioRxTxP_DEFAULT_RECEIVED, client, call ArbiterInfo.userId(), 0xff); + call Debug.log(DEBUG_LEVEL_IMPORTANT, 3, client, call ArbiterInfo.userId(), 0xff); return frame; } default async event void MacRadioOff.offDone[uint8_t client]() { - call Debug.log(LEVEL_CRITICAL, RadioRxTxP_DEFAULT_OFFDONE, 0, 0, 0); + call Debug.log(DEBUG_LEVEL_CRITICAL, 4, 0, 0, 0); + } + default async event void MacTx.transmitUnslottedCsmaCaDone[uint8_t client](ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result) + { + call Debug.log(DEBUG_LEVEL_CRITICAL, 5, 0, 0, 0); + } + default async event void MacTx.transmitSlottedCsmaCaDone[uint8_t client](ieee154_txframe_t *frame, + ieee154_reftime_t *txTime, bool ackPendingFlag, uint16_t remainingBackoff, + ieee154_csma_t *csmaParams, error_t result) + { + call Debug.log(DEBUG_LEVEL_CRITICAL, 6, 0, 0, 0); } } diff --git a/tos/lib/mac/tkn154/ScanP.nc b/tos/lib/mac/tkn154/ScanP.nc index d5cd2355..cf49f222 100644 --- a/tos/lib/mac/tkn154/ScanP.nc +++ b/tos/lib/mac/tkn154/ScanP.nc @@ -297,11 +297,10 @@ implementation async event void RadioTx.loadDone() { - call RadioTx.transmit(0, 0, 0, FALSE); + call RadioTx.transmit(NULL, 0); // transmit immediately } - async event void RadioTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error) + async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime) { if (call RadioRx.prepare() != SUCCESS) // must succeed call Leds.led0On(); @@ -388,6 +387,12 @@ implementation nextIteration(); } + async event void RadioTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result){} + + async event void RadioTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result){} + default event message_t* MLME_BEACON_NOTIFY.indication ( message_t *beaconFrame ){return beaconFrame;} default event void MLME_SCAN.confirm ( ieee154_status_t status, diff --git a/tos/lib/mac/tkn154/TKN154P.nc b/tos/lib/mac/tkn154/TKN154P.nc index 99d3c848..bcfdecc6 100644 --- a/tos/lib/mac/tkn154/TKN154P.nc +++ b/tos/lib/mac/tkn154/TKN154P.nc @@ -135,23 +135,23 @@ implementation #ifndef IEEE154_BEACON_SYNC_DISABLED BeaconSynchronizeP, - new CsmaQueueP() as DeviceCapQueue, - new CsmaP(INCOMING_SUPERFRAME) as DeviceCap, + new FrameDispatchQueueP() as DeviceCapQueue, + new FrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap, #else NoBeaconSynchronizeP as BeaconSynchronizeP, - new NoCsmaQueueP() as DeviceCapQueue, - new NoCsmaP() as DeviceCap, + new NoFrameDispatchQueueP() as DeviceCapQueue, + new NoFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap, #endif NoDeviceCfpP as DeviceCfp, #ifndef IEEE154_BEACON_TX_DISABLED BeaconTransmitP, - new CsmaQueueP() as CoordCapQueue, - new CsmaP(OUTGOING_SUPERFRAME) as CoordCap, + new FrameDispatchQueueP() as CoordCapQueue, + new FrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap, #else NoBeaconTransmitP as BeaconTransmitP, - new NoCsmaQueueP() as CoordCapQueue, - new NoCsmaP() as CoordCap, + new NoFrameDispatchQueueP() as CoordCapQueue, + new NoFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap, #endif NoCoordCfpP as CoordCfp, @@ -272,7 +272,7 @@ implementation BeaconTransmitP.IsBroadcastReady -> CoordBroadcastP.IsBroadcastReady; BeaconTransmitP.TimeCalc -> PibP; BeaconTransmitP.Leds = Leds; - BeaconTransmitP.Debug = Ieee802154Debug[START_CLIENT]; + BeaconTransmitP.Debug = Ieee802154Debug[DEBUG_BEACON_TRANSMIT_ID]; BeaconTxRadioClient.TransferTo -> CoordBroadcastRadioClient.TransferFrom; /* ------------------ Beacon Tracking (MLME-SYNC) ------------------ */ @@ -290,7 +290,7 @@ implementation BeaconSynchronizeP.BeaconRx -> SyncRadioClient; BeaconSynchronizeP.RadioOff -> SyncRadioClient; BeaconSynchronizeP.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN; - BeaconSynchronizeP.DataRequest -> PollP.DataRequest[SYNC_CLIENT]; + BeaconSynchronizeP.DataRequest -> PollP.DataRequest[SYNC_POLL_CLIENT]; BeaconSynchronizeP.Token -> SyncRadioClient; BeaconSynchronizeP.IsTokenRequested -> SyncRadioClient; BeaconSynchronizeP.TokenTransferred -> SyncRadioClient; @@ -298,7 +298,7 @@ implementation BeaconSynchronizeP.TimeCalc -> PibP; BeaconSynchronizeP.CoordRealignmentRx -> DeviceCap.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_COORDINATOR_REALIGNMENT]; BeaconSynchronizeP.Leds = Leds; - BeaconSynchronizeP.Debug = Ieee802154Debug[SYNC_CLIENT]; + BeaconSynchronizeP.Debug = Ieee802154Debug[DEBUG_BEACON_SYNCHRONIZE_ID]; SyncRadioClient.TransferTo -> DeviceCapRadioClient.TransferFrom; /* -------------------- Association (MLME-ASSOCIATE) -------------------- */ @@ -308,7 +308,7 @@ implementation AssociateP.AssociationRequestTx -> DeviceCapQueue.FrameTx[unique(CAP_TX_CLIENT)]; AssociateP.AssociationResponseExtracted -> DeviceCap.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_RESPONSE]; AssociateP.AssociationResponseTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)]; - AssociateP.DataRequest -> PollP.DataRequest[ASSOCIATE_CLIENT]; + AssociateP.DataRequest -> PollP.DataRequest[ASSOCIATE_POLL_CLIENT]; AssociateP.ResponseTimeout = Timer3; AssociateP.TxFramePool -> TxFramePoolP; AssociateP.TxControlPool -> TxControlPoolP; @@ -317,7 +317,7 @@ implementation AssociateP.FrameUtility -> PibP; AssociateP.Frame -> PibP; AssociateP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress; - AssociateP.Debug = Ieee802154Debug[ASSOCIATE_CLIENT]; + AssociateP.Debug = Ieee802154Debug[DEBUG_ASSOCIATE_ID]; /* --------------- Disassociation (MLME-DISASSOCIATE) --------------- */ @@ -337,7 +337,7 @@ implementation DisassociateP.FrameUtility -> PibP; DisassociateP.Frame -> PibP; DisassociateP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress; - DisassociateP.Debug = Ieee802154Debug[DISASSOCIATE_CLIENT]; + DisassociateP.Debug = Ieee802154Debug[DEBUG_DISASSOCIATE_ID]; /* ------------------ Data Transmission (MCPS-DATA) ------------------- */ @@ -372,7 +372,7 @@ implementation PollP.FrameUtility -> PibP; PollP.TxFramePool -> TxFramePoolP; PollP.TxControlPool -> TxControlPoolP; - PollP.Debug = Ieee802154Debug[POLL_CLIENT]; + PollP.Debug = Ieee802154Debug[DEBUG_POLL_ID]; PollP.MLME_GET -> PibP; PollP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress; @@ -386,7 +386,7 @@ implementation IndirectTxP.IndirectTxTimeout = Timer4; IndirectTxP.TimeCalc -> PibP; IndirectTxP.Leds = Leds; - IndirectTxP.Debug = Ieee802154Debug[INDIRECTTX_DEBUG_CLIENT]; + IndirectTxP.Debug = Ieee802154Debug[DEBUG_INDIRECTTX_ID]; /* ---------------------------- Realignment --------------------------- */ @@ -424,7 +424,6 @@ implementation components new RadioClientC() as DeviceCapRadioClient; PibP.CapReset -> DeviceCap; - DeviceCap.Random = Random; DeviceCap.CapEndAlarm = Alarm3; DeviceCap.BLEAlarm = Alarm4; DeviceCap.IndirectTxWaitAlarm = Alarm5; @@ -440,6 +439,7 @@ implementation DeviceCap.BLELen -> BeaconSynchronizeP.BLELen; DeviceCap.IsRxBroadcastPending -> BeaconSynchronizeP.IsRxBroadcastPending; DeviceCap.IsRxEnableActive -> RxEnableP.IsRxEnableActive; + DeviceCap.GetIndirectTxFrame -> IndirectTxP; DeviceCap.RxEnableStateChange -> RxEnableP.RxEnableStateChange; DeviceCap.IsTrackingBeacons -> BeaconSynchronizeP.IsTrackingBeacons; DeviceCap.FrameUtility -> PibP; @@ -449,7 +449,7 @@ implementation DeviceCap.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN; DeviceCap.MLME_GET -> PibP; DeviceCap.MLME_SET -> PibP.MLME_SET; - DeviceCap.Debug = Ieee802154Debug[DEVICE_CAP_CLIENT]; + DeviceCap.Debug = Ieee802154Debug[DEBUG_FRAME_DISPATCH_DEVICE_ID]; DeviceCap.TimeCalc -> PibP; DeviceCap.Leds = Leds; DeviceCapRadioClient.TransferTo -> DeviceCfpRadioClient.TransferFrom; @@ -459,7 +459,6 @@ implementation components new RadioClientC() as CoordCapRadioClient, new BackupP(ieee154_cap_frame_backup_t); PibP.CapReset -> CoordCap; - CoordCap.Random = Random; CoordCap.CapEndAlarm = Alarm7; CoordCap.BLEAlarm = Alarm8; CoordCap.Token -> CoordCapRadioClient; @@ -472,6 +471,7 @@ implementation CoordCap.IsBLEActive -> BeaconTransmitP.IsBLEActive; CoordCap.BLELen -> BeaconTransmitP.BLELen; CoordCap.IsRxEnableActive -> RxEnableP.IsRxEnableActive; + CoordCap.GetIndirectTxFrame -> IndirectTxP; CoordCap.RxEnableStateChange -> RxEnableP.RxEnableStateChange; CoordCap.IsTrackingBeacons -> BeaconSynchronizeP.IsTrackingBeacons; CoordCap.FrameUtility -> PibP; @@ -481,7 +481,7 @@ implementation CoordCap.IsBeaconEnabledPAN -> PibP.IsBeaconEnabledPAN; CoordCap.MLME_GET -> PibP; CoordCap.MLME_SET -> PibP.MLME_SET; - CoordCap.Debug = Ieee802154Debug[COORD_CAP_CLIENT]; + CoordCap.Debug = Ieee802154Debug[DEBUG_FRAME_DISPATCH_COORD_ID]; CoordCap.TimeCalc -> PibP; CoordCap.Leds = Leds; CoordCapRadioClient.TransferTo -> CoordCfpRadioClient.TransferFrom; @@ -540,7 +540,7 @@ implementation PromiscuousModeP.PromiscuousRx -> PromiscuousModeRadioClient; PromiscuousModeP.RadioOff -> PromiscuousModeRadioClient; PromiscuousModeP.RadioPromiscuousMode = RadioPromiscuousMode; - PromiscuousModeP.Debug = Ieee802154Debug[PROMISCUOUS_MODE_CLIENT]; + PromiscuousModeP.Debug = Ieee802154Debug[DEBUG_PROMISCUOUSMODE_ID]; /* --------------------------- MLME-RX-ENABLE ------------------------ */ @@ -557,7 +557,7 @@ implementation RxEnableP.WasRxEnabled -> DeviceCap.WasRxEnabled; RxEnableP.WasRxEnabled -> CoordCap.WasRxEnabled; RxEnableP.RxEnableTimer = Timer5; - RxEnableP.Debug = Ieee802154Debug[RXENABLE_CLIENT]; + RxEnableP.Debug = Ieee802154Debug[DEBUG_RXENABLE_ID]; /* ------------------------------- PIB -------------------------------- */ @@ -578,5 +578,5 @@ implementation RadioControlP.PhyRadioOff = RadioOff; RadioControlP.RadioPromiscuousMode -> PromiscuousModeP; RadioControlP.Leds = Leds; - RadioControlP.Debug = Ieee802154Debug[RADIORXTX_CLIENT]; + RadioControlP.Debug = Ieee802154Debug[DEBUG_RADIOCONTROL_ID]; } diff --git a/tos/lib/mac/tkn154/TKN154_DEBUG.h b/tos/lib/mac/tkn154/TKN154_DEBUG.h index 8169f913..41bf8fdf 100644 --- a/tos/lib/mac/tkn154/TKN154_DEBUG.h +++ b/tos/lib/mac/tkn154/TKN154_DEBUG.h @@ -36,66 +36,6 @@ #ifndef __TKN154_DEBUG_H #define __TKN154_DEBUG_H -#define LEVEL_INFO 0 -#define LEVEL_IMPORTANT 50 -#define LEVEL_CRITICAL 100 - -#define RadioRxTxP_ACQUIRED 0 -#define RadioRxTxP_NOT_ACQUIRED 1 -#define RadioRxTxP_TRANSFERRED 2 -#define RadioRxTxP_NOT_TRANSFERRED 3 -#define RadioRxTxP_RELEASED 4 -#define RadioRxTxP_NOT_RELEASED 5 -#define RadioRxTxP_TRANSFER_REQUEST 6 -#define RadioRxTxP_DEFAULT_PREPARE_TX_DONE 7 -#define RadioRxTxP_DEFAULT_TX_DONE 8 -#define RadioRxTxP_DEFAULT_PREPARE_RX_DONE 9 -#define RadioRxTxP_DEFAULT_RECEIVED 10 -#define RadioRxTxP_DEFAULT_OFFDONE 11 -#define RadioRxTxP_DEFAULT_TRANSFERRED 12 -#define RadioRxTxP_DEFAULT_TRANSFERREQUEST 13 -#define RadioRxTxP_ASK_ISOWNER 14 -#define RadioRxTxP_RX_NOOWNER 15 -#define RadioRxTxP_DEFAULT_CANCEL_TX_DONE 16 -#define RadioRxTxP_DEFAULT_CANCEL_RX_DONE 17 - -#define SyncP_BEACON_MISSED_1 0 -#define SyncP_BEACON_MISSED_2 1 -#define SyncP_BEACON_MISSED_3 2 -#define SyncP_TRACK_ALARM 3 -#define SyncP_INVALID_PARAM 4 -#define SyncP_RX_ON 5 -#define SyncP_INTERNAL_ERROR 6 -#define SyncP_BEACON_RX 7 -#define SyncP_RADIO_BUSY 8 -#define SyncP_LOST_SYNC 9 -#define SyncP_RX_PACKET 10 -#define SyncP_NEXT_RX_TIME 11 -#define SyncP_SWITCHOFF 12 -#define SyncP_RX_GARBAGE 13 -#define SyncP_GOT_RESOURCE 14 -#define SyncP_RELEASE_RESOURCE 15 -#define SyncP_RESOURCE_REQUEST 16 -#define SyncP_TRANSFER_RESOURCE 17 -#define SyncP_PREPARE_RX 18 -#define SyncP_REQUEST 19 -#define SyncP_UPDATING 20 -#define SyncP_PREPARE_RX_DONE 21 -#define SyncP_INVALID_TIMESTAMP 22 -#define SyncP_RX_BEACON SyncP_RX_PACKET - -#define StartP_BEACON_TRANSMITTED 0 -#define StartP_UPDATE_STATE 1 -#define StartP_REQUEST 2 -#define StartP_OWNER_TOO_FAST 3 -#define StartP_BEACON_UPDATE 4 -#define StartP_BEACON_UPDATE_2 5 -#define StartP_PREPARE_TX 6 -#define StartP_PREPARE_TXDONE 7 -#define StartP_SKIPPED_BEACON 8 -#define StartP_GOT_RESOURCE 9 -#define StartP_TRANSMIT 10 - #define PollP_ALLOC_FAIL1 0 #define PollP_ALLOC_FAIL2 1 #define PollP_INTERNAL_POLL 2 @@ -162,53 +102,41 @@ #define CoordCapTransmitP_FINISH_TX 5 #define CoordCapTransmitP_RADIO_RX 6 -#define Phy_RX_CANCEL 0 -#define Phy_RX_NOW 1 -#define Phy_LOAD_TX_FIFO 2 -#define Phy_LOAD_TX_FIFO_DONE 3 -#define Phy_LOAD_TX_CANCEL 4 -#define Phy_LOAD_TX_NOW 5 -#define Phy_LOAD_TX_RX_NOW 6 -#define Phy_SEND_DONE 7 -#define Phy_SPI_GRANTED 8 -#define Phy_RADIO_OFF 9 -#define Phy_RADIO_OFF_DONE 10 -#define Phy_RADIO_PREPARE_RX 11 -#define Phy_RADIO_PREPARE_TX 12 -#define Phy_RADIO_TX_DONE 13 -#define Phy_RADIO_RECEIVED 14 #define PhyRx_START 0 #define PhyRx_STOP 1 #define PhyRx_FIFOP 2 #define PhyRx_RXON 3 + enum { + DEBUG_LEVEL_INFO = 0, + DEBUG_LEVEL_IMPORTANT = 1, + DEBUG_LEVEL_CRITICAL = 2, + // IDs assigned for debugging - START_CLIENT = 0, - COORD_CAP_CLIENT = 1, - COORD_CFP_CLIENT = 2, - - SYNC_CLIENT = 3, - DEVICE_CAP_CLIENT = 4, - DEVICE_CFP_CLIENT = 5, - - SCAN_CLIENT = 6, - - RADIORXTX_CLIENT = 7, - PIBDATABASE_CLIENT = 8, - ASSOCIATE_CLIENT = 9, - DISASSOCIATE_CLIENT = 10, - DEVICECAPQUEUE_CLIENT = 11, - INDIRECTTX_DEBUG_CLIENT = 12, - DATA_CLIENT = 13, - POLL_CLIENT = 14, - RXENABLE_CLIENT = 15, - PROMISCUOUS_MODE_CLIENT = 16, - - PHY_CLIENT = 17, - PHY_TXCLIENT = 18, - PHY_RXCLIENT = 19, + DEBUG_BEACON_TRANSMIT_ID = 0, + DEBUG_FRAME_DISPATCH_COORD_ID = 1, + DEBUG_COORD_CFP_ID = 2, + + DEBUG_BEACON_SYNCHRONIZE_ID = 3, + DEBUG_FRAME_DISPATCH_DEVICE_ID = 4, + DEBUG_DEVICE_CFP_ID = 5, + + DEBUG_SCAN_ID = 6, + + DEBUG_RADIOCONTROL_ID = 7, + DEBUG_PIB_ID = 8, + DEBUG_ASSOCIATE_ID = 9, + DEBUG_DISASSOCIATE_ID = 10, + DEBUG_FRAMEDISPATCHQUEUE_ID = 11, + DEBUG_INDIRECTTX_ID = 12, + DEBUG_DATA_ID = 13, + DEBUG_POLL_ID = 14, + DEBUG_RXENABLE_ID = 15, + DEBUG_PROMISCUOUSMODE_ID = 16, + DEBUG_RADIO_DRIVER_ID = 17, + }; typedef nx_struct serial_debug_msg { @@ -223,7 +151,7 @@ typedef nx_struct serial_debug_msg { } serial_debug_msg_t; #ifndef SERIAL_DBG_MSGBUF_SIZE -#define SERIAL_DBG_MSGBUF_SIZE 25 +#define SERIAL_DBG_MSGBUF_SIZE 150 #endif enum { diff --git a/tos/lib/mac/tkn154/TKN154_MAC.h b/tos/lib/mac/tkn154/TKN154_MAC.h index 8edccc00..6f1d3a90 100644 --- a/tos/lib/mac/tkn154/TKN154_MAC.h +++ b/tos/lib/mac/tkn154/TKN154_MAC.h @@ -128,6 +128,8 @@ enum { FC2_FRAME_VERSION_MASK = 0x30, }; +#define SYNC_POLL_CLIENT unique("PollP.client") +#define ASSOCIATE_POLL_CLIENT unique("PollP.client") #define CAP_TX_CLIENT "CapQueueP.FrameTx.client" #define INDIRECT_TX_CLIENT "IndirectTx.client" #define IEEE802154_RADIO_RESOURCE "RadioRxTxP.resource" @@ -164,16 +166,17 @@ typedef struct ieee154_header_t header; ieee154_metadata_t metadata; } ieee154_txcontrol_t; + +typedef struct ieee154_csma { + uint8_t BE; // initial backoff exponent + uint8_t macMaxBE; // maximum backoff exponent + uint8_t macMaxCsmaBackoffs; // maximum number of allowed backoffs + uint8_t NB; // number of backoff during current transmission +} ieee154_csma_t; typedef struct { ieee154_txframe_t *frame; - ieee154_macMaxBE_t BE; - ieee154_macMaxCSMABackoffs_t allowedBackoffs; - ieee154_macMaxBE_t macMaxBE; - ieee154_macMinBE_t macMinBE; - uint8_t NB; - uint16_t backoff; - uint16_t backoffElapsed; + ieee154_csma_t csmaParams; uint32_t transactionTime; } ieee154_cap_frame_backup_t; diff --git a/tos/lib/mac/tkn154/dummies/NoBeaconTransmitP.nc b/tos/lib/mac/tkn154/dummies/NoBeaconTransmitP.nc index 9d6a059f..7bed6f11 100644 --- a/tos/lib/mac/tkn154/dummies/NoBeaconTransmitP.nc +++ b/tos/lib/mac/tkn154/dummies/NoBeaconTransmitP.nc @@ -124,8 +124,13 @@ implementation async event void BeaconTx.loadDone() {} - async event void BeaconTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool pendingFlag, error_t error) { } + async event void BeaconTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime){} + + async event void BeaconTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParameters, error_t result){} + + async event void BeaconTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParameters, error_t result){} command error_t IEEE154TxBeaconPayload.setBeaconPayload(void *beaconPayload, uint8_t length) { return ESIZE; } diff --git a/tos/lib/mac/tkn154/dummies/NoCoordCfpP.nc b/tos/lib/mac/tkn154/dummies/NoCoordCfpP.nc index 76974d2d..5ea62932 100644 --- a/tos/lib/mac/tkn154/dummies/NoCoordCfpP.nc +++ b/tos/lib/mac/tkn154/dummies/NoCoordCfpP.nc @@ -124,8 +124,7 @@ implementation } async event void RadioTx.loadDone(){} - async event void RadioTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error){} + async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime){} async event void RadioRx.prepareDone(){} event message_t* RadioRx.received(message_t *frame, ieee154_reftime_t *timestamp){return frame;} @@ -138,4 +137,8 @@ implementation } async event void TokenRequested.immediateRequested(){ } + async event void RadioTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result){} + async event void RadioTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result){} } diff --git a/tos/lib/mac/tkn154/dummies/NoCsmaP.nc b/tos/lib/mac/tkn154/dummies/NoCsmaP.nc deleted file mode 100644 index 7137064c..00000000 --- a/tos/lib/mac/tkn154/dummies/NoCsmaP.nc +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2008, Technische Universitaet Berlin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the Technische Universitaet Berlin nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - Revision ------------------------------------------------------------- - * $Revision$ - * $Date$ - * @author Jan Hauer - * ======================================================================== - */ - -#include "TKN154_PHY.h" -#include "TKN154_MAC.h" - -generic module NoCsmaP() -{ - provides - { - interface Init as Reset; - interface FrameTx as FrameTx; - interface FrameRx as FrameRx[uint8_t frameType]; - interface FrameExtracted as FrameExtracted[uint8_t frameType]; - interface FrameTxNow as BroadcastTx; - interface Notify as WasRxEnabled; - interface Notify as FindBeacon; - } - uses - { - interface Random; - interface Alarm as CapEndAlarm; - interface Alarm as BLEAlarm; - interface Alarm as IndirectTxWaitAlarm; - interface Alarm as BroadcastAlarm; - interface Resource as Token; - interface ResourceTransfer as TokenToCfp; - interface ResourceTransferred as TokenTransferred; - interface ResourceRequested as TokenRequested; - interface GetNow as IsTokenRequested; - interface GetNow as CapStart; - interface GetNow as CapStartRefTime; - interface GetNow as CapLen; - interface GetNow as IsBLEActive; - interface GetNow as BLELen; - interface GetNow as IsRxEnableActive; - interface GetNow as IsRxBroadcastPending; - interface Notify as RxEnableStateChange; - interface GetNow as IsTrackingBeacons; - interface FrameUtility; - interface RadioTx; - interface RadioRx; - interface RadioOff; - interface GetNow as IsBeaconEnabledPAN; - interface MLME_GET; - interface MLME_SET; - interface Ieee802154Debug as Debug; - interface TimeCalc; - interface Leds; - interface SetNow as FrameBackup; - interface GetNow as FrameRestore; - } -} -implementation -{ - command error_t Reset.init() - { - return SUCCESS; - } - - async event void TokenTransferred.transferred() - { - call TokenToCfp.transfer(); - } - - command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) - { - return IEEE154_TRANSACTION_OVERFLOW; - } - - async event void RadioTx.loadDone(){ } - async event void RadioOff.offDone(){ } - async event void RadioRx.prepareDone(){ } - - async event void CapEndAlarm.fired(){ } - async event void BLEAlarm.fired(){ } - event void RxEnableStateChange.notify(bool x){ } - async event void BroadcastAlarm.fired(){ } - - async event void IndirectTxWaitAlarm.fired() { } - - async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t - *referenceTime, bool ackPendingFlag, error_t error) { } - - event message_t* RadioRx.received(message_t* frame, ieee154_reftime_t* referenceTime) { return frame; } - async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame){ return IEEE154_TRANSACTION_OVERFLOW; } - - async event void TokenRequested.requested() {} - async event void TokenRequested.immediateRequested() {} - event void Token.granted(){} - command error_t WasRxEnabled.enable(){return FAIL;} - command error_t WasRxEnabled.disable(){return FAIL;} - command error_t FindBeacon.enable(){return FAIL;} - command error_t FindBeacon.disable(){return FAIL;} -} diff --git a/tos/lib/mac/tkn154/dummies/NoCsmaQueueP.nc b/tos/lib/mac/tkn154/dummies/NoCsmaQueueP.nc deleted file mode 100644 index b8e7554a..00000000 --- a/tos/lib/mac/tkn154/dummies/NoCsmaQueueP.nc +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2008, Technische Universitaet Berlin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the Technische Universitaet Berlin nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - Revision ------------------------------------------------------------- - * $Revision$ - * $Date$ - * @author Jan Hauer - * ======================================================================== - */ -#include "TKN154_MAC.h" -generic module NoCsmaQueueP() -{ - provides - { - interface Init; - interface FrameTx[uint8_t client]; - interface FrameRx as FrameExtracted[uint8_t client]; - interface Purge; - } - uses - { - interface Queue; - interface FrameTx as FrameTxCsma; - interface FrameRx as SubFrameExtracted; - } -} -implementation -{ - command error_t Init.init() - { - return SUCCESS; - } - - command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *data) - { - return IEEE154_TRANSACTION_OVERFLOW; - } - - event void FrameTxCsma.transmitDone(ieee154_txframe_t *data, ieee154_status_t status) { } - - event message_t* SubFrameExtracted.received(message_t* frame) { return frame; } - - command ieee154_status_t Purge.purge(uint8_t msduHandle) { return IEEE154_INVALID_HANDLE; } -} diff --git a/tos/lib/mac/tkn154/dummies/NoDeviceCapQueueP.nc b/tos/lib/mac/tkn154/dummies/NoDeviceCapQueueP.nc deleted file mode 100644 index 31c9a28f..00000000 --- a/tos/lib/mac/tkn154/dummies/NoDeviceCapQueueP.nc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2008, Technische Universitaet Berlin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - Neither the name of the Technische Universitaet Berlin nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - Revision ------------------------------------------------------------- - * $Revision$ - * $Date$ - * @author Jan Hauer - * ======================================================================== - */ -#include "TKN154_MAC.h" -module NoDeviceCapQueueP -{ - provides - { - interface Init; - interface FrameTx[uint8_t client]; - interface FrameRx as FrameExtracted[uint8_t client]; - interface Purge; - } - uses - { - interface Queue; - interface FrameTx as DeviceCapTx; - interface FrameRx as SubFrameExtracted; - } -} -implementation -{ - command error_t Init.init() { return SUCCESS; } - - command ieee154_status_t FrameTx.tx[uint8_t client](ieee154_txframe_t *data) { return TRANSACTION_OVERFLOW; } - - event void DeviceCapTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status) { } - - event message_t* SubFrameExtracted.received(message_t* data) { return data; } - - command ieee154_status_t Purge.purge(uint8_t msduHandle) { return INVALID_HANDLE; } -} diff --git a/tos/lib/mac/tkn154/dummies/NoDeviceCfpP.nc b/tos/lib/mac/tkn154/dummies/NoDeviceCfpP.nc index 0cda4b60..0b3dfc79 100644 --- a/tos/lib/mac/tkn154/dummies/NoDeviceCfpP.nc +++ b/tos/lib/mac/tkn154/dummies/NoDeviceCfpP.nc @@ -106,8 +106,7 @@ implementation async event void RadioOff.offDone() {} async event void RadioTx.loadDone(){} - async event void RadioTx.transmitDone(ieee154_txframe_t *frame, - ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error){} + async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime){} async event void RadioRx.prepareDone(){} event message_t* RadioRx.received(message_t *frame, ieee154_reftime_t *timestamp){return frame;} @@ -120,4 +119,9 @@ implementation } async event void TokenRequested.immediateRequested(){ } + + async event void RadioTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result){} + async event void RadioTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result){} } diff --git a/tos/lib/mac/tkn154/dummies/NoFrameDispatchP.nc b/tos/lib/mac/tkn154/dummies/NoFrameDispatchP.nc new file mode 100644 index 00000000..eec51664 --- /dev/null +++ b/tos/lib/mac/tkn154/dummies/NoFrameDispatchP.nc @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2008, Technische Universitaet Berlin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the Technische Universitaet Berlin nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * - Revision ------------------------------------------------------------- + * $Revision$ + * $Date$ + * @author Jan Hauer + * ======================================================================== + */ + +#include "TKN154_PHY.h" +#include "TKN154_MAC.h" + +generic module NoFrameDispatchP(uint8_t superframeDirection) +{ + provides + { + interface Init as Reset; + interface FrameTx as FrameTx; + interface FrameRx as FrameRx[uint8_t frameType]; + interface FrameExtracted as FrameExtracted[uint8_t frameType]; + interface FrameTxNow as BroadcastTx; + interface Notify as WasRxEnabled; + interface Notify as FindBeacon; + } + uses + { + interface Alarm as CapEndAlarm; + interface Alarm as BLEAlarm; + interface Alarm as IndirectTxWaitAlarm; + interface Alarm as BroadcastAlarm; + interface Resource as Token; + interface GetNow as IsTokenRequested; + interface ResourceTransfer as TokenToCfp; + interface ResourceTransferred as TokenTransferred; + interface GetNow as CapStart; + interface GetNow as CapStartRefTime; + interface GetNow as CapLen; + interface GetNow as IsBLEActive; + interface GetNow as BLELen; + interface GetNow as IsRxBroadcastPending; + interface GetNow as IsRxEnableActive; + interface Get as GetIndirectTxFrame; + interface Notify as RxEnableStateChange; + interface GetNow as IsTrackingBeacons; + interface FrameUtility; + interface RadioTx; + interface RadioRx; + interface RadioOff; + interface GetNow as IsBeaconEnabledPAN; + interface MLME_GET; + interface MLME_SET; + interface Ieee802154Debug as Debug; + interface TimeCalc; + interface Leds; + interface SetNow as FrameBackup; + interface GetNow as FrameRestore; + } +} +implementation +{ + command error_t Reset.init() + { + return SUCCESS; + } + + async event void TokenTransferred.transferred() + { + call TokenToCfp.transfer(); + } + + command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) + { + return IEEE154_TRANSACTION_OVERFLOW; + } + + async event void RadioTx.loadDone(){ } + async event void RadioOff.offDone(){ } + async event void RadioRx.prepareDone(){ } + + async event void CapEndAlarm.fired(){ } + async event void BLEAlarm.fired(){ } + event void RxEnableStateChange.notify(bool whatever){ } + async event void BroadcastAlarm.fired(){ } + + async event void IndirectTxWaitAlarm.fired() { } + + async event void RadioTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result) + { + } + + async event void RadioTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParams, error_t result) + { + } + + void transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, ieee154_csma_t *csmaParams, error_t result) + { + } + + event message_t* RadioRx.received(message_t* frame, ieee154_reftime_t *timestamp) + { + return frame; + } + + async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) + { + return IEEE154_TRANSACTION_OVERFLOW; + } + + event void Token.granted() + { + } + + async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime){} + + default event void FrameTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status){} + default event message_t* FrameRx.received[uint8_t client](message_t* data){return data;} + default async command bool IsRxEnableActive.getNow(){return FALSE;} + + default async command void IndirectTxWaitAlarm.start(uint32_t dt){call Leds.led0On();} + default async command void IndirectTxWaitAlarm.stop(){call Leds.led0On();} + default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();} + + default async command void BroadcastAlarm.start(uint32_t dt){call Leds.led0On();} + default async command void BroadcastAlarm.stop(){call Leds.led0On();} + default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt){call Leds.led0On();} + + default async command bool IsRxBroadcastPending.getNow(){ return FALSE;} + default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status){} + default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame){return msg;} + default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val ){return FAIL;} + default async command ieee154_cap_frame_backup_t* FrameRestore.getNow(){return NULL;} + + command error_t WasRxEnabled.enable(){return FAIL;} + command error_t WasRxEnabled.disable(){return FAIL;} + command error_t FindBeacon.enable(){return FAIL;} + command error_t FindBeacon.disable(){return FAIL;} +} diff --git a/tos/lib/mac/tkn154/dummies/NoFrameDispatchQueueP.nc b/tos/lib/mac/tkn154/dummies/NoFrameDispatchQueueP.nc new file mode 100644 index 00000000..54671cd0 --- /dev/null +++ b/tos/lib/mac/tkn154/dummies/NoFrameDispatchQueueP.nc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008, Technische Universitaet Berlin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the Technische Universitaet Berlin nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * - Revision ------------------------------------------------------------- + * $Revision$ + * $Date$ + * @author Jan Hauer + * ======================================================================== + */ +#include "TKN154_MAC.h" +generic module NoFrameDispatchQueueP() { + provides + { + interface Init as Reset; + interface FrameTx[uint8_t client]; + interface FrameRx as FrameExtracted[uint8_t client]; + interface Purge; + } uses { + interface Queue; + interface FrameTx as FrameTxCsma; + interface FrameRx as SubFrameExtracted; + } +} +implementation +{ + command error_t Reset.init() { return SUCCESS; } + + command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame) + { + return IEEE154_TRANSACTION_OVERFLOW; + } + + event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { } + + event message_t* SubFrameExtracted.received(message_t* frame) { return frame; } + + default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){} + + command ieee154_status_t Purge.purge(uint8_t msduHandle) + { + return IEEE154_INVALID_HANDLE; + } + + default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status){} +} diff --git a/tos/lib/mac/tkn154/dummies/NoScanP.nc b/tos/lib/mac/tkn154/dummies/NoScanP.nc index 38a7697a..2ff5a045 100644 --- a/tos/lib/mac/tkn154/dummies/NoScanP.nc +++ b/tos/lib/mac/tkn154/dummies/NoScanP.nc @@ -96,9 +96,14 @@ implementation } async event void RadioTx.loadDone() { } - - async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *t0, - bool ackPendingFlag, error_t error){} + + async event void RadioTx.transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime){} + + async event void RadioTx.transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParameters, error_t result){} + + async event void RadioTx.transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParameters, error_t result){} event void ScanTimer.fired() { } diff --git a/tos/lib/mac/tkn154/interfaces/MCPS/MCPS_DATA.nc b/tos/lib/mac/tkn154/interfaces/MCPS/MCPS_DATA.nc index 58709438..6c2cf76c 100644 --- a/tos/lib/mac/tkn154/interfaces/MCPS/MCPS_DATA.nc +++ b/tos/lib/mac/tkn154/interfaces/MCPS/MCPS_DATA.nc @@ -44,12 +44,12 @@ interface MCPS_DATA * SPDU (i.e., MSDU) from a local SSCS entity to a single peer SSCS * entity." (IEEE 802.15.4-2006, Sec. 7.1.1.1) * - * The MSDU is the payload portion of a message_t (frame<\code> - * parameter) and can be accessed through the IEEE154Frame<\code> + * The MSDU is the payload portion of a message_t (frame + * parameter) and can be accessed through the IEEE154Frame * interface. In contrast to the standard interface definition address * information is not passed as separate parameters; instead, the - * address information is already part of the frame<\code>, - * i.e. it must have been set (through the IEEE154Frame<\code> + * address information is already part of the frame, + * i.e. it must have been set (through the IEEE154Frame * interface) before this command is called. * * If this command returns IEEE154_SUCCESS, then the confirm event @@ -93,7 +93,7 @@ interface MCPS_DATA /** * Indicates the arrival of a frame. Address information can be accessed - * through the IEEE154Frame<\code> interface. + * through the IEEE154Frame interface. * * @return A frame buffer for the stack to use for the next received frame */ diff --git a/tos/lib/mac/tkn154/interfaces/MLME/MLME_BEACON_NOTIFY.nc b/tos/lib/mac/tkn154/interfaces/MLME/MLME_BEACON_NOTIFY.nc index c7e81d94..3b9d9dd6 100644 --- a/tos/lib/mac/tkn154/interfaces/MLME/MLME_BEACON_NOTIFY.nc +++ b/tos/lib/mac/tkn154/interfaces/MLME/MLME_BEACON_NOTIFY.nc @@ -43,8 +43,8 @@ interface MLME_BEACON_NOTIFY { * beacon payload is not empty. * * The beacon parameters can be accessed through the - * IEEE154BeaconFrame<\code> interface. The - * IEEE154Frame<\code> interface can be used to + * IEEE154BeaconFrame<\tt> interface. The + * IEEE154Frame<\tt> interface can be used to * inspect the addressing fields in the MAC header. * * @param beacon The beacon frame diff --git a/tos/lib/mac/tkn154/interfaces/MLME/MLME_GET.nc b/tos/lib/mac/tkn154/interfaces/MLME/MLME_GET.nc index 73783230..29efcc3a 100644 --- a/tos/lib/mac/tkn154/interfaces/MLME/MLME_GET.nc +++ b/tos/lib/mac/tkn154/interfaces/MLME/MLME_GET.nc @@ -39,7 +39,7 @@ * command per attribute (and there are no confirm events). * * NOTE: for the attributes macBeaconPayload (0x45) and - * macBeaconPayloadLength (0x46) use the IEEE154TxBeaconPayload <\code> + * macBeaconPayloadLength (0x46) use the IEEE154TxBeaconPayload <\tt> * interface; for promiscuous mode there is a separate (SplitControl) * interface. **/ @@ -87,7 +87,7 @@ interface MLME_GET { command ieee154_macBattLifeExtPeriods_t macBattLifeExtPeriods(); /* macBeaconPayload (0x45) and macBeaconPayloadLength (0x46) are read - * through the IEEE154TxBeaconPayload<\code> interface. */ + * through the IEEE154TxBeaconPayload<\tt> interface. */ /** @return PIB attribute macBeaconOrder (0x47) */ command ieee154_macBeaconOrder_t macBeaconOrder(); diff --git a/tos/lib/mac/tkn154/interfaces/MLME/MLME_SET.nc b/tos/lib/mac/tkn154/interfaces/MLME/MLME_SET.nc index b2ba46ee..2935fc01 100644 --- a/tos/lib/mac/tkn154/interfaces/MLME/MLME_SET.nc +++ b/tos/lib/mac/tkn154/interfaces/MLME/MLME_SET.nc @@ -40,7 +40,7 @@ * command per attribute (and there are no confirm events). * * NOTE: for the attributes macBeaconPayload (0x45) and - * macBeaconPayloadLength (0x46) use the IEEE154TxBeaconPayload <\code> + * macBeaconPayloadLength (0x46) use the IEEE154TxBeaconPayload <\tt> * interface; for promiscuous mode there is a separate (SplitControl) * interface. **/ @@ -90,7 +90,7 @@ interface MLME_SET { command ieee154_status_t macBattLifeExtPeriods(ieee154_macBattLifeExtPeriods_t value); /* macBeaconPayload (0x45) and macBeaconPayloadLength (0x46) are set - * through the IEEE154TxBeaconPayload<\code> interface. */ + * through the IEEE154TxBeaconPayload<\tt> interface. */ /** @param value new PIB attribute value for macBeaconOrder (0x47) * @returns IEEE154_SUCCESS if PIB attribute was updated, INVALID_PARAMETER if @@ -138,7 +138,7 @@ interface MLME_SET { command ieee154_status_t macPANId(ieee154_macPANId_t value); /* macPromiscuousMode (0x51) is (re-)set through the - * PromiscuousMode<\code> (SplitControl) interface. */ + * PromiscuousMode<\tt> (SplitControl) interface. */ /** @param value new PIB attribute value for macRxOnWhenIdle (0x52) * @returns IEEE154_SUCCESS if PIB attribute was updated, INVALID_PARAMETER if diff --git a/tos/lib/mac/tkn154/interfaces/private/EnergyDetection.nc b/tos/lib/mac/tkn154/interfaces/private/EnergyDetection.nc index fb17fe46..a3476cb2 100644 --- a/tos/lib/mac/tkn154/interfaces/private/EnergyDetection.nc +++ b/tos/lib/mac/tkn154/interfaces/private/EnergyDetection.nc @@ -37,24 +37,24 @@ interface EnergyDetection { /** * Requests to measure the energy level on the current channel; the - * measurement should last for duration<\code> symbols and the - * maximum energy level is signalled through the done<\code> + * measurement should last for duration symbols and the + * maximum energy level is signalled through the done * event. * * @param duration Duration of the energy detection measurement * (in symbol time) * @return SUCCESS if the request was accepted and only then - * the done<\code> event will be signalled, FAIL otherwise + * the done event will be signalled, FAIL otherwise **/ command error_t start(uint32_t duration); /** - * Signalled in response to a call to start<\code>; + * Signalled in response to a call to start<\tt>; * returns the maximum energy measured on the channel over the * specified period of time. * * @param status SUCCESS if the measurement succeeded - * and only then EnergyLevel<\code> is valid, FAIL + * and only then EnergyLevel<\tt> is valid, FAIL * otherwise * @param EnergyLevel The maximum energy on the channel **/ diff --git a/tos/lib/mac/tkn154/interfaces/private/FrameTx.nc b/tos/lib/mac/tkn154/interfaces/private/FrameTx.nc index d9e3aef6..665d5543 100644 --- a/tos/lib/mac/tkn154/interfaces/private/FrameTx.nc +++ b/tos/lib/mac/tkn154/interfaces/private/FrameTx.nc @@ -38,7 +38,7 @@ interface FrameTx * * @param txFrame the frame to transmit * @return IEEE154_SUCCESS if the request was accepted and - * only then transmitDone() will be signalled + * only then transmitDone() will be signalled */ command ieee154_status_t transmit(ieee154_txframe_t *txFrame); diff --git a/tos/lib/mac/tkn154/interfaces/private/FrameTxNow.nc b/tos/lib/mac/tkn154/interfaces/private/FrameTxNow.nc index ce876296..beca22a1 100644 --- a/tos/lib/mac/tkn154/interfaces/private/FrameTxNow.nc +++ b/tos/lib/mac/tkn154/interfaces/private/FrameTxNow.nc @@ -38,7 +38,7 @@ interface FrameTxNow * * @param txFrame the frame to transmit * @return IEEE154_SUCCESS if the request was accepted and - * only then transmitDone() will be signalled + * only then transmitDone() will be signalled */ async command ieee154_status_t transmitNow(ieee154_txframe_t *frame); diff --git a/tos/lib/mac/tkn154/interfaces/private/RadioOff.nc b/tos/lib/mac/tkn154/interfaces/private/RadioOff.nc index 24317842..3405932c 100644 --- a/tos/lib/mac/tkn154/interfaces/private/RadioOff.nc +++ b/tos/lib/mac/tkn154/interfaces/private/RadioOff.nc @@ -37,14 +37,14 @@ interface RadioOff { /** - * Switches the radio off and changes the radio state to RADIO_OFF. This + * Disables the transceiver and changes the radio state to RADIO_OFF. This * command will succeed only if the current state of the radio is either * TX_LOADED, RX_PREPARED or RECEIVING. * - * @return EALREADY if radio is already switched off
FAIL if radio the - * current radio state is neither TX_LOADED, RX_PREPARED nor RECEIVING
- * SUCCESS if the command was accepted and the offDone() event will - * be signalled. + * @return SUCCESS if the command was accepted and the offDone() + * event will be signalled; EALREADY if radio is already switched off; FAIL + * if the current radio state is neither TX_LOADED, RX_PREPARED nor + * RECEIVING. */ async command error_t off(); @@ -54,6 +54,9 @@ interface RadioOff **/ async event void offDone(); - /** @return TRUE if the radio is in the state RADIO_OFF, FALSE otherwise */ - async command bool isOff(); + /** + * Tells whether the radio is in state RADIO_OFF. + * @return TRUE if the radio is in the state RADIO_OFF, FALSE otherwise + */ + async command bool isOff(); } diff --git a/tos/lib/mac/tkn154/interfaces/private/RadioRx.nc b/tos/lib/mac/tkn154/interfaces/private/RadioRx.nc index e548e20f..597ab758 100644 --- a/tos/lib/mac/tkn154/interfaces/private/RadioRx.nc +++ b/tos/lib/mac/tkn154/interfaces/private/RadioRx.nc @@ -35,7 +35,6 @@ #include "TKN154_platform.h" interface RadioRx { - /** * Prepares the radio for receive mode. This command will fail, if the radio * is not in the state RADIO_OFF. The actual receive operation will be @@ -55,13 +54,15 @@ interface RadioRx **/ async event void prepareDone(); - /** @return TRUE if the radio is in the state RX_PREPARED, FALSE otherwise */ + /** + * Tells whether the radio is in state RX_PREPARED. + * @return TRUE if the radio is in the state RX_PREPARED, FALSE otherwise + */ async command bool isPrepared(); /** * Switches the radio to receive mode at time t0 + dt. If - * t0 is NULL, then the callee interprets t0 as the current - * time. + * t0 is NULL, then the callee interprets t0 as now. * * @param t0 Reference time for receive operation (NULL means now) * @@ -73,7 +74,10 @@ interface RadioRx */ async command error_t receive(ieee154_reftime_t *t0, uint32_t dt); - /** @return TRUE if the radio is in the state RECEIVING, FALSE otherwise */ + /** + * Tells whether the radio is in state RECEIVING. + * @return TRUE if the radio is in the state RECEIVING, FALSE otherwise + */ async command bool isReceiving(); /** diff --git a/tos/lib/mac/tkn154/interfaces/private/RadioTx.nc b/tos/lib/mac/tkn154/interfaces/private/RadioTx.nc index 7229b192..f5d45c89 100644 --- a/tos/lib/mac/tkn154/interfaces/private/RadioTx.nc +++ b/tos/lib/mac/tkn154/interfaces/private/RadioTx.nc @@ -49,7 +49,7 @@ interface RadioTx * The frame will be loaded (and the radio will stay in the state * TX_LOADED) until either the transmission was successful, i.e. * transmitDone() was signalled with a status IEEE154_SUCCESS, or - * the radio is explicitly switched off through the RadioOff + * the radio is switched off through the RadioOff * interface. Until then the callee might have to reserve certain resources * (e.g. the bus connected to the radio), so the caller should keep the time * while a frame is loaded as short as possible. @@ -80,87 +80,137 @@ interface RadioTx /** * Transmits the frame whose transmission has previously been prepared - * through a call to load(). The actual time of transmission -- the - * point in time when the first symbol of the PPDU is transmitted -- is - * defined by: t0 + dt. The data type of the t0 parameter - * is platform-specific (symbol precision or better) while dt is - * expressed in 802.15.4 symbols. If t0 is NULL, then the callee - * interprets t0 as the current time. The caller guarantees (through + * through a call to load() at time t0+dt or immediately if + * t0 is NULL. In the first case the caller has to guarantee (through * platform-specific guard times and by calling transmit in an - * atomic block) that the callee can start the transmission on time, taking - * any prior clear channel assesment(s) into consideration. - * - * A transmission may require 0, 1 or 2 prior clear channel assesments - * (numCCA parameter) to be performed 0, 20 or 40 symbols, - * respectively, before the actual transmission. If a CCA determines a busy - * channel, then the frame will not be transmitted. - * - * A successful transmission may also require an acknowledgement from the - * destination (indicated through the ackRequest parameter); then, - * the callee has to perform the necessary steps for receiving that - * acknowledgement (switching the radio to Rx mode immediately after - * transmission, etc.; for details see IEEE 802.15.4-2006). - * - * The transmit() command will succeed iff the radio is in state - * TX_LOADED. The transmitDone() event will then signal the result + * atomic block) that the callee can start the transmission on time. + * The frame is transmitted without carrier sense (without CCA). + * The transmitDone() event will signal the result * of the transmission. * * @param t0 Reference time for transmission (NULL means now) - * * @param dt A positive offset relative to t0. * - * @param numCCA Number of clear channel assesments. - * - * @param ackRequest TRUE means an acknowledgement is required, FALSE means - * no acknowledgement is not required - * * @return SUCCESS if the transmission was triggered successfully and only * then transmitDone() will be signalled; FAIL, if the transmission * was not triggered because no frame was loaded. - */ - async command error_t transmit(ieee154_reftime_t *t0, uint32_t dt, - uint8_t numCCA, bool ackRequest); + */ + async command error_t transmit(ieee154_reftime_t *t0, uint32_t dt); /** - * Signalled in response to a call to transmit(). Depending on the - * error parameter the radio is now in state RADIO_OFF - * (error == IEEE154_SUCCESS) or still in state TX_LOADED - * (error != IEEE154_SUCCESS). If the transmission succeeded then - * the time of transmission -- the point in time when the first symbol of the - * PPDU was transmitted -- will be stored in the metadata field of the frame. - * In addition, the t0 parameter will hold a platform-specific - * representation of the same point in time (possibly with higher precision) - * to be used as future reference time in a transmit() command. If - * the transmission did not succeed no timestamp will be stored in the - * metadata portion, but t0 will still represent the hypothetical - * transmission time. - * - * If error has a value other than IEEE154_SUCCESS the frame will - * stay loaded and a subsequent call to transmit will (re-)transmit - * the same frame again. If error has a value of - * IEEE154_SUCCESS then the frame was automatically un-loaded and a new frame - * has to be loaded before the transmit() command will succeed. - * - * When the transmit() command was called with an - * ackRequest parameter with value TRUE, and error has a - * value of IEEE154_SUCCESS, then this means that a corresponding - * acknowledgement was successfully received. In this case, the - * ackPendingFlag represents the "pending" flag in the header of the - * acknowledgement frame (TRUE means set, FALSE means reset). + * Signalled in response to a call to transmit() and completing the transmission. Depending on the + * error parameter the radio is now in the state RADIO_OFF + * (error == IEEE154_SUCCESS) or back in state TX_LOADED + * (error != IEEE154_SUCCESS). * * @param frame The frame that was transmitted. + * @param txTime The time of transmission of the first symbol of the PPDU or NULL if the transmission failed. + */ + async event void transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime); + + + /** + * Transmits the frame whose transmission has previously been prepared + * through a call to load() using the unslotted CSMA-CA + * algorithm as specified in the IEEE 802.15.4-2006 standard Sect. 7.5.1.4. The initial + * CSMA-CA parameters are passed as a parameter, the algorithm should start immediately. + * The transmitUnslottedCsmaCaDone() event will signal the result + * of the transmission. + * A successful transmission may include an acknowledgement from the + * destination if the ACK_REQUESTED flag is set in the loaded frame's header; then, + * the callee also has to perform the necessary steps for receiving the + * acknowledgement (switching the radio to Rx mode immediately after + * transmission, etc., as specified in IEEE 802.15.4-2006 Sect. 7.5.6.4). + * + * @param csmaParameters parameters for the unslotted CSMA-CA algorithm. * - * @param t0 The (hypothetical) transmission time; the pointer is only valid - * until the eventhandler returns. + * @return SUCCESS if the unslotted CSMA-CA was triggered successfully, + * FAIL otherwise. + */ + async command error_t transmitUnslottedCsmaCa(ieee154_csma_t *csmaParameters); + + /** + * Signalled in response to a call to transmitUnslottedCsmaCa(). + * Depending on the + * error parameter the radio is now in the state RADIO_OFF + * (error == IEEE154_SUCCESS) or still in state TX_LOADED + * (error != IEEE154_SUCCESS). If the transmission succeeded then + * the time of the transmission -- the point in time when the first symbol of the + * PPDU was transmitted -- will be stored in the metadata field of the frame. * + * @param frame The frame that was transmitted. + * @param csmaParameters csmaParameters parameters for the unslotted CSMA-CA algorithm * @param ackPendingFlag TRUE if an acknowledgement was received and the * "pending" flag is set in the header of the ACK frame, FALSE otherwise + * @param result SUCCESS if the the frame was transmitted (and a matching + * acknowledgement was received, if requested); FAIL if the CSMA-CA algorithm failed + * because NB > macMaxCsmaBackoffs. + * + * unslotted CSMA-CA was triggered successfully, + * FAIL otherwiseThe time of transmission or NULL if the transmission failed. + */ + async event void transmitUnslottedCsmaCaDone(ieee154_txframe_t *frame, + bool ackPendingFlag, ieee154_csma_t *csmaParameters, error_t result); + + + /** + * Transmits the frame whose transmission has previously been prepared + * through a call to load() using the slotted CSMA-CA + * algorithm as specified in the IEEE 802.15.4-2006 standard Sect. 7.5.1.4. The initial + * CSMA-CA parameters are passed as a parameter, the algorithm should start immediately, + * but the frame transmission should start no later than slot0Time+dtMax. The backoff slot boundaries + * are defined relative to slot0Time, if the resume + * then the initial backoff (in symbols) is passed as the initialBackoff parameter. + * + * The transmitSlottedCsmaCaDone() event will signal the result + * of the transmission. + * A successful transmission may include an acknowledgement from the + * destination if the ACK_REQUESTED flag is set in the loaded frame's header; then, + * the callee also has to perform the necessary steps for receiving the + * acknowledgement (switching the radio to Rx mode immediately after + * transmission, etc., as specified in IEEE 802.15.4-2006 Sect. 7.5.6.4). + * + * @param slot0Time Reference time (last beacon) + * @param dtMax slot0Time+dtMax is the last time the frame may be transmitted. + * @param resume TRUE means that the initial backoff is defined by the + * initialBackoff parameter, FALSE means the initialBackoff + * should be ignored. + * @param initialBackoff initial backoff. + * @param csmaParameters parameters for the slotted CSMA-CA algorithm. + * + * @return SUCCESS if the slotted CSMA-CA was triggered successfully, + * FAIL otherwise. + */ + async command error_t transmitSlottedCsmaCa(ieee154_reftime_t *slot0Time, uint32_t dtMax, + bool resume, uint16_t initialBackoff, ieee154_csma_t *csmaParameters); + + /** + * Signalled in response to a call to transmitSlottedCsmaCa(). + * Depending on the + * error parameter the radio is now in the state RADIO_OFF + * (error == IEEE154_SUCCESS) or still in state TX_LOADED + * (error != IEEE154_SUCCESS). If the transmission succeeded then + * the time of the transmission -- the point in time when the first symbol of the + * PPDU was transmitted -- will be stored in the metadata field of the frame. + * It will also passed (possibly with higher precision) through the + * txTime parameter. * - * @param error SUCCESS if the transmission succeeded (including successful - * CCA and acknowledgement reception, if requested); EBUSY if CCA was - * unsuccessful (frame was not transmitted); ENOACK if frame was transmitted - * but no matching acknowledgement was received. - **/ - async event void transmitDone(ieee154_txframe_t *frame, ieee154_reftime_t *t0, - bool ackPendingFlag, error_t error); + * @param frame The frame that was transmitted. + * @param txTime The time of transmission of the first symbol of the PPDU or NULL if the transmission failed. + * @param ackPendingFlag TRUE if an acknowledgement was received and the + * "pending" flag is set in the header of the ACK frame, FALSE otherwise + * @param remainingBackoff only valid if error == ERETRY, i.e. + * when the frame could not be transmitted because transmission would have + * started later than slot0Time+dtMax; then it + * specifies the remaining offset (in symbols) relative to slot0Time+dtMax, + * when the frame would have been transmitted + * @param csmaParameters csmaParameters parameters for the unslotted CSMA-CA algorithm + * + * @result result SUCCESS if the the frame was transmitted (and a matching + * acknowledgement was received, if requested); FAIL if the CSMA-CA algorithm failed + * because NB > macMaxCsmaBackoffs; ERETRY if the frame could not be transmitted because transmission would have + * started later than slot0Time+dtMax + */ + async event void transmitSlottedCsmaCaDone(ieee154_txframe_t *frame, ieee154_reftime_t *txTime, + bool ackPendingFlag, uint16_t remainingBackoff, ieee154_csma_t *csmaParameters, error_t result); } diff --git a/tos/lib/mac/tkn154/interfaces/public/IEEE154Frame.nc b/tos/lib/mac/tkn154/interfaces/public/IEEE154Frame.nc index 01d59541..eaa1c3bf 100644 --- a/tos/lib/mac/tkn154/interfaces/public/IEEE154Frame.nc +++ b/tos/lib/mac/tkn154/interfaces/public/IEEE154Frame.nc @@ -115,10 +115,10 @@ interface IEEE154Frame /** * Sets the addressing fields in the MAC header of a frame. The source * PAN identifier and the source address will be set automatically, their - * values depend on the SrcAddrMode parameter: if - * SrcAddrMode is a short or extended address, then - * the current PIB attributes macShortAddress or - * aExtendedAddress and macPANId are used. + * values depend on the SrcAddrMode parameter: if + * SrcAddrMode is a short or extended address, then + * the current PIB attributes macShortAddress or + * aExtendedAddress and macPANId are used. * * @param frame the frame * @param srcAddrMode the source addressing mode @@ -157,7 +157,7 @@ interface IEEE154Frame /** * Returns the point in time when the frame was received. If - * isTimestampValid()<\code> returns FALSE then the + * isTimestampValid()<\tt> returns FALSE then the * timestamp is not valid and must be ignored. * * @param frame the frame @@ -192,7 +192,7 @@ interface IEEE154Frame * Returns the type of the frame * BEACON=0, DATA=1, ACK=2, COMMAND=3. * - * Note: For beacon frames one can use the IEEE154BeaconFrame<\code> + * Note: For beacon frames one can use the IEEE154BeaconFrame<\tt> * interface to inspect additional fields of the frame. * * @param frame the frame @@ -233,8 +233,8 @@ interface IEEE154Frame * received while in promiscuous mode, because then no filtering * (except CRC check) was applied. Note: if this command returns * FALSE, then all other commands in this interface (except - * wasPromiscuousModeEnabled()) and the - * IEEE154BeaconFrame interface return undefined values! + * wasPromiscuousModeEnabled()) and the + * IEEE154BeaconFrame interface return undefined values! * * @param frame the frame * @return TRUE if frame has a standard compliant header, diff --git a/tos/lib/mac/tkn154/interfaces/public/IEEE154TxBeaconPayload.nc b/tos/lib/mac/tkn154/interfaces/public/IEEE154TxBeaconPayload.nc index 4415ee60..bc42d77c 100644 --- a/tos/lib/mac/tkn154/interfaces/public/IEEE154TxBeaconPayload.nc +++ b/tos/lib/mac/tkn154/interfaces/public/IEEE154TxBeaconPayload.nc @@ -42,28 +42,28 @@ interface IEEE154TxBeaconPayload * Sets the beacon payload portion for all subsequently transmitted beacons. * This command replaces the MLME-SET command for the PIB attribute values * 0x45 (macBeaconPayload) and 0x46 (macBeaconPayloadLength). The - * setBeaconPayloadDone()<\code> event will be signalled when the - * beacon payload has been set -- until then beaconPayload<\code> must + * setBeaconPayloadDone()<\tt> event will be signalled when the + * beacon payload has been set -- until then beaconPayload<\tt> must * not be modified. * * @param beaconPayload the new beacon payload * @param length the length of the new beacon payload (in byte) * * @return EBUSY if another transaction is pending, ESIZE if length is too big, - * SUCCESS otherwise (and only then the setBeaconPayloadDone<\code> event + * SUCCESS otherwise (and only then the setBeaconPayloadDone<\tt> event * will be signalled) */ command error_t setBeaconPayload(void *beaconPayload, uint8_t length); /** - * Signalled in response to a setBeaconPayload()<\code> request. + * Signalled in response to a setBeaconPayload()<\tt> request. * Indicates that the beacon payload has been copied and returns the * ownership of the buffer to the next higher layer. * - * @param beaconPayload the beaconPayload<\code> passed in the - * setBeaconPayload()<\code> command - * @param length the length<\code> passed in the - * setBeaconPayload()<\code> command + * @param beaconPayload the beaconPayload<\tt> passed in the + * setBeaconPayload()<\tt> command + * @param length the length<\tt> passed in the + * setBeaconPayload()<\tt> command */ event void setBeaconPayloadDone(void *beaconPayload, uint8_t length); @@ -84,9 +84,9 @@ interface IEEE154TxBeaconPayload /** * Replaces (overwrites) a portion of the current beacon payload. Whenever * possible, to minimize overhead, the next higher layer should prefer this - * command over the setBeaconPayload()<\code> command. The - * modifyBeaconPayloadDone()<\code> event will be signalled when the - * beacon payload has been updated -- until then buffer<\code> must + * command over the setBeaconPayload()<\tt> command. The + * modifyBeaconPayloadDone()<\tt> event will be signalled when the + * beacon payload has been updated -- until then buffer<\tt> must * not be modified. * * @param offset offset into the current beacon payload @@ -94,21 +94,21 @@ interface IEEE154TxBeaconPayload * @param length the length of the buffer * * @return EBUSY if another transaction is pending, ESIZE if offset+length is too big, - * SUCCESS otherwise (and only then the modifyBeaconPayloadDone<\code> event + * SUCCESS otherwise (and only then the modifyBeaconPayloadDone<\tt> event * will be signalled) */ command error_t modifyBeaconPayload(uint8_t offset, void *buffer, uint8_t bufferLength); /** - * Signalled in response to a modifyBeaconPayload()<\code> request. + * Signalled in response to a modifyBeaconPayload()<\tt> request. * Indicates that the beacon payload has been updated. * - * @param offset the offset<\code> passed in the - * modifyBeaconPayload()<\code> command - * @param buffer the buffer<\code> passed in the - * modifyBeaconPayload()<\code> command - * @param bufferLength the bufferLength<\code> passed in the - * modifyBeaconPayload()<\code> command + * @param offset the offset<\tt> passed in the + * modifyBeaconPayload()<\tt> command + * @param buffer the buffer<\tt> passed in the + * modifyBeaconPayload()<\tt> command + * @param bufferLength the bufferLength<\tt> passed in the + * modifyBeaconPayload()<\tt> command */ event void modifyBeaconPayloadDone(uint8_t offset, void *buffer, uint8_t bufferLength); @@ -117,7 +117,7 @@ interface IEEE154TxBeaconPayload * time to update the beacon payload (if desired). * * The usual policy is that (1) this event is signalled before every beacon - * transmission, and (2) that a subsequent call to setPayload<\code> + * transmission, and (2) that a subsequent call to setPayload<\tt> * will update the beacon payload portion of this beacon. However, * because of tight timing constraints in beacon-enabled mode neither can be * guaranteed! @@ -126,7 +126,7 @@ interface IEEE154TxBeaconPayload /** * Indicates that a beacon frame has been transmitted (the - * getBeaconPayload<\code> command can be used to inspect the + * getBeaconPayload<\tt> command can be used to inspect the * beacon payload). */ event void beaconTransmitted(); diff --git a/tos/platforms/telosb/mac/tkn154/Ieee802154MacC.nc b/tos/platforms/telosb/mac/tkn154/Ieee802154MacC.nc index f59ebd76..950db2f0 100644 --- a/tos/platforms/telosb/mac/tkn154/Ieee802154MacC.nc +++ b/tos/platforms/telosb/mac/tkn154/Ieee802154MacC.nc @@ -95,8 +95,9 @@ implementation Packet = MAC; components CC2420TKN154C as PHY, - new Alarm62500hz32VirtualizedC() as PHYAlarm1, + new Alarm62500hz32C() as PHYAlarm1, new Alarm62500hz32VirtualizedC() as PHYAlarm2, + new Alarm62500hz32C() as TKN154TimingPAlarm, LocalTime62500hzC, TKN154TimingP; // wire PHY to the PIB @@ -117,7 +118,8 @@ implementation PHY.TimeCalc -> MAC; PHY.Leds -> LedsC; TKN154TimingP.TimeCalc -> MAC; - TKN154TimingP.LocalTime -> LocalTime62500hzC; + TKN154TimingP.Leds -> LedsC; + TKN154TimingP.SymbolAlarm -> TKN154TimingPAlarm; components new Alarm62500hz32VirtualizedC() as MACAlarm1, new Alarm62500hz32VirtualizedC() as MACAlarm2, @@ -164,6 +166,7 @@ implementation components RandomC, LedsC, NoLedsC; MAC.Random -> RandomC; MAC.Leds -> LedsC; + PHY.Random -> RandomC; #ifdef TKN154_SERIAL_DEBUG components SerialDebugC as Debug; diff --git a/tos/platforms/telosb/mac/tkn154/Makefile.include b/tos/platforms/telosb/mac/tkn154/Makefile.include index 2d728211..b109e1d7 100644 --- a/tos/platforms/telosb/mac/tkn154/Makefile.include +++ b/tos/platforms/telosb/mac/tkn154/Makefile.include @@ -1,3 +1,7 @@ +ifdef TKN154_PIERCEBOARD +CFLAGS += -I$(TOSDIR)/platforms/telosb/mac/tkn154/timer/pierceboard +endif + CFLAGS += -I$(TOSDIR)/platforms/telosb/mac/tkn154 \ -I$(TOSDIR)/platforms/telosb/mac/tkn154/timer \ -I$(TOSDIR)/chips/cc2420_tkn154 diff --git a/tos/platforms/telosb/mac/tkn154/TKN154TimingP.nc b/tos/platforms/telosb/mac/tkn154/TKN154TimingP.nc index d9713c20..ceb71191 100644 --- a/tos/platforms/telosb/mac/tkn154/TKN154TimingP.nc +++ b/tos/platforms/telosb/mac/tkn154/TKN154TimingP.nc @@ -34,12 +34,9 @@ */ /** - * NOTE: * In slotted CSMA-CA frames must be sent on backoff boundaries (slot width: - * 320 us). On TelosB the only clock source with sufficient accuracy is the - * external quartz, unfortunately it is not precise enough (32.768 Hz). - * Therefore, currently the following code is not even trying to achieve - * accurate timing. + * 320 us). The TelosB platform lacks a clock with sufficient precision/ + * accuracy, i.e. for slotted CSMA-CA the timing is *not* standard compliant. */ #include "TKN154_platform.h" @@ -49,15 +46,18 @@ module TKN154TimingP provides interface ReliableWait; provides interface ReferenceTime; uses interface TimeCalc; - uses interface LocalTime; + uses interface Alarm as SymbolAlarm; + uses interface Leds; } implementation { - -#define UWAIT1 nop();nop();nop();nop() -#define UWAIT2 UWAIT1;UWAIT1 -#define UWAIT4 UWAIT2;UWAIT2 -#define UWAIT8 UWAIT4;UWAIT4 + enum { + S_WAIT_OFF, + S_WAIT_RX, + S_WAIT_TX, + S_WAIT_BACKOFF, + }; + uint8_t m_state = S_WAIT_OFF; async command void CaptureTime.convert(uint16_t time, ieee154_reftime_t *localTime, int16_t offset) { @@ -65,7 +65,7 @@ implementation // we now need to convert the capture "time" into ieee154_reftime_t. // With the 32768Hz quartz we don't have enough precision anyway, // so the code below generates a timestamp that is not accurate - // (deviating about +-50 microseconds; this could probably + // (deviating about +-50 microseconds, which could probably // improved if we don't go through LocalTime) uint16_t tbr1, tbr2, delta; uint32_t now; @@ -74,7 +74,7 @@ implementation tbr1 = TBR; tbr2 = TBR; } while (tbr1 != tbr2); // majority vote required (see msp430 manual) - now = call LocalTime.get(); + now = call SymbolAlarm.getNow(); } if (time < tbr1) delta = tbr1 - time; @@ -85,35 +85,76 @@ implementation async command void ReliableWait.busyWait(uint16_t dt) { - uint32_t start = call LocalTime.get(); - while (!call TimeCalc.hasExpired(start, dt)) - ; + uint16_t tbr1, tbr2, tbrVal; + atomic { + do { + tbr1 = TBR; + tbr2 = TBR; + } while (tbr1 != tbr2); // majority vote required (see msp430 manual) + } + tbrVal = tbr1 + dt; + atomic { + do { + tbr1 = TBR; + tbr2 = TBR; + } while (tbr1 != tbr2 || tbr1 != tbrVal); // majority vote required (see msp430 manual) + } } - async command void ReliableWait.waitCCA(ieee154_reftime_t *t0, uint16_t dt) + async command void ReliableWait.waitRx(ieee154_reftime_t *t0, uint16_t dt) { - while (!call TimeCalc.hasExpired(*t0, dt)) - ; - signal ReliableWait.waitCCADone(); + if (m_state != S_WAIT_OFF){ + call Leds.led0On(); + return; + } + m_state = S_WAIT_RX; + call SymbolAlarm.startAt(*t0 - 12, dt); // subtract 12 symbols required for Rx calibration + //signal SymbolAlarm.fired(); } async command void ReliableWait.waitTx(ieee154_reftime_t *t0, uint16_t dt) { - while (!call TimeCalc.hasExpired(*t0, dt)) - ; - signal ReliableWait.waitTxDone(); + if (m_state != S_WAIT_OFF){ + call Leds.led0On(); + return; + } + m_state = S_WAIT_TX; + call SymbolAlarm.startAt(*t0 - 12, dt); // subtract 12 symbols required for Tx calibration + } + + async command void ReliableWait.waitBackoff(ieee154_reftime_t *t0, uint16_t dt) + { + if (m_state != S_WAIT_OFF){ + call Leds.led0On(); + return; + } + m_state = S_WAIT_BACKOFF; + call SymbolAlarm.startAt(*t0, dt); + //signal SymbolAlarm.fired(); } - async command void ReliableWait.waitRx(ieee154_reftime_t *t0, uint16_t dt) + async event void SymbolAlarm.fired() { - while (!call TimeCalc.hasExpired(*t0, dt)) - ; - signal ReliableWait.waitRxDone(); + switch (m_state) + { + case S_WAIT_RX: m_state = S_WAIT_OFF; signal ReliableWait.waitRxDone(); break; + case S_WAIT_TX: m_state = S_WAIT_OFF; signal ReliableWait.waitTxDone(); break; + case S_WAIT_BACKOFF: m_state = S_WAIT_OFF; signal ReliableWait.waitBackoffDone(); break; + default: call Leds.led0On(); break; + } } - + + async command void ReliableWait.busyWaitSlotBoundaryCCA(ieee154_reftime_t *t0, uint16_t *dt) { } + async command void ReliableWait.busyWaitSlotBoundaryTx(ieee154_reftime_t *t0, uint16_t dt) + { + // we cannot meet the timing constraints, but there should at least roughly + // be 20 symbols between the first and the seconds CCA + call ReliableWait.busyWait(20); + } + async command void ReferenceTime.getNow(ieee154_reftime_t* reftime, uint16_t dt) { - *reftime = call LocalTime.get(); + *reftime = call SymbolAlarm.getNow() + dt; } async command uint32_t ReferenceTime.toLocalTime(ieee154_reftime_t* refTime) diff --git a/tos/platforms/telosb/mac/tkn154/TKN154_platform.h b/tos/platforms/telosb/mac/tkn154/TKN154_platform.h index e129e255..cf5b1972 100644 --- a/tos/platforms/telosb/mac/tkn154/TKN154_platform.h +++ b/tos/platforms/telosb/mac/tkn154/TKN154_platform.h @@ -43,7 +43,7 @@ enum { // guard time to give up the token before actual end of CAP/CFP - IEEE154_RADIO_GUARD_TIME = 1000, + IEEE154_ACTIVE_PERIOD_GUARD_TIME = 300, // the expected time for a RadioTx.prepare() operation to execute (return) IEEE154_RADIO_TX_PREPARE_DELAY = 220, diff --git a/tos/platforms/telosb/mac/tkn154/timer/Alarm32khzTo62500hzTransformC.nc b/tos/platforms/telosb/mac/tkn154/timer/Alarm32khzTo62500hzTransformC.nc index 20f0822d..2af284dd 100644 --- a/tos/platforms/telosb/mac/tkn154/timer/Alarm32khzTo62500hzTransformC.nc +++ b/tos/platforms/telosb/mac/tkn154/timer/Alarm32khzTo62500hzTransformC.nc @@ -41,10 +41,13 @@ module Alarm32khzTo62500hzTransformC implementation { /** - * This is the place where we cheat: since we don't have a clock source - * running at 62500 Hz, we cast 2 symbols to 1 tick of the 32768 - * clock, which introduces a small (5%) error. -*/ + * TelosB lacks a clock with the precision and accuracy + * required by the 802.15.4 standard (62500 Hz, 40 ppm). + * As a workaround, we cast one tick of the 32768 Hz clock to + * two 802.15.4 symbols, which introduces a small (5%) error. + * Thus the channel access in particular in beacon-enabled PANs + * (slotted CSMA-CA) is not be standard-compliant! + */ #warning "Warning: MAC timing is not standard compliant (the symbol clock is based on the 32768 Hz oscillator)!" async command void Alarm.start[ uint8_t num ](uint32_t dt){ call AlarmFrom.start[num](dt >> 1);} @@ -61,15 +64,17 @@ implementation async command void Alarm.startAt[ uint8_t num ](uint32_t t0, uint32_t dt){ // t0 occured before "now" - uint32_t now = call Alarm.getNow[num](), elapsed; - if (t0 <= now) - elapsed = now - t0; - else - elapsed = ~(t0 - now) + 1; - if (elapsed > dt) - elapsed = dt; - dt -= elapsed; - call AlarmFrom.start[num](dt >> 1); + atomic { + uint32_t now = call Alarm.getNow[num](), elapsed; + if (t0 < now) + elapsed = now - t0; + else + elapsed = ~(t0 - now) + 1; + if (elapsed > dt) + dt = elapsed; + dt -= elapsed; + call Alarm.start[num](dt); + } } /******************** Defaults ****************************/ diff --git a/tos/platforms/telosb/mac/tkn154/timer/Alarm62500hz32C.nc b/tos/platforms/telosb/mac/tkn154/timer/Alarm62500hz32C.nc new file mode 100644 index 00000000..26f5de2e --- /dev/null +++ b/tos/platforms/telosb/mac/tkn154/timer/Alarm62500hz32C.nc @@ -0,0 +1,15 @@ +#include "Timer62500hz.h" +generic configuration Alarm62500hz32C() +{ + provides interface Alarm as Alarm; +} +implementation +{ + components new Alarm32khz32C(), MainC; + components new Alarm62500hz32P(); + + Alarm = Alarm62500hz32P; + + MainC -> Alarm32khz32C.Init; + Alarm62500hz32P.AlarmFrom -> Alarm32khz32C; +} diff --git a/tos/platforms/telosb/mac/tkn154/timer/Alarm62500hz32P.nc b/tos/platforms/telosb/mac/tkn154/timer/Alarm62500hz32P.nc new file mode 100644 index 00000000..7d6d8860 --- /dev/null +++ b/tos/platforms/telosb/mac/tkn154/timer/Alarm62500hz32P.nc @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2008, Technische Universitaet Berlin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * - Neither the name of the Technische Universitaet Berlin nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * - Revision ------------------------------------------------------------- + * $Date$ + * @author Jan Hauer + * ======================================================================== + */ + +generic module Alarm62500hz32P() + +{ + provides interface Alarm as Alarm; + uses interface Alarm as AlarmFrom; +} +implementation +{ +/** + * TelosB lacks a clock with the precision and accuracy + * required by the 802.15.4 standard (62500 Hz, 40 ppm). + * As a workaround, we cast one tick of the 32768 Hz clock to + * two 802.15.4 symbols, which introduces a small (5%) error. + * Thus the channel access in particular in beacon-enabled PANs + * (slotted CSMA-CA) is not be standard-compliant! + */ + + async command void Alarm.start(uint32_t dt){ call AlarmFrom.start(dt >> 1);} + async command void Alarm.stop(){ call AlarmFrom.stop();} + async event void AlarmFrom.fired(){ signal Alarm.fired();} + async command bool Alarm.isRunning(){ return call AlarmFrom.isRunning();} + async command uint32_t Alarm.getAlarm(){ return call AlarmFrom.getAlarm() << 1;} + + async command uint32_t Alarm.getNow(){ + // this might shift out the most significant bit + // that's why Alarm.startAt() is converted to a Alarm.start() + return call AlarmFrom.getNow() << 1; + } + + async command void Alarm.startAt(uint32_t t0, uint32_t dt){ + // t0 occured before "now" + atomic { + uint32_t now = call Alarm.getNow(), elapsed; + if (t0 < now) + elapsed = now - t0; + else + elapsed = ~(t0 - now) + 1; + if (elapsed > dt) + dt = elapsed; + dt -= elapsed; + call Alarm.start(dt); + } + } + + /******************** Defaults ****************************/ + + default async command void AlarmFrom.start(uint32_t dt){ } + default async command void AlarmFrom.stop(){ } + default async command bool AlarmFrom.isRunning(){ return FALSE;} + default async event void Alarm.fired(){} + default async command void AlarmFrom.startAt(uint32_t t0, uint32_t dt){ } + default async command uint32_t AlarmFrom.getNow(){ return 0;} + default async command uint32_t AlarmFrom.getAlarm(){ return 0;} +}