📄 zmac_receive.c
字号:
if ( currentQueueItem == MAX_MAC_FRAME_STATUS )
currentQueueItem = 0;
// If an entry is in use, see if it is ack'ed.
if ( pCurrentFrame->Flags.bits.bIsInUse )
{
// If not ack'ed and timeout has occurred,
if ( !pCurrentFrame->Flags.bits.bIsConfirmed )
{
// Mark it as as timed out.
if ( TickGetDiff(TickGet(), pCurrentFrame->lastTick) >= MAC_ACK_WAIT_DURATION )
{
pCurrentFrame->Flags.bits.bIsTimedOut = TRUE;
// Notify of a timeout condition.
AppMACFrameTimeOutOccurred();
}
}
}
#if defined(MAC_USE_TX_INDIRECT_BUFFER)
// Do same for tx stagged frames.
ProcessTxIndirectBuffer();
#endif
return TRUE;
}
// See if it has a valid header.
if ( !MACGetHeader() )
return TRUE;
// Notify application of arrival of a new frame.
AppMACFrameReceived();
// Mark that we have a valid frame.
macCurrentFrame.Flags.bits.bIsGetReady = TRUE;
// Send ack back if requested.
if ( macCurrentFrame.frameCONLSB.bits.AckRequest )
{
MACSendAck();
}
// If this is ACK, update our queue status.
if ( MACIsAck() )
{
UpdateQueue(macCurrentFrame.macDSN);
// Once registered, discard ACK frame.
MACDiscardRx();
}
#if defined(I_AM_COORDINATOR)
else if ( MACIsCommand() )
{
// If this is coordinator, respond to beacon requests.
// A coordinator will respond to following requests only
// after it has established its own network.
if ( MACIsBeaconRequest() )
{
MACDiscardRx();
if ( MACIsNetworkEstablished() )
{
DEBUG_OUT("MAC: MACTask(): Sending Beacon...\r\n");
MACSendBeacon();
}
}
// New associations are allowed only if it is permitted by application.
else if ( MACIsAssocRequest() )
{
if ( MACIsJoinPermitted() )
{
if ( !MACProcessAssociation() )
MACDiscardRx();
}
else
MACDiscardRx();
}
// Same with disassociation.
else if ( MACIsDisassocNotice() )
{
if ( !MACProcessDisassociation() )
MACDiscardRx();
}
// Orphan can be rejoined only after we have established new network.
else if ( MACIsOrphanNotice() )
{
if ( MACIsNetworkEstablished() )
{
if ( !MACProcessOrphanNotice() )
MACDiscardRx();
}
else
MACDiscardRx();
}
// Same with data request.
else if ( MACIsDataReq() )
{
if ( MACIsNetworkEstablished() )
{
// This function always discards packet.
MACProcessDataReq();
}
else
MACDiscardRx();
}
}
#endif
return TRUE;
}
/*********************************************************************
* Function: static BOOL MACGetHeader(void)
*
* PreCondition: _MACIsGetReady() == TRUE
*
* Input: None
*
* Output: TRUE - if current frame has valid header
* FALSE - if current frame does not have
* valid header
*
* Side Effects: None
*
* Overview: Fetches rx frame one byte at a time and validates
* as per 802.15.4 spec.
*
* Note: This is private function, called MAC module only.
********************************************************************/
static BOOL MACGetHeader(void)
{
BYTE_VAL temp;
BYTE frameType;
BYTE_VAL length;
PHYBegin();
// Start reading RX FIFO.
PHYSelectRxFIFO();
// First byte is length
length.Val = PHYGetMac();
// Make sure that this is a valid length
if ( length.Val == 0 || length.bits.b7 == 1 )
goto DiscardAndReturn;
// Save received packet length minus 2 bytes of CRC/(RSSI + CORRELATION for CC2420)
macCurrentFrame.frameLength = length.Val - 2;
// Get frame control field - LSB.
temp.Val = PHYGetMac();
// One less byte from packet count.
macCurrentFrame.frameLength--;
// save frame LSB
macCurrentFrame.frameCONLSB.Val = temp.Val;
// Extract and save frame type
macCurrentFrame.type = temp.Val & 0x07;
// Reject "Reserved" frame type.
frameType = macCurrentFrame.type;
if ( frameType > 0x03 )
goto DiscardAndReturn;
// Other bits will be processed later...
// Now get MSB
temp.Val = PHYGetMac();
// One less byte from packet count.
macCurrentFrame.frameLength--;
// Save MSB
macCurrentFrame.frameCONMSB.Val = temp.Val;
// Save frame MSB.
macCurrentFrame.dst.addrMode = temp.Val & 0x0c;
macCurrentFrame.src.addrMode = temp.Val & 0xc0;
// Get Sequence number
macCurrentFrame.macDSN = PHYGetMac();
macCurrentFrame.frameLength--;
// Mode value of non-zero means that destination PAN identifier is present.
if ( macCurrentFrame.dst.addrMode == MAC_DST_ADDR_RESERVED )
goto DiscardAndReturn;
// If the destination addressing mode field is non-zero, there is a dst PAN ID.
if ( macCurrentFrame.dst.addrMode )
{
macCurrentFrame.dst.panID.byte.LSB = PHYGetMac();
macCurrentFrame.dst.panID.byte.MSB = PHYGetMac();
macCurrentFrame.frameLength -= 2;
}
// Fetch destination address according to its type
if ( macCurrentFrame.dst.addrMode == MAC_DST_SHORT_ADDR )
{
macCurrentFrame.dst.shortAddr.byte.LSB = PHYGetMac();
macCurrentFrame.dst.shortAddr.byte.MSB = PHYGetMac();
macCurrentFrame.frameLength -= 2;
}
else if ( macCurrentFrame.dst.addrMode == MAC_DST_LONG_ADDR )
{
macCurrentFrame.dst.longAddr.v[0] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[1] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[2] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[3] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[4] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[5] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[6] = PHYGetMac();
macCurrentFrame.dst.longAddr.v[7] = PHYGetMac();
macCurrentFrame.frameLength -= 8;
}
// Mode value of non-zero means that source PAN identifier is present.
if ( macCurrentFrame.src.addrMode == MAC_SRC_ADDR_RESERVED )
goto DiscardAndReturn;
// If the source addressing mode field is non-zero and the IntraPAN flag is clear,
// the IEEE spec says there will be a src PAN ID.
if ( macCurrentFrame.src.addrMode &&
macCurrentFrame.frameCONLSB.bits.IntraPAN == 0 )
{
macCurrentFrame.src.panID.byte.LSB = PHYGetMac();
macCurrentFrame.src.panID.byte.MSB = PHYGetMac();
macCurrentFrame.frameLength -= 2;
}
// Fetch source address according to its type
if ( macCurrentFrame.src.addrMode == MAC_SRC_SHORT_ADDR )
{
macCurrentFrame.src.shortAddr.byte.LSB = PHYGetMac();
macCurrentFrame.src.shortAddr.byte.MSB = PHYGetMac();
macCurrentFrame.frameLength -= 2;
}
else if ( macCurrentFrame.src.addrMode == MAC_SRC_LONG_ADDR )
{
macCurrentFrame.src.longAddr.v[0] = PHYGetMac();
macCurrentFrame.src.longAddr.v[1] = PHYGetMac();
macCurrentFrame.src.longAddr.v[2] = PHYGetMac();
macCurrentFrame.src.longAddr.v[3] = PHYGetMac();
macCurrentFrame.src.longAddr.v[4] = PHYGetMac();
macCurrentFrame.src.longAddr.v[5] = PHYGetMac();
macCurrentFrame.src.longAddr.v[6] = PHYGetMac();
macCurrentFrame.src.longAddr.v[7] = PHYGetMac();
macCurrentFrame.frameLength -= 8;
}
// If this is a command frame, extract and save command id.
if ( macCurrentFrame.type == MAC_FRAME_CMD )
{
macCurrentFrame.frameLength--;
macCurrentFrame.cmd = PHYGetMac();
}
#if defined(I_AM_END_DEVICE)
else if ( macCurrentFrame.type == MAC_FRAME_DATA )
macState.bits.bIsPollDone = TRUE;
#endif
PHYEnd();
return TRUE;
DiscardAndReturn:
PHYEnd();
PHYBegin();
PHYFlushRx();
PHYEnd();
return FALSE;
}
/*********************************************************************
* Function: void MACStartAssociation(void)
*
* PreCondition: MACAcceptCurrentPAN() is already called.
* A network scan was performed and appropriate
* coordinator was selected.
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Prepares MAC state machine to begin association
* sequence.
*
* Note: This is available for end device only.
********************************************************************/
#if defined(I_AM_END_DEVICE)
void MACStartAssociation(void)
{
// Forget about previous association.
macState.bits.bIsAssociated = FALSE;
macFrameRetryCount = MAC_MAX_FRAME_RETRIES;
// Reset the state machine.
smAssociation = SM_SEND_ASSOCIATE_REQ;
}
#endif
/*********************************************************************
* Function: BOOL MACIsAssociationComplete(void)
*
* PreCondition: MACStartAssociation() is called.
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: performs association sequence as per 802.15.4
* spec.
*
* Note: This is available for end device only.
********************************************************************/
#if defined(I_AM_END_DEVICE)
BOOL MACIsAssociationComplete(void)
{
BOOL result;
MAC_ASSOCIATE_STATUS macAssociationStatus;
result = FALSE;
switch(smAssociation)
{
case SM_SEND_ASSOCIATE_REQ:
macFrameRetryCount--;
// When associating, provide long address and no pan id.
macInfo.addrMode = MAC_SRC_LONG_ADDR;
macInfo.panID.Val = 0xffff;
MACPutHeader(&macCoordInfo, // Dest
MAC_FRAME_CMD | // Frame Control LSB
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_YES|
MAC_INTRA_PAN_NO);
PHYBeginTxFIFOAccess();
PHYPutTxData(MAC_CMD_ASSOCIATE_REQ);
PHYPutTxData(MAC_CAP_INFO);
PHYEndTxFIFOAccess();
// Manually update packet length here instead of calling MACPut() and adding more code
// and time.
macPacketLen += 2;
hFrame = MACFlush();
DEBUG_OUT("MAC: MACSendAssociateRequest(): Sent association request...\r\n");
macStartTick = TickGet();
smAssociation = SM_WAIT_FOR_ACK;
break;
case SM_WAIT_FOR_ACK:
if ( MACFrameIsAcked(hFrame) )
{
MACFrameRemove(hFrame);
DEBUG_OUT("MAC: MACIsAssociated(): Valid ACK received, asking for response...\r\n");
smAssociation = SM_SEND_DATA_REQ;
}
else if ( TickGetDiff(TickGet(), macStartTick) >= MAC_ACK_WAIT_DURATION )
{
// Remove current frame and try again, if needed.
MACFrameRemove(hFrame);
if ( macFrameRetryCount == 0 )
{
DEBUG_OUT("MAC: MACIsAssociated(): No ACK.\r\n");
SetZError(ZCODE_NO_ACK);
result = TRUE;
}
else
{
DEBUG_OUT("MAC: MACIsAssociated(): ACK Timeout, retrying...\r\n");
smAssociation = SM_SEND_ASSOCIATE_REQ;
}
}
break;
case SM_SEND_DATA_REQ:
DEBUG_OUT("MAC: MACIsAssociated(); Sending Data Request...\r\n");
hFrame = MACPoll();
macStartTick = TickGet();
smAssociation = SM_WAIT_FOR_ASSOC_RESP;
break;
case SM_DATA_REQ_ACK_WAIT:
if ( MACFrameIsAcked(hFrame) )
{
MACFrameRemove(hFrame);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -