📄 mac_tx_engine.c
字号:
/*******************************************************************************************************
* *
* ********** *
* ************ *
* *** *** *
* *** +++ *** *
* *** + + *** *
* *** + CHIPCON CC2420 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, 2004 *
*******************************************************************************************************
* This module contains the MAC TX engine, which is used to transmit all RF packets. *
*******************************************************************************************************
* Compiler: AVR-GCC *
* Target platform: CC2420DB, CC2420 + any ATMEGA MCU *
*******************************************************************************************************
* The revision history is located at the bottom of this file *
*******************************************************************************************************/
#pragma SFR
#pragma NOP
#pragma STOP
#pragma HALT
#pragma DI
#pragma EI
#include "mac_headers.h"
//-------------------------------------------------------------------------------------------------------
// Transmission related variables
MAC_TX_INFO mtxInfo;
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// 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
//-------------------------------------------------------------------------------------------------------
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 = (*pTemp & DEST_ADDR_BM) >> (DEST_ADDR_MODE_IDX - 8);
srcAddrMode = (*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(...)
//-------------------------------------------------------------------------------------------------------
void mtxFinishTransmission(MAC_ENUM status, MAC_TX_PACKET *pPacket, MAC_TASK_INFO *pTask) {
BOOL isMacInternal;
BOOL handleCmdSuccess;
MAC_STATE_TYPE macState;
ENABLE_FIFOP_INT();
// 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->mc.commandType == CMD_ASSOCIATION_RESPONSE) || ///
(pPacket->mc.commandType == CMD_DISASSOCIATION_NOTIFICATION) ||///
(pPacket->mc.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->mc.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->mc.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, (aBaseSuperframeDuration / aUnitBackoffPeriod) * ((1 << mscInfo.scanDuration) + 1));
break;
case CMD_PAN_ID_CONFLICT_NOTIFICATION:
break;
case CMD_ORPHAN_NOTIFICATION:
mtimSetCallback(mscChannelTimeout, aResponseWaitTime / 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 mtxLocateBeaconTimeout(void)
//
// DESCRIPTION:
// This timeout function is used when transmitting packets in a beacon network without tracking the
// beacon (the packet is supposed to be transmitted using unslotted CSMA-CA if the beacon cannot be
// located). The timeout is also set when tracking the beacon, because the tracking could suddenly
// stop.
//-------------------------------------------------------------------------------------------------------
void mtxLocateBeaconTimeout(void) {
// The beacon is currently being tracked (but we've missed at least one) -> continue waiting
// Or we could be transmitting beacons.
if (mbcnInfo.trackBeacon || GET_MF(MF_TRANSMIT_BEACON)) {
mtimSetCallback(mtxLocateBeaconTimeout, msupCalcBeaconInterval());
// Automatic beacon location has failed
} else {
// Stop the beacon search
if (mtxInfo.searchForBeacon) {
mtxInfo.searchForBeacon = FALSE;
mrxDecrOnCounter();
}
// Switch to unslotted CSMA-CA and transmit immediately
mtxInfo.waitForBeacon = FALSE;
mtxInfo.nb = 0;
mtxInfo.be = mpib.macMinBE;
mtxInfo.pPacket->slotted = FALSE;
mtxCreateStartTask();
}
} // mtxLocateBeaconTimeout
//-------------------------------------------------------------------------------------------------------
// void mtxCreateStartTask(void)
//
// DESCRIPTION:
// Creates the task that starts the transmission of the packet.
//-------------------------------------------------------------------------------------------------------
void mtxCreateStartTask(void) {
mschAddTask(mtxInfo.startTxTask, MAC_TASK_PRI_HIGHEST, mtxStartTransmission, (WORD) mtxInfo.pPacket);
} // mtxCreateStartTask
//-------------------------------------------------------------------------------------------------------
// void mtxStartAfterDelay(UINT8 delay)
//
// DESCRIPTION:
// Starts TX after the given number of backoff slots, using a callback timer when the delay is > 0
//
// PARAMETERS:
// UINT8 delay
// The number of backoff slots to delay the call to mtxCreateStartTask()
//-------------------------------------------------------------------------------------------------------
BOOL mtxStartAfterDelay(UINT8 delay) {
if (delay) {
return mtimSetCallback(mtxCreateStartTask, delay);
} else {
mtxCreateStartTask();
return TRUE;
}
} // mtxStartAfterDelay
//-------------------------------------------------------------------------------------------------------
// void csmaSetStartupTime(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -