📄 mac_rx.c
字号:
pRxBuf->mac.srcAddr.addr.shortAddr = BUILD_UINT16(p[0], p[1]);
}
}
/*-------------------------------------------------------------------------------
* Prepare for payload interrupts.
*/
pFuncRxState = &rxPayloadIsr;
rxPrepPayload();
}
/*=================================================================================================
* @fn rxPrepPayload
*
* @brief Common code to prepare for the payload ISR.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxPrepPayload(void)
{
if (rxPayloadLen == 0)
{
MAC_RADIO_SET_RX_THRESHOLD(MAC_FCS_FIELD_LEN);
pFuncRxState = &rxFcsIsr;
}
else
{
rxNextLen = MIN(rxPayloadLen, MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT);
MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
}
}
/*=================================================================================================
* @fn rxPayloadIsr
*
* @brief Receive ISR state for reading out and storing the packet payload.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxPayloadIsr(void)
{
MAC_RADIO_READ_RX_FIFO(pRxBuf->msdu.p, rxNextLen);
pRxBuf->msdu.p += rxNextLen;
rxPayloadLen -= rxNextLen;
rxPrepPayload();
}
/*=================================================================================================
* @fn rxFcsIsr
*
* @brief Receive ISR state for handling the FCS.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxFcsIsr(void)
{
uint8 crcOK;
/* read FCS, rxBuf is now available storage */
MAC_RADIO_READ_RX_FIFO(rxBuf, MAC_FCS_FIELD_LEN);
/*
* The FCS has actually been replaced within the radio by a proprietary version of the FCS.
* This proprietary FCS is two bytes (same length as the real FCS) and contains:
* 1) the RSSI value
* 2) the average correlation value (used for LQI)
* 3) a CRC passed bit
*/
/* save the "CRC-is-OK" status */
crcOK = PROPRIETARY_FCS_CRC_OK(rxBuf);
/*
* See if the frame should be passed up to high-level MAC. If the CRC is OK, the
* the frame is always passed up. Frames with a bad CRC are also passed up *if*
* a special variant of promiscuous mode is active.
*/
if (crcOK || (rxPromiscuousMode == MAC_PROMISCUOUS_MODE_WITH_BAD_CRC))
{
int8 rssiDbm;
uint8 corr;
/*
* As power saving optimization, set state variable to indicate physical receive
* has completed and then request turning of the receiver. This means the receiver
* can be off (if other conditions permit) during execution of the callback function.
*
* The receiver will be requested to turn off once again at the end of the receive
* logic. There is no harm in doing this.
*/
macRxActive = MAC_RX_ACTIVE_DONE;
macRxOffRequest();
/* decode RSSI and correlation values */
rssiDbm = PROPRIETARY_FCS_RSSI(rxBuf) + MAC_RADIO_RSSI_OFFSET;
corr = PROPRIETARY_FCS_CORRELATION_VALUE(rxBuf);
/* record parameters that get passed up to high-level */
pRxBuf->internal.flags |= crcOK;
pRxBuf->mac.mpduLinkQuality = macRadioComputeLQI(rssiDbm, corr);
pRxBuf->mac.rssi = rssiDbm;
pRxBuf->mac.correlation = corr;
/* set the MSDU pointer to point at start of data */
pRxBuf->msdu.p = (uint8 *) (pRxBuf + 1);
/* finally... execute callback function */
macRxCompleteCallback(pRxBuf);
pRxBuf = NULL; /* needed to indicate buffer is no longer allocated */
}
else
{
/*
* The CRC is bad so no ACK was sent. Cancel any callback and clear the flag.
* (It's OK to cancel the outgoing ACK even if an ACK was not requested. It's
* slightly more efficient to do so.)
*/
MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();
macRxOutgoingAckFlag = 0;
/* the CRC failed so the packet must be discarded */
MEM_FREE((uint8 *) pRxBuf);
pRxBuf = NULL; /* needed to indicate buffer is no longer allocated */
}
/* reset threshold level, reset receive state, and complete receive logic */
MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);
pFuncRxState = &rxStartIsr;
rxDone();
}
/*=================================================================================================
* @fn rxDone
*
* @brief Common exit point for receive.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxDone(void)
{
/* if the receive FIFO has overflowed, flush it here */
if (MAC_RADIO_RX_FIFO_HAS_OVERFLOWED())
{
MAC_RADIO_FLUSH_RX_FIFO();
}
/* mark receive as inactive */
macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;
/* if there is no outgoing ACK, run the post receive updates */
if (!macRxOutgoingAckFlag)
{
rxPostRxUpdates();
}
}
/**************************************************************************************************
* @fn macRxAckTxDoneCallback
*
* @brief Function called when the outoing ACK has completed transmitting.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxAckTxDoneCallback(void)
{
macRxOutgoingAckFlag = 0;
/*
* With certain interrupt priorities and timing conditions, it is possible this callback
* could be executed before the primary receive logic completes. To prevent this, the
* post updates are only executed if receive logic is no longer active. In the case the
* post updates are not executed here, they will execute when the main receive logic
* completes.
*/
if (!macRxActive)
{
rxPostRxUpdates();
}
}
/*=================================================================================================
* @fn rxPostRxUpdates
*
* @brief Updates that need to be performed once receive is complete.
*
* It is not fatal to execute this function if somehow receive is active. Under
* certain timing/interrupt conditions a new receive may have started before this
* function executes. This should happen very rarely (if it happens at all) and
* would cause no problems.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxPostRxUpdates(void)
{
/* turn off receiver if permitted */
macRxOffRequest();
/* update the transmit power, update may have been blocked by transmit of outgoing ACK */
macRadioUpdateTxPower();
/* initiate and transmit that was queued during receive */
macTxStartQueuedFrame();
}
/*=================================================================================================
* @fn rxDiscardFrame
*
* @brief Initializes for discarding a packet. Must be called before ACK is strobed.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxDiscardFrame(void)
{
MAC_ASSERT(pFuncRxState == &rxStartIsr); /* illegal state for calling discard frame function */
if (rxUnreadLen == 0)
{
rxDone();
}
else
{
rxNextLen = MIN(rxUnreadLen, MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT);
MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
pFuncRxState = &rxDiscardIsr;
}
}
/*=================================================================================================
* @fn rxDiscardIsr
*
* @brief Receive ISR state for discarding a packet.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxDiscardIsr(void)
{
uint8 buf[MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT];
MAC_RADIO_READ_RX_FIFO(buf, rxNextLen);
rxUnreadLen -= rxNextLen;
/* read out and discard bytes until all bytes of packet are disposed of */
if (rxUnreadLen != 0)
{
if (rxUnreadLen < MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT)
{
rxNextLen = rxUnreadLen;
MAC_RADIO_SET_RX_THRESHOLD(rxNextLen);
}
}
else
{
/* reset threshold level, reset receive state, and complete receive logic */
MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);
pFuncRxState = &rxStartIsr;
rxDone();
}
}
/**************************************************************************************************
* @fn macRxPromiscuousMode
*
* @brief Sets promiscuous mode - enabling or disabling it.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxPromiscuousMode(uint8 mode)
{
rxPromiscuousMode = mode;
if (rxPromiscuousMode == MAC_PROMISCUOUS_MODE_OFF)
{
MAC_RADIO_TURN_ON_RX_FRAME_FILTERING();
}
else
{
MAC_ASSERT((mode == MAC_PROMISCUOUS_MODE_WITH_BAD_CRC) ||
(mode == MAC_PROMISCUOUS_MODE_COMPLIANT)); /* invalid mode */
MAC_RADIO_TURN_OFF_RX_FRAME_FILTERING();
}
}
/**************************************************************************************************
* Compile Time Integrity Checks
**************************************************************************************************
*/
/* check for changes to the spec that would affect the source code */
#if ((MAC_A_MAX_PHY_PACKET_SIZE != 0x7F ) || \
(MAC_FCF_FIELD_LEN != 2 ) || \
(MAC_FCF_FRAME_TYPE_POS != 0 ) || \
(MAC_FCF_FRAME_PENDING_POS != 4 ) || \
(MAC_FCF_ACK_REQUEST_POS != 5 ) || \
(MAC_FCF_INTRA_PAN_POS != 6 ) || \
(MAC_FCF_DST_ADDR_MODE_POS != 10 ) || \
(MAC_FCF_FRAME_VERSION_POS != 12 ) || \
(MAC_FCF_SRC_ADDR_MODE_POS != 14 ))
#error "ERROR! Change to the spec that requires modification of source code."
#endif
/* check for changes to the internal flags format */
#if ((MAC_RX_FLAG_VERSION != 0x03) || \
(MAC_RX_FLAG_ACK_PENDING != 0x04) || \
(MAC_RX_FLAG_SECURITY != 0x08) || \
(MAC_RX_FLAG_PENDING != 0x10) || \
(MAC_RX_FLAG_ACK_REQUEST != 0x20) || \
(MAC_RX_FLAG_INTRA_PAN != 0x40))
#error "ERROR! Change to the internal RX flags format. Requires modification of source code."
#endif
/* validate CRC OK bit optimization */
#if (MAC_RX_FLAG_CRC_OK != PROPRIETARY_FCS_CRC_OK_BIT)
#error "ERROR! Optimization relies on these bits having the same position."
#endif
#if (MAC_RX_ACTIVE_NO_ACTIVITY != 0x00)
#error "ERROR! Zero is reserved value of macRxActive. Allows boolean operations, e.g !macRxActive."
#endif
#if (MAC_PROMISCUOUS_MODE_OFF != 0x00)
#error "ERROR! Zero is reserved value of rxPromiscuousMode. Allows boolean operations, e.g !rxPromiscuousMode."
#endif
/**************************************************************************************************
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -