📄 mac.c
字号:
/*
V0.1 Initial Release 10/July/2006
*
*/
/*
V0.21 fixed problem in OrphanResponse, was not copying the parent's
long address 27/July/2006
V0.2 added PC-based binding 21/July/2006
V0.1 Initial Release 10/July/2006
*/
#include "compiler.h"
#include "lrwpan_config.h" //user configurations
#include "lrwpan_common_types.h" //types common acrosss most files
#include "ieee_lrwpan_defs.h"
#include "console.h"
#include "debug.h"
#include "memalloc.h"
#include "hal.h"
#include "halStack.h"
#include "phy.h"
#include "mac.h"
#include "nwk.h"
#include "neighbor.h"
typedef enum _MAC_RXSTATE_ENUM {
MAC_RXSTATE_IDLE,
MAC_RXSTATE_NWK_HANDOFF,
MAC_RXSTATE_CMD_PENDING
} MAC_RXSTATE_ENUM;
static MAC_RXSTATE_ENUM macRxState;
MAC_PIB mac_pib;
MAC_SERVICE a_mac_service;
MAC_STATE_ENUM macState;
//there can only be one TX in progress at a time, so
//a_mac_tx_data contains the arguments for that TX.
MAC_TX_DATA a_mac_tx_data;
//this is used for parsing of current packet.
MAC_RX_DATA a_mac_rx_data;
LRWPAN_STATUS_ENUM macTxFSM_status;
//locals
static UINT32 mac_utility_timer; //utility timer
//local functions
static void macTxData(void);
static void macTxFSM(void);
static void macParseHdr(void);
static void macRxFSM(void);
static void macParseBeacon(void);
static void macFormatAssocRequest(void);
static BOOL macCheckDataRejection(void);
static void macFormatOrphanNotify(void);
#ifndef LRWPAN_COORDINATOR
static void macParseOrphanResponse(void);
#endif
#ifdef LRWPAN_FFD
static void macFormatBeacon(void);
static void macFormatAssociationResponse(void);
static void macFormatCoordRealign(SADDR orphan_saddr);
#endif
#ifndef LRWPAN_COORDINATOR
static void macParseAssocResponse(void);
#endif
//does not turn on radio.
void macInit(void){
macState = MAC_STATE_IDLE;
macRxState = MAC_RXSTATE_IDLE;
mac_pib.macCoordShortAddress = 0;
mac_pib.flags.val = 0;
mac_pib.rxTail = 0;
mac_pib.rxHead = 0;
mac_pib.macPANID = LRWPAN_DEFAULT_PANID;
mac_pib.macMaxAckRetries = aMaxFrameRetries;
ntInitAddressMap(); //init the address map
#ifdef LRWPAN_COORDINATOR
mac_pib.depth = 0;
#else
mac_pib.depth = 1; //depth will be at least one
#endif
mac_pib.bcnDepth = 0xFF; //remembers depth of node that responded to beacon
//other capability information
mac_pib.macCapInfo = 0;
#ifdef LRWPAN_ALT_COORDINATOR //not supported, included for completeness
LRWPAN_SET_CAPINFO_ALTPAN(mac_pib.macCapInfo);
#endif
#ifdef LRWPAN_FFD
LRWPAN_SET_CAPINFO_DEVTYPE(mac_pib.macCapInfo);
#endif
#ifdef LRWPAN_ACMAIN_POWERED
LRWPAN_SET_CAPINFO_PWRSRC(mac_pib.macCapInfo);
#endif
#ifdef LRWPAN_RCVR_ON_WHEN_IDLE
LRWPAN_SET_CAPINFO_RONIDLE(mac_pib.macCapInfo);
#endif
#ifdef LRWPAN_SECURITY_CAPABLE
LRWPAN_SET_CAPINFO_SECURITY(mac_pib.macCapInfo);
#endif
//always allocate a short address
LRWPAN_SET_CAPINFO_ALLOCADDR(mac_pib.macCapInfo);
}
LRWPAN_STATUS_ENUM macWarmStartRadio(void){
halWarmstart();
a_phy_service.cmd = LRWPAN_SVC_PHY_INIT_RADIO; //no args
a_phy_service.args.phy_init_radio_args.radio_flags.bits.listen_mode = 0;
#ifdef LRWPAN_COORDINATOR
a_phy_service.args.phy_init_radio_args.radio_flags.bits.pan_coordinator = 1;
#else
a_phy_service.args.phy_init_radio_args.radio_flags.bits.pan_coordinator = 0;
#endif
phyDoService();
halSetChannel(phy_pib.phyCurrentChannel);
halSetRadioPANID(mac_pib.macPANID); //listen on this PANID
halSetRadioShortAddr(macGetShortAddr()); //non-broadcast, reserved
return(a_phy_service.status);
}
//this assumes that phyInit, macInit has previously been called.
//turns on the radio
LRWPAN_STATUS_ENUM macInitRadio(void) {
phy_pib.phyCurrentFrequency = LRWPAN_DEFAULT_FREQUENCY;
phy_pib.phyCurrentChannel = LRWPAN_DEFAULT_START_CHANNEL;
if (phy_pib.phyCurrentChannel < 11){
mac_pib.macAckWaitDuration = SYMBOLS_TO_MACTICKS(120);
}
else {
mac_pib.macAckWaitDuration = SYMBOLS_TO_MACTICKS(54);
}
a_phy_service.cmd = LRWPAN_SVC_PHY_INIT_RADIO; //no args
a_phy_service.args.phy_init_radio_args.radio_flags.bits.listen_mode = 0;
#ifdef LRWPAN_COORDINATOR
a_phy_service.args.phy_init_radio_args.radio_flags.bits.pan_coordinator = 1;
#else
a_phy_service.args.phy_init_radio_args.radio_flags.bits.pan_coordinator = 0;
#endif
phyDoService();
#ifdef LRWPAN_USE_STATIC_PANID
halSetRadioPANID(LRWPAN_DEFAULT_PANID); //listen on this PANID
#else
halSetRadioPANID(0xFFFF); //broadcast
#endif
halSetRadioShortAddr(0xFFFE); //non-broadcast, reserved
return(a_phy_service.status);
}
void macSetPANID(UINT16 panid){
mac_pib.macPANID = panid;
halSetRadioPANID(mac_pib.macPANID);
}
void macSetChannel(BYTE channel){
phy_pib.phyCurrentChannel = channel;
halSetChannel(channel);
}
void macSetShortAddr(UINT16 saddr) {
#ifdef LRWPAN_RFD
//when changing the short address for an RFD, always clear the map first
//since the short address may have changed.
//for RFDs, there is only one entry
ntInitAddressMap();
#endif
ntAddOurselvesToAddressTable(saddr);
halSetRadioShortAddr(saddr);
}
void macFSM(void) {
BYTE cmd;
#ifdef LRWPAN_FFD
NAYBORENTRY *nt_ptr;
#endif
#ifdef LRWPAN_DEBUG
//assume 2.4 GHZ
if (debug_level == 0) {
mac_pib.macAckWaitDuration = SYMBOLS_TO_MACTICKS(54);
} else {
mac_pib.macAckWaitDuration = SYMBOLS_TO_MACTICKS(270); //give longer due to debug output
}
#endif
phyFSM();
//if TxFSM is busy we need to call it
if (macTXBusy()) macTxFSM();
macRxFSM();
#ifdef LRWPAN_FFD
macFSM_start:
#endif
//check background tasks here
switch (macState) {
case MAC_STATE_IDLE:
if (mac_pib.flags.bits.macPending ) {
//there is a MAC CMD packet pending in the RX buffer. Handle it.
cmd = *(a_mac_rx_data.orgpkt->data + a_mac_rx_data.pload_offset);
switch (cmd) {
case LRWPAN_MACCMD_BCN_REQ:
//Beacon Request
#ifdef LRWPAN_RFD
//as an RFD, I do not handle this. Release this.
mac_pib.flags.bits.macPending = 0;
#else
//as a Coordinator or Router, I will only respond
//only respond if association permitted
//as this is the stack's only use of beacons
if (mac_pib.flags.bits.macAssociationPermit) {
//will keep spinning through here until TX buffer unlocked
if (phyTxUnLocked()) {
phyGrabTxLock(); //grab the lock
macState = MAC_STATE_SEND_BEACON_RESPONSE;
mac_pib.flags.bits.macPending = 0; //release packet
goto macFSM_start;
}
}else {
//release packet.
mac_pib.flags.bits.macPending = 0;
}
#endif
break;
case LRWPAN_MACCMD_ORPHAN:
//Orphan Notify
#ifdef LRWPAN_RFD
//as an RFD, I do not handle this. Release this.
mac_pib.flags.bits.macPending = 0;
#else
//will keep spinning through here until TX buffer unlocked
if (phyTxUnLocked()) {
phyGrabTxLock(); //grab the lock
macState = MAC_STATE_HANDLE_ORPHAN_NOTIFY;
mac_pib.flags.bits.macPending = 0; //release packet
goto macFSM_start;
}
#endif
case LRWPAN_MACCMD_ASSOC_REQ:
//Association Request
#ifdef LRWPAN_RFD
//as an RFD, I do not handle this. Release this.
mac_pib.flags.bits.macPending = 0;
#else
//as a Coordinator or Router, I can respond
//only respond if association permitted
if (mac_pib.flags.bits.macAssociationPermit) {
//will keep spinning through here until TX buffer unlocked
if (phyTxUnLocked()) {
phyGrabTxLock(); //grab the lock
macState = MAC_STATE_SEND_ASSOC_RESPONSE;
mac_pib.flags.bits.macPending = 0; //release packet
goto macFSM_start;
}
}else {
//release packet.
mac_pib.flags.bits.macPending = 0;
}
#endif
break;
default:
DEBUG_STRING(1,"MAC: Received MAC CMD that is not currently implemented, discarding.\n");
mac_pib.flags.bits.macPending = 0;
}
}//end if(mac_pib.flags.bits.macPending )
break;
case MAC_STATE_COMMAND_START:
switch(a_mac_service.cmd) {
case LRWPAN_SVC_MAC_ERROR:
//dummy service, just return the status that was passed in
a_mac_service.status = a_mac_service.args.error.status;
macState = MAC_STATE_IDLE;
break;
case LRWPAN_SVC_MAC_GENERIC_TX:
//send a generic packet with arguments specified by upper level
macTxData();
macState = MAC_STATE_GENERIC_TX_WAIT;
break;
case LRWPAN_SVC_MAC_RETRANSMIT:
//retransmit the last packet
//used for frames that are only transmitted once because of no ACK request
//assumes the TX lock is grabbed, and the TX buffer formatted.
macSetTxBusy();
macTxFSM_status = LRWPAN_STATUS_MAC_INPROGRESS;
a_phy_service.cmd = LRWPAN_SVC_PHY_TX_DATA;
phyDoService();
macState = MAC_STATE_GENERIC_TX_WAIT;
break;
case LRWPAN_SVC_MAC_ORPHAN_NOTIFY:
if (phyTxLocked()) break;
phyGrabTxLock(); //Grab the lock
//no ack, long SRC, short DST, broadcast PAN
a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_MAC;
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_LADDR;
a_mac_tx_data.DestAddr.saddr = LRWPAN_BCAST_PANID;
a_mac_tx_data.DestPANID = LRWPAN_BCAST_PANID;
a_mac_tx_data.SrcPANID = LRWPAN_BCAST_PANID;
macFormatOrphanNotify();
mac_pib.flags.bits.GotOrphanResponse = 0;
mac_pib.flags.bits.WaitingForOrphanResponse = 1;
macTxData();
macState = MAC_STATE_ORPHAN_WAIT1;
break;
case LRWPAN_SVC_MAC_BEACON_REQ:
//clear Beacon Response Flag
mac_pib.flags.bits.GotBeaconResponse =0; //will be set when get response
//wait for TX lock to send the beacon request
if (phyTxLocked()) break;
phyGrabTxLock(); //Grab the lock
mac_pib.flags.bits.WaitingForBeaconResponse = 1; //will be cleared when get response
//set the channel
halSetChannel(a_mac_service.args.beacon_req.LogicalChannel);
//stuff the MAC BEACON REQ command into the TX buffer
phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE-1];
*phy_pib.currentTxFrm = LRWPAN_MACCMD_BCN_REQ;
phy_pib.currentTxFlen = 1;
//no MAC ack requested
a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_MAC|LRWPAN_FCF_INTRAPAN_MASK;
//using no src address, dst address and PAN are both broadcast address
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_NOADDR;
a_mac_tx_data.DestAddr.saddr = LRWPAN_BCAST_SADDR;
#ifdef LRWPAN_USE_STATIC_PANID
//we only want to talk to nodes who use this PANID
//this is not compliant with 802.15.4
//we do this to reduce the number of responses, only want routers/coord
//to respond who use this panid
a_mac_tx_data.DestPANID = LRWPAN_DEFAULT_PANID;
#else
//talk to any nodes willing to send us a beacon
a_mac_tx_data.DestPANID = LRWPAN_BCAST_PANID;
#endif
macTxData();
macState = MAC_STATE_GENERIC_TX_WAIT_AND_UNLOCK;
break;
case LRWPAN_SVC_MAC_ASSOC_REQ:
//break if the TXBUFFER is locked
if (phyTxLocked()) break;
phyGrabTxLock(); //Grab the lock
//may want to put this in a function
halSetChannel(a_mac_service.args.assoc_req.LogicalChannel);
mac_pib.flags.bits.macIsAssociated = 0; //clear to zero
macFormatAssocRequest();
a_mac_tx_data.fcflsb = LRWPAN_FRAME_TYPE_MAC|LRWPAN_FCF_ACKREQ_MASK;
#ifdef LRWPAN_FORCE_ASSOCIATION_TARGET
//forced association occurs on DEFAULT PANID
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_LADDR|LRWPAN_FCF_SRCMODE_LADDR;
a_mac_tx_data.DestPANID = LRWPAN_DEFAULT_PANID;
a_mac_tx_data.DestAddr.laddr.bytes[0] = parent_addr_B0;
a_mac_tx_data.DestAddr.laddr.bytes[1] = parent_addr_B1;
a_mac_tx_data.DestAddr.laddr.bytes[2] = parent_addr_B2;
a_mac_tx_data.DestAddr.laddr.bytes[3] = parent_addr_B3;
a_mac_tx_data.DestAddr.laddr.bytes[4] = parent_addr_B4;
a_mac_tx_data.DestAddr.laddr.bytes[5] = parent_addr_B5;
a_mac_tx_data.DestAddr.laddr.bytes[6] = parent_addr_B6;
a_mac_tx_data.DestAddr.laddr.bytes[7] = parent_addr_B7;
#else
//using short address for DST
a_mac_tx_data.fcfmsb = LRWPAN_FCF_DSTMODE_SADDR|LRWPAN_FCF_SRCMODE_LADDR;
//use addressing discovered by beacon request
a_mac_tx_data.DestAddr.saddr = mac_pib.bcnSADDR;
a_mac_tx_data.DestPANID = mac_pib.bcnPANID;
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -