X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Flib%2Fmac%2Ftkn154%2FBeaconSynchronizeP.nc;h=ff2a0c0061438d1b75fdd1b00e8e741f01ed00aa;hb=34c0ece49130644031d58a17f64e81dc66e3587e;hp=57f4faeb753ec26a7649801071bcbf3718cf18e4;hpb=c4bc60fec625455726b47dfd0f922673a36450c8;p=tinyos-2.x.git 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() {}