📄 mac_rx.c
字号:
/**************************************************************************************************
Filename:
Revised: $Date: 2007-03-28 18:21:19 -0700 (Wed, 28 Mar 2007) $
Revision: $Revision: 13888 $
Description:
Describe the purpose and contents of the file.
Copyright (c) 2006 by Texas Instruments, Inc.
All Rights Reserved. Permission to use, reproduce, copy, prepare
derivative works, modify, distribute, perform, display or sell this
software and/or its documentation for any purpose is prohibited
without the express written consent of Texas Instruments, Inc.
**************************************************************************************************/
/* ------------------------------------------------------------------------------------------------
* Includes
* ------------------------------------------------------------------------------------------------
*/
/* hal */
#include "hal_defs.h"
#include "hal_types.h"
/* high-level */
#include "mac_high_level.h"
#include "mac_spec.h"
/* exported low-level */
#include "mac_low_level.h"
/* low-level specific */
#include "mac_rx.h"
#include "mac_tx.h"
#include "mac_rx_onoff.h"
#include "mac_radio.h"
/* target specific */
#include "mac_radio_defs.h"
/* debug */
#include "mac_assert.h"
/* ------------------------------------------------------------------------------------------------
* Defines
* ------------------------------------------------------------------------------------------------
*/
#define MAX_PAYLOAD_BYTES_READ_PER_INTERRUPT 16 /* adjustable to tune performance */
/* receive FIFO bytes needed to start a valid receive (see function rxStartIsr for details) */
#define RX_THRESHOLD_START_LEN (MAC_PHY_PHR_LEN + \
MAC_FCF_FIELD_LEN + \
MAC_SEQ_NUM_FIELD_LEN + \
MAC_FCS_FIELD_LEN)
/* maximum size of addressing fields (note: command frame identifier processed as part of address) */
#define MAX_ADDR_FIELDS_LEN ((MAC_EXT_ADDR_FIELD_LEN + MAC_PAN_ID_FIELD_LEN) * 2)
/* addressing mode reserved value */
#define ADDR_MODE_RESERVERED 1
/* length of command frame identifier */
#define CMD_FRAME_ID_LEN 1
/* packet size mask is equal to the maximum value */
#define PHY_PACKET_SIZE_MASK 0x7F
/* value for promiscuous off, must not conflict with other mode variants from separate include files */
#define PROMISCUOUS_MODE_OFF 0x00
/* bit of proprietary FCS format that indicates if the CRC is OK */
#define PROPRIETARY_FCS_CRC_OK_BIT 0x80
/* dummy length value for unused entry in lookup table */
#define DUMMY_LEN 0xBE
/* value for rxThresholdIntState */
#define RX_THRESHOLD_INT_STATE_INACTIVE 0
#define RX_THRESHOLD_INT_STATE_ACTIVE 1
#define RX_THRESHOLD_INT_STATE_RESET 2
/* ------------------------------------------------------------------------------------------------
* Macros
* ------------------------------------------------------------------------------------------------
*/
#define MEM_ALLOC(x) macDataRxMemAlloc(x)
#define MEM_FREE(x) macDataRxMemFree((uint8 *)x)
/*
* Macro for encoding frame control information into internal flags format.
* Parameter is pointer to the frame. NOTE! If either the internal frame
* format *or* the specification changes, this macro will need to be modified.
*/
#define INTERNAL_FCF_FLAGS(p) ((((p)[1] >> 4) & 0x03) | ((p)[0] & 0x78))
/*
* The radio replaces the actual FCS with different information. This proprietary FCS is
* the same length as the original and includes:
* 1) the RSSI value
* 2) the average correlation value (used for LQI)
* 3) a CRC passed bit
*
* These macros decode the proprietary FCS. The macro parameter is a pointer to the two byte FCS.
*/
#define PROPRIETARY_FCS_RSSI(p) ((int8)((p)[0]))
#define PROPRIETARY_FCS_CRC_OK(p) ((p)[1] & PROPRIETARY_FCS_CRC_OK_BIT)
#define PROPRIETARY_FCS_CORRELATION_VALUE(p) ((p)[1] & ~PROPRIETARY_FCS_CRC_OK_BIT)
/* ------------------------------------------------------------------------------------------------
* Global Variables
* ------------------------------------------------------------------------------------------------
*/
uint8 macRxActive;
uint8 macRxFilter;
uint8 macRxOutgoingAckFlag;
/* ------------------------------------------------------------------------------------------------
* Local Constants
* ------------------------------------------------------------------------------------------------
*/
static const uint8 CODE macRxAddrLen[] =
{
0, /* no address */
DUMMY_LEN, /* reserved */
MAC_PAN_ID_FIELD_LEN + MAC_SHORT_ADDR_FIELD_LEN, /* short address + pan id */
MAC_PAN_ID_FIELD_LEN + MAC_EXT_ADDR_FIELD_LEN /* extended address + pan id */
};
/* ------------------------------------------------------------------------------------------------
* Local Prototypes
* ------------------------------------------------------------------------------------------------
*/
static void rxHaltCleanupFinalStep(void);
static void rxStartIsr(void);
static void rxAddrIsr(void);
static void rxPayloadIsr(void);
static void rxDiscardIsr(void);
static void rxFcsIsr(void);
static void rxPrepPayload(void);
static void rxDiscardFrame(void);
static void rxDone(void);
static void rxPostRxUpdates(void);
/* ------------------------------------------------------------------------------------------------
* Local Variables
* ------------------------------------------------------------------------------------------------
*/
static void (* pFuncRxState)(void);
static macRx_t * pRxBuf;
static uint8 rxBuf[MAC_PHY_PHR_LEN + MAC_FCF_FIELD_LEN + MAC_SEQ_NUM_FIELD_LEN];
static uint8 rxUnreadLen;
static uint8 rxNextLen;
static uint8 rxPayloadLen;
static uint8 rxFilter;
static uint8 rxPromiscuousMode;
static uint8 rxIsrActiveFlag;
static uint8 rxResetFlag;
/**************************************************************************************************
* @fn macRxInit
*
* @brief Initialize receive variable states.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxInit(void)
{
macRxFilter = RX_FILTER_OFF;
rxPromiscuousMode = PROMISCUOUS_MODE_OFF;
pRxBuf = NULL; /* required for macRxReset() to function correctly */
macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;
pFuncRxState = &rxStartIsr;
macRxOutgoingAckFlag = 0;
rxIsrActiveFlag = 0;
rxResetFlag = 0;
}
/**************************************************************************************************
* @fn macRxRadioPowerUpInit
*
* @brief Initialization for after radio first powers up.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxRadioPowerUpInit(void)
{
/* set threshold at initial value */
MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);
/* clear any accidental threshold interrupt that happened as part of power up sequence */
MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG();
/* enable threshold interrupts */
MAC_RADIO_ENABLE_RX_THRESHOLD_INTERRUPT();
}
/**************************************************************************************************
* @fn macRxTxReset
*
* @brief Reset the receive state.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxTxReset(void)
{
/* forces receiver off, cleans up by calling macRxHaltCleanup() and macTxHaltCleanup() */
macRxHardDisable();
/*
* Note : transmit does not require any reset logic
* beyond what macRxHardDisable() provides.
*/
/* restore deault filter mode to off */
macRxFilter = RX_FILTER_OFF;
/* return promiscuous mode to default off state */
macRxPromiscuousMode(MAC_PROMISCUOUS_MODE_OFF);
}
/**************************************************************************************************
* @fn macRxHaltCleanup
*
* @brief Cleanup up the receive logic after receiver is forced off.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxHaltCleanup(void)
{
rxResetFlag = 1;
if (!rxIsrActiveFlag)
{
rxHaltCleanupFinalStep();
rxResetFlag = 0;
}
}
/*=================================================================================================
* @fn rxHaltCleanupFinalStep
*
* @brief Required cleanup if receiver is halted in the middle of a receive.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxHaltCleanupFinalStep(void)
{
/* cancel any upcoming ACK transmit complete callback */
MAC_RADIO_CANCEL_ACK_TX_DONE_CALLBACK();
/* set start of frame threshold */
MAC_RADIO_SET_RX_THRESHOLD(RX_THRESHOLD_START_LEN);
/* flush the receive FIFO */
MAC_RADIO_FLUSH_RX_FIFO();
/* clear any receive interrupt that happened to squeak through */
MAC_RADIO_CLEAR_RX_THRESHOLD_INTERRUPT_FLAG();
/* if data buffer has been allocated, free it */
if (pRxBuf != NULL)
{
MEM_FREE((uint8 *) pRxBuf);
}
pRxBuf = NULL; /* needed to indicate buffer is no longer allocated */
pFuncRxState = &rxStartIsr;
/* if receive was active, perform the post receive updates */
if (macRxActive || macRxOutgoingAckFlag)
{
macRxActive = MAC_RX_ACTIVE_NO_ACTIVITY;
macRxOutgoingAckFlag = 0;
rxPostRxUpdates();
}
}
/**************************************************************************************************
* @fn macRxThresholdIsr
*
* @brief Interrupt service routine called when bytes in FIFO reach threshold value.
* It implements a state machine for receiving a packet.
*
* @param none
*
* @return none
**************************************************************************************************
*/
void macRxThresholdIsr(void)
{
/* if currently reseting, do not execute receive ISR logic */
if (rxResetFlag)
{
return;
}
/*
* Call the function that handles the current receive state.
* A flag is set for the duration of the call to indicate
* the ISR is executing. This is necessary for the reset
* logic so it does not perform a reset in the middle of
* executing the ISR.
*/
rxIsrActiveFlag = 1;
(*pFuncRxState)();
rxIsrActiveFlag = 0;
/* if a reset occurred during the ISR, peform cleanup here */
if (rxResetFlag)
{
rxHaltCleanupFinalStep();
rxResetFlag = 0;
}
}
/*=================================================================================================
* @fn rxStartIsr
*
* @brief First ISR state for receiving a packet - compute packet length, allocate
* buffer, initialize buffer. Acknowledgements are handled immediately without
* allocating a buffer.
*
* @param none
*
* @return none
*=================================================================================================
*/
static void rxStartIsr(void)
{
uint8 addrLen;
uint8 ackWithPending;
uint8 dstAddrMode;
uint8 srcAddrMode;
MAC_ASSERT(!macRxActive); /* receive on top of receive */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -