?? mac_beacon_handler.c
字號:
*(pPayload++) = (BYTE) ((newPanId & 0xFF00) >> 8);
*(pPayload++) = (BYTE) mpib.macShortAddress;
*(pPayload++) = (BYTE) ((mpib.macShortAddress & 0xFF00) >> 8);
*(pPayload++) = logicalChannel;
*(pPayload++) = (BYTE) shortAddr;
*(pPayload) = (BYTE) ((shortAddr & 0xFF00) >> 8);
// Calculate the packet duration (including ack. and IFS)
pPacket->duration = msupCalcPacketDuration(pPacket->length, (BYTE)(txOptions & TX_OPT_ACK_REQ));
} // mbcnPrepareCoordinatorRealignment
//-------------------------------------------------------------------------------------------------------
// void mbcnPrepareBeacon(void)
//
// DESCRIPTION:
// Prepares a valid beacon frame which can be transmitted using the TX engine.
//
// ARGUMENTS:
// MAC_TX_PACKET *pPacket
// A pointer to the packet to be transmitted
//-------------------------------------------------------------------------------------------------------
void mbcnPrepareBeacon(MAC_TX_PACKET *pPacket) NEAR {
BYTE srcAddrMode;
WORD superframeSpec;
BYTE *pMacBeaconPayload;
BYTE pendAddrSpec;
MAC_TX_PACKET *pIndirectPacket;
UINT8 n, pendShortAddrCount, pendExtAddrCount;
BYTE *pPayload = pPacket->pPayload;
// TX mode
pPacket->txMode = 0;
// pPacket->retriesLeft will be ignored (no ack)
// Header
srcAddrMode = (mpib.macShortAddress < 0xFFFE) ? SRC_ADDR_SHORT : SRC_ADDR_EXT;
msupPrepareHeader(pPacket, FT_BEACON, srcAddrMode, mpib.macPANId, ((srcAddrMode == SRC_ADDR_SHORT) ? (ADDRESS *)&mpib.macShortAddress : (ADDRESS *) &aExtendedAddress), 0, NULL, (BYTE)(GET_MF(MF_BEACON_SECURITY)));
// Superframe specification
superframeSpec = (mpib.macBeaconOrder << SS_BEACON_ORDER_IDX) |
(mpib.macSuperframeOrder << SS_SUPERFRAME_ORDER_IDX) |
(15 << SS_FINAL_CAP_SLOT_IDX) |
(mpib.macBattLifeExt ? SS_BATT_LIFE_EXT_BM : 0) |
(GET_MF(MF_PAN_COORDINATOR) ? SS_PAN_COORDINATOR_BM : 0) |
(mpib.macAssociationPermit ? SS_ASSOCIATION_PERMIT_BM : 0);
*((WORD *) pPayload) = superframeSpec;
pPayload += 2;
// GTS list (not implemented)
*(pPayload++) = 0x00;
// Pending address list
// Count the number of pending addresses to get the packet length
n = miqInfo.firstIndirectPacket;
pendShortAddrCount = 0;
pendExtAddrCount = 0;
while ((n != NO_PACKET) && ((pendShortAddrCount + pendExtAddrCount) < MAX_PENDING_LIST_SIZE)) {
pIndirectPacket = &pMtxPacketPool[n];
if (pIndirectPacket->timeToLive > 0) {
if (pIndirectPacket->isFirstPacket) {
if ((pIndirectPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_EXT) {
pendExtAddrCount++;
} else {
pendShortAddrCount++;
}
}
}
n = pIndirectPacket->nextPacket;
}
// Pending address specification (indicates the number of short and extended addresses)
pendAddrSpec = pendShortAddrCount + (pendExtAddrCount << 4);
*(pPayload++) = pendAddrSpec;
// Address list
if (pendAddrSpec) {
// Short addresses
n = miqInfo.firstIndirectPacket;
do {
pIndirectPacket = &pMtxPacketPool[n];
if (pIndirectPacket->isFirstPacket && (pIndirectPacket->timeToLive > 0) && ((pIndirectPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_SHORT)) {
// Copy the packet destination address
memcpy(pPayload, pIndirectPacket->pHeader + 5, 2);
pendShortAddrCount--;
pPayload += 2;
}
n = pIndirectPacket->nextPacket;
} while (pendShortAddrCount);
// Extended addresses
n = miqInfo.firstIndirectPacket;
do {
pIndirectPacket = &pMtxPacketPool[n];
if (pIndirectPacket->isFirstPacket && (pIndirectPacket->timeToLive > 0) && ((pIndirectPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_EXT)) {
// Copy the packet destination address
memcpy(pPayload, pIndirectPacket->pHeader + 5, 8);
pendExtAddrCount--;
pPayload += 8;
}
n = pIndirectPacket->nextPacket;
} while (pendExtAddrCount);
}
// Beacon payload (safe access to mpib.pMacBeaconPayload)
DISABLE_GLOBAL_INT();
pMacBeaconPayload = mpib.pMacBeaconPayload;
ENABLE_GLOBAL_INT();
memcpy(pPayload, pMacBeaconPayload, mpib.macBeaconPayloadLength);
pPayload += mpib.macBeaconPayloadLength;
// Set the total packet length
pPacket->length = pPacket->headerLength + (pPayload - pPacket->pPayload) + MAC_FCS_LENGTH;
// Calculate the packet duration
pPacket->duration = msupCalcPacketDuration(pPacket->length, pPacket->txOptions & TX_OPT_ACK_REQ);
} // mbcnPrepareBeacon
#endif // MAC_OPT_FFD
/*******************************************************************************************************
*******************************************************************************************************
************************** UTILITY FUNCTIONS **************************
*******************************************************************************************************
*******************************************************************************************************/
//-------------------------------------------------------------------------------------------------------
// void mbcnGetBeaconMargin(void)
//
// DESCRIPTION:
// Because of the crystal inaccuracy, a margin must be added before the beacon that will
// be received. The result is that:
// - RX must be turned on a short while before the beacon is expected to be received.
// - TX must stop before this margin is reached
//
// The Excel worksheet called "Beacon reception margin.xls" can be used to calculate these
// constants.
//
// RETURN VALUE:
// UINT8
// The margin as a number of backoff periods
//-------------------------------------------------------------------------------------------------------
UINT8 mbcnGetBeaconMargin(void) NEAR {
switch (mpib.macBeaconOrder) {
case 7: return 2;
case 8: return 3;
case 9: return 5;
case 10: return 10;
case 11: return 20;
case 12: return 40;
case 13: return 79;
case 14: return 158;
default: return 1;
}
} // mbcnGetBeaconMargin
//-------------------------------------------------------------------------------------------------------
// void mbcnUpdateBufferedAttributes(void)
//
// DESCRIPTION:
// Updates category 4 attributes (see mlmeSetRequest()) before the beacon is received or
// transmitted. Only attributes indicated in the update mask will be changed.
//-------------------------------------------------------------------------------------------------------
void mbcnUpdateBufferedPibAttributes(void) NEAR {
DISABLE_GLOBAL_INT();
if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_BATT_LIFE_EXT_BM) mpib.macBattLifeExt = macInfo.pibTempBuffer.macBattLifeExt;
if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_BEACON_ORDER_BM) mpib.macBeaconOrder = macInfo.pibTempBuffer.macBeaconOrder;
if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_RX_ON_WHEN_IDLE_BM) mpib.macRxOnWhenIdle = macInfo.pibTempBuffer.macRxOnWhenIdle;
if (macInfo.pibTempBuffer.updateMask & MPIB_UPD_SUPERFRAME_ORDER_BM) mpib.macSuperframeOrder = macInfo.pibTempBuffer.macSuperframeOrder;
macInfo.pibTempBuffer.updateMask = 0x00;
ENABLE_GLOBAL_INT();
} // mbcnUpdateBufferedPibAttributes
//-------------------------------------------------------------------------------------------------------
// void mbcnHandleBeaconModeChange(BOOL wasNonBeacon)
//
// DESCRIPTION:
// Handles the change from a beacon network to a non-beacon network and vice versa.
//
// ARGUMENTS:
// BOOL wasNonBeacon
// Indicates the earlier state (BEFORE the mpib.macBeaconOrder variable was updated)
//-------------------------------------------------------------------------------------------------------
void mbcnHandleBeaconModeChange(BOOL wasNonBeacon) NEAR {
// Handle non-beacon -> beacon network
if (wasNonBeacon && (mpib.macBeaconOrder < 15)) {
// Send backoff slot synchronous acknowledgments
MDMCTRL1H |= 0x80;
// "RX on when idle" should only be active in the superframe (set up by the beacon transmission task
if (mpib.macRxOnWhenIdle) mrxDecrOnCounter();
#if MAC_OPT_FFD
// The beacon transmission task will handle indirect packet expiration
mtimCancelCallback(mbcnExpirePacketsNonBeacon);
#endif
// Handle beacon -> non-beacon network
} else if (!wasNonBeacon && (mpib.macBeaconOrder == 15)) {
// Send acknowledgments ASAP
MDMCTRL1H &= ~0x80;
// Update buffered PIB attributes before the buffering mechanism is disabled
macInfo.pibTempBuffer.updateMask &= MPIB_UPD_BATT_LIFE_EXT_BM | MPIB_UPD_RX_ON_WHEN_IDLE_BM;
mbcnUpdateBufferedPibAttributes();
// "RX on when idle" is always valid from now on
if (mpib.macRxOnWhenIdle) mrxIncrOnCounter();
// Cancel beacon transmission and reception, and turn on indirect packet expiration for non-beacon networks
#if MAC_OPT_FFD
mtimCancelCallback(mbcnTxPeriodicalBeacon);
#endif
mtimCancelCallback(mbcnRxPeriodicalBeacon);
#if MAC_OPT_FFD
mtimSetCallback(mbcnExpirePacketsNonBeacon, (INT32)(aBaseSuperframeDuration / aUnitBackoffPeriod));
#endif
}
} // mbcnHandleBeaconModeChange
/*******************************************************************************************************
*******************************************************************************************************
************************** BEACON TRACKING **************************
*******************************************************************************************************
*******************************************************************************************************/
//-------------------------------------------------------------------------------------------------------
// void mbcnSyncToBeacons(MAC_TASK_INFO *pTask)
//
// DESCRIPTION:
// This task starts synchronization to beacons
//
// TASK DATA:
// 0
//-------------------------------------------------------------------------------------------------------
void mbcnSyncToBeacons(MAC_TASK_INFO *pTask) NEAR {
// Reserve the beacon tracking task if necessary
if (mbcnInfo.rxTaskNumber == NO_TASK) mbcnInfo.rxTaskNumber = mschReserveTask();
// Set track status variables
mbcnInfo.findBeacon = TRUE;
mbcnInfo.noBcnCountdown = aMaxLostBeacons;
mbcnInfo.trackBeacon = (BOOL) LOBYTE(pTask->taskData);
// Switch radio channel if necessary
msupSetChannel(HIBYTE(pTask->taskData), TRUE);
mrxIncrOnCounter();
// Start receiving beacons
mbcnRxPeriodicalBeacon();
// Remove this task
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
} // mbcnSyncToBeacons
/*******************************************************************************************************
*******************************************************************************************************
************************** NON-BEACON INDIRECT EXPIRATION **************************
*******************************************************************************************************
*******************************************************************************************************/
#if MAC_OPT_FFD
//-------------------------------------------------------------------------------------------------------
// void mbcnExpirePacketsNonBeacon(void)
//
// DESCRIPTION:
// Schedules the next expiration "tick", and starts the expiration task
//-------------------------------------------------------------------------------------------------------
void mbcnExpirePacketsNonBeacon(void) NEAR {
// Schedule the next round (48 backoff periods from now)
mtimSetCallback(mbcnExpirePacketsNonBeacon, (INT32)(aBaseSuperframeDuration / aUnitBackoffPeriod));
// Create the task that will expire old packets
mschAddTask(mschReserveTask(), MAC_TASK_PRI_MEDIUM, mbcnExpirePacketsNonBeaconTask, 0);
} // mbcnExpirePacketsNonBeacon
//-------------------------------------------------------------------------------------------------------
// void mbcnExpirePacketsNonBeaconTask(MAC_TASK_INFO *pTask)
//
// DESCRIPTION:
// Expires indirect packets in a non-beacon network by decrementing the "time to live" counter, and
// then transforming the task into an miqExpireIndirectPacketsTask().
//
// TASK DATA:
// 0
//-------------------------------------------------------------------------------------------------------
void mbcnExpirePacketsNonBeaconTask(MAC_TASK_INFO *pTask) NEAR {
// Decrement "time to live"
miqDecrTimeToLive();
// Continue in the miqExpireIndirectPacketsTask() function
pTask->pTaskFunc = miqExpireIndirectPacketsTask;
} // mbcnExpirePacketsNonBeaconTask
#endif // MAC_OPT_FFD
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -