From: janhauer Date: Thu, 5 Mar 2009 10:07:11 +0000 (+0000) Subject: renaming X-Git-Tag: rc_6_tinyos_2_1_1~478 X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=commitdiff_plain;h=9b57b0f71ad5b0c00ca230b4e181c113ea88b88c renaming --- diff --git a/tos/lib/mac/tkn154/DispatchQueueP.nc b/tos/lib/mac/tkn154/DispatchQueueP.nc new file mode 100644 index 00000000..85669850 --- /dev/null +++ b/tos/lib/mac/tkn154/DispatchQueueP.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 DispatchQueueP() { + 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/DispatchSlottedCsmaP.nc b/tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc new file mode 100644 index 00000000..9c1ad6a5 --- /dev/null +++ b/tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc @@ -0,0 +1,746 @@ +/* + * 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 the transmission/reception of DATA and + * COMMAND frames in the CAP of beacon-enabled PANs. Its main tasks are + * initialization of the parameters of the slotted CSMA-CA algorithm (NB, BE, + * etc.), initiating retransmissions and dealing with broadcast transmissions. + * It does not implement the actual CSMA-CA algorithm, because due to its + * timing requirements the CSMA-CA algorithm is not part of the MAC + * implementation but of the chip-specific radio driver. + * + * This module does slightly different things depending on whether it is the + * CAP for an outgoing superframe (sfDirection = OUTGOING_SUPERFRAME), i.e. the + * CAP from the perspective of a coordinator after it has transmitted its own + * beacon; or for an incoming superframe (sfDirection = 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 + * typically listen for incoming frames from the devices, and a device will + * typically switch the radio off unless it has a frame to transmit. + */ + +#ifndef IEEE154_BEACON_ENABLED_PAN +#error "The IEEE154_BEACON_ENABLED_PAN macro MUST be defined when using this component!" +#endif + +generic module DispatchSlottedCsmaP(uint8_t sfDirection) +{ + 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; + } + 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 SuperframeStructure; + interface GetNow as IsRxEnableActive; + interface Get as GetIndirectTxFrame; + interface Notify as RxEnableStateChange; + interface GetNow as IsTrackingBeacons; + interface FrameUtility; + interface SlottedCsmaCa; + interface RadioRx; + interface RadioOff; + interface MLME_GET; + interface MLME_SET; + interface TimeCalc; + interface Leds; + interface SetNow as FrameBackup; + interface GetNow as FrameRestore; + interface StdControl as TrackSingleBeacon; + } +} +implementation +{ + typedef enum { + SWITCH_OFF, + WAIT_FOR_RXDONE, + WAIT_FOR_TXDONE, + DO_NOTHING, + } next_state_t; + + typedef enum { + INDIRECT_TX_ALARM, + BROADCAST_ALARM, + NO_ALARM, + } rx_alarm_t; + + enum { + COORD_ROLE = (sfDirection == OUTGOING_SUPERFRAME), + DEVICE_ROLE = !COORD_ROLE, + }; + + /* state / frame management */ + norace bool m_lock; + norace bool m_resume; + norace ieee154_txframe_t *m_currentFrame; + norace ieee154_txframe_t *m_bcastFrame; + norace ieee154_txframe_t *m_lastFrame; + norace uint16_t m_remainingBackoff; + + /* variables for the slotted CSMA-CA */ + norace ieee154_csma_t m_csma; + norace ieee154_macMaxBE_t m_BE; + norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs; + norace ieee154_macMaxBE_t m_macMaxBE; + norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries; + norace ieee154_status_t m_txStatus; + norace uint32_t m_transactionTime; + norace bool m_indirectTxPending = FALSE; + norace bool m_broadcastRxPending; + norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime; + + /* function / task prototypes */ + 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(); + +#ifdef TKN154_DEBUG + enum { + HEADER_STR_LEN = 27, + DBG_STR_SIZE = 250, + }; + norace uint16_t m_dbgNumEntries; + norace char m_dbgStr[HEADER_STR_LEN + DBG_STR_SIZE] = "updateState() transitions: "; + void dbg_push_state(uint8_t state) { + if (m_dbgNumEntries < DBG_STR_SIZE-3) + m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '0' + state; + } + void dbg_flush_state() { + m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '\n'; + m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = 0; + dbg_serial("DispatchSlottedCsmaP",m_dbgStr); + m_dbgNumEntries = 0; + } +#else +#define dbg_push_state(X) +#define dbg_flush_state() +#endif + + 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 capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * + (uint32_t) call SuperframeStructure.sfSlotDuration(); + uint16_t guardTime = call SuperframeStructure.guardTime(); + + dbg_serial("DispatchSlottedCsmaP", "Got token, remaining CAP time: %lu\n", + call SuperframeStructure.sfStartTime() + capDuration - guardTime - call CapEndAlarm.getNow()); + if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) { + // 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 + // we'd actually have to transmit the current frame using unslotted CSMA-CA + // but we don't have that functionality available... signal FAIL... + m_lastFrame = m_currentFrame; + m_currentFrame = NULL; + m_txStatus = IEEE154_NO_BEACON; + dbg_serial("DispatchSlottedCsmaP", "CAP component got token, remaining time: %lu\n"); + post signalTxDoneTask(); + return; + } else if (capDuration < guardTime) { + // CAP is too short to do anything practical + dbg_serial("DispatchSlottedCsmaP", "CAP too short!\n"); + call TokenToCfp.transfer(); + return; + } else { + capDuration -= guardTime; + if (DEVICE_ROLE) + m_broadcastRxPending = call SuperframeStructure.isBroadcastPending(); + else { + // COORD_ROLE + if (m_bcastFrame != NULL) { + // we have to transmit a broadcast frame immediately; this + // may require to 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(); + dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast.\n"); + } + } + call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration); + if (call SuperframeStructure.battLifeExtDuration() > 0) + call BLEAlarm.startAt(call SuperframeStructure.sfStartTime(), call SuperframeStructure.battLifeExtDuration()); + } + updateState(); + } + + command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) + { + if (m_currentFrame != NULL) { + // we've not finished transmitting the current frame yet + dbg_serial("DispatchSlottedCsmaP", "Overflow\n"); + return IEEE154_TRANSACTION_OVERFLOW; + } else { + setCurrentFrame(frame); + dbg("DispatchSlottedCsmaP", "New frame to transmit, DSN: %lu\n", (uint32_t) MHR(frame)[MHR_INDEX_SEQNO]); + // a beacon must be found before transmitting in a beacon-enabled PAN + if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) { + call TrackSingleBeacon.start(); + dbg_serial("DispatchSlottedCsmaP", "Tracking single beacon now\n"); + // we'll receive the Token after a beacon was found or after + // aBaseSuperframeDuration*(2n+1) symbols if none was found + } + 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_csma.NB = 0; + m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs(); + m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE(); + m_csma.BE = call MLME_GET.macMinBE(); + if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2) + m_csma.BE = 2; + m_BE = m_csma.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_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 something happened that + * might require a state transition; it implements a lock mechanism (m_lock) + * to prevent race conditions. Whenever the lock is set a "done"-event (from + * the SlottedCsmaCa/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. + */ + + void updateState() + { + uint32_t capDuration; + 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 (there are no loops) + if (m_lock || !call Token.isOwner()) + return; + m_lock = TRUE; // lock + capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * + (uint32_t) call SuperframeStructure.sfSlotDuration(); + + // Check 1: has the CAP finished? + if ((COORD_ROLE || call IsTrackingBeacons.getNow()) && + (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), + capDuration - call SuperframeStructure.guardTime()) || + !call CapEndAlarm.isRunning())) { + dbg_push_state(1); + if (call RadioOff.isOff()) { + stopAllAlarms(); // may still fire, but is 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 + dbg_flush_state(); + dbg_serial("DispatchSlottedCsmaP", "Handing over to CFP.\n"); + 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 + dbg_push_state(2); + next = tryReceive(BROADCAST_ALARM); + } else if (COORD_ROLE && m_bcastFrame) { + dbg_push_state(2); + 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) { + dbg_push_state(3); + next = tryReceive(INDIRECT_TX_ALARM); + } + + // Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending? + else if (call IsTokenRequested.getNow()) { + dbg_push_state(4); + 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 + dbg_serial("DispatchSlottedCsmaP", "Token requested: Handing over to CFP.\n"); + 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 SuperframeStructure.battLifeExtDuration() > 0 && + call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), + call SuperframeStructure.battLifeExtDuration()) && + !call IsRxEnableActive.getNow()) { + dbg_push_state(5); + next = trySwitchOff(); + } + + // Check 6: is there a frame ready to transmit? + else if (m_currentFrame != NULL) { + dbg_push_state(6); + next = tryTransmit(); + } + + // Check 7: should we be in receive mode? + else if (COORD_ROLE || call IsRxEnableActive.getNow()) { + dbg_push_state(7); + next = tryReceive(NO_ALARM); + if (next == DO_NOTHING) { + // 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 respective component + post wasRxEnabledTask(); + } + } + + // Check 8: just make sure the radio is switched off + else { + dbg_push_state(8); + next = trySwitchOff(); + if (next == DO_NOTHING && (DEVICE_ROLE && capDuration == 0)) { + // nothing more to do... just release the Token + stopAllAlarms(); // may still fire, but is locked through isOwner() + m_lock = FALSE; // unlock + dbg_serial("DispatchSlottedCsmaP", "Releasing token\n"); + 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: ASSERT(call RadioOff.off() == SUCCESS); break; + case WAIT_FOR_RXDONE: break; + case WAIT_FOR_TXDONE: break; + case DO_NOTHING: break; + } + } + + next_state_t tryTransmit() + { + // tries to transmit m_currentFrame + uint32_t capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * + (uint32_t) call SuperframeStructure.sfSlotDuration(); + next_state_t next; + + if (!call RadioOff.isOff()) + next = SWITCH_OFF; + else { + uint32_t dtMax = capDuration - call SuperframeStructure.guardTime() - m_transactionTime; + // round to backoff boundary + dtMax = dtMax + (IEEE154_aUnitBackoffPeriod - (dtMax % IEEE154_aUnitBackoffPeriod)); + if (dtMax > capDuration) + dtMax = 0; + if (call SuperframeStructure.battLifeExtDuration() > 0) { + // battery life extension + uint16_t bleLen = call SuperframeStructure.battLifeExtDuration(); + if (bleLen < dtMax) + dtMax = bleLen; + } + if (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), dtMax)) + next = DO_NOTHING; // frame doesn't fit in the remaining CAP + else { + error_t res; + res = call SlottedCsmaCa.transmit(m_currentFrame, &m_csma, + call SuperframeStructure.sfStartTimeRef(), dtMax, m_resume, m_remainingBackoff); + dbg("DispatchSlottedCsmaP", "SlottedCsmaCa.transmit() -> %lu\n", (uint32_t) res); + next = WAIT_FOR_TXDONE; // this will NOT clear the lock + } + } + return next; + } + + next_state_t tryReceive(rx_alarm_t alarmType) + { + next_state_t next; + if (call RadioRx.isReceiving()) + next = DO_NOTHING; + else if (!call RadioOff.isOff()) + next = SWITCH_OFF; + else { + call RadioRx.enableRx(0, 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 = WAIT_FOR_RXDONE; + } + 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 RadioOff.offDone() { m_lock = FALSE; updateState();} + async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();} + + async event void CapEndAlarm.fired() { + dbg_serial("DispatchSlottedCsmaP", "CapEndAlarm.fired()\n"); + 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 SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma, + bool ackPendingFlag, uint16_t remainingBackoff, error_t result) + { + bool done = TRUE; + dbg("DispatchSlottedCsmaP", "SlottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result); + m_resume = FALSE; + + switch (result) + { + case SUCCESS: + // frame was successfully transmitted, if ACK was requested + // then a matching ACK was successfully received as well + m_txStatus = 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_txStatus = 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; + ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS); + return; + } + } + break; + case FAIL: + // The CSMA-CA algorithm failed: the frame was not transmitted, + // because channel was never idle + m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE; + break; + case ENOACK: + // frame was transmitted, but we didn't receive an ACK (although + // we requested an one). note: coordinator never retransmits an + // indirect transmission (see above) + if (m_macMaxFrameRetries > 0) { + // retransmit: reinitialize CSMA-CA parameters + done = FALSE; + m_csma.NB = 0; + m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs; + m_csma.macMaxBE = m_macMaxBE; + m_csma.BE = m_BE; + m_macMaxFrameRetries -= 1; + } else + m_txStatus = IEEE154_NO_ACK; + break; + case EINVAL: // DEBUG!!! + dbg_serial("DispatchSlottedCsmaP", "EINVAL returned by transmitDone()!\n"); + // fall through + case ERETRY: + // frame was not transmitted, because the transaction does not + // fit in the remaining CAP (in beacon-enabled PANs only) + dbg_serial("DispatchSlottedCsmaP", "Transaction didn't fit, current BE: %lu\n", (uint32_t) csma->BE); + m_resume = TRUE; + m_remainingBackoff = remainingBackoff; + done = FALSE; + m_lock = FALSE; // debug! problem: if CAP endalarm has fired it's a deadlock! + if (!call CapEndAlarm.isRunning()) + updateState(); + return; + break; + default: + ASSERT(0); + break; + } + + if (COORD_ROLE && frame == m_bcastFrame) { + // always signal result of broadcast transmissions immediately + restoreFrameFromBackup(); + signalTxBroadcastDone(m_bcastFrame, (!done) ? IEEE154_CHANNEL_ACCESS_FAILURE : m_txStatus); + 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; + ieee154_status_t status = m_txStatus; + m_indirectTxPending = FALSE; + m_lastFrame = NULL; // only now can the next transmission can begin + if (lastFrame) { + dbg("DispatchSlottedCsmaP", "Transmit done, DSN: %lu, result: 0x%lx\n", + (uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status); + signal FrameTx.transmitDone(lastFrame, status); + } + updateState(); + } + + event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) + { + // received a frame -> find out frame type and + // signal it to responsible 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_txStatus = 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_csma, 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_csma, &backup->csma, 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 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 { + ASSERT(0); + 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() + { + ASSERT(0); // should never happen + } + + 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) {ASSERT(0);} + default async command void IndirectTxWaitAlarm.stop() {ASSERT(0);} + default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);} + + default async command void BroadcastAlarm.start(uint32_t dt) {ASSERT(0);} + default async command void BroadcastAlarm.stop() {ASSERT(0);} + default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);} + + default async command bool SuperframeStructure.isBroadcastPending() { 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;} + default command error_t TrackSingleBeacon.start() {return FAIL;} + + command error_t WasRxEnabled.enable() {return FAIL;} + command error_t WasRxEnabled.disable() {return FAIL;} +} diff --git a/tos/lib/mac/tkn154/DispatchUnslottedCsmaP.nc b/tos/lib/mac/tkn154/DispatchUnslottedCsmaP.nc new file mode 100644 index 00000000..cb00450b --- /dev/null +++ b/tos/lib/mac/tkn154/DispatchUnslottedCsmaP.nc @@ -0,0 +1,497 @@ +/* + * 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 the transmission/reception of DATA and + * COMMAND frames in a nonbeacon-enabled PAN. Its main tasks are initialization + * of the parameters of the unslotted CSMA-CA algorithm (NB, BE, etc.), + * initiating retransmissions and managing requests for enabling the receiver + * for a finite period of time. It does not implement the actual CSMA-CA + * algorithm, because due to its timing requirements the CSMA-CA algorithm is + * not part of the MAC implementation but of the chip-specific radio driver. + */ + +#if IEEE154_BEACON_ENABLED_PAN +#error "The IEEE154_BEACON_ENABLED_PAN macro MUST NOT be set when using this component!" +#endif + +module DispatchUnslottedCsmaP +{ + provides + { + interface Init as Reset; + interface MLME_START; + interface FrameTx as FrameTx; + interface FrameRx as FrameRx[uint8_t frameType]; + interface FrameExtracted as FrameExtracted[uint8_t frameType]; + interface Notify as WasRxEnabled; + } + uses + { + interface Timer as IndirectTxWaitTimer; + interface Resource as Token; + interface GetNow as IsTokenRequested; + interface GetNow as IsRxEnableActive; + interface Set as SetMacSuperframeOrder; + interface Set as SetMacPanCoordinator; + interface Get as GetIndirectTxFrame; + interface Notify as RxEnableStateChange; + interface FrameUtility; + interface UnslottedCsmaCa; + interface RadioRx; + interface RadioOff; + interface MLME_GET; + interface MLME_SET; + interface TimeCalc; + interface Leds; + } +} +implementation +{ + typedef enum { + SWITCH_OFF, + WAIT_FOR_RXDONE, + WAIT_FOR_TXDONE, + DO_NOTHING, + } next_state_t; + + typedef enum { + INDIRECT_TX_ALARM, + NO_ALARM, + } rx_alarm_t; + + /* state / frame management */ + norace bool m_lock; + norace bool m_resume; + norace ieee154_txframe_t *m_currentFrame; + norace ieee154_txframe_t *m_lastFrame; + + /* variables for the unslotted CSMA-CA */ + norace ieee154_csma_t m_csma; + norace ieee154_macMaxBE_t m_BE; + norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs; + norace ieee154_macMaxBE_t m_macMaxBE; + norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries; + norace ieee154_status_t m_txStatus; + norace uint32_t m_transactionTime; + norace bool m_indirectTxPending = FALSE; + norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime; + + /* function / task prototypes */ + next_state_t tryReceive(bool startIndirectTxTimer); + 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 wasRxEnabledTask(); + task void startIndirectTxTimerTask(); + task void signalStartConfirmTask(); + + 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); + m_currentFrame = m_lastFrame = NULL; + call IndirectTxWaitTimer.stop(); + return SUCCESS; + } + + command ieee154_status_t MLME_START.request ( + uint16_t panID, + uint8_t logicalChannel, + uint8_t channelPage, + uint32_t startTime, + uint8_t beaconOrder, + uint8_t superframeOrder, + bool panCoordinator, + bool batteryLifeExtension, + bool coordRealignment, + ieee154_security_t *coordRealignSecurity, + ieee154_security_t *beaconSecurity) + { + ieee154_status_t status; + ieee154_macShortAddress_t shortAddress = call MLME_GET.macShortAddress(); + + // check parameters + if ((coordRealignSecurity && coordRealignSecurity->SecurityLevel) || + (beaconSecurity && beaconSecurity->SecurityLevel)) + status = IEEE154_UNSUPPORTED_SECURITY; + else if (shortAddress == 0xFFFF) + status = IEEE154_NO_SHORT_ADDRESS; + else if (logicalChannel > 26 || + (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || + !(IEEE154_SUPPORTED_CHANNELS & ((uint32_t) 1 << logicalChannel))) + status = IEEE154_INVALID_PARAMETER; + else if (beaconOrder != 15) + status = IEEE154_INVALID_PARAMETER; + else { + call MLME_SET.macPANId(panID); + call MLME_SET.phyCurrentChannel(logicalChannel); + call MLME_SET.macBeaconOrder(beaconOrder); + call SetMacSuperframeOrder.set(superframeOrder); + call SetMacPanCoordinator.set(panCoordinator); + //TODO: check realignment + post signalStartConfirmTask(); + status = IEEE154_SUCCESS; + } + return status; + } + + task void signalStartConfirmTask() + { + signal MLME_START.confirm(IEEE154_SUCCESS); + } + + command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) + { + if (m_currentFrame != NULL) { + // we've not finished transmitting the current frame yet + dbg_serial("DispatchUnslottedCsmaP", "Overflow\n"); + return IEEE154_TRANSACTION_OVERFLOW; + } else { + setCurrentFrame(frame); + call Token.request(); + return IEEE154_SUCCESS; + } + } + + event void Token.granted() + { + 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_csma.NB = 0; + m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs(); + m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE(); + m_csma.BE = call MLME_GET.macMinBE(); + if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2) + m_csma.BE = 2; + m_BE = m_csma.BE; + if (call GetIndirectTxFrame.get() == frame) + m_macMaxFrameRetries = 0; // this is an indirect transmissions (never retransmit) + else + m_macMaxFrameRetries = call MLME_GET.macMaxFrameRetries(); + 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; + } + + /** + * The updateState() function is called whenever some event happened that + * might require a state transition; 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. Calling this function more than + * necessary can do no harm. + */ + + void updateState() + { + 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 (there are no loops) + if (m_lock || !call Token.isOwner()) + return; + m_lock = TRUE; // lock + + // Check 1: was an indirect transmission successfully started + // and are we now waiting for a frame from the coordinator? + if (m_indirectTxPending) { + next = tryReceive(TRUE); + } + + // Check 2: is some other operation (like MLME-SCAN or MLME-RESET) pending? + else if (call IsTokenRequested.getNow()) { + if (call RadioOff.isOff()) { + // nothing more to do... just release the Token + m_lock = FALSE; // unlock + dbg_serial("DispatchUnslottedCsmaP", "Token requested: releasing it.\n"); + call Token.release(); + return; + } else + next = SWITCH_OFF; + } + + // Check 3: is there a frame ready to transmit? + else if (m_currentFrame != NULL) { + next = tryTransmit(); + } + + // Check 4: should we be in receive mode? + else if (call IsRxEnableActive.getNow()) { + next = tryReceive(FALSE); + if (next == DO_NOTHING) { + // 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 6: just make sure the radio is switched off + else { + next = trySwitchOff(); + if (next == DO_NOTHING) { + // nothing more to do... just release the Token + m_lock = FALSE; // unlock + dbg_serial("DispatchUnslottedCsmaP", "Releasing token\n"); + 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: ASSERT(call RadioOff.off() == SUCCESS); break; + case WAIT_FOR_RXDONE: break; + case WAIT_FOR_TXDONE: break; + case DO_NOTHING: break; + } + } + + next_state_t tryTransmit() + { + // tries to transmit m_currentFrame + next_state_t next; + + if (!call RadioOff.isOff()) + next = SWITCH_OFF; + else { + error_t res; + res = call UnslottedCsmaCa.transmit(m_currentFrame, &m_csma); + dbg("DispatchUnslottedCsmaP", "UnslottedCsmaCa.transmit() -> %lu\n", (uint32_t) res); + next = WAIT_FOR_TXDONE; // this will NOT clear the lock + } + return next; + } + + next_state_t tryReceive(bool startIndirectTxTimer) + { + next_state_t next; + if (call RadioRx.isReceiving()) + next = DO_NOTHING; + else if (!call RadioOff.isOff()) + next = SWITCH_OFF; + else { + call RadioRx.enableRx(0, 0); + if (startIndirectTxTimer) + post startIndirectTxTimerTask(); + next = WAIT_FOR_RXDONE; + } + 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 RadioOff.offDone() { m_lock = FALSE; updateState();} + async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();} + event void RxEnableStateChange.notify(bool whatever) { updateState();} + + event void IndirectTxWaitTimer.fired() + { + atomic { + if (m_indirectTxPending) { + m_indirectTxPending = FALSE; + post signalTxDoneTask(); + } + } + } + + task void startIndirectTxTimerTask() + { + call IndirectTxWaitTimer.startOneShot(m_macMaxFrameTotalWaitTime); + } + + async event void UnslottedCsmaCa.transmitDone(ieee154_txframe_t *frame, + ieee154_csma_t *csma, bool ackPendingFlag, error_t result) + { + bool done = TRUE; + dbg("DispatchUnslottedCsmaP", "UnslottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result); + m_resume = FALSE; + + switch (result) + { + case SUCCESS: + // frame was successfully transmitted, if ACK was requested + // then a matching ACK was successfully received as well + m_txStatus = IEEE154_SUCCESS; + if (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_txStatus = 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; + ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS); + return; + } + } + break; + case FAIL: + // The CSMA-CA algorithm failed: the frame was not transmitted, + // because channel was never idle + m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE; + break; + case ENOACK: + // frame was transmitted, but we didn't receive an ACK (although + // we requested an one). note: coordinator never retransmits an + // indirect transmission (see above) + if (m_macMaxFrameRetries > 0) { + // retransmit: reinitialize CSMA-CA parameters + done = FALSE; + m_csma.NB = 0; + m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs; + m_csma.macMaxBE = m_macMaxBE; + m_csma.BE = m_BE; + m_macMaxFrameRetries -= 1; + } else + m_txStatus = IEEE154_NO_ACK; + break; + default: + ASSERT(0); + break; + } + + if (done) { + m_lastFrame = m_currentFrame; + m_currentFrame = NULL; + post signalTxDoneTask(); + } + + m_lock = FALSE; + updateState(); + } + + task void signalTxDoneTask() + { + ieee154_txframe_t *lastFrame = m_lastFrame; + ieee154_status_t status = m_txStatus; + m_indirectTxPending = FALSE; + m_lastFrame = NULL; // only now the next transmission can begin + if (lastFrame) { + dbg("DispatchUnslottedCsmaP", "Transmit done, DSN: %lu, result: 0x%lx\n", + (uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status); + signal FrameTx.transmitDone(lastFrame, status); + } + updateState(); + } + + event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) + { + // received a frame -> find out frame type and + // signal it to responsible 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 (m_indirectTxPending) { + message_t* frameBuf; + call IndirectTxWaitTimer.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_txStatus = IEEE154_SUCCESS; + frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); + signal IndirectTxWaitTimer.fired(); + return frameBuf; + } else + return signal FrameRx.received[frameType](frame); + } + } + + task void wasRxEnabledTask() + { + signal WasRxEnabled.notify(TRUE); + } + + + 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 event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame) {return msg;} + + command error_t WasRxEnabled.enable() {return FAIL;} + command error_t WasRxEnabled.disable() {return FAIL;} + default event void MLME_START.confirm(ieee154_status_t status) {} +} diff --git a/tos/lib/mac/tkn154/FrameDispatchQueueP.nc b/tos/lib/mac/tkn154/FrameDispatchQueueP.nc deleted file mode 100644 index 6693ade0..00000000 --- a/tos/lib/mac/tkn154/FrameDispatchQueueP.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 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/PibP.nc b/tos/lib/mac/tkn154/PibP.nc index bf8a0ac2..b4e7f6f9 100644 --- a/tos/lib/mac/tkn154/PibP.nc +++ b/tos/lib/mac/tkn154/PibP.nc @@ -62,8 +62,8 @@ module PibP { uses { interface Get as PromiscuousModeGet; - interface Init as FrameDispatchReset; - interface Init as FrameDispatchQueueReset; + interface Init as DispatchReset; + interface Init as DispatchQueueReset; interface Init as MacReset; interface SplitControl as RadioControl; interface Random; @@ -206,9 +206,9 @@ implementation event void RadioControl.stopDone(error_t result) { ASSERT(result == SUCCESS); - call FrameDispatchReset.init(); // resets the CAP component(s), spool out frames - call FrameDispatchQueueReset.init(); // resets the CAP queue component(s), spool out frames - call MacReset.init(); // resets the remaining components + call DispatchReset.init(); // resets the dispatch component(s), spools out frames + call DispatchQueueReset.init(); // resets the dispatch queue component(s), spools out frames + call MacReset.init(); // resets the remaining components m_resetSpin = 5; post resetSpinTask(); } @@ -217,8 +217,8 @@ implementation { if (m_resetSpin == 2) { // just to be safe... - call FrameDispatchReset.init(); - call FrameDispatchQueueReset.init(); + call DispatchReset.init(); + call DispatchQueueReset.init(); call MacReset.init(); } if (m_resetSpin--) { diff --git a/tos/lib/mac/tkn154/SlottedFrameDispatchP.nc b/tos/lib/mac/tkn154/SlottedFrameDispatchP.nc deleted file mode 100644 index 4abb5269..00000000 --- a/tos/lib/mac/tkn154/SlottedFrameDispatchP.nc +++ /dev/null @@ -1,746 +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 is responsible for the transmission/reception of DATA and - * COMMAND frames in the CAP of beacon-enabled PANs. Its main tasks are - * initialization of the parameters of the slotted CSMA-CA algorithm (NB, BE, - * etc.), initiating retransmissions and dealing with broadcast transmissions. - * It does not implement the actual CSMA-CA algorithm, because due to its - * timing requirements the CSMA-CA algorithm is not part of the MAC - * implementation but of the chip-specific radio driver. - * - * This module does slightly different things depending on whether it is the - * CAP for an outgoing superframe (sfDirection = OUTGOING_SUPERFRAME), i.e. the - * CAP from the perspective of a coordinator after it has transmitted its own - * beacon; or for an incoming superframe (sfDirection = 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 - * typically listen for incoming frames from the devices, and a device will - * typically switch the radio off unless it has a frame to transmit. - */ - -#ifndef IEEE154_BEACON_ENABLED_PAN -#error "The IEEE154_BEACON_ENABLED_PAN macro MUST be defined when using this component!" -#endif - -generic module SlottedFrameDispatchP(uint8_t sfDirection) -{ - 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; - } - 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 SuperframeStructure; - interface GetNow as IsRxEnableActive; - interface Get as GetIndirectTxFrame; - interface Notify as RxEnableStateChange; - interface GetNow as IsTrackingBeacons; - interface FrameUtility; - interface SlottedCsmaCa; - interface RadioRx; - interface RadioOff; - interface MLME_GET; - interface MLME_SET; - interface TimeCalc; - interface Leds; - interface SetNow as FrameBackup; - interface GetNow as FrameRestore; - interface StdControl as TrackSingleBeacon; - } -} -implementation -{ - typedef enum { - SWITCH_OFF, - WAIT_FOR_RXDONE, - WAIT_FOR_TXDONE, - DO_NOTHING, - } next_state_t; - - typedef enum { - INDIRECT_TX_ALARM, - BROADCAST_ALARM, - NO_ALARM, - } rx_alarm_t; - - enum { - COORD_ROLE = (sfDirection == OUTGOING_SUPERFRAME), - DEVICE_ROLE = !COORD_ROLE, - }; - - /* state / frame management */ - norace bool m_lock; - norace bool m_resume; - norace ieee154_txframe_t *m_currentFrame; - norace ieee154_txframe_t *m_bcastFrame; - norace ieee154_txframe_t *m_lastFrame; - norace uint16_t m_remainingBackoff; - - /* variables for the slotted CSMA-CA */ - norace ieee154_csma_t m_csma; - norace ieee154_macMaxBE_t m_BE; - norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs; - norace ieee154_macMaxBE_t m_macMaxBE; - norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries; - norace ieee154_status_t m_txStatus; - norace uint32_t m_transactionTime; - norace bool m_indirectTxPending = FALSE; - norace bool m_broadcastRxPending; - norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime; - - /* function / task prototypes */ - 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(); - -#ifdef TKN154_DEBUG - enum { - HEADER_STR_LEN = 27, - DBG_STR_SIZE = 250, - }; - norace uint16_t m_dbgNumEntries; - norace char m_dbgStr[HEADER_STR_LEN + DBG_STR_SIZE] = "updateState() transitions: "; - void dbg_push_state(uint8_t state) { - if (m_dbgNumEntries < DBG_STR_SIZE-3) - m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '0' + state; - } - void dbg_flush_state() { - m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '\n'; - m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = 0; - dbg_serial("SlottedFrameDispatchP",m_dbgStr); - m_dbgNumEntries = 0; - } -#else -#define dbg_push_state(X) -#define dbg_flush_state() -#endif - - 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 capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * - (uint32_t) call SuperframeStructure.sfSlotDuration(); - uint16_t guardTime = call SuperframeStructure.guardTime(); - - dbg_serial("SlottedFrameDispatchP", "Got token, remaining CAP time: %lu\n", - call SuperframeStructure.sfStartTime() + capDuration - guardTime - call CapEndAlarm.getNow()); - if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) { - // 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 - // we'd actually have to transmit the current frame using unslotted CSMA-CA - // but we don't have that functionality available... signal FAIL... - m_lastFrame = m_currentFrame; - m_currentFrame = NULL; - m_txStatus = IEEE154_NO_BEACON; - dbg_serial("SlottedFrameDispatchP", "CAP component got token, remaining time: %lu\n"); - post signalTxDoneTask(); - return; - } else if (capDuration < guardTime) { - // CAP is too short to do anything practical - dbg_serial("SlottedFrameDispatchP", "CAP too short!\n"); - call TokenToCfp.transfer(); - return; - } else { - capDuration -= guardTime; - if (DEVICE_ROLE) - m_broadcastRxPending = call SuperframeStructure.isBroadcastPending(); - else { - // COORD_ROLE - if (m_bcastFrame != NULL) { - // we have to transmit a broadcast frame immediately; this - // may require to 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(); - dbg_serial("SlottedFrameDispatchP", "Preparing broadcast.\n"); - } - } - call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration); - if (call SuperframeStructure.battLifeExtDuration() > 0) - call BLEAlarm.startAt(call SuperframeStructure.sfStartTime(), call SuperframeStructure.battLifeExtDuration()); - } - updateState(); - } - - command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) - { - if (m_currentFrame != NULL) { - // we've not finished transmitting the current frame yet - dbg_serial("SlottedFrameDispatchP", "Overflow\n"); - return IEEE154_TRANSACTION_OVERFLOW; - } else { - setCurrentFrame(frame); - dbg("SlottedFrameDispatchP", "New frame to transmit, DSN: %lu\n", (uint32_t) MHR(frame)[MHR_INDEX_SEQNO]); - // a beacon must be found before transmitting in a beacon-enabled PAN - if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) { - call TrackSingleBeacon.start(); - dbg_serial("SlottedFrameDispatchP", "Tracking single beacon now\n"); - // we'll receive the Token after a beacon was found or after - // aBaseSuperframeDuration*(2n+1) symbols if none was found - } - 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_csma.NB = 0; - m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs(); - m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE(); - m_csma.BE = call MLME_GET.macMinBE(); - if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2) - m_csma.BE = 2; - m_BE = m_csma.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_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 something happened that - * might require a state transition; it implements a lock mechanism (m_lock) - * to prevent race conditions. Whenever the lock is set a "done"-event (from - * the SlottedCsmaCa/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. - */ - - void updateState() - { - uint32_t capDuration; - 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 (there are no loops) - if (m_lock || !call Token.isOwner()) - return; - m_lock = TRUE; // lock - capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * - (uint32_t) call SuperframeStructure.sfSlotDuration(); - - // Check 1: has the CAP finished? - if ((COORD_ROLE || call IsTrackingBeacons.getNow()) && - (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), - capDuration - call SuperframeStructure.guardTime()) || - !call CapEndAlarm.isRunning())) { - dbg_push_state(1); - if (call RadioOff.isOff()) { - stopAllAlarms(); // may still fire, but is 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 - dbg_flush_state(); - dbg_serial("SlottedFrameDispatchP", "Handing over to CFP.\n"); - 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 - dbg_push_state(2); - next = tryReceive(BROADCAST_ALARM); - } else if (COORD_ROLE && m_bcastFrame) { - dbg_push_state(2); - 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) { - dbg_push_state(3); - next = tryReceive(INDIRECT_TX_ALARM); - } - - // Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending? - else if (call IsTokenRequested.getNow()) { - dbg_push_state(4); - 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 - dbg_serial("SlottedFrameDispatchP", "Token requested: Handing over to CFP.\n"); - 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 SuperframeStructure.battLifeExtDuration() > 0 && - call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), - call SuperframeStructure.battLifeExtDuration()) && - !call IsRxEnableActive.getNow()) { - dbg_push_state(5); - next = trySwitchOff(); - } - - // Check 6: is there a frame ready to transmit? - else if (m_currentFrame != NULL) { - dbg_push_state(6); - next = tryTransmit(); - } - - // Check 7: should we be in receive mode? - else if (COORD_ROLE || call IsRxEnableActive.getNow()) { - dbg_push_state(7); - next = tryReceive(NO_ALARM); - if (next == DO_NOTHING) { - // 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 respective component - post wasRxEnabledTask(); - } - } - - // Check 8: just make sure the radio is switched off - else { - dbg_push_state(8); - next = trySwitchOff(); - if (next == DO_NOTHING && (DEVICE_ROLE && capDuration == 0)) { - // nothing more to do... just release the Token - stopAllAlarms(); // may still fire, but is locked through isOwner() - m_lock = FALSE; // unlock - dbg_serial("SlottedFrameDispatchP", "Releasing token\n"); - 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: ASSERT(call RadioOff.off() == SUCCESS); break; - case WAIT_FOR_RXDONE: break; - case WAIT_FOR_TXDONE: break; - case DO_NOTHING: break; - } - } - - next_state_t tryTransmit() - { - // tries to transmit m_currentFrame - uint32_t capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * - (uint32_t) call SuperframeStructure.sfSlotDuration(); - next_state_t next; - - if (!call RadioOff.isOff()) - next = SWITCH_OFF; - else { - uint32_t dtMax = capDuration - call SuperframeStructure.guardTime() - m_transactionTime; - // round to backoff boundary - dtMax = dtMax + (IEEE154_aUnitBackoffPeriod - (dtMax % IEEE154_aUnitBackoffPeriod)); - if (dtMax > capDuration) - dtMax = 0; - if (call SuperframeStructure.battLifeExtDuration() > 0) { - // battery life extension - uint16_t bleLen = call SuperframeStructure.battLifeExtDuration(); - if (bleLen < dtMax) - dtMax = bleLen; - } - if (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), dtMax)) - next = DO_NOTHING; // frame doesn't fit in the remaining CAP - else { - error_t res; - res = call SlottedCsmaCa.transmit(m_currentFrame, &m_csma, - call SuperframeStructure.sfStartTimeRef(), dtMax, m_resume, m_remainingBackoff); - dbg("SlottedFrameDispatchP", "SlottedCsmaCa.transmit() -> %lu\n", (uint32_t) res); - next = WAIT_FOR_TXDONE; // this will NOT clear the lock - } - } - return next; - } - - next_state_t tryReceive(rx_alarm_t alarmType) - { - next_state_t next; - if (call RadioRx.isReceiving()) - next = DO_NOTHING; - else if (!call RadioOff.isOff()) - next = SWITCH_OFF; - else { - call RadioRx.enableRx(0, 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 = WAIT_FOR_RXDONE; - } - 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 RadioOff.offDone() { m_lock = FALSE; updateState();} - async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();} - - async event void CapEndAlarm.fired() { - dbg_serial("SlottedFrameDispatchP", "CapEndAlarm.fired()\n"); - 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 SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma, - bool ackPendingFlag, uint16_t remainingBackoff, error_t result) - { - bool done = TRUE; - dbg("SlottedFrameDispatchP", "SlottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result); - m_resume = FALSE; - - switch (result) - { - case SUCCESS: - // frame was successfully transmitted, if ACK was requested - // then a matching ACK was successfully received as well - m_txStatus = 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_txStatus = 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; - ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS); - return; - } - } - break; - case FAIL: - // The CSMA-CA algorithm failed: the frame was not transmitted, - // because channel was never idle - m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE; - break; - case ENOACK: - // frame was transmitted, but we didn't receive an ACK (although - // we requested an one). note: coordinator never retransmits an - // indirect transmission (see above) - if (m_macMaxFrameRetries > 0) { - // retransmit: reinitialize CSMA-CA parameters - done = FALSE; - m_csma.NB = 0; - m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs; - m_csma.macMaxBE = m_macMaxBE; - m_csma.BE = m_BE; - m_macMaxFrameRetries -= 1; - } else - m_txStatus = IEEE154_NO_ACK; - break; - case EINVAL: // DEBUG!!! - dbg_serial("SlottedFrameDispatchP", "EINVAL returned by transmitDone()!\n"); - // fall through - case ERETRY: - // frame was not transmitted, because the transaction does not - // fit in the remaining CAP (in beacon-enabled PANs only) - dbg_serial("SlottedFrameDispatchP", "Transaction didn't fit, current BE: %lu\n", (uint32_t) csma->BE); - m_resume = TRUE; - m_remainingBackoff = remainingBackoff; - done = FALSE; - m_lock = FALSE; // debug! problem: if CAP endalarm has fired it's a deadlock! - if (!call CapEndAlarm.isRunning()) - updateState(); - return; - break; - default: - ASSERT(0); - break; - } - - if (COORD_ROLE && frame == m_bcastFrame) { - // always signal result of broadcast transmissions immediately - restoreFrameFromBackup(); - signalTxBroadcastDone(m_bcastFrame, (!done) ? IEEE154_CHANNEL_ACCESS_FAILURE : m_txStatus); - 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; - ieee154_status_t status = m_txStatus; - m_indirectTxPending = FALSE; - m_lastFrame = NULL; // only now can the next transmission can begin - if (lastFrame) { - dbg("SlottedFrameDispatchP", "Transmit done, DSN: %lu, result: 0x%lx\n", - (uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status); - signal FrameTx.transmitDone(lastFrame, status); - } - updateState(); - } - - event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) - { - // received a frame -> find out frame type and - // signal it to responsible 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_txStatus = 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_csma, 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_csma, &backup->csma, 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 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 { - ASSERT(0); - 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() - { - ASSERT(0); // should never happen - } - - 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) {ASSERT(0);} - default async command void IndirectTxWaitAlarm.stop() {ASSERT(0);} - default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);} - - default async command void BroadcastAlarm.start(uint32_t dt) {ASSERT(0);} - default async command void BroadcastAlarm.stop() {ASSERT(0);} - default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);} - - default async command bool SuperframeStructure.isBroadcastPending() { 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;} - default command error_t TrackSingleBeacon.start() {return FAIL;} - - command error_t WasRxEnabled.enable() {return FAIL;} - command error_t WasRxEnabled.disable() {return FAIL;} -} diff --git a/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc b/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc index 2f718b0c..ea794c3b 100644 --- a/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc +++ b/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc @@ -136,23 +136,23 @@ implementation #ifndef IEEE154_BEACON_SYNC_DISABLED BeaconSynchronizeP, - new FrameDispatchQueueP() as DeviceCapQueue, - new SlottedFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap, + new DispatchQueueP() as DeviceCapQueue, + new DispatchSlottedCsmaP(INCOMING_SUPERFRAME) as DeviceCap, #else NoBeaconSynchronizeP as BeaconSynchronizeP, - new NoFrameDispatchQueueP() as DeviceCapQueue, - new NoSlottedFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap, + new NoDispatchQueueP() as DeviceCapQueue, + new NoDispatchSlottedCsmaP(INCOMING_SUPERFRAME) as DeviceCap, #endif NoDeviceCfpP as DeviceCfp, #ifndef IEEE154_BEACON_TX_DISABLED BeaconTransmitP, - new FrameDispatchQueueP() as CoordCapQueue, - new SlottedFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap, + new DispatchQueueP() as CoordCapQueue, + new DispatchSlottedCsmaP(OUTGOING_SUPERFRAME) as CoordCap, #else NoBeaconTransmitP as BeaconTransmitP, - new NoFrameDispatchQueueP() as CoordCapQueue, - new NoSlottedFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap, + new NoDispatchQueueP() as CoordCapQueue, + new NoDispatchSlottedCsmaP(OUTGOING_SUPERFRAME) as CoordCap, #endif NoCoordCfpP as CoordCfp, @@ -402,16 +402,16 @@ implementation /* --------------------- CAP (incoming superframe) -------------------- */ - PibP.FrameDispatchQueueReset -> DeviceCapQueue; + PibP.DispatchQueueReset -> DeviceCapQueue; DeviceCapQueue.Queue -> DeviceCapQueueC; DeviceCapQueue.FrameTxCsma -> DeviceCap; - PibP.FrameDispatchQueueReset -> CoordCapQueue; + PibP.DispatchQueueReset -> CoordCapQueue; CoordCapQueue.Queue -> CoordCapQueueC; CoordCapQueue.FrameTxCsma -> CoordCap; components new RadioClientC() as DeviceCapRadioClient; - PibP.FrameDispatchReset -> DeviceCap; + PibP.DispatchReset -> DeviceCap; DeviceCap.CapEndAlarm = Alarm3; DeviceCap.BLEAlarm = Alarm4; DeviceCap.IndirectTxWaitAlarm = Alarm5; @@ -440,7 +440,7 @@ implementation components new RadioClientC() as CoordCapRadioClient, new BackupP(ieee154_cap_frame_backup_t); - PibP.FrameDispatchReset -> CoordCap; + PibP.DispatchReset -> CoordCap; CoordCap.CapEndAlarm = Alarm7; CoordCap.BLEAlarm = Alarm8; CoordCap.Token -> CoordCapRadioClient; diff --git a/tos/lib/mac/tkn154/TKN154NonBeaconEnabledP.nc b/tos/lib/mac/tkn154/TKN154NonBeaconEnabledP.nc index f5bc50a4..9924fbd0 100644 --- a/tos/lib/mac/tkn154/TKN154NonBeaconEnabledP.nc +++ b/tos/lib/mac/tkn154/TKN154NonBeaconEnabledP.nc @@ -118,8 +118,8 @@ implementation #else NoDisassociateP as DisassociateP, #endif - new FrameDispatchQueueP() as FrameDispatchQueueP, - UnslottedFrameDispatchP as FrameDispatchP, + new DispatchQueueP() as DispatchQueueP, + DispatchUnslottedCsmaP as DispatchP, #ifndef IEEE154_RXENABLE_DISABLED RxEnableP, @@ -142,7 +142,7 @@ implementation new PoolC(ieee154_txframe_t, TXFRAME_POOL_SIZE) as TxFramePoolP, new PoolC(ieee154_txcontrol_t, TXCONTROL_POOL_SIZE) as TxControlPoolP, - new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as FrameDispatchQueueC; + new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as DispatchQueueC; components MainC; @@ -151,7 +151,7 @@ implementation MCPS_PURGE = DataP; /* MLME */ - MLME_START = FrameDispatchP; + MLME_START = DispatchP; MLME_ASSOCIATE = AssociateP; MLME_DISASSOCIATE = DisassociateP; MLME_BEACON_NOTIFY = ScanP; @@ -194,9 +194,9 @@ implementation /* -------------------- Association (MLME-ASSOCIATE) -------------------- */ PibP.MacReset -> AssociateP; - AssociateP.AssociationRequestRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_REQUEST]; - AssociateP.AssociationRequestTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; - AssociateP.AssociationResponseExtracted -> FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_RESPONSE]; + AssociateP.AssociationRequestRx -> DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_REQUEST]; + AssociateP.AssociationRequestTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + AssociateP.AssociationResponseExtracted -> DispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_RESPONSE]; AssociateP.AssociationResponseTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)]; AssociateP.DataRequest -> PollP.DataRequest[ASSOCIATE_POLL_CLIENT]; AssociateP.ResponseTimeout = Timer2; @@ -212,12 +212,12 @@ implementation PibP.MacReset -> DisassociateP; DisassociateP.DisassociationIndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)]; - DisassociateP.DisassociationDirectTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; - DisassociateP.DisassociationToCoord -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + DisassociateP.DisassociationDirectTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + DisassociateP.DisassociationToCoord -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; DisassociateP.DisassociationExtractedFromCoord -> - FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION]; + DispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION]; DisassociateP.DisassociationRxFromDevice -> - FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION]; + DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION]; DisassociateP.TxFramePool -> TxFramePoolP; DisassociateP.TxControlPool -> TxControlPoolP; DisassociateP.MLME_GET -> PibP; @@ -227,15 +227,15 @@ implementation /* ------------------ Data Transmission (MCPS-DATA) ------------------- */ - DataP.DeviceCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; - DataP.CoordCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + DataP.DeviceCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + DataP.CoordCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; DataP.DeviceCapRx -> PollP.DataRx; DataP.DeviceCapRx -> PromiscuousModeP.FrameRx; DataP.TxFramePool -> TxFramePoolP; DataP.IndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)]; DataP.FrameUtility -> PibP; DataP.Frame -> PibP; - DataP.PurgeDirect -> FrameDispatchQueueP; + DataP.PurgeDirect -> DispatchQueueP; DataP.PurgeIndirect -> IndirectTxP; DataP.MLME_GET -> PibP; DataP.Packet -> PibP; @@ -244,8 +244,8 @@ implementation /* ------------------------ Polling (MLME-POLL) ----------------------- */ PibP.MacReset -> PollP; - PollP.PollTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; - PollP.DataExtracted -> FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_DATA]; + PollP.PollTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + PollP.DataExtracted -> DispatchP.FrameExtracted[FC1_FRAMETYPE_DATA]; PollP.FrameUtility -> PibP; PollP.TxFramePool -> TxFramePoolP; PollP.TxControlPool -> TxControlPoolP; @@ -255,8 +255,8 @@ implementation /* ---------------------- Indirect transmission ----------------------- */ PibP.MacReset -> IndirectTxP; - IndirectTxP.CoordCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; - IndirectTxP.DataRequestRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DATA_REQUEST]; + IndirectTxP.CoordCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + IndirectTxP.DataRequestRx -> DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DATA_REQUEST]; IndirectTxP.MLME_GET -> PibP; IndirectTxP.FrameUtility -> PibP; IndirectTxP.IndirectTxTimeout = Timer3; @@ -266,8 +266,8 @@ implementation /* ---------------------------- Realignment --------------------------- */ PibP.MacReset -> CoordRealignmentP; - CoordRealignmentP.CoordRealignmentTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; - CoordRealignmentP.OrphanNotificationRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ORPHAN_NOTIFICATION]; + CoordRealignmentP.CoordRealignmentTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)]; + CoordRealignmentP.OrphanNotificationRx -> DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ORPHAN_NOTIFICATION]; CoordRealignmentP.FrameUtility -> PibP; CoordRealignmentP.Frame -> PibP; CoordRealignmentP.TxFramePool -> TxFramePoolP; @@ -275,31 +275,31 @@ implementation CoordRealignmentP.MLME_GET -> PibP; CoordRealignmentP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress; - /* --------------------- FrameDispatchP -------------------- */ + /* --------------------- DispatchP -------------------- */ - PibP.FrameDispatchReset -> FrameDispatchP; - PibP.FrameDispatchQueueReset -> FrameDispatchQueueP; - FrameDispatchQueueP.Queue -> FrameDispatchQueueC; - FrameDispatchQueueP.FrameTxCsma -> FrameDispatchP; + PibP.DispatchReset -> DispatchP; + PibP.DispatchQueueReset -> DispatchQueueP; + DispatchQueueP.Queue -> DispatchQueueC; + DispatchQueueP.FrameTxCsma -> DispatchP; - components new RadioClientC() as FrameDispatchRadioClient; - PibP.FrameDispatchReset -> FrameDispatchP; - FrameDispatchP.IndirectTxWaitTimer = Timer4; - FrameDispatchP.Token -> FrameDispatchRadioClient; - FrameDispatchP.SetMacSuperframeOrder -> PibP.SetMacSuperframeOrder; - FrameDispatchP.SetMacPanCoordinator -> PibP.SetMacPanCoordinator; - FrameDispatchP.IsTokenRequested -> FrameDispatchRadioClient; - FrameDispatchP.IsRxEnableActive -> RxEnableP.IsRxEnableActive; - FrameDispatchP.GetIndirectTxFrame -> IndirectTxP; - FrameDispatchP.RxEnableStateChange -> RxEnableP.RxEnableStateChange; - FrameDispatchP.FrameUtility -> PibP; - FrameDispatchP.UnslottedCsmaCa -> FrameDispatchRadioClient; - FrameDispatchP.RadioRx -> FrameDispatchRadioClient; - FrameDispatchP.RadioOff -> FrameDispatchRadioClient; - FrameDispatchP.MLME_GET -> PibP; - FrameDispatchP.MLME_SET -> PibP.MLME_SET; - FrameDispatchP.TimeCalc -> PibP; - FrameDispatchP.Leds = Leds; + components new RadioClientC() as DispatchRadioClient; + PibP.DispatchReset -> DispatchP; + DispatchP.IndirectTxWaitTimer = Timer4; + DispatchP.Token -> DispatchRadioClient; + DispatchP.SetMacSuperframeOrder -> PibP.SetMacSuperframeOrder; + DispatchP.SetMacPanCoordinator -> PibP.SetMacPanCoordinator; + DispatchP.IsTokenRequested -> DispatchRadioClient; + DispatchP.IsRxEnableActive -> RxEnableP.IsRxEnableActive; + DispatchP.GetIndirectTxFrame -> IndirectTxP; + DispatchP.RxEnableStateChange -> RxEnableP.RxEnableStateChange; + DispatchP.FrameUtility -> PibP; + DispatchP.UnslottedCsmaCa -> DispatchRadioClient; + DispatchP.RadioRx -> DispatchRadioClient; + DispatchP.RadioOff -> DispatchRadioClient; + DispatchP.MLME_GET -> PibP; + DispatchP.MLME_SET -> PibP.MLME_SET; + DispatchP.TimeCalc -> PibP; + DispatchP.Leds = Leds; /* -------------------------- promiscuous mode ------------------------ */ @@ -314,8 +314,8 @@ implementation PibP.MacReset -> RxEnableP; RxEnableP.TimeCalc -> PibP.TimeCalc; - RxEnableP.WasRxEnabled -> FrameDispatchP.WasRxEnabled; - RxEnableP.WasRxEnabled -> FrameDispatchP.WasRxEnabled; + RxEnableP.WasRxEnabled -> DispatchP.WasRxEnabled; + RxEnableP.WasRxEnabled -> DispatchP.WasRxEnabled; RxEnableP.RxEnableTimer = Timer5; /* ------------------------------- PIB -------------------------------- */ diff --git a/tos/lib/mac/tkn154/UnslottedFrameDispatchP.nc b/tos/lib/mac/tkn154/UnslottedFrameDispatchP.nc deleted file mode 100644 index a261dc39..00000000 --- a/tos/lib/mac/tkn154/UnslottedFrameDispatchP.nc +++ /dev/null @@ -1,497 +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 is responsible for the transmission/reception of DATA and - * COMMAND frames in a nonbeacon-enabled PAN. Its main tasks are initialization - * of the parameters of the unslotted CSMA-CA algorithm (NB, BE, etc.), - * initiating retransmissions and managing requests for enabling the receiver - * for a finite period of time. It does not implement the actual CSMA-CA - * algorithm, because due to its timing requirements the CSMA-CA algorithm is - * not part of the MAC implementation but of the chip-specific radio driver. - */ - -#if IEEE154_BEACON_ENABLED_PAN -#error "The IEEE154_BEACON_ENABLED_PAN macro MUST NOT be set when using this component!" -#endif - -module UnslottedFrameDispatchP -{ - provides - { - interface Init as Reset; - interface MLME_START; - interface FrameTx as FrameTx; - interface FrameRx as FrameRx[uint8_t frameType]; - interface FrameExtracted as FrameExtracted[uint8_t frameType]; - interface Notify as WasRxEnabled; - } - uses - { - interface Timer as IndirectTxWaitTimer; - interface Resource as Token; - interface GetNow as IsTokenRequested; - interface GetNow as IsRxEnableActive; - interface Set as SetMacSuperframeOrder; - interface Set as SetMacPanCoordinator; - interface Get as GetIndirectTxFrame; - interface Notify as RxEnableStateChange; - interface FrameUtility; - interface UnslottedCsmaCa; - interface RadioRx; - interface RadioOff; - interface MLME_GET; - interface MLME_SET; - interface TimeCalc; - interface Leds; - } -} -implementation -{ - typedef enum { - SWITCH_OFF, - WAIT_FOR_RXDONE, - WAIT_FOR_TXDONE, - DO_NOTHING, - } next_state_t; - - typedef enum { - INDIRECT_TX_ALARM, - NO_ALARM, - } rx_alarm_t; - - /* state / frame management */ - norace bool m_lock; - norace bool m_resume; - norace ieee154_txframe_t *m_currentFrame; - norace ieee154_txframe_t *m_lastFrame; - - /* variables for the unslotted CSMA-CA */ - norace ieee154_csma_t m_csma; - norace ieee154_macMaxBE_t m_BE; - norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs; - norace ieee154_macMaxBE_t m_macMaxBE; - norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries; - norace ieee154_status_t m_txStatus; - norace uint32_t m_transactionTime; - norace bool m_indirectTxPending = FALSE; - norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime; - - /* function / task prototypes */ - next_state_t tryReceive(bool startIndirectTxTimer); - 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 wasRxEnabledTask(); - task void startIndirectTxTimerTask(); - task void signalStartConfirmTask(); - - 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); - m_currentFrame = m_lastFrame = NULL; - call IndirectTxWaitTimer.stop(); - return SUCCESS; - } - - command ieee154_status_t MLME_START.request ( - uint16_t panID, - uint8_t logicalChannel, - uint8_t channelPage, - uint32_t startTime, - uint8_t beaconOrder, - uint8_t superframeOrder, - bool panCoordinator, - bool batteryLifeExtension, - bool coordRealignment, - ieee154_security_t *coordRealignSecurity, - ieee154_security_t *beaconSecurity) - { - ieee154_status_t status; - ieee154_macShortAddress_t shortAddress = call MLME_GET.macShortAddress(); - - // check parameters - if ((coordRealignSecurity && coordRealignSecurity->SecurityLevel) || - (beaconSecurity && beaconSecurity->SecurityLevel)) - status = IEEE154_UNSUPPORTED_SECURITY; - else if (shortAddress == 0xFFFF) - status = IEEE154_NO_SHORT_ADDRESS; - else if (logicalChannel > 26 || - (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || - !(IEEE154_SUPPORTED_CHANNELS & ((uint32_t) 1 << logicalChannel))) - status = IEEE154_INVALID_PARAMETER; - else if (beaconOrder != 15) - status = IEEE154_INVALID_PARAMETER; - else { - call MLME_SET.macPANId(panID); - call MLME_SET.phyCurrentChannel(logicalChannel); - call MLME_SET.macBeaconOrder(beaconOrder); - call SetMacSuperframeOrder.set(superframeOrder); - call SetMacPanCoordinator.set(panCoordinator); - //TODO: check realignment - post signalStartConfirmTask(); - status = IEEE154_SUCCESS; - } - return status; - } - - task void signalStartConfirmTask() - { - signal MLME_START.confirm(IEEE154_SUCCESS); - } - - command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) - { - if (m_currentFrame != NULL) { - // we've not finished transmitting the current frame yet - dbg_serial("UnslottedFrameDispatchP", "Overflow\n"); - return IEEE154_TRANSACTION_OVERFLOW; - } else { - setCurrentFrame(frame); - call Token.request(); - return IEEE154_SUCCESS; - } - } - - event void Token.granted() - { - 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_csma.NB = 0; - m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs(); - m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE(); - m_csma.BE = call MLME_GET.macMinBE(); - if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2) - m_csma.BE = 2; - m_BE = m_csma.BE; - if (call GetIndirectTxFrame.get() == frame) - m_macMaxFrameRetries = 0; // this is an indirect transmissions (never retransmit) - else - m_macMaxFrameRetries = call MLME_GET.macMaxFrameRetries(); - 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; - } - - /** - * The updateState() function is called whenever some event happened that - * might require a state transition; 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. Calling this function more than - * necessary can do no harm. - */ - - void updateState() - { - 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 (there are no loops) - if (m_lock || !call Token.isOwner()) - return; - m_lock = TRUE; // lock - - // Check 1: was an indirect transmission successfully started - // and are we now waiting for a frame from the coordinator? - if (m_indirectTxPending) { - next = tryReceive(TRUE); - } - - // Check 2: is some other operation (like MLME-SCAN or MLME-RESET) pending? - else if (call IsTokenRequested.getNow()) { - if (call RadioOff.isOff()) { - // nothing more to do... just release the Token - m_lock = FALSE; // unlock - dbg_serial("UnslottedFrameDispatchP", "Token requested: releasing it.\n"); - call Token.release(); - return; - } else - next = SWITCH_OFF; - } - - // Check 3: is there a frame ready to transmit? - else if (m_currentFrame != NULL) { - next = tryTransmit(); - } - - // Check 4: should we be in receive mode? - else if (call IsRxEnableActive.getNow()) { - next = tryReceive(FALSE); - if (next == DO_NOTHING) { - // 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 6: just make sure the radio is switched off - else { - next = trySwitchOff(); - if (next == DO_NOTHING) { - // nothing more to do... just release the Token - m_lock = FALSE; // unlock - dbg_serial("UnslottedFrameDispatchP", "Releasing token\n"); - 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: ASSERT(call RadioOff.off() == SUCCESS); break; - case WAIT_FOR_RXDONE: break; - case WAIT_FOR_TXDONE: break; - case DO_NOTHING: break; - } - } - - next_state_t tryTransmit() - { - // tries to transmit m_currentFrame - next_state_t next; - - if (!call RadioOff.isOff()) - next = SWITCH_OFF; - else { - error_t res; - res = call UnslottedCsmaCa.transmit(m_currentFrame, &m_csma); - dbg("UnslottedFrameDispatchP", "UnslottedCsmaCa.transmit() -> %lu\n", (uint32_t) res); - next = WAIT_FOR_TXDONE; // this will NOT clear the lock - } - return next; - } - - next_state_t tryReceive(bool startIndirectTxTimer) - { - next_state_t next; - if (call RadioRx.isReceiving()) - next = DO_NOTHING; - else if (!call RadioOff.isOff()) - next = SWITCH_OFF; - else { - call RadioRx.enableRx(0, 0); - if (startIndirectTxTimer) - post startIndirectTxTimerTask(); - next = WAIT_FOR_RXDONE; - } - 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 RadioOff.offDone() { m_lock = FALSE; updateState();} - async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();} - event void RxEnableStateChange.notify(bool whatever) { updateState();} - - event void IndirectTxWaitTimer.fired() - { - atomic { - if (m_indirectTxPending) { - m_indirectTxPending = FALSE; - post signalTxDoneTask(); - } - } - } - - task void startIndirectTxTimerTask() - { - call IndirectTxWaitTimer.startOneShot(m_macMaxFrameTotalWaitTime); - } - - async event void UnslottedCsmaCa.transmitDone(ieee154_txframe_t *frame, - ieee154_csma_t *csma, bool ackPendingFlag, error_t result) - { - bool done = TRUE; - dbg("UnslottedFrameDispatchP", "UnslottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result); - m_resume = FALSE; - - switch (result) - { - case SUCCESS: - // frame was successfully transmitted, if ACK was requested - // then a matching ACK was successfully received as well - m_txStatus = IEEE154_SUCCESS; - if (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_txStatus = 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; - ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS); - return; - } - } - break; - case FAIL: - // The CSMA-CA algorithm failed: the frame was not transmitted, - // because channel was never idle - m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE; - break; - case ENOACK: - // frame was transmitted, but we didn't receive an ACK (although - // we requested an one). note: coordinator never retransmits an - // indirect transmission (see above) - if (m_macMaxFrameRetries > 0) { - // retransmit: reinitialize CSMA-CA parameters - done = FALSE; - m_csma.NB = 0; - m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs; - m_csma.macMaxBE = m_macMaxBE; - m_csma.BE = m_BE; - m_macMaxFrameRetries -= 1; - } else - m_txStatus = IEEE154_NO_ACK; - break; - default: - ASSERT(0); - break; - } - - if (done) { - m_lastFrame = m_currentFrame; - m_currentFrame = NULL; - post signalTxDoneTask(); - } - - m_lock = FALSE; - updateState(); - } - - task void signalTxDoneTask() - { - ieee154_txframe_t *lastFrame = m_lastFrame; - ieee154_status_t status = m_txStatus; - m_indirectTxPending = FALSE; - m_lastFrame = NULL; // only now the next transmission can begin - if (lastFrame) { - dbg("UnslottedFrameDispatchP", "Transmit done, DSN: %lu, result: 0x%lx\n", - (uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status); - signal FrameTx.transmitDone(lastFrame, status); - } - updateState(); - } - - event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) - { - // received a frame -> find out frame type and - // signal it to responsible 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 (m_indirectTxPending) { - message_t* frameBuf; - call IndirectTxWaitTimer.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_txStatus = IEEE154_SUCCESS; - frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); - signal IndirectTxWaitTimer.fired(); - return frameBuf; - } else - return signal FrameRx.received[frameType](frame); - } - } - - task void wasRxEnabledTask() - { - signal WasRxEnabled.notify(TRUE); - } - - - 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 event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame) {return msg;} - - command error_t WasRxEnabled.enable() {return FAIL;} - command error_t WasRxEnabled.disable() {return FAIL;} - default event void MLME_START.confirm(ieee154_status_t status) {} -} diff --git a/tos/lib/mac/tkn154/dummies/NoDispatchQueueP.nc b/tos/lib/mac/tkn154/dummies/NoDispatchQueueP.nc new file mode 100644 index 00000000..01e1a1b4 --- /dev/null +++ b/tos/lib/mac/tkn154/dummies/NoDispatchQueueP.nc @@ -0,0 +1,73 @@ +/* + * 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 + * ======================================================================== + */ + + /** Empty placeholder component for DispatchQueueP. */ + +#include "TKN154_MAC.h" +generic module NoDispatchQueueP() { + 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/NoDispatchSlottedCsmaP.nc b/tos/lib/mac/tkn154/dummies/NoDispatchSlottedCsmaP.nc new file mode 100644 index 00000000..73d201ef --- /dev/null +++ b/tos/lib/mac/tkn154/dummies/NoDispatchSlottedCsmaP.nc @@ -0,0 +1,113 @@ +/* + * 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 + * ======================================================================== + */ + + /** Empty placeholder component for DispatchSlottedCsmaP. */ + +#include "TKN154_PHY.h" +#include "TKN154_MAC.h" + +generic module NoDispatchSlottedCsmaP(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; + } + 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 SuperframeStructure; + interface GetNow as IsRxEnableActive; + interface Get as GetIndirectTxFrame; + interface Notify as RxEnableStateChange; + interface GetNow as IsTrackingBeacons; + interface FrameUtility; + interface SlottedCsmaCa; + interface RadioRx; + interface RadioOff; + interface MLME_GET; + interface MLME_SET; + interface TimeCalc; + interface Leds; + interface SetNow as FrameBackup; + interface GetNow as FrameRestore; + interface StdControl as TrackSingleBeacon; + } +} +implementation +{ + command error_t Reset.init() { return SUCCESS; } + + async event void TokenTransferred.transferred() { } + + command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) { return IEEE154_TRANSACTION_OVERFLOW; } + + async event void RadioOff.offDone(){ } + + async event void RadioRx.enableRxDone(){} + + 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 SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma, + bool ackPendingFlag, uint16_t remainingBackoff, error_t result) { } + + event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) { return frame; } + + async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) { } + + event void Token.granted() { } + + command error_t WasRxEnabled.enable(){return FAIL;} + command error_t WasRxEnabled.disable(){return FAIL;} +} diff --git a/tos/lib/mac/tkn154/dummies/NoFrameDispatchQueueP.nc b/tos/lib/mac/tkn154/dummies/NoFrameDispatchQueueP.nc deleted file mode 100644 index 890c816b..00000000 --- a/tos/lib/mac/tkn154/dummies/NoFrameDispatchQueueP.nc +++ /dev/null @@ -1,73 +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 - * ======================================================================== - */ - - /** Empty placeholder component for FrameDispatchQueueP. */ - -#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/NoSlottedFrameDispatchP.nc b/tos/lib/mac/tkn154/dummies/NoSlottedFrameDispatchP.nc deleted file mode 100644 index 92b7cb0e..00000000 --- a/tos/lib/mac/tkn154/dummies/NoSlottedFrameDispatchP.nc +++ /dev/null @@ -1,113 +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 - * ======================================================================== - */ - - /** Empty placeholder component for SlottedFrameDispatchP. */ - -#include "TKN154_PHY.h" -#include "TKN154_MAC.h" - -generic module NoSlottedFrameDispatchP(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; - } - 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 SuperframeStructure; - interface GetNow as IsRxEnableActive; - interface Get as GetIndirectTxFrame; - interface Notify as RxEnableStateChange; - interface GetNow as IsTrackingBeacons; - interface FrameUtility; - interface SlottedCsmaCa; - interface RadioRx; - interface RadioOff; - interface MLME_GET; - interface MLME_SET; - interface TimeCalc; - interface Leds; - interface SetNow as FrameBackup; - interface GetNow as FrameRestore; - interface StdControl as TrackSingleBeacon; - } -} -implementation -{ - command error_t Reset.init() { return SUCCESS; } - - async event void TokenTransferred.transferred() { } - - command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) { return IEEE154_TRANSACTION_OVERFLOW; } - - async event void RadioOff.offDone(){ } - - async event void RadioRx.enableRxDone(){} - - 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 SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma, - bool ackPendingFlag, uint16_t remainingBackoff, error_t result) { } - - event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) { return frame; } - - async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) { } - - event void Token.granted() { } - - command error_t WasRxEnabled.enable(){return FAIL;} - command error_t WasRxEnabled.disable(){return FAIL;} -}