From 34c0ece49130644031d58a17f64e81dc66e3587e Mon Sep 17 00:00:00 2001 From: janhauer Date: Mon, 14 Dec 2009 12:50:06 +0000 Subject: [PATCH] - reduced RAM usage of the beacon sync component - fixed spooling out of messages in case of a SYNC_LOSS --- tos/lib/mac/tkn154/AssociateP.nc | 4 +- tos/lib/mac/tkn154/BeaconSynchronizeP.nc | 310 ++++++++++++--------- tos/lib/mac/tkn154/DispatchQueueP.nc | 39 ++- tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc | 65 +++-- tos/lib/mac/tkn154/IndirectTxP.nc | 4 +- tos/lib/mac/tkn154/PollP.nc | 7 +- tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc | 1 + 7 files changed, 252 insertions(+), 178 deletions(-) diff --git a/tos/lib/mac/tkn154/AssociateP.nc b/tos/lib/mac/tkn154/AssociateP.nc index 3d697f65..494745fb 100644 --- a/tos/lib/mac/tkn154/AssociateP.nc +++ b/tos/lib/mac/tkn154/AssociateP.nc @@ -207,8 +207,8 @@ implementation if (m_assocRespStatus == IEEE154_ASSOCIATION_SUCCESSFUL) call MLME_SET.macShortAddress(m_shortAddress); signal MLME_ASSOCIATE.confirm(m_shortAddress, m_assocRespStatus, 0); - dbg_serial("AssociationP", "confirm: %lx, %lu\n", - (uint32_t) m_shortAddress, (uint32_t) m_assocRespStatus); + dbg_serial("AssociationP", "confirm, status: %lu, my new address: 0x%lx\n", + (uint32_t) m_assocRespStatus, (uint32_t) m_shortAddress); } } diff --git a/tos/lib/mac/tkn154/BeaconSynchronizeP.nc b/tos/lib/mac/tkn154/BeaconSynchronizeP.nc index 57f4faeb..ff2a0c00 100644 --- a/tos/lib/mac/tkn154/BeaconSynchronizeP.nc +++ b/tos/lib/mac/tkn154/BeaconSynchronizeP.nc @@ -50,7 +50,7 @@ module BeaconSynchronizeP interface MLME_SYNC_LOSS; interface SuperframeStructure as IncomingSF; interface GetNow as IsTrackingBeacons; - interface StdControl as TrackSingleBeacon; + interface SplitControl as TrackSingleBeacon; } uses { @@ -72,23 +72,18 @@ module BeaconSynchronizeP implementation { /* state variables */ - norace bool m_tracking; - bool m_stopTracking ; - norace uint8_t m_numBeaconsLost; norace uint8_t m_state; - norace bool m_bufferBusy; + norace uint8_t m_numBeaconsMissed; - /* buffers for the parameters of the MLME-SYNC request */ - norace bool m_updatePending; + /* temporary buffers for the MLME-SYNC parameters */ uint8_t m_updateLogicalChannel; bool m_updateTrackBeacon; - /* variables that describe the current configuration */ - norace uint32_t m_beaconInterval; + /* variables that describe the current beacon configuration */ + norace ieee154_macBeaconOrder_t m_beaconOrder; norace uint32_t m_dt; norace uint32_t m_lastBeaconRxTime; norace ieee154_timestamp_t m_lastBeaconRxRefTime; - norace uint8_t m_beaconOrder; message_t m_beacon; norace message_t *m_beaconPtr = &m_beacon; @@ -101,31 +96,64 @@ implementation uint8_t m_gtsField[1+1+3*7]; enum { - S_PREPARE = 0, - S_RECEIVING = 1, - S_RADIO_OFF = 2, - S_INITIAL_SCAN= 3, - + RX_PREPARE = 0x00, + RX_RECEIVING = 0x01, + RX_RADIO_OFF = 0x02, + RX_FIRST_SCAN= 0x03, + RX_MASK = 0x03, + + MODE_INACTIVE = 0x00, + MODE_TRACK_SINGLE = 0x04, + MODE_TRACK_CONTINUOUS = 0x08, + MODE_MASK = 0x0C, + + BEACON_RECEIVED = 0x10, + UPDATE_PENDING = 0x20, + INTERNAL_REQUEST = 0x40, + EXTERNAL_REQUEST = 0x80, }; - /* function/task prototypes */ - task void processBeaconTask(); void trackNextBeacon(); + uint32_t getBeaconInterval(ieee154_macBeaconOrder_t BO); + task void processBeaconTask(); task void signalGrantedTask(); + /* accessing/manipulating the current state */ + void setBeaconReceived() { m_state |= BEACON_RECEIVED; } + void resetBeaconReceived() { m_state &= ~BEACON_RECEIVED; } + bool wasBeaconReceived() { return (m_state & BEACON_RECEIVED) ? TRUE : FALSE; } + void setUpdatePending() { m_state |= UPDATE_PENDING; } + void resetUpdatePending() { m_state &= ~UPDATE_PENDING; } + bool isUpdatePending() { return (m_state & UPDATE_PENDING) ? TRUE : FALSE; } + void setInternalRequest() { m_state |= INTERNAL_REQUEST; } + void resetInternalRequest() { m_state &= ~INTERNAL_REQUEST; } + bool isInternalRequest() { return (m_state & INTERNAL_REQUEST) ? TRUE : FALSE; } + void setExternalRequest() { m_state |= EXTERNAL_REQUEST; } + void resetExternalRequest() { m_state &= ~EXTERNAL_REQUEST; } + bool isExternalRequest() { return (m_state & EXTERNAL_REQUEST) ? TRUE : FALSE; } + uint8_t getMode() { return (m_state & MODE_MASK); } + void setMode(uint8_t mode) { m_state &= ~MODE_MASK; m_state |= (mode & MODE_MASK); } + uint8_t getRxState() { return (m_state & RX_MASK); } + void setRxState(uint8_t state) { m_state &= ~RX_MASK; m_state |= (state & RX_MASK); } + command error_t Reset.init() { - // reset this component. will only be called - // while we're not owning the token - if (m_tracking || m_updatePending) + // Reset this component - will only be called while we're not owning the token + if (call IsTrackingBeacons.getNow() || + (isUpdatePending() && isExternalRequest() && m_updateTrackBeacon)) signal MLME_SYNC_LOSS.indication( IEEE154_BEACON_LOSS, call MLME_GET.macPANId(), call MLME_GET.phyCurrentChannel(), call MLME_GET.phyCurrentPage(), NULL); - m_updatePending = m_stopTracking = m_tracking = FALSE; + if (isInternalRequest()) + signal TrackSingleBeacon.startDone(FAIL); + resetUpdatePending(); + resetInternalRequest(); + resetExternalRequest(); + setMode(MODE_INACTIVE); return SUCCESS; } @@ -148,57 +176,44 @@ implementation (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) || !IEEE154_BEACON_ENABLED_PAN) status = IEEE154_INVALID_PARAMETER; else { - if (!trackBeacon && m_tracking) { - // stop tracking after next received beacon - m_stopTracking = TRUE; - } else { - m_stopTracking = FALSE; - m_updateLogicalChannel = logicalChannel; - m_updateTrackBeacon = trackBeacon; - m_updatePending = TRUE; - atomic { - // if we are tracking then we'll get the RadioToken automatically, - // otherwise request it now - if (!m_tracking && !call RadioToken.isOwner()) - call RadioToken.request(); - } - } + m_updateTrackBeacon = trackBeacon; + m_updateLogicalChannel = logicalChannel; + setExternalRequest(); + setUpdatePending(); + call RadioToken.request(); } + dbg_serial("BeaconSynchronizeP", "MLME_SYNC.request -> result: %lu\n", (uint32_t) status); return status; } event void RadioToken.granted() { - dbg_serial("BeaconSynchronizeP","Got token, expecting beacon in %lu\n", - (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); - if (m_updatePending) { - dbg_serial("BeaconSynchronizeP", "Preparing initial scan\n"); - m_state = S_INITIAL_SCAN; - m_updatePending = FALSE; - m_beaconOrder = call MLME_GET.macBeaconOrder(); - if (m_beaconOrder >= 15) - m_beaconOrder = 14; + if (isUpdatePending()) { + dbg_serial("BeaconSynchronizeP", "Updating configuration...\n"); + if (m_updateTrackBeacon) + setMode(MODE_TRACK_CONTINUOUS); + else + setMode(MODE_TRACK_SINGLE); call MLME_SET.phyCurrentChannel(m_updateLogicalChannel); - m_tracking = m_updateTrackBeacon; - m_beaconInterval = ((uint32_t) 1 << m_beaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; - m_dt = m_beaconInterval; - m_numBeaconsLost = IEEE154_aMaxLostBeacons; // will be reset when beacon is received - } + m_beaconOrder = call MLME_GET.macBeaconOrder(); + m_dt = getBeaconInterval(m_beaconOrder); + m_numBeaconsMissed = IEEE154_aMaxLostBeacons; // will be reset when first beacon is received + resetUpdatePending(); + setRxState(RX_FIRST_SCAN); + } trackNextBeacon(); } async event void RadioToken.transferredFrom(uint8_t clientFrom) { - dbg_serial("BeaconSynchronizeP","Token.transferred(), expecting beacon in %lu symbols.\n", - (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); - if (m_updatePending) + dbg_serial("BeaconSynchronizeP", "Got token (transferred).\n"); + if (isUpdatePending()) post signalGrantedTask(); else trackNextBeacon(); } - task void signalGrantedTask() { signal RadioToken.granted(); @@ -208,26 +223,30 @@ implementation { bool missed = FALSE; - if (m_state != S_INITIAL_SCAN) { + if (getMode() == MODE_INACTIVE) { + // nothing to do, just give up the token + dbg_serial("BeaconSynchronizeP", "Stop tracking.\n"); + call RadioToken.release(); + return; + } - if (!m_tracking) { - // nothing to do, just give up the token - dbg_serial("BeaconSynchronizeP", "Stop tracking.\n"); - call RadioToken.release(); - return; - } + if (getRxState() != RX_FIRST_SCAN) { + + dbg_serial("BeaconSynchronizeP","Token.transferred(), expecting beacon in %lu symbols.\n", + (uint32_t) ((m_lastBeaconRxTime + m_dt) - call TrackAlarm.getNow())); + + // we have received at least one previous beacon, get ready for the next + setRxState(RX_PREPARE); - // we have received at least one previous beacon - m_state = S_PREPARE; while (call TimeCalc.hasExpired(m_lastBeaconRxTime, m_dt)) { // missed a beacon! dbg_serial("BeaconSynchronizeP", "Missed a beacon, expected it: %lu, now: %lu\n", m_lastBeaconRxTime + m_dt, call TrackAlarm.getNow()); missed = TRUE; - m_dt += m_beaconInterval; - m_numBeaconsLost++; + m_dt += getBeaconInterval(m_beaconOrder); + m_numBeaconsMissed++; } - if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) { + if (m_numBeaconsMissed >= IEEE154_aMaxLostBeacons) { dbg_serial("BeaconSynchronizeP", "Missed too many beacons.\n"); post processBeaconTask(); return; @@ -236,7 +255,7 @@ implementation if (missed) { // let other components get a chance to use the radio call RadioToken.request(); - dbg_serial("BeaconSynchronizeP", "Allowing other components to get the token.\n"); + dbg_serial("BeaconSynchronizeP", "Skipping a beacon.\n"); call RadioToken.release(); return; } @@ -252,10 +271,10 @@ implementation { uint32_t delay = IEEE154_RADIO_RX_DELAY + IEEE154_MAX_BEACON_JITTER(m_beaconOrder); - if (m_state == S_INITIAL_SCAN) { - // initial scan + if (getRxState() == RX_FIRST_SCAN) { + // initial scan: switch to Rx immediately call BeaconRx.enableRx(0, 0); - } else if (m_state == S_PREPARE) { + } else if (getRxState() == RX_PREPARE) { if (!call TimeCalc.hasExpired(m_lastBeaconRxTime - delay, m_dt)) call TrackAlarm.startAt(m_lastBeaconRxTime - delay, m_dt); else @@ -268,27 +287,28 @@ implementation async event void BeaconRx.enableRxDone() { uint32_t dt; + uint8_t previousState = getRxState(); + + setRxState(RX_RECEIVING); - switch (m_state) + switch (previousState) { - case S_INITIAL_SCAN: + case RX_FIRST_SCAN: // "To acquire beacon synchronization, a device shall enable its // receiver and search for at most [aBaseSuperframeDuration * (2^n + 1)] // symbols, where n is the value of macBeaconOrder [...] Once the number // of missed beacons reaches aMaxLostBeacons, the MLME shall notify the // next higher layer." (Sect. 7.5.4.1) - m_state = S_RECEIVING; dt = (((uint32_t) 1 << m_beaconOrder) + (uint32_t) 1) * (uint32_t) IEEE154_aBaseSuperframeDuration * (uint32_t) IEEE154_aMaxLostBeacons; call TrackAlarm.start(dt); - dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon within %lu symbols.\n", dt); + dbg_serial("BeaconSynchronizeP","Rx enabled, expecting first beacon within next %lu symbols.\n", dt); break; - case S_PREPARE: - m_state = S_RECEIVING; + case RX_PREPARE: dt = m_dt + IEEE154_MAX_BEACON_LISTEN_TIME(m_beaconOrder); call TrackAlarm.startAt(m_lastBeaconRxTime, dt); - dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon within %lu symbols.\n", + dbg_serial("BeaconSynchronizeP","Rx enabled, expecting beacon within next %lu symbols.\n", (uint32_t) ((m_lastBeaconRxTime + dt) - call TrackAlarm.getNow())); break; default: @@ -299,32 +319,32 @@ implementation async event void TrackAlarm.fired() { - if (m_state == S_PREPARE) { + if (getRxState() == RX_PREPARE) { // enable Rx uint32_t maxBeaconJitter = IEEE154_MAX_BEACON_JITTER(m_beaconOrder); if (maxBeaconJitter > m_dt) maxBeaconJitter = m_dt; // receive immediately call BeaconRx.enableRx(m_lastBeaconRxTime, m_dt - maxBeaconJitter); - } else { - ASSERT(m_state == S_RECEIVING && call RadioOff.off() == SUCCESS); + } else { // disable Rx + error_t error = call RadioOff.off(); + ASSERT(getRxState() == RX_RECEIVING && error == SUCCESS); } } event message_t* BeaconRx.received(message_t *frame, const ieee154_timestamp_t *timestamp) { - if (m_bufferBusy || !call FrameUtility.isBeaconFromCoord(frame)) - { - if (m_bufferBusy) { - dbg_serial("BeaconSynchronizeP", "Got another beacon, dropping it.\n");} - else - dbg_serial("BeaconSynchronizeP", "Got a beacon, but not from my coordinator.\n"); + if (wasBeaconReceived()) { + dbg_serial("BeaconSynchronizeP", "Got another beacon! -> ignoring it ...\n"); + return frame; + } else if (!call FrameUtility.isBeaconFromCoord(frame)) { + dbg_serial("BeaconSynchronizeP", "Got a beacon, but not from my coordinator.\n"); return frame; } else { message_t *tmp = m_beaconPtr; - m_bufferBusy = TRUE; + setBeaconReceived(); m_beaconPtr = frame; if (timestamp != NULL) memcpy(&m_lastBeaconRxRefTime, timestamp, sizeof(ieee154_timestamp_t)); - if (m_state == S_RECEIVING) { + if (getRxState() == RX_RECEIVING) { call TrackAlarm.stop(); // may fail call RadioOff.off(); // may fail } @@ -332,36 +352,55 @@ implementation } } + + task void processBeaconTask() { - // if we received a beacon from our coordinator then it is processed now - if (!m_bufferBusy || !call Frame.isTimestampValid(m_beaconPtr)) { - // missed a beacon or received a beacon with invalid timestamp - if (!m_bufferBusy) - dbg_serial("BeaconSynchronizeP", "No beacon received!\n"); - else - dbg_serial("BeaconSynchronizeP", "Beacon has invalid timestamp!\n"); - - m_numBeaconsLost += 1; - m_dt += m_beaconInterval; - m_bufferBusy = FALSE; + // task will be executed after every (un)successful attempt to track a beacon + bool wasInternalRequest = isInternalRequest(); + + if (wasBeaconReceived() && !call Frame.isTimestampValid(m_beaconPtr)) { + dbg_serial("BeaconSynchronizeP", "Received beacon has invalid timestamp, discarding it!\n"); + resetBeaconReceived(); + } - if (m_numBeaconsLost >= IEEE154_aMaxLostBeacons) { - // lost too many beacons, give up! - m_tracking = FALSE; + if (getMode() == MODE_TRACK_SINGLE) + setMode(MODE_INACTIVE); // we're done with a single shot + resetInternalRequest(); + + // whether we next release the token or pass it to the CAP + // component, we want it back (because we decide later + // whether we'll actually stop tracking the beacon in future) + call RadioToken.request(); + + if (!wasBeaconReceived()) { + + resetBeaconReceived(); // buffer ready + m_numBeaconsMissed += 1; + m_dt += getBeaconInterval(m_beaconOrder); + dbg_serial("BeaconSynchronizeP", "Missed a beacon (total missed: %lu).\n", (uint32_t) m_numBeaconsMissed); + + if (wasInternalRequest) { + // note: if it only was an internal request, the + // mode was reset above already (SINGLE_SHOT) + signal TrackSingleBeacon.startDone(FAIL); + } + if (isExternalRequest() && m_numBeaconsMissed >= IEEE154_aMaxLostBeacons) { + resetExternalRequest(); + setMode(MODE_INACTIVE); dbg_serial("BeaconSynchronizeP", "MLME_SYNC_LOSS!\n"); - signal MLME_SYNC_LOSS.indication( - IEEE154_BEACON_LOSS, - call MLME_GET.macPANId(), - call MLME_GET.phyCurrentChannel(), - call MLME_GET.phyCurrentPage(), - NULL); - } else - call RadioToken.request(); // make another request again (before giving the token up) + signal MLME_SYNC_LOSS.indication( + IEEE154_BEACON_LOSS, + call MLME_GET.macPANId(), + call MLME_GET.phyCurrentChannel(), + call MLME_GET.phyCurrentPage(), + NULL); + } call RadioToken.release(); + } else { - // got the beacon! + // received the beacon! uint8_t *payload = (uint8_t *) m_beaconPtr->data; ieee154_macAutoRequest_t autoRequest = call MLME_GET.macAutoRequest(); uint8_t pendAddrSpecOffset = 3 + (((payload[2] & 7) > 0) ? 1 + (payload[2] & 7) * 3: 0); // skip GTS @@ -369,7 +408,6 @@ implementation uint8_t *beaconPayload = payload + pendAddrSpecOffset + 1; uint8_t beaconPayloadSize = call BeaconFrame.getBeaconPayloadLength(m_beaconPtr); uint8_t pendingAddrMode = ADDR_MODE_NOT_PRESENT; - uint8_t coordBeaconOrder; uint8_t *mhr = MHR(m_beaconPtr); uint8_t frameLen = ((uint8_t*) m_beaconPtr)[0] & FRAMECTL_LENGTH_MASK; uint8_t gtsFieldLength; @@ -378,6 +416,7 @@ implementation dbg_serial("BeaconSynchronizeP", "Got beacon, timestamp: %lu, offset to previous: %lu\n", (uint32_t) timestamp, (uint32_t) (timestamp - m_lastBeaconRxTime)); + m_numBeaconsMissed = 0; m_numGtsSlots = (payload[2] & 7); gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0); m_lastBeaconRxTime = timestamp; @@ -398,22 +437,11 @@ implementation m_battLifeExtDuration = 0; m_framePendingBit = mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING ? TRUE : FALSE; - coordBeaconOrder = (payload[0] & 0x0F); - m_dt = m_beaconInterval = ((uint32_t) 1 << coordBeaconOrder) * (uint32_t) IEEE154_aBaseSuperframeDuration; - - if (m_stopTracking) { - m_tracking = FALSE; - dbg_serial("BeaconSynchronizeP", "Stop tracking.\n"); - if (m_updatePending) // there is already a new request ... - call RadioToken.request(); - call RadioToken.release(); - } else { - dbg_serial("BeaconSynchronizeP", "Handing over to CAP.\n"); - // we pass on the token now, but make a reservation to get it back - // to receive the next beacon (at the start of the next superframe) - call RadioToken.request(); - call RadioToken.transferTo(RADIO_CLIENT_DEVICECAP); - } + m_beaconOrder = (payload[0] & 0x0F); + m_dt = getBeaconInterval(m_beaconOrder); + + dbg_serial("BeaconSynchronizeP", "Handing over to CAP.\n"); + call RadioToken.transferTo(RADIO_CLIENT_DEVICECAP); if (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK) beaconPayload += (pendAddrSpec & PENDING_ADDRESS_SHORT_MASK) * 2; @@ -439,12 +467,9 @@ implementation call DataRequest.poll(CoordAddrMode, CoordPANId, CoordAddress, SrcAddrMode); } - // Beacon Tracking: update state - m_numBeaconsLost = 0; - // TODO: check PAN ID conflict here? if (!autoRequest || beaconPayloadSize) m_beaconPtr = signal MLME_BEACON_NOTIFY.indication(m_beaconPtr); - m_bufferBusy = FALSE; + resetBeaconReceived(); // buffer ready } dbg_serial_flush(); } @@ -452,20 +477,20 @@ implementation command error_t TrackSingleBeacon.start() { // Track a single beacon now - if (!m_tracking && !m_updatePending && !call RadioToken.isOwner()) { - // find a single beacon now (treat this like a user request) + dbg_serial("BeaconSynchronizeP", "Internal request.\n"); + setInternalRequest(); + call RadioToken.request(); + if (!isUpdatePending()) { m_updateLogicalChannel = call MLME_GET.phyCurrentChannel(); m_updateTrackBeacon = FALSE; - m_stopTracking = TRUE; - m_updatePending = TRUE; - call RadioToken.request(); + setUpdatePending(); } return SUCCESS; } command error_t TrackSingleBeacon.stop() { - // will stop automatically after beacon was tracked/not found + // we will stop automatically after beacon was tracked/not found return FAIL; } @@ -518,7 +543,14 @@ implementation async command bool IsTrackingBeacons.getNow() { - return m_tracking; + return (getMode() == MODE_TRACK_CONTINUOUS); + } + + uint32_t getBeaconInterval(ieee154_macBeaconOrder_t BO) + { + if (BO >= 15) + BO = 14; + return (((uint32_t) 1 << BO) * (uint32_t) IEEE154_aBaseSuperframeDuration); } event void DataRequest.pollDone() {} diff --git a/tos/lib/mac/tkn154/DispatchQueueP.nc b/tos/lib/mac/tkn154/DispatchQueueP.nc index 85669850..18731a89 100644 --- a/tos/lib/mac/tkn154/DispatchQueueP.nc +++ b/tos/lib/mac/tkn154/DispatchQueueP.nc @@ -49,23 +49,37 @@ generic module DispatchQueueP() { implementation { task void txTask(); - bool m_busy; + bool m_state; uint8_t m_client; + enum { + TX_DONE_PENDING = 0x01, + RESET_PENDING = 0x02, + }; + + bool isTxDonePending() { return (m_state & TX_DONE_PENDING) ? TRUE : FALSE; } + void setTxDonePending() { m_state |= TX_DONE_PENDING; } + void resetTxDonePending() { m_state &= ~TX_DONE_PENDING; } + + bool isResetPending() { return (m_state & RESET_PENDING) ? TRUE : FALSE; } + void setResetPending() { m_state |= RESET_PENDING; } + void resetResetPending() { m_state &= ~RESET_PENDING; } + command error_t Reset.init() { + setResetPending(); while (call Queue.size()) { ieee154_txframe_t *txFrame = call Queue.dequeue(); signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_OVERFLOW); } - m_busy = FALSE; + resetResetPending(); return SUCCESS; } command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame) { txFrame->client = client; - if (call Queue.enqueue(txFrame) != SUCCESS) + if (isResetPending() || call Queue.enqueue(txFrame) != SUCCESS) return IEEE154_TRANSACTION_OVERFLOW; else { post txTask(); @@ -75,7 +89,7 @@ implementation task void txTask() { - if (!m_busy && call Queue.size()) { + if (!isTxDonePending() && call Queue.size()) { ieee154_txframe_t *txFrame = call Queue.head(); if (txFrame->headerLen == 0) { // was purged @@ -84,17 +98,26 @@ implementation post txTask(); } m_client = txFrame->client; - if (call FrameTxCsma.transmit(txFrame) == IEEE154_SUCCESS) { - m_busy = TRUE; - } + setTxDonePending(); + if (call FrameTxCsma.transmit(txFrame) != IEEE154_SUCCESS) + resetTxDonePending(); } } event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { + resetTxDonePending(); + if (!call Queue.size()) + return; // all frames were spooled out (reset) call Queue.dequeue(); - m_busy = FALSE; signal FrameTx.transmitDone[txFrame->client](txFrame, status); + if (IEEE154_BEACON_ENABLED_PAN && status == IEEE154_NO_BEACON) { + // this means that we lost sync -> spool out all queued frames + while (call Queue.size()) { + ieee154_txframe_t *frame = call Queue.dequeue(); + signal FrameTx.transmitDone[frame->client](frame, IEEE154_NO_BEACON); + } + } post txTask(); } diff --git a/tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc b/tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc index c2b29323..3a173d69 100644 --- a/tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc +++ b/tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc @@ -91,7 +91,8 @@ generic module DispatchSlottedCsmaP(uint8_t sfDirection) interface Leds; interface SetNow as FrameBackup; interface GetNow as FrameRestore; - interface StdControl as TrackSingleBeacon; + interface SplitControl as TrackSingleBeacon; + interface MLME_SYNC_LOSS; } } implementation @@ -172,20 +173,39 @@ implementation #define dbg_flush_state() #endif - command error_t Reset.init() + error_t reset(error_t error) { + if (call RadioToken.isOwner()) // internal error! this must not happen! + return FAIL; if (m_currentFrame) - signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW); + signal FrameTx.transmitDone(m_currentFrame, error); if (m_lastFrame) - signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW); + signal FrameTx.transmitDone(m_lastFrame, error); if (m_bcastFrame) - signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW); + signalTxBroadcastDone(m_bcastFrame, error); m_currentFrame = m_lastFrame = m_bcastFrame = NULL; m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime(); stopAllAlarms(); return SUCCESS; } + command error_t Reset.init() + { + return reset(IEEE154_TRANSACTION_OVERFLOW); + } + + event void MLME_SYNC_LOSS.indication ( + ieee154_status_t lossReason, + uint16_t PANId, + uint8_t LogicalChannel, + uint8_t ChannelPage, + ieee154_security_t *security + ) + { + // we lost sync to the coordinator -> spool out current packet + reset(IEEE154_NO_BEACON); + } + async event void RadioToken.transferredFrom(uint8_t fromClient) { // we got the token, i.e. CAP has just started @@ -195,19 +215,9 @@ implementation 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; - post signalTxDoneTask(); - return; - } else if (capDuration < guardTime) { - // CAP is too short to do anything practical + + if (capDuration < guardTime) { + // CAP is too short to do anything useful dbg_serial("DispatchSlottedCsmaP", "CAP too short!\n"); call RadioToken.transferTo(RADIO_CLIENT_CFP); return; @@ -224,7 +234,7 @@ implementation // in task context and then continue m_lock = TRUE; post setupTxBroadcastTask(); - dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast.\n"); + dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast...\n"); } } call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration); @@ -247,14 +257,21 @@ implementation 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 + // we'll get the Token after a beacon was found or a SYNC_LOSS event + // if none was found during the next aBaseSuperframeDuration*(2n+1) symbols } updateState(); return IEEE154_SUCCESS; } } + event void TrackSingleBeacon.startDone(error_t error) + { + if (error != SUCCESS) // beacon could not be tracked + reset(IEEE154_NO_BEACON); + // else: we'll get the RadioToken and continue as usual ... + } + task void setupTxBroadcastTask() { ieee154_macDSN_t tmp; @@ -345,8 +362,7 @@ implementation (uint32_t) call SuperframeStructure.sfSlotDuration(); // Check 1: has the CAP finished? - if ((COORD_ROLE || call IsTrackingBeacons.getNow()) && - (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), + if ((call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), capDuration - call SuperframeStructure.guardTime()) || !call CapEndAlarm.isRunning())) { dbg_push_state(1); @@ -738,7 +754,8 @@ implementation 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;} + event void TrackSingleBeacon.stopDone(error_t error){} + default command error_t TrackSingleBeacon.start() {if (DEVICE_ROLE) ASSERT(0); return SUCCESS;} command error_t WasRxEnabled.enable() {return FAIL;} command error_t WasRxEnabled.disable() {return FAIL;} diff --git a/tos/lib/mac/tkn154/IndirectTxP.nc b/tos/lib/mac/tkn154/IndirectTxP.nc index 36d1988d..9a712f49 100644 --- a/tos/lib/mac/tkn154/IndirectTxP.nc +++ b/tos/lib/mac/tkn154/IndirectTxP.nc @@ -236,11 +236,11 @@ implementation } if (dataResponseFrame != NULL) { // found a matching frame, mark it for transmission - dbg_serial("IndirectTxP", "We have data for this device, trying to transmit..."); + dbg_serial("IndirectTxP", "We have data for this device, trying to transmit...\n"); dataResponseFrame->client |= SEND_THIS_FRAME; post tryCoordCapTxTask(); } else { - dbg_serial("IndirectTxP", "We don't have data for this device, sending an empty frame..."); + dbg_serial("IndirectTxP", "We don't have data for this device, sending an empty frame...\n"); transmitEmptyDataFrame(frame); } return frame; diff --git a/tos/lib/mac/tkn154/PollP.nc b/tos/lib/mac/tkn154/PollP.nc index d00e986f..e44f7106 100644 --- a/tos/lib/mac/tkn154/PollP.nc +++ b/tos/lib/mac/tkn154/PollP.nc @@ -125,13 +125,13 @@ implementation ieee154_txcontrol_t *txControl; ieee154_status_t status = IEEE154_TRANSACTION_OVERFLOW; - dbg_serial("PollP", "InternalPoll\n"); + dbg_serial("PollP", "Internal Poll\n"); if (client == SYNC_POLL_CLIENT && m_numPending != 0) { // no point in auto-requesting if user request is pending signal DataRequest.pollDone[client](); return IEEE154_SUCCESS; - } else if ((txFrame = call TxFramePool.get())) { - if (!(txControl = call TxControlPool.get())) + } else if ((txFrame = call TxFramePool.get()) != NULL) { + if ((txControl = call TxControlPool.get()) != NULL) call TxFramePool.put(txFrame); else { txFrame->header = &txControl->header; @@ -149,6 +149,7 @@ implementation } if (status != IEEE154_SUCCESS) signal DataRequest.pollDone[client](); + dbg_serial("PollP", "Status %lu, numPending: %lu\n", (uint32_t) status, (uint32_t) m_numPending); return status; } diff --git a/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc b/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc index 474995d7..1176a1d2 100644 --- a/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc +++ b/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc @@ -423,6 +423,7 @@ implementation DeviceCap.TimeCalc -> PibP; DeviceCap.Leds = Leds; DeviceCap.TrackSingleBeacon -> BeaconSynchronizeP.TrackSingleBeacon; + DeviceCap.MLME_SYNC_LOSS -> BeaconSynchronizeP; /* ---------------------- CAP (outgoing superframe) ------------------- */ -- 2.39.2