📄 mac_tx_engine.c
字号:
/*******************************************************************************************************
* *
* ********** *
* ************ *
* *** *** *
* *** +++ *** *
* *** + + *** *
* *** + CHIPCON CC2430 INTEGRATED 802.15.4 MAC AND PHY *
* *** + + *** TX Engine *
* *** +++ *** *
* *** *** *
* ************ *
* ********** *
* *
********************************************************************************************************
* CONFIDENTIAL *
* The use of this file is restricted by the signed MAC software license agreement. *
* *
* Copyright Chipcon AS, 2005 *
********************************************************************************************************
* This module contains the MAC TX engine, which is used to transmit all RF packets. *
*******************************************************************************************************/
#include "mac_headers.h"
//-------------------------------------------------------------------------------------------------------
// Transmission related variables
MAC_TX_INFO mtxInfo;
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
//
// Prototypes
//
//-------------------------------------------------------------------------------------------------------
static ROOT void HandleOutgoingClearText (MAC_TX_PACKET *macTxPacket,
FRAME *frame);
static ROOT void HandleOutgoingFrame (MAC_TX_PACKET *macTxPacket,
FRAME *frame,
SECURITY_STATUS *securityStatus);
static ROOT void HandleOutgoingSecurity (MAC_TX_PACKET *macTxPacket,
FRAME *frame,
SECURITY_STATUS *securityStatus);
static ROOT void LoadAndStartStrobe (BYTE txMode,
BOOL slotted,
BYTE be,
BYTE nb,
BYTE randomBackoff,
BYTE noOfBackoffsLeft);
static ROOT void ReadCsmaParams (BYTE *be,
BYTE *nb,
BYTE *randomBackoff);
ROOT void WriteCsmaParams (BYTE be,
BYTE nb,
BYTE randomBackoff,
BYTE noOfBackoffsLeft);
ROOT void PrepareFrameAndWriteToRf (MAC_TX_PACKET *macTxPacket,
SECURITY_STATUS *securityStatus);
//-------------------------------------------------------------------------------------------------------
// void mtxCommStatusIndication(MAC_TX_PACKET *pPacket, BYTE status)
//
// DESCRIPTION:
// This function generates comm-status indications for transmitted packets, by parsing the
// packet header.
//
// ARGUMENTS:
// MAC_TX_PACKET *pPacket
// A pointer to the transmitted packet (which the address information will be extracted from)
// BYTE status
// The status to be passed in mlmeCommStatusIndication
//-------------------------------------------------------------------------------------------------------
ROOT void mtxCommStatusIndication(MAC_TX_PACKET *pPacket, BYTE status) {
BYTE dstAddrMode;
ADDRESS *pDstAddr;
BYTE srcAddrMode;
ADDRESS *pSrcAddr;
BYTE *pTemp;
// Point to the first byte of the frame control field
pTemp = pPacket->pHeader;
// Move on to the high byte, which contains the address modes
pTemp += 1;
dstAddrMode = (BYTE)((*pTemp & DEST_ADDR_BM) >> (DEST_ADDR_MODE_IDX - 8));
srcAddrMode = (BYTE)((*pTemp & SRC_ADDR_BM) >> (SRC_ADDR_MODE_IDX - 8));
// Move on to the PAN ID (skip the sequence number)
pTemp += 2;
// Get a pointer to each address, without modifying the pointer any further
pDstAddr = (ADDRESS *) (pTemp + 2);
pSrcAddr = (ADDRESS *) ((BYTE *) pDstAddr + ((dstAddrMode == DEST_ADDR_SHORT) ?
2 : 8) + ((*(pPacket->pHeader) & INTRA_PAN_BM) ? 0 : 2));
// Make the call to the higher layer
mlmeCommStatusIndication(*((WORD *) pTemp), srcAddrMode, pSrcAddr, dstAddrMode, pDstAddr, status);
} // mtxCommStatusIndication
//-------------------------------------------------------------------------------------------------------
// void mtxFinishTransmission(MAC_ENUM status, MAC_TX_PACKET *pPacket, MAC_TASK_INFO *pTask)
//
// DESCRIPTION:
// This function is used to avoid code duplication when finishing a packet transmission (using the
// TX engine. This function is called by mtxScheduleTransmission(...) as the last step of the
// transmission procedure.
//
// This function handles failures for all transmission types, and success for all data, and some
// MAC commands. The other MAC commands are handled by the RX engine.
//
// PARAMETERS:
// MAC_ENUM status
// The result of the transmission (SUCCESS, CHANNEL_ACCESS_FAILURE, etc.)
// MAC_TX_PACKET *pPacket
// A pointer to the packet that was transmitted
// MAC_TASK_INFO *pTask
// A pointer to the task running mtxScheduleTransmission(...)
//-------------------------------------------------------------------------------------------------------
ROOT void mtxFinishTransmission(MAC_ENUM status, MAC_TX_PACKET *pPacket, MAC_TASK_INFO *pTask) {
BOOL isMacInternal;
BOOL handleCmdSuccess;
MAC_STATE_TYPE macState;
// Copy some variables from the packet structure, since we'll release the packet before we make the call to
// the higher layer
isMacInternal = pPacket->txMode & MTX_MODE_MAC_INTERNAL_BM;
handleCmdSuccess = (pPacket->txMode & MTX_MODE_SCAN_RELATED_BM) ||
(pPacket->commandType == CMD_ASSOCIATION_RESPONSE) ||
(pPacket->commandType == CMD_DISASSOCIATION_NOTIFICATION) ||
(pPacket->commandType == CMD_COORDINATOR_REALIGNMENT);
mtxInfo.status = MTX_STATUS_FINISHED;
// Make the call to the higher layer
switch (pPacket->type) {
case FT_DATA:
if (!isMacInternal) mcpsDataConfirm(status, pPacket->msduHandle);
break;
case FT_MAC_COMMAND:
// SUCCESS is usually handled by the RX engine or not at all
if ((status == SUCCESS) && !handleCmdSuccess) break;
switch (pPacket->commandType) {
case CMD_ASSOCIATION_REQUEST:
macSetState(MAC_STATE_DEFAULT);
mlmeAssociateConfirm(0xFFFF, status);
break;
case CMD_DISASSOCIATION_NOTIFICATION:
mlmeDisassociateConfirm(status);
break;
case CMD_DATA_REQUEST:
macState = macInfo.state;
macSetState(MAC_STATE_DEFAULT);
switch (macState) {
case MAC_STATE_TX_MANUAL_DATA_REQUEST: mlmePollConfirm(status); break;
case MAC_STATE_TX_ASSOC_DATA_REQUEST: mlmeAssociateConfirm(0xFFFF, status); break;
default: break;
}
break;
case CMD_BEACON_REQUEST:
mtimSetCallback(mscChannelTimeout, ((UINT32) aBaseSuperframeDuration / (UINT32) aUnitBackoffPeriod) * (((UINT32) 1 << mscInfo.scanDuration) + 1));
break;
case CMD_PAN_ID_CONFLICT_NOTIFICATION:
break;
case CMD_ORPHAN_NOTIFICATION:
mtimSetCallback(mscChannelTimeout, (UINT32) aResponseWaitTime / (UINT32) aUnitBackoffPeriod);
break;
#if MAC_OPT_FFD
case CMD_ASSOCIATION_RESPONSE:
case CMD_COORDINATOR_REALIGNMENT:
if (!isMacInternal) mtxCommStatusIndication(pPacket, status);
break;
#endif
case CMD_GTS_REQUEST:
break;
default:
break;
}
break;
}
#if MAC_OPT_FFD
// Remove the task and the packet
if (pPacket->txOptions & TX_OPT_INDIRECT) {
miqSetRequested(pPacket, FALSE);
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_RESERVED_BM | MSCH_KEEP_TASK_IN_PROGRESS_BM);
DISABLE_GLOBAL_INT();
mschAddTask(pTask->taskNumber, MAC_TASK_PRI_MEDIUM, miqRemoveIndirectPacket, (WORD) pPacket);
ENABLE_GLOBAL_INT();
} else {
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
mtxpReleasePacket(pPacket);
}
#else
// Only direct transmission from a RFD
mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
mtxpReleasePacket(pPacket);
#endif
} // mtxFinishTransmission
//-------------------------------------------------------------------------------------------------------
// void mtxCreateStartTask(void)
//
// DESCRIPTION:
// Creates the task that starts the transmission of the packet.
//-------------------------------------------------------------------------------------------------------
ROOT void mtxCreateStartTask(void) {
mschAddTask(mtxInfo.startTxTask, MAC_TASK_PRI_HIGHEST, mtxStartTransmission, (WORD) mtxInfo.pPacket);
} // mtxCreateStartTask
UINT8 mtxCalcCspTimeout(void) {
INT32 bosLeft;
// Calculate the number of FULL backoff slots left in the CAP, when transmission, ack and IFS is taken into consideration
if (!mtxInfo.pPacket->slotted) {
// Set bosLeft high enough to avoid CSP timeout
bosLeft = CSP_TIMEOUT_RUN_FOREVER;
} else {
if (T2_IS_CAP_ACTIVE()) {
if (mbcnInfo.lastSfSpec.battLifeExt && mtxInfo.pPacket->toCoord) {
// <----------------- The CAP duration -----------------> - <--------- Used CAP ----------> - <---- Overhead ----->
bosLeft = (mbcnInfo.beaconDuration + mpib.macBattLifeExtPeriods) - (T2_GET_OVERFLOW_COUNTER() + 1) - (MTX_START_CSP_DELAY);
} else {
// <- The CAP duration > - <--------- Used CAP ----------> - <------------- Overhead + duration -------------> - <-- Beacon margin -->
bosLeft = msupCalcCapDuration() - (T2_GET_OVERFLOW_COUNTER() + 1) - (MTX_START_CSP_DELAY + mtxInfo.pPacket->duration) - mbcnGetBeaconMargin();
}
} else
bosLeft = 0;
}
// Calculate the CSP timeout
if (bosLeft >= CSP_TIMEOUT_RUN_FOREVER) {
return CSP_TIMEOUT_RUN_FOREVER;
} else if (bosLeft < 1) {
return CSP_TIMEOUT_STOP;
} else {
return (UINT8) bosLeft;
}
} // mtxCalcCspTimeout
//-------------------------------------------------------------------------------------------------------
// void mtxResumeAfterBeacon(void)
//
// DESCRIPTION:
// Resumes transmission after the beacon has been received, if there is a sufficient number of
// backoff slot left in the CAP.
//-------------------------------------------------------------------------------------------------------
void mtxResumeAfterBeaconCallback(void) NEAR { mschAddTask(mschReserveTask(), MAC_TASK_PRI_HIGH, mtxResumeAfterBeaconTask, NULL); }
void mtxResumeAfterBeaconTask(MAC_TASK_INFO *pTask) NEAR { mtxResumeAfterBeacon(); mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM); }
void mtxResumeAfterBeacon(void) NEAR {
if (mtxInfo.waitForBeacon) {
// Cancel beacon search when enabled (the WAIT -> OUT_OF_CAP state will turn it back on if necessary)
if (mtxInfo.beaconSearchEnabled) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -