📄 zmac_receive.c
字号:
DEBUG_OUT("MAC: MACIsAssociated(): Valid ACK received, waiting for response...\r\n");
macStartTick = TickGet();
smAssociation = SM_WAIT_FOR_ASSOC_RESP;
}
else if ( TickGetDiff(TickGet(), macStartTick) >= MAC_ACK_WAIT_DURATION )
{
// Remove current frame and try again, if needed.
MACFrameRemove(hFrame);
if ( macFrameRetryCount == 0 )
{
SetZError(ZCODE_NO_ACK);
result = TRUE;
}
DEBUG_OUT("MAC: MACIsAssociated(): ACK Timeout.\r\n");
smAssociation = SM_SEND_ASSOCIATE_REQ;
}
break;
case SM_WAIT_FOR_ASSOC_RESP:
if( MACIsGetReady() )
{
//length = MACGetHeader();
// First of all make sure that the payload length with that
// of execpted Association response frame.
if ( macCurrentFrame.frameLength == 3 )
{
// A valid association response must have following frame control LSB
// xx10?011 = Frame Type = MAC Command
// Security Enabled = 1 or 0 to match with our compile-time option
// Frame Pending is '0' and ignored
// Ack Required is '1'.
// Intra PAN is don't care
// Reserved bit don't care
// And both source and destination address must be 64-bit long
#if defined(MAC_USE_SECURITY)
if ( (macCurrentFrame.frameCONLSB.Val & 0x2B == 0x2B) &&
(macCurrentFrame.frameCONMSB.Val & 0xCC == 0xCC) )
#else
if ( ((BYTE)(macCurrentFrame.frameCONLSB.Val & 0x23) == (BYTE)0x23) &&
((BYTE)(macCurrentFrame.frameCONMSB.Val & 0xCC) == (BYTE)0xCC) )
#endif
{
// The command type must be MAC_CMD_ASSOCIATE_RPLY
if ( macCurrentFrame.cmd == MAC_CMD_ASSOCIATE_RPLY )
{
// If coordinator was able to associate with us, next two bytes will
// be the our new short address, or else it will be 0xffff.
// If it is 0xffff, associationStatus will tell us the reason.
macInfo.shortAddr.byte.LSB = MACGet();
macInfo.shortAddr.byte.MSB = MACGet();
macAssociationStatus = MACGet();
// Is association successful?
if ( macAssociationStatus != MAC_ASSOCIATE_SUCCESS )
{
DEBUG_OUT("MAC: MACIsAssociated(): Association attempt has failed.\r\n");
result = TRUE;
}
else
{
// Once we receive this frame, coordinator expects an acknowledgement.
// MACInit() has already configured CC2420 to automatically acknolwedge all
// frames with AckReq bit set.
DEBUG_OUT("MAC: MACIsAssociated(): Association successful.\r\n");
macState.bits.bIsAssociated = TRUE;
result = TRUE;
MACSetPANIdLSB(macCoordInfo.panID.byte.LSB);
MACSetPANIdMSB(macCoordInfo.panID.byte.MSB);
MACUpdateAddressInfo();
}
}
}
}
MACDiscardRx();
}
else if ( TickGetDiff(TickGet(), macStartTick) >= MAC_RESPONSE_WAIT_TIME )
{
if ( macFrameRetryCount == 0 )
{
DEBUG_OUT("MAC: MACIsAssociated(): No DATA REQ reply.\r\n");
SetZError(ZCODE_NO_ACK);
result = TRUE;
}
else
{
DEBUG_OUT("MAC: MACIsAssociated(): DATA REQ reply timeout, retrying...\r\n");
smAssociation = SM_SEND_ASSOCIATE_REQ;
}
}
break;
}
return result;
}
#endif
/*********************************************************************
* Function: static void MACSendAck(void)
*
* PreCondition: A valid frame has just arrived.
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Sends ACK frame in response to just received
* frame.
*
* Note: This is a private function
********************************************************************/
static void MACSendAck(void)
{
//DEBUG_OUT("MAC: MACSendAck(): Sending ACK.\r\n");
#if defined(WIN32)
MACPutHeader(NULL, MAC_FRAME_ACK);
MACFlush();
#else
// First, update the packet length.
PHYBegin();
PHYSendAck();
// Terminate RAM access
PHYEnd();
#endif
}
/*********************************************************************
* Function: HFRAME MACPoll(void)
*
* PreCondition: MACIsPutReady() = TRUE
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Sends Data request frame as per 802.15.4 spec.
*
* Note: Available to end device only
********************************************************************/
#if defined(I_AM_END_DEVICE)
HFRAME MACPoll(void)
{
// Use long address only if short address is not yet assigned.
if ( macInfo.shortAddr.byte.MSB == 0xff &&
(macInfo.shortAddr.byte.LSB == 0xff ||
macInfo.shortAddr.byte.LSB == 0xfe) )
macInfo.addrMode = MAC_SRC_LONG_ADDR;
else
macInfo.addrMode = MAC_SRC_SHORT_ADDR;
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_DATA_REQ);
PHYEndTxFIFOAccess();
// Manually update packet length here instead of calling MACPut() and adding more code
// and time.
macPacketLen++;
// For Poll request, we don't care to wait or confirm ack from remote node.
// If it was received by remote node and there is some pending data for us
// remote node will send it to us and that will serve as a confirmation
// to our poll request.
// By default, bToBeQueued was set by MACPutHeader because of MAC_ACK_YES flag.
macCurrentFrame.Flags.bits.bToBeQueued = FALSE;
macState.bits.bIsPollDone = FALSE;
return MACFlush();
}
#endif
/*********************************************************************
* Function: BOOL MACProcessAssociation(void)
*
* PreCondition: A valid frame is in RX buffer and
* header is already fetched and processed.
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Fetches rest of the frame and processes it if
* is a valid association request frame.
*
* Note: Available to coordinator only.
********************************************************************/
#if defined(I_AM_COORDINATOR)
BOOL MACProcessAssociation(void)
{
BOOL lbResult;
lbResult = FALSE;
// There must be exactly two bytes of data in association request frame.
if( macCurrentFrame.frameLength == 1 )
{
// Make sure that current frame is indeed association request.
// LSB = Mask: 0b00100111 Value: 0b00100011,
// MSB = Mask: 0b11001100 Value: 0b11001100
if ( ((BYTE)(macCurrentFrame.frameCONLSB.Val & 0x27) == (BYTE)0x23) &&
((BYTE)(macCurrentFrame.frameCONMSB.Val & 0xCC) == (BYTE)0xCC) )
{
macCurrentFrame.capInfo.Val = MACGet();
return TRUE;
}
}
return FALSE;
}
#endif
/*********************************************************************
* Function: HFRAME MACSendAssociateResponse(
* SHORT_ADDR *assocShortAddr,
* MAC_ASSOCIATE_STATUS status)
*
* PreCondition: assocShortAddr - Short address to be sent
* as part of association response
* status - Association result code to be sent
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Creates and sends valid association response frame
* as per IEEE spec.
*
* Note: Available to coordinator only.
********************************************************************/
#if defined(I_AM_COORDINATOR)
HFRAME MACSendAssociateResponse(SHORT_ADDR *assocShortAddr,
MAC_ASSOCIATE_STATUS status)
{
macInfo.addrMode = MAC_SRC_LONG_ADDR;
// Use information from macCurrentFrame to build response frame.
// If we arrive at this point, macCurrentFrame must be a valid
// Associate Request and as a result, we will only change those fields
// that needs to changed as part of response frame format.
macCurrentFrame.src.addrMode = MAC_DST_LONG_ADDR;
// Dest panID will be same as ours.
macCurrentFrame.src.panID.Val = macInfo.panID.Val;
MACPutHeader(&macCurrentFrame.src, // 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_RPLY);
PHYPutTxData(assocShortAddr->byte.LSB);
PHYPutTxData(assocShortAddr->byte.MSB);
PHYPutTxData((BYTE)status);
PHYEndTxFIFOAccess();
// Manually update packet length here instead of calling MACPut() and adding more code
// and time.
macPacketLen += 4;
return MACFlush();
}
#endif
/*********************************************************************
* Function: HFRAME MACSendRealignment(
* SHORT_ADDR *destShortAddr, BOOL bBroadcast)
*
* PreCondition: MACIsPutReady() = TRUE
*
* Input: destShortAddr - node to whom relignment frame to send
* bBroadcast - indicates if this is to be broadcast
*
* Output: Handle to frame that was just transmitted.
* Caller must use this handle to determine if this
* frame was ack'ed by intended remote node.
*
* Side Effects: None
*
* Overview: Creates and sends valid relignment frame
* as per IEEE spec.
*
* Note: Available to coordinator only.
********************************************************************/
#if defined(I_AM_COORDINATOR)
HFRAME MACSendRealignment(SHORT_ADDR *destShortAddr, BOOL bBroadcast)
{
BYTE frameFlags;
macInfo.addrMode = MAC_SRC_LONG_ADDR;
// Other information is already set.
// If this is a unicast, we need to use LONG address.
// Since we already have remote device's address information
// in current frame, we will use current frame's source as
// destination for this frame.
if ( bBroadcast == FALSE )
{
macCurrentFrame.src.addrMode = MAC_DST_LONG_ADDR;
// For unicast frame, request ack.
frameFlags = MAC_FRAME_CMD |
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_YES |
MAC_INTRA_PAN_NO;
}
else
{
macCurrentFrame.src.addrMode = MAC_DST_SHORT_ADDR;
macCurrentFrame.src.shortAddr.Val = 0xffff;
// For broadcast, do not request ack.
frameFlags = MAC_FRAME_CMD |
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_NO |
MAC_INTRA_PAN_NO;
}
// The destination PAN will be 0xFFFF
macCurrentFrame.src.panID.Val = 0xffff;
MACPutHeader(&macCurrentFrame.src, frameFlags);
// Now load coord realignment specific payload.
PHYBegin();
PHYSelectTxFIFO();
PHYPut(MAC_CMD_COORD_REALIGNMENT);
// Current PAN ID.
PHYPut(macInfo.panID.byte.LSB);
PHYPut(macInfo.panID.byte.MSB);
// Coordinator's short address
PHYPut(macInfo.shortAddr.byte.LSB);
PHYPut(macInfo.shortAddr.byte.MSB);
// Logical channel
PHYPut(macCurrentChannel);
// If this is a unicast, supply dest short addr.
if ( bBroadcast == FALSE )
{
PHYPut(destShortAddr->byte.LSB);
PHYPut(destShortAddr->byte.MSB);
}
else
{
// For broadcast, this will be 0xffff.
PHYPut(0xff);
PHYPut(0xff);
}
PHYEnd();
// Update MACPacketLen manually.
macPacketLen += 8;
return MACFlush();
}
#endif
/*********************************************************************
* Function: void MACStartOrphanNotification(void)
*
* PreCondition: MACIsPutReady() = TRUE
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Prepares the state machine for orphan notification
*
* Note: Available to end devices only.
********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -