📄 mac.c
字号:
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = a_mac_tx_data.DestAddr.laddr.bytes[7-c];
}
phy_pib.currentTxFlen=phy_pib.currentTxFlen+8;
break;
default:
break;
}
//format dst PANID, will be present if both dst is nonzero
if (dstmode != LRWPAN_ADDRMODE_NOADDR){
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = (BYTE) (a_mac_tx_data.DestPANID >> 8);
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = (BYTE)a_mac_tx_data.DestPANID;
phy_pib.currentTxFlen=phy_pib.currentTxFlen+2;
}
//format dsn
mac_pib.macDSN = halGetRandomByte();
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = mac_pib.macDSN; //set DSN
//format MSB Fcontrol
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = a_mac_tx_data.fcfmsb;
//format LSB Fcontrol
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = a_mac_tx_data.fcflsb;
phy_pib.currentTxFlen = phy_pib.currentTxFlen + 3; //DSN, FCFLSB, FCFMSB
// at this point, we will attempt a TX
mac_pib.flags.bits.ackPending = 0;
//now send the data, ignore the GTS and INDIRECT bits for now
DEBUG_STRING(DBG_TX,"TX DSN: ");
DEBUG_UINT8(DBG_TX,mac_pib.macDSN);
DEBUG_STRING(DBG_TX,"\n");
macSetTxBusy();
mac_pib.currentAckRetries = mac_pib.macMaxAckRetries;
macTxFSM_status = LRWPAN_STATUS_MAC_INPROGRESS;
}
a_phy_service.cmd = LRWPAN_SVC_PHY_TX_DATA;
phyDoService();
}
//might be able to simplify this later.
static void macRxFSM(void){
MACPKT *pkt;
BYTE cmd;
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-1];
*phy_pib.currentTxFrm = mac_pib.depth;
//now 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;
//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;
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
ptr = ptr + 4;
//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++;
//at this point, we have a valid magic number
//we can accept this node.
//che
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 = *ptr; //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;
phy_pib.currentTxFrm--;
*phy_pib.currentTxFrm = LRWPAN_NWK_MAGICNUM_B0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -