📄 mac.c
字号:
#include "includes.h"
//-------------------------------------------------------------------------------------------------------
extern MAC_TX_INFO mtxInfo;
// Extended address, must be set by higher layer
BYTE aExtendedAddress[8];
//-------------------------------------------------------------------------------------------------------
/*
*********************************************************************************************************
* VARIABLES
*********************************************************************************************************
*/
extern OS_STK miqAddIndirectPacketStk[TASK_STK_SIZE];
extern OS_STK mtxScheduleTransmissionStk[TASK_STK_SIZE];
//-------------------------------------------------------------------------------------------------------
// MAC_ENUM mlmeResetRequest(ZBOOL setDefaultPIB)
//
// DESCRIPTION:
// Reset the MAC and PHY layers, including CC2420, the microcontroller, and all state variables.
// NOTE: The initialization and power-up sequence must be performed according to
// the MAC documentation prior to calling mlmeResetRequest or other
// MAC primitives
//
// PARAMETERS:
// ZBOOL setDefaultPIB
// Reset the PHY and MAC PIBs
//
// RETURN VALUE:
// MAC_ENUM
// Always SUCCESS
//-------------------------------------------------------------------------------------------------------
MAC_ENUM mlmeResetRequest(ZBOOL setDefaultPIB) {
// Disable the FIFOP interrupt, and also T1_COMPA, which would otherwise turn the FIFOP interrupt back on
//DISABLE_FIFOP_INT();
//DISABLE_T1_COMPA_INT();
//DISABLE_T1_CAPTURE_INT();
// Initialise random number generator
msupInitRandom();
// Initialize time variables and timer callbacks
mtimInit();
// Initialize the scheduler before the other modules (task reservation...)
mschInit();
// Initialize variables in the various modules
mrxpInit();
mtxpInit();
mscInit();
#if MAC_OPT_FFD
miqInit();
#endif
mtxInfo.startTxTask = mschReserveTask();
mrxInfo.state = MRX_STATE_LEN_FCF_SEQ;
mrxInfo.onCounter = 0;
mrxInfo.keepFifopIntOff = FALSE;
mrxInfo.handleFifoUnderflow = FALSE;
mbcnInfo.trackBeacon = FALSE;
mbcnInfo.findBeacon = FALSE;
mbcnInfo.rxTaskNumber = NO_TASK;
mbcnInfo.txTaskNumber = NO_TASK;
mbcnInfo.pTxPacket = NULL;
// Reset flags
RESET_MF();
// MAC command state
macInfo.state = MAC_STATE_DEFAULT;
// Other state variables
mbcnInfo.lastSfSpec.battLifeExt = FALSE;
mbcnInfo.lastSfSpec.finalCap = 15;
// Set all MAC/PHY PIB attributes to their default values.
if (setDefaultPIB) {
ppib.phyCurrentChannel = 11;
ppib.phyTransmitPower = OUTPUT_POWER_0DBM; //0dBm an +/- 1dBm tolerance
ppib.phyCcaMode = 1;
mpib.macAckWaitDuration = 54;
mpib.macAssociationPermit = FALSE;
mpib.macAutoRequest = TRUE;
mpib.macBattLifeExt = FALSE;
mpib.macBattLifeExtPeriods = 6;
mpib.pMacBeaconPayload = NULL;
mpib.macBeaconPayloadLength = 0;
mpib.macBeaconOrder = 15;
mpib.macBeaconTxTime = 0;
mpib.macBSN = msupGetRandomByte();
mpib.macCoordShortAddress = 0xFFFF;
mpib.macDSN = msupGetRandomByte();
mpib.macGTSPermit = TRUE;
mpib.macMaxCsmaBackoffs = 4;
mpib.macMinBE = 3;
mpib.macPANId = 0xFFFF;
mpib.macPromiscuousMode = FALSE;
mpib.macRxOnWhenIdle = FALSE;
mpib.macShortAddress = 0xFFFF;
mpib.macSuperframeOrder = 15;
mpib.macTransactionPersistenceTime = 0x01F4;
mpib.macCoordExtendedAddress = 0xFFFF;
mpib.macAssocatedPanCordinator = TRUE;
#if MAC_OPT_ACL_SIZE > 0
mpib.ppMacACLEntryDescriptorSet = NULL;
mpib.macACLEntryDescriptorSetSize = 0;
#endif
#if MAC_OPT_SECURITY
mpib.macDefaultSecurity = FALSE;
mpib.macDefaultSecurityMaterialLength = 0x15;
mpib.pMacDefaultSecurityMaterial = NULL;
mpib.macDefaultSecuritySuite = 0;
#endif
#if ((MAC_OPT_SECURITY) || (MAC_OPT_ACL_SIZE>0))
mpib.macSecurityMode = 0;
#endif
}
// Configure CC2420 registers
mpmRestoreRegsAndRam();
// Turn the interrupts back on
//ENABLE_FIFOP_INT();
//ENABLE_T1_COMPA_INT();
//ENABLE_T1_CAPTURE_INT(); --li
// Confirm
return SUCCESS;
} // mlmeResetRequest
//-------------------------------------------------------------------------------------------------------
// void mcpsDataRequest(BYTE addrModes, WORD srcPanId, ADDRESS *pSrcAddr, WORD destPanId, ADDRESS ...)
//
// DESCRIPTION:
// Transmit a data packet.
//
// PARAMETERS:
// BYTE addrModes
// Address mode for source and destination
// (SRC_ADDR_SHORT, SRC_ADDR_EXT or 0) | (DEST_ADDR_SHORT, DEST_ADDR_EXT or 0)
// WORD srcPanId
// Source PAN identifier
// ADDRESS *pSrcAddr
// Pointer to the source address (short or extended)
// WORD destPanId,
// Destination PAN identifier
// ADDRESS *pDestAddr,
// Pointer to the destination address (short or extended)
// UINT8 msduLength,
// The length of pMsdu[]
// BYTE *pMsdu,
// A pointer to the packet payload
// BYTE msduHandle,
// A handle to this packet which is used later on with mcpsPurgeRequest)( and mcpsDataConfirm()
// BYTE txOptions
// (TX_OPT_SECURITY_ENABLE | TX_OPT_INDIRECT | TX_OPT_GTS | TX_OPT_ACK_REQ) or TX_OPT_NONE
// Note: Indirect transmission only available for MAC_OPT_FFD=1
//-------------------------------------------------------------------------------------------------------
void mcpsDataRequest(BYTE addrModes, WORD srcPanId, ADDRESS *pSrcAddr, WORD destPanId, ADDRESS *pDestAddr, UINT8 msduLength, BYTE *pMsdu, BYTE msduHandle, BYTE txOptions) {
MAC_TX_PACKET *pPacket;
UINT8 temp;
BYTE *pPayload;
// Reserve a packet to use with the TX engine
#if MAC_OPT_FFD
reservePacket:
pPacket = mtxpReservePacket();
if (!pPacket) {
if (txOptions & TX_OPT_INDIRECT) {
mcpsDataConfirm(TRANSACTION_OVERFLOW, msduHandle);
return;
} else {
goto reservePacket;
}
}
#else // RFD
if (txOptions & TX_OPT_INDIRECT) {
mcpsDataConfirm(INVALID_PARAMETER, msduHandle);
return;
}
reservePacket:
pPacket = mtxpReservePacket();
if (!pPacket) {
goto reservePacket;
}
#endif
// Set transmission mode
pPacket->txMode = MTX_MODE_USE_CSMACA_BM;
// Set number of retries
pPacket->retriesLeft = aMaxFrameRetries;
// Store the msdu handle
pPacket->msduHandle = msduHandle;
// Generate the packet header (and find security material, if enabled)
msupPrepareHeader(pPacket, FT_DATA, addrModes, srcPanId, pSrcAddr, destPanId, pDestAddr, txOptions);
pPayload = pPacket->pPayload;
#if MAC_OPT_SECURITY
// Before calculating the PSDU length; make sure that the payload + MIC is less than aMaxMACFrameSize
// #bytes in frame counter + key sequence counter (0 or 5)
temp = msecProcessSecurityCounters(pPacket, pPayload);
// In case of frame counter overflow or missing key
// Generate error with FAILED_SECURITY_CHECK or UNAVAILABLE_KEY
if (pPacket->securitySuite >= 8) {
mtxpReleasePacket(pPacket);
mcpsDataConfirm(pPacket->securitySuite, msduHandle);
return;
}
// Increment payload pointer when counters inserted
pPayload += temp;
// Include msduLength and optional MIC (integrity code) length
temp += msduLength + pPacket->securitySetup.micLength;
#else
temp = msduLength;
#endif
// Is frame too long?
if (temp > aMaxMACFrameSize) {
mtxpReleasePacket(pPacket);
mcpsDataConfirm(FRAME_TOO_LONG, msduHandle);
return;
}
// Calculate total frame length
pPacket->length = pPacket->headerLength + temp + MAC_FCS_LENGTH;
// Copy data into packet buffer
memcpy(pPayload, pMsdu, msduLength);
// Calculate the packet duration (including ack. and IFS)
pPacket->duration = msupCalcPacketDuration(pPacket->length, pPacket->txOptions & TX_OPT_ACK_REQ);
// Initiate the transmission
do {
temp = mschReserveTask();
} while (temp == NO_TASK);
#if MAC_OPT_FFD
if (txOptions & TX_OPT_INDIRECT)
{
// mschAddTask(temp, MAC_TASK_PRI_MEDIUM, miqAddIndirectPacket, (WORD) pPacket);
}
else
{
// mschAddTask(temp, MAC_TASK_PRI_LOW, mtxScheduleTransmission, (WORD) pPacket);
}
#else // RFD
mschAddTask(temp, MAC_TASK_PRI_LOW, mtxScheduleTransmission, (WORD) pPacket);
#endif
} // mcpsDataRequest
//-------------------------------------------------------------------------------------------------------
// MAC_ENUM mlmeStartRequest(WORD panId, UINT8 logicalChannel, UINT8 beaconOrder, UINT8 ...)
//
// DESCRIPTION:
// As a coordinator: Start or stop transmitting beacons.
//
// PARAMETERS:
// WORD panId
// The new PAN identifier
// UINT8 logicalChannel
// The channel to operate on (11-26)
// UINT8 beaconOrder
// The beacon order, which defines the beacon interval (0-14 for beacon PAN, 15 for non-beacon PAN)
// UINT8 superframeOrder
// The superframe order, which defines the superframe duration (that is the active period of the
// beacon interval). superframeOrder must be <= beaconOrder
// ZBOOL panCoordinator
// TRUE if this node should be the PAN coordinator
// ZBOOL batteryLifeExtension
// Enable battery life extension
// ZBOOL coordRealignment
// Transmit a coordinator realignment frame before making the changes
// ZBOOL securityEnable
// Security is enabled?
//
// RETURN VALUE:
// MAC_ENUM
// SUCCESS, NO_SHORT_ADDRESS or INVALID_PARAMETER
//-------------------------------------------------------------------------------------------------------
#if MAC_OPT_FFD
MAC_ENUM mlmeStartRequest(WORD panId, UINT8 logicalChannel, UINT8 beaconOrder, UINT8 superframeOrder, ZBOOL panCoordinator, ZBOOL batteryLifeExtension, ZBOOL coordRealignment, ZBOOL securityEnable) {
ZBOOL firstBeaconNow;
WORD mdmctrl0;
volatile ZBOOL waiting;
MAC_TX_PACKET *pPacket;
UINT8 taskNumber;
// Is the short address OK?
if (mpib.macShortAddress == 0xFFFF) {
return NO_SHORT_ADDRESS;
// Are the parameters OK?
} else if ((!msupChannelValid(logicalChannel)) || (beaconOrder > 15) || ((superframeOrder > beaconOrder) && (superframeOrder != 15))) {
return INVALID_PARAMETER;
// Go ahead...
} else {
// Transmit coordinator realignment?
if (coordRealignment) {
// Reserve a packet to use with the TX engine
do {
pPacket = mtxpReservePacket();
} while (!pPacket);
// Prepare the packet data
mbcnPrepareCoordinatorRealignment(pPacket, NULL, 0xFFFF, securityEnable, panId, logicalChannel);
#if MAC_OPT_SECURITY
// In case of frame counter overflow or missing key
// Generate error with FAILED_SECURITY_CHECK or UNAVAILABLE_KEY
if (pPacket->securitySuite >= 8) {
mtxpReleasePacket(pPacket);
return pPacket->securitySuite;
}
#endif
// Initiate the transmission
do {
taskNumber = mschReserveTask();
} while (taskNumber == NO_TASK);
mschAddTask(taskNumber, MAC_TASK_PRI_LOW, mtxScheduleTransmission, (WORD) pPacket);
// Dirty trick: Create another task to tell us when the transmission task has completed
do {
taskNumber = mschReserveTask();
} while (taskNumber == NO_TASK);
waiting = TRUE;
mschAddTask(taskNumber, MAC_TASK_PRI_LOW, msupWaitTask, (WORD) &waiting);
while (waiting);
}
// Set beacon and superframe order
firstBeaconNow = !GET_MF(MF_TRANSMIT_BEACON);
mlmeSetRequest(MAC_BEACON_ORDER, &beaconOrder);
if (beaconOrder == 15) {
mpib.macSuperframeOrder = 15;
CLEAR_MF(MF_TRANSMIT_BEACON);
// Release task number and TX packet, if reserved
if (mbcnInfo.txTaskNumber != NO_TASK) {
mschReleaseTask(mbcnInfo.txTaskNumber);
mbcnInfo.txTaskNumber = NO_TASK;
}
if (mbcnInfo.pTxPacket != NULL) {
mtxpReleasePacket(mbcnInfo.pTxPacket);
mbcnInfo.pTxPacket = NULL;
}
} else {
mpib.macSuperframeOrder = superframeOrder;
}
// Prepare to modify the CC2420 PAN coordinator bit
mdmctrl0 = 0x0AE2;
// PAN coordinator?
if (panCoordinator) {
// Set the PAN ID
mlmeSetRequest(MAC_PAN_ID, &panId);
// Change the RF channel
msupSetChannel(logicalChannel, TRUE);
// Set PAN coordinator flags
SET_MF(MF_PAN_COORDINATOR);
mdmctrl0 |= 0x1000;
} else {
// Just clear the flag
CLEAR_MF(MF_PAN_COORDINATOR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -