📄 zmac.c
字号:
//Notify the application of a timeout condition.
//ConsolePutString("time out and remove\n");
//du 直接从DSN中移除
//MACFrameRemove(i);
#if 0
if(pMACFrameStatus->retryCount == 0)
{
//DumpMacFrameStatusQ();
//MACRemoveFrame(i);
}
#endif
}
}
}
}
}
/*********************************************************************
* Function: BOOL MACTask(void)
*
* PreCondition: MACInit() is called
*
* Input: None
*
* Output: TRUE - If Processing is complete
* FALSE - If further processing is required
*
* Side Effects: None
*
* Overview: If previous frame is processed, it checks
* for new RX frame.
* Fetches the header and determiens if it is valid
* Automatically sends ACK if remote node has
* requested it.
* Also performs some other automatic processing
* based on the frame type.
* If there is no frame in buffer, it goes through
* DSN queue and calculates timeout for unack'ed
* TX frames.
*
* Note: This function must be called as many times as
* possible to keep handling MAC frames.
********************************************************************/
BOOL MACTask(void)
{
MACUpdateTimeoutFlags();
// If there was an overflow, handle it.
// Since this is a half-duplex and the way CC2420 indicates RX FIFO OVERFLOW,
// check for overflow condition only when RF is not actively transmitting a packet.
if ( macState.bits.bIsTxBusy == FALSE )
{
if ( PHYProcessRxOverflow() )
{
ConsolePutString("MAC: A receive overflow was detected and removed.\r\n");
}
}
//du 当过去的数据被处理完成后,才接受新的数据
if ( MACIsGetReady() ){
ConsolePutString("mac not handled\n");
return TRUE;
}
if ( !PHYIsGetReady() )
{
return TRUE;
}
if ( !MACGetHeader() )
{
ConsolePutString("mac header wrong\n");
return TRUE;
}
ConsolePutString("mac receive right frame\n");
macCurrentFrame.Flags.bits.bIsGetReady = TRUE;
// Send ack back if requested.
if ( macCurrentFrame.frameCONLSB.bits.AckRequest )
{
if((MACIsCommand()) && (MACIsDataReq()))
{
MACSendAck(ACK_DATA_PENDING);
MACSendAck(ACK_NO_DATA);
}
else
{
MACSendAck(ACK_NO_DATA);
}
}
if (MACIsAck())
{
UpdateQueue(macCurrentFrame.macDSN);
MACDiscardRx();
}
else if (MACIsCommand())
{
if (MACIsBeaconRequest())
{
if (macState.bits.bIsAssociated)
{
MACSendBeacon();
}
MACDiscardRx();
}
// New associations are allowed only if it is permitted by application.
else if (MACIsAssocRequest())
{
if ( !MACProcessAssociation() )
{
MACDiscardRx();
}
else {
MACDiscardRx();
//du macInfo.shortAddr接收被忽略
MACSendAssociateResponse(&macInfo.shortAddr, MAC_ASSOCIATE_SUCCESS);
}
}
// Orphan can be rejoined only after we have established new network.
else if ( MACIsOrphanNotice() )
{
if ( macState.bits.bIsAssociated )
{
if ( !MACProcessOrphanNotice() )
MACDiscardRx();
else {
MACDiscardRx();
//du macInfo.shortAddr接收被忽略
MACSendRealignment(&macInfo.shortAddr, FALSE);
}
}
else
MACDiscardRx();
}
else if ( MACIsDisassocNotice() )
{
#ifdef I_AM_COORDINATOR
if ( !MACProcessDisassociation() )
MACDiscardRx();
else {
MACDiscardRx();
}
#endif
#ifdef I_AM_END_DEVICE
//The coordinator or router I am associated to has asked
//me to leave.
//MLME-DISASSOCIATION.indication
macState.bits.bIsAssociated = FALSE;
// Forget PAN ID.
MACSetPANIdLSB(0xff);
MACSetPANIdMSB(0xff);
// Update the transceiver
MACUpdateAddressInfo();
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 = PHYGet();
// 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 = PHYGet();
// 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 = PHYGet();
// 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 = PHYGet();
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 = PHYGet();
macCurrentFrame.dst.panID.byte.MSB = PHYGet();
macCurrentFrame.frameLength -= 2;
}
// Fetch destination address according to its type
if ( macCurrentFrame.dst.addrMode == MAC_DST_SHORT_ADDR )
{
macCurrentFrame.dst.shortAddr.byte.LSB = PHYGet();
macCurrentFrame.dst.shortAddr.byte.MSB = PHYGet();
macCurrentFrame.frameLength -= 2;
}
else if ( macCurrentFrame.dst.addrMode == MAC_DST_LONG_ADDR )
{
macCurrentFrame.dst.longAddr.v[0] = PHYGet();
macCurrentFrame.dst.longAddr.v[1] = PHYGet();
macCurrentFrame.dst.longAddr.v[2] = PHYGet();
macCurrentFrame.dst.longAddr.v[3] = PHYGet();
macCurrentFrame.dst.longAddr.v[4] = PHYGet();
macCurrentFrame.dst.longAddr.v[5] = PHYGet();
macCurrentFrame.dst.longAddr.v[6] = PHYGet();
macCurrentFrame.dst.longAddr.v[7] = PHYGet();
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 = PHYGet();
macCurrentFrame.src.panID.byte.MSB = PHYGet();
macCurrentFrame.frameLength -= 2;
}
// Fetch source address according to its type
if ( macCurrentFrame.src.addrMode == MAC_SRC_SHORT_ADDR )
{
macCurrentFrame.src.shortAddr.byte.LSB = PHYGet();
macCurrentFrame.src.shortAddr.byte.MSB = PHYGet();
macCurrentFrame.frameLength -= 2;
}
else if ( macCurrentFrame.src.addrMode == MAC_SRC_LONG_ADDR )
{
macCurrentFrame.src.longAddr.v[0] = PHYGet();
macCurrentFrame.src.longAddr.v[1] = PHYGet();
macCurrentFrame.src.longAddr.v[2] = PHYGet();
macCurrentFrame.src.longAddr.v[3] = PHYGet();
macCurrentFrame.src.longAddr.v[4] = PHYGet();
macCurrentFrame.src.longAddr.v[5] = PHYGet();
macCurrentFrame.src.longAddr.v[6] = PHYGet();
macCurrentFrame.src.longAddr.v[7] = PHYGet();
macCurrentFrame.frameLength -= 8;
}
// If this is a command frame, extract and save command id.
if ( macCurrentFrame.type == MAC_FRAME_CMD )
{
macCurrentFrame.frameLength--;
macCurrentFrame.cmd = PHYGet();
}
#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;
}
#if defined(I_AM_END_DEVICE)
/*********************************************************************
* 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.
********************************************************************/
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;
}
/*********************************************************************
* 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.
********************************************************************/
BOOL MACIsAssociationComplete(void)
{
BOOL result = FALSE;
MAC_ASSOCIATE_STATUS macAssociationStatus;
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;
//du macCoordInfo 不一定是真正的Coord
MACPutHeader(&macCoordInfo,
MAC_FRAME_CMD |
MAC_SECURITY |
MAC_FRAME_PENDING_NO |
MAC_ACK_YES|
MAC_INTRA_PAN_NO);
PHYBeginTxFIFOAccess();
PHYPutTxData(MAC_CMD_ASSOCIATE_REQ);
PHYPutTxData(0x00); //MAC_CAP_INFO,接收忽略
PHYEndTxFIFOAccess();
macPacketLen += 2;
hFrame = MACFlush();
ConsolePutString("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);
ConsolePutString("MAC: MACIsAssociated(): Valid ACK received, asking for response...\r\n");
smAssociation = SM_WAIT_FOR_ASSOC_RESP;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -