X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Flib%2Fmac%2Ftkn154%2FIndirectTxP.nc;h=c404bcec7932ae8182749e0e9137eb72843f84b9;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=cf654ce6763a6f6ce4f0df2933550a720e0fee92;hpb=adf1de6c009d13b7b52e68535c63b28f59c97400;p=tinyos-2.x.git diff --git a/tos/lib/mac/tkn154/IndirectTxP.nc b/tos/lib/mac/tkn154/IndirectTxP.nc index cf654ce6..c404bcec 100644 --- a/tos/lib/mac/tkn154/IndirectTxP.nc +++ b/tos/lib/mac/tkn154/IndirectTxP.nc @@ -30,6 +30,7 @@ * $Revision$ * $Date$ * @author Jan Hauer + * @author: Jasper Buesch * ======================================================================== */ @@ -41,6 +42,7 @@ module IndirectTxP interface FrameTx[uint8_t client]; interface WriteBeaconField as PendingAddrWrite; interface Notify as PendingAddrSpecUpdated; + interface Get as GetIndirectTxFrame; interface Purge; } uses @@ -48,11 +50,10 @@ module IndirectTxP interface FrameTx as CoordCapTx; interface FrameRx as DataRequestRx; interface MLME_GET; - interface FrameUtility; + interface IEEE154Frame; interface Timer as IndirectTxTimeout; interface TimeCalc; interface Leds; - interface Ieee802154Debug as Debug; } } implementation @@ -68,8 +69,13 @@ implementation uint8_t m_numTableEntries; uint8_t m_numShortPending; uint8_t m_numExtPending; + ieee154_txframe_t m_emptyDataFrame; + ieee154_metadata_t m_emptyDataFrameMetadata; + ieee154_header_t m_emptyDataFrameHeader; + task void tryCoordCapTxTask(); void tryCoordCapTx(); + void transmitEmptyDataFrame(message_t* dataRequestFrame); command error_t Reset.init() { @@ -86,26 +92,49 @@ implementation m_numTableEntries = 0; m_numShortPending = 0; m_numExtPending = 0; + + m_emptyDataFrame.header = &m_emptyDataFrameHeader; + m_emptyDataFrame.metadata = &m_emptyDataFrameMetadata; + m_emptyDataFrame.payload = &m_numExtPending; // dummy (payloadLen is always 0) + m_emptyDataFrame.payloadLen = 0; + m_emptyDataFrame.client = 0; // unlock return SUCCESS; } - uint32_t getPersistenceTime() + uint32_t getPersistenceTimeSymbols() { - uint32_t persistenceTime; - persistenceTime = call MLME_GET.macTransactionPersistenceTime(); - persistenceTime *= IEEE154_aBaseSuperframeDuration; - persistenceTime *= ((uint16_t) 1) << call MLME_GET.macBeaconOrder(); - return persistenceTime; + // transform macTransactionPersistenceTime PIB attribute + // from "unit periods" to symbols (cf. page 166) + uint32_t unitPeriod; + ieee154_macBeaconOrder_t BO = call MLME_GET.macBeaconOrder(); + + if (BO <= 14) { + unitPeriod = IEEE154_aBaseSuperframeDuration; + unitPeriod *= ((uint16_t) 1) << BO; + } else + unitPeriod = IEEE154_aBaseSuperframeDuration; + return unitPeriod * call MLME_GET.macTransactionPersistenceTime(); } command ieee154_status_t Purge.purge(uint8_t msduHandle) { - return IEEE154_INVALID_HANDLE; // TODO + uint8_t i = 0; + for (i=0; ihandle == msduHandle) && (m_client != m_txFrameTable[i]->client) ){ + ieee154_txframe_t *purgedFrame; + purgedFrame = m_txFrameTable[i]; + m_txFrameTable[i] = NULL; + m_numTableEntries -= 1; + signal Purge.purgeDone(purgedFrame, IEEE154_PURGED); + return IEEE154_SUCCESS; + } + } + return IEEE154_INVALID_HANDLE; } command uint8_t PendingAddrWrite.write(uint8_t *pendingAddrField, uint8_t maxlen) { - // write the pending addr field (inside the beacon frame) + // writes the pending addr field (inside the beacon frame) uint8_t i, j, k=0; uint8_t *longAdrPtr[NUM_MAX_PENDING]; nxle_uint16_t *adrPtr; @@ -116,11 +145,11 @@ implementation return 0; pendingAddrField[0] = 0; adrPtr = (nxle_uint16_t *) &pendingAddrField[1]; - for (i=0; iheader->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT){ + if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_SHORT) { *adrPtr++ = *((nxle_uint16_t*) &txFrame->header->mhr[MHR_INDEX_ADDRESS + sizeof(ieee154_macPANId_t)]); } else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED) longAdrPtr[k++] = &(txFrame->header->mhr[MHR_INDEX_ADDRESS + sizeof(ieee154_macPANId_t)]); @@ -129,7 +158,6 @@ implementation for (j=0; j<8; j++) pendingAddrField[1 + 2*m_numShortPending + i*8 + j] = longAdrPtr[i][j]; pendingAddrField[0] = m_numShortPending | (m_numExtPending << 4); - call Debug.log(LEVEL_INFO, IndirectTxP_BEACON_ASSEMBLY, len,0,0); return len; } @@ -140,10 +168,10 @@ implementation command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame) { - // send a frame through indirect transmission + // sends a frame using indirect transmission uint8_t i; - if (m_numTableEntries >= NUM_MAX_PENDING){ - call Debug.log(LEVEL_IMPORTANT, IndirectTxP_OVERFLOW, 0,0,0); + if (m_numTableEntries >= NUM_MAX_PENDING) { + dbg_serial("IndirectTxP", "Overflow\n"); return IEEE154_TRANSACTION_OVERFLOW; } txFrame->client = client; @@ -158,8 +186,8 @@ implementation else if ((txFrame->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK) == FC2_DEST_MODE_EXTENDED) m_numExtPending++; if (!call IndirectTxTimeout.isRunning()) - call IndirectTxTimeout.startOneShot(getPersistenceTime()); - call Debug.log(LEVEL_INFO, IndirectTxP_NOTIFIED, 0,0,0); + call IndirectTxTimeout.startOneShot(getPersistenceTimeSymbols()); + dbg_serial("IndirectTxP", "Preparing a transmission.\n"); signal PendingAddrSpecUpdated.notify(TRUE); return IEEE154_SUCCESS; } @@ -168,13 +196,12 @@ implementation { uint8_t i, j, srcAddressMode, dstAddressMode, *src; uint8_t *mhr = MHR(frame); - uint8_t destMode = (mhr[1] & FC2_DEST_MODE_MASK); + uint8_t destMode = (mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK); + ieee154_txframe_t *dataResponseFrame = NULL; // received a data request frame from a device // have we got some pending data for it ? - if (!m_numTableEntries) - return frame; - srcAddressMode = (mhr[1] & FC2_SRC_MODE_MASK); + srcAddressMode = (mhr[MHR_INDEX_FC2] & FC2_SRC_MODE_MASK); if (!(srcAddressMode & FC2_SRC_MODE_SHORT)) return frame; // no source address src = mhr + MHR_INDEX_ADDRESS; @@ -182,13 +209,13 @@ implementation src += 4; else if (destMode == FC2_DEST_MODE_EXTENDED) src += 10; - if (!((mhr[0] & FC1_PAN_ID_COMPRESSION) && (mhr[1] & FC2_DEST_MODE_SHORT))) + if (!((mhr[MHR_INDEX_FC1] & FC1_PAN_ID_COMPRESSION) && (mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_SHORT))) src += 2; - for (i=0; iheader->mhr[1] & FC2_DEST_MODE_MASK); + dstAddressMode = (m_txFrameTable[i]->header->mhr[MHR_INDEX_FC2] & FC2_DEST_MODE_MASK); if ((dstAddressMode << 4) != srcAddressMode) continue; else { @@ -196,39 +223,70 @@ implementation uint8_t *dst = &(m_txFrameTable[i]->header->mhr[MHR_INDEX_ADDRESS]) + 2; uint8_t len = ((srcAddressMode == FC2_SRC_MODE_SHORT) ? 2 : 8); for (j=0; jheader->mhr[MHR_INDEX_FC1] |= FC1_FRAME_PENDING; + } } } } - call Debug.log(LEVEL_INFO, IndirectTxP_REQUESTED, NUM_MAX_PENDING-i,i,*src); - if (i != NUM_MAX_PENDING){ + if (dataResponseFrame != NULL) { // found a matching frame, mark it for transmission - m_txFrameTable[i]->client |= SEND_THIS_FRAME; + dbg_serial("IndirectTxP", "We have data for this device, trying to transmit...\n"); + dataResponseFrame->client |= SEND_THIS_FRAME; post tryCoordCapTxTask(); } else { - // TODO: send an empty data frame to the device + dbg_serial("IndirectTxP", "We don't have data for this device, sending an empty frame...\n"); + transmitEmptyDataFrame(frame); } return frame; } + void transmitEmptyDataFrame(message_t* dataRequestFrame) + { + // the cast in the next line is dangerous -> this is only a temporary workaround! + // (until the new T2 message buffer abstraction is available) + message_t *emptyDataMsg = (message_t *) m_emptyDataFrame.header; + ieee154_address_t dstAddr; + uint16_t dstPanID; + + if (m_emptyDataFrame.client != 0) + return; // locked (already transmitting an empty data frame) + if (call IEEE154Frame.getSrcAddr(dataRequestFrame, &dstAddr) != IEEE154_SUCCESS || + call IEEE154Frame.getSrcPANId(dataRequestFrame, &dstPanID) != IEEE154_SUCCESS) + return; + call IEEE154Frame.setAddressingFields(emptyDataMsg, + call IEEE154Frame.getDstAddrMode(dataRequestFrame), // will become srcAddrMode + call IEEE154Frame.getSrcAddrMode(dataRequestFrame), // will become dstAddrMode + dstPanID, + &dstAddr, + NULL //security + ); + MHR(&m_emptyDataFrame)[MHR_INDEX_FC1] |= FC1_FRAMETYPE_DATA; + m_emptyDataFrame.headerLen = call IEEE154Frame.getHeaderLength(emptyDataMsg); + m_emptyDataFrame.client = 1; // lock + if (call CoordCapTx.transmit(&m_emptyDataFrame) != IEEE154_SUCCESS) + m_emptyDataFrame.client = 0; // unlock + } + void tryCoordCapTx() { // iterate over the queued frames and transmit them in the CAP // (if they are marked for transmission) uint8_t i; - if (!m_pendingTxFrame && m_numTableEntries){ + if (m_pendingTxFrame == NULL && m_numTableEntries) { for (i=0; iclient & SEND_THIS_FRAME)){ - // TODO: set frame pending bit, if there's more data for this destination + if (m_txFrameTable[i] && (m_txFrameTable[i]->client & SEND_THIS_FRAME)) { m_pendingTxFrame = m_txFrameTable[i]; m_client = m_txFrameTable[i]->client; - if (call CoordCapTx.transmit(m_txFrameTable[i]) == IEEE154_SUCCESS){ - call Debug.log(LEVEL_INFO, IndirectTxP_SEND_NOW, 0,0,0); + if (call CoordCapTx.transmit(m_txFrameTable[i]) == IEEE154_SUCCESS) { + dbg_serial("IndirectTxP", "Started a transmission.\n"); } else { - m_pendingTxFrame = 0; + m_pendingTxFrame = NULL; post tryCoordCapTxTask(); } return; // done - wait for txDone @@ -245,12 +303,12 @@ implementation { // a transaction has expired uint32_t now = call IndirectTxTimeout.getNow(), dt=0; - uint32_t persistenceTime = getPersistenceTime(); + uint32_t persistenceTime = getPersistenceTimeSymbols(); uint8_t i; for (i=0; imetadata->timestamp, persistenceTime)){ + if (m_txFrameTable[i] && m_txFrameTable[i] != m_pendingTxFrame) { + if (call TimeCalc.hasExpired(m_txFrameTable[i]->metadata->timestamp, persistenceTime)) { ieee154_txframe_t *txFrame = m_txFrameTable[i]; txFrame->client &= ~SEND_THIS_FRAME; m_txFrameTable[i] = NULL; @@ -261,11 +319,11 @@ implementation m_numExtPending--; signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_EXPIRED); signal PendingAddrSpecUpdated.notify(TRUE); - } else if (call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now) > dt){ + } else if (call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now) > dt) { dt = call TimeCalc.timeElapsed(m_txFrameTable[i]->metadata->timestamp, now); } } - if (dt != 0){ + if (dt != 0) { if (dt > persistenceTime) dt = persistenceTime; call IndirectTxTimeout.startOneShot(persistenceTime - dt); @@ -275,9 +333,15 @@ implementation event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { uint8_t i; - // TODO: if CSMA-CA algorithm failed, then frame shall remain in transaction queue + // TODO: if CSMA-CA algorithm failed, then frame shall still remain in transaction queue + dbg_serial("IndirectTxP", "transmitDone(), status: %lu\n", (uint32_t) status); + + if (txFrame == &m_emptyDataFrame) { + m_emptyDataFrame.client = 0; // unlock + return; + } for (i=0; iclient](txFrame, status); post tryCoordCapTxTask(); - call Debug.log(LEVEL_INFO, IndirectTxP_SEND_DONE, status,m_numTableEntries,0); } - command error_t PendingAddrSpecUpdated.enable(){return FAIL;} - command error_t PendingAddrSpecUpdated.disable(){return FAIL;} - default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status){} + command ieee154_txframe_t* GetIndirectTxFrame.get() { return m_pendingTxFrame;} + command error_t PendingAddrSpecUpdated.enable() {return FAIL;} + command error_t PendingAddrSpecUpdated.disable() {return FAIL;} + default event void PendingAddrSpecUpdated.notify( bool val ) {return;} + default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status) {} }