📄 mac.c
字号:
macRxFSM_start:
switch(macRxState) {
case MAC_RXSTATE_IDLE:
if (macRxBuffEmpty()) break; //no data, break
//buffer not empty, start decode
pkt = macGetRxPacket();
//dbgPrintPacket(pkt->data+1, *(pkt->data));
//must be either a DATA, BCN, or MAC packet
//at this point, we throw away BCN packets if are not waiting
//for a beacon response
if ((LRWPAN_IS_BCN(*(pkt->data+1))) &&
!mac_pib.flags.bits.WaitingForBeaconResponse) {
DEBUG_STRING(DBG_INFO,"MAC: Received BCN pkt, discarding.\n");
macFreeRxPacket(TRUE);
break;
}
if (LRWPAN_IS_ACK(*(pkt->data+1))) {
//This should not happen. ACK packets should be parsed
//in the HAL layer that copies ACK packets to temp storage.
//will keep this for completeness.
DEBUG_STRING(DBG_INFO,"MAC: Received ACK pkt in macStartRxDecode, discarding, check ack packet parsing..\n");
macFreeRxPacket(TRUE);
break;
}
//at this point, we have a DATA, MAC CMD, or BCN packet.. do something with it.
//need to parse the header information get to the payload.
a_mac_rx_data.orgpkt = pkt;
macParseHdr();
if ((LRWPAN_IS_BCN(*(pkt->data+1)))){
DEBUG_STRING(DBG_INFO,"MAC: Parsing BCN pkt.\n");
//now finished with it.
macParseBeacon();
macFreeRxPacket(TRUE);
break;
}
if (LRWPAN_IS_DATA(*(pkt->data+1))){
//this is a data packet, check if we should reject it
if (!macCheckDataRejection()) {
//we need to reject this packet.
DEBUG_STRING(DBG_INFO,"MAC: Rejecting Data packet from unassociated node, rejecting.\n");
macFreeRxPacket(TRUE);
break;
}
mac_pib.last_data_rx_time = halGetMACTimer(); //time of last data or mac command
//at this point, will accept packet, indicate this to network layer
//set a flag, and pass the nwkStart offset to the NWK layer
//RX buffer.
macRxState = MAC_RXSTATE_NWK_HANDOFF;
goto macRxFSM_start;
}
//at this point, we have a MAC command packet, lets do something with it.
DEBUG_STRING(DBG_INFO,"MAC: Received MAC cmd packet, proceeding.\n");
//there are some MAC CMDs that we can handle right here.
//If it is a response, we handle it here. If it is a request,
//that has to be handled in the main FSM.
cmd = *(a_mac_rx_data.orgpkt->data + a_mac_rx_data.pload_offset);
switch(cmd) {
case LRWPAN_MACCMD_ASSOC_RSP:
#ifndef LRWPAN_COORDINATOR
if (mac_pib.flags.bits.WaitingForAssocResponse){
macParseAssocResponse();
}
#endif
//free this packet, we are finished with it.
macFreeRxPacket(TRUE);
break;
case LRWPAN_MACCMD_COORD_REALIGN:
#ifndef LRWPAN_COORDINATOR
if (mac_pib.flags.bits.WaitingForOrphanResponse){
macParseOrphanResponse();
}
#endif
//free this packet, we are finished with it.
macFreeRxPacket(TRUE);
break;
#ifdef LRWPAN_FFD
//only FFDs handle this
case LRWPAN_MACCMD_BCN_REQ:
case LRWPAN_MACCMD_ASSOC_REQ:
case LRWPAN_MACCMD_ORPHAN:
//requests must be handled in the main FSM. We need to signal that a MAC
//CMD packet is packet is pending, and freeze the RX FSM until the
//main FSM has taken care of it.
mac_pib.flags.bits.macPending = 1;
macRxState = MAC_RXSTATE_CMD_PENDING;
break;
#endif
default:
//unhandled MAC packets
DEBUG_STRING(DBG_INFO,"MAC: Received MAC CMD that is not implemented or not handled by this node, discarding.\n");
DEBUG_STRING(DBG_INFO,"Cmd is: ");
DEBUG_UINT8(DBG_INFO,cmd);
DEBUG_STRING(DBG_INFO,"\n");
macFreeRxPacket(TRUE);
break;
}
break;
case MAC_RXSTATE_NWK_HANDOFF:
if (nwkRxBusy()) break; //nwkRX is still busy
//handoff the current packet
nwkRxHandoff();
//we are finished with this packet.
//free the MAC resource, but not the memory. The NWK layer
// or above has to free the memory
macFreeRxPacket(FALSE);
macRxState = MAC_RXSTATE_IDLE;
break;
case MAC_RXSTATE_CMD_PENDING:
if (mac_pib.flags.bits.macPending ) break;
//when macPending is cleared, this means main FSM is finished with packet.
//So free the packet, and start parsing new packets again
macFreeRxPacket(TRUE);
macRxState = MAC_RXSTATE_IDLE;
break;
default: break;
}
}
//parse the header currently in a_mac_rx_data
//return the offset to the network header.
static void macParseHdr() {
BYTE *ptr;
BYTE len,i;
BYTE srcmode, dstmode;
ptr = a_mac_rx_data.orgpkt->data;
//skip first byte since the first byte in the a_mac_rx_data.orgpkt is the
//packet length
len = 1;ptr++;
a_mac_rx_data.fcflsb = *ptr; ptr++;
a_mac_rx_data.fcfmsb = *ptr; ptr++;
dstmode = LRWPAN_GET_DST_ADDR(a_mac_rx_data.fcfmsb);
srcmode = LRWPAN_GET_SRC_ADDR(a_mac_rx_data.fcfmsb);
//skip DSN
ptr++;
len = len +3;
if (dstmode != LRWPAN_ADDRMODE_NOADDR){
//get the DEST PANDID
a_mac_rx_data.DestPANID = *ptr;
ptr++;
a_mac_rx_data.DestPANID += (((UINT16)*ptr) << 8);
ptr++;
len = len + 2;
}
//DST address
if (dstmode == LRWPAN_ADDRMODE_SADDR) {
a_mac_rx_data.DestAddr.saddr = *ptr;
ptr++;
a_mac_rx_data.DestAddr.saddr += (((UINT16)*ptr) << 8);
ptr++;
len = len + 2;
}else if (dstmode == LRWPAN_ADDRMODE_LADDR) {
for (i=0;i<8;i++) {
a_mac_rx_data.DestAddr.laddr.bytes[i] = *ptr;
ptr++;
}
len = len + 8;
}
if ( !LRWPAN_GET_INTRAPAN(a_mac_rx_data.fcflsb) &&
srcmode != LRWPAN_ADDRMODE_NOADDR
) {
//PANID present if INTRAPAN is zero, and src is nonzero
a_mac_rx_data.SrcPANID = *ptr;
ptr++;
a_mac_rx_data.SrcPANID += (((UINT16)*ptr) << 8);
ptr++;
len = len + 2;
}
//SRC address
if (srcmode == LRWPAN_ADDRMODE_SADDR) {
a_mac_rx_data.SrcAddr.saddr = *ptr;
ptr++;
a_mac_rx_data.SrcAddr.saddr += (((UINT16)*ptr) << 8);
ptr++;
len = len + 2;
}else if (srcmode == LRWPAN_ADDRMODE_LADDR) {
for (i=0;i<8;i++) {
a_mac_rx_data.SrcAddr.laddr.bytes[i] = *ptr;
ptr++;
}
len = len + 8;
}
//save offset.
a_mac_rx_data.pload_offset = len;
}
#ifdef LRWPAN_FFD
//Beacon payload format
// nwk magic number ( 4 bytes) | mac depth
static void macFormatBeacon(void){
BYTE i;
//fill in the beacon payload, we have the TX buffer lock
phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE];
#ifndef LRWPAN_ZIGBEE_BEACON_COMPLY
//fill in the magic number
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B3;
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B2;
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B1;
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B0;
#endif
//next three bytes are zero for timestep difference
//for multi-hop beaconing networks. This is currently filled in
//as zero
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm =0;
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm =0;
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm =0;
//see if I have space for an END device
--phy_pib.currentTxFrm;
if (mac_pib.ChildRFDs == LRWPAN_MAX_NON_ROUTER_CHILDREN) {
*phy_pib.currentTxFrm =0; //no room
} else {
*phy_pib.currentTxFrm =1; //have space.
}
//fill in my depth
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = mac_pib.depth;
//see if I have space for a ROUTER device
--phy_pib.currentTxFrm;
if (mac_pib.ChildRouters == LRWPAN_MAX_ROUTERS_PER_PARENT) {
*phy_pib.currentTxFrm =0; //no room
} else {
*phy_pib.currentTxFrm =1; //have space.
}
//network protocol version
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm =LRWPAN_ZIGBEE_PROTOCOL_VER;
//stack protocol
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm =LRWPAN_STACK_PROFILE;
//Zigbee protocol ID
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm =LRWPAN_ZIGBEE_PROTOCOL_ID;
//pending address field
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = 0; //makes this a NOP
//GTS directions field
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = 0; //makes this a NOP
//2 bytes of superframe
#ifdef LRWPAN_COORDINATOR
i = LRWPAN_BEACON_SF_PAN_COORD_MASK;
#else
i = 0;
#endif
if (mac_pib.flags.bits.macAssociationPermit) {
i = i | LRWPAN_BEACON_SF_ASSOC_PERMIT_MASK;
}
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = i; //MSB of superframe
--phy_pib.currentTxFrm;
*phy_pib.currentTxFrm = 0xFF; //LSB of superframe
phy_pib.currentTxFlen = LRWPAN_NWK_BEACON_SIZE;
}
#endif
//parse the beacon
static void macParseBeacon(void){
BYTE *ptr;
BYTE depth;
if ( (*(a_mac_rx_data.orgpkt->data)-a_mac_rx_data.pload_offset-PACKET_FOOTER_SIZE +1)
!= LRWPAN_NWK_BEACON_SIZE ) {
return; //wrong length
}
ptr = a_mac_rx_data.orgpkt->data + a_mac_rx_data.pload_offset;
//check association bit in MSB of superframe
if (!LRWPAN_GET_BEACON_SF_ASSOC_PERMIT(*(ptr+1))) {
//cannot associate with this node. reject
return;
}
// point at payload (skip four bytes of header)
ptr = ptr + 4;
//skip if any mismatches on protocol ID/Ver, stack profile, etc.
//check protocol ID
if (*ptr != LRWPAN_ZIGBEE_PROTOCOL_ID) return;
ptr++;
//check stack profile
if (*ptr != LRWPAN_STACK_PROFILE) return;
ptr++;
//check protocol version
if (*ptr != LRWPAN_ZIGBEE_PROTOCOL_VER) return;
ptr++;
//check router capacity
//for right now, if I am a router, I have to join as a router.
//no option as of now for a router joining as an end-device
#ifdef LRWPAN_FFD
//only routers have to check this
if (*ptr == 0) return; //no room to join as router
#endif
ptr++;
//get the depth
depth = *ptr;
ptr++;
//check end device capacity
#ifdef LRWPAN_RFD
//only end devices have to check this.
if (*ptr == 0) return; //no room to join as end device
#endif
ptr++;
//skip the next three bytes, only for beaconing.
ptr = ptr + 3;
#ifndef LRWPAN_ZIGBEE_BEACON_COMPLY
//check the magic number
if (*ptr != LRWPAN_NWK_MAGICNUM_B0) return;
ptr++;
if (*ptr != LRWPAN_NWK_MAGICNUM_B1) return;
ptr++;
if (*ptr != LRWPAN_NWK_MAGICNUM_B2) return;
ptr++;
if (*ptr != LRWPAN_NWK_MAGICNUM_B3) return;
ptr++;
#endif
//at this point, we could accept this node as a parent
if ((mac_pib.bcnDepth == 0xFF) ||
(a_mac_rx_data.orgpkt->rssi > mac_pib.bcnRSSI)) {
//either our first response, or from a closer node
//save this information.
//use value with higher RSSI.
//the RSSI byte is assumed to be formatted as HIGHER IS BETTER
//the HAL layer converts any native signed RSSI to an unsigned value
mac_pib.bcnDepth = depth; //get depth
mac_pib.bcnRSSI = a_mac_rx_data.orgpkt->rssi;
mac_pib.bcnSADDR = a_mac_rx_data.SrcAddr.saddr;
mac_pib.bcnPANID = a_mac_rx_data.SrcPANID;
DEBUG_STRING(DBG_INFO,"MAC: Bcn rsp is Panid: ");
DEBUG_UINT16(DBG_INFO, mac_pib.bcnPANID);
DEBUG_STRING(DBG_INFO,", Saddr: ");
DEBUG_UINT16(DBG_INFO, mac_pib.bcnSADDR);
DEBUG_STRING(DBG_INFO,", LQI: ");
DEBUG_UINT8(DBG_INFO, mac_pib.bcnRSSI);
DEBUG_STRING(DBG_INFO,", Dpth: ");
DEBUG_UINT8(DBG_INFO, mac_pib.bcnDepth);
DEBUG_STRING(DBG_INFO,"\n");
}
mac_pib.flags.bits.GotBeaconResponse = 1;
}
static void macFormatAssocRequest(void){
//fill in payload of request
phy_pib.currentTxFrm = &tmpTxBuff[LRWPAN_MAX_FRAME_SIZE];
#ifndef IEEE_802_COMPLY
//put the magic number in the association request
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B3;
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B2;
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -