mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 15:17:47 +00:00
[cc2652] refactored polling loop and propagated ack frames (#2080)
Updated cc2650 and cc2652 platforms to place ieee ack frame types in the RX queue and to propagate those frames to the higher level. Initialize extra RX buffers.
This commit is contained in:
committed by
Jonathan Hui
parent
e875f5e86f
commit
6e8aef9644
@@ -35,7 +35,6 @@ enum
|
||||
{
|
||||
IEEE802154_FRAME_TYPE_MASK = 0x7, ///< (IEEE 802.15.4-2006) PSDU.FCF.frameType
|
||||
IEEE802154_FRAME_TYPE_ACK = 0x2, ///< (IEEE 802.15.4-2006) frame type: ACK
|
||||
IEEE802154_FRAME_PENDING = (1<<4), ///< (IEEE 802.15.4-2006) PSDU.FCF.bFramePending
|
||||
IEEE802154_ACK_REQUEST = (1<<5), ///< (IEEE 802.15.4-2006) PSDU.FCF.bAR
|
||||
IEEE802154_DSN_OFFSET = 2, ///< (IEEE 802.15.4-2006) PSDU.sequenceNumber
|
||||
IEEE802154_MAC_MIN_BE = 1, ///< (IEEE 802.15.4-2006) macMinBE
|
||||
@@ -155,19 +154,19 @@ typedef enum cc2650_address
|
||||
* The following are valid radio state transitions for the cc2650:
|
||||
*
|
||||
* (Radio ON)
|
||||
* +----------+ Enable() +-------+ Receive() +---------+ Transmit() +----------+
|
||||
* | |----------->| |------------->| |-------------->| |
|
||||
* | Disabled | | Sleep | | Receive | | Transmit |
|
||||
* | |<-----------| |<-------------| |<--------------| |
|
||||
* +----------+ Disable() | | Sleep() | |<-- Receive() +----------+
|
||||
* | | (Radio OFF) +---------+ \ | transmit
|
||||
* | | \-----\ | complete
|
||||
* | | EnergyScan() +--------+ | V
|
||||
* | |------------->| | +------------------+
|
||||
* | | | EdScan | | |
|
||||
* | |<-------------| | | TransmitComplete |
|
||||
* | | signal ED | | | |
|
||||
* +-------+ scan done +--------+ +------------------+
|
||||
* +----------+ Enable() +-------+ Receive() +---------+ Transmit() +----------+
|
||||
* | |----------->| |------------->| |--------------->| |
|
||||
* | Disabled | | Sleep | | Receive | | Transmit |
|
||||
* | |<-----------| |<-------------| |<---------------| |
|
||||
* +----------+ Disable() | | Sleep() | | AckFrame RX or +----------+
|
||||
* | | (Radio OFF) +---------+ sTxCmdChainDone == true
|
||||
* | |
|
||||
* | | EnergyScan() +--------+
|
||||
* | |------------->| |
|
||||
* | | | EdScan |
|
||||
* | |<-------------| |
|
||||
* | | signal ED | |
|
||||
* +-------+ scan done +--------+
|
||||
*
|
||||
* These states slightly differ from the states in \ref include/platform/radio.h.
|
||||
* The additional states the phy can be in are due to the asynchronous nature
|
||||
@@ -192,7 +191,6 @@ typedef enum cc2650_PhyState
|
||||
cc2650_stateReceive,
|
||||
cc2650_stateEdScan,
|
||||
cc2650_stateTransmit,
|
||||
cc2650_stateTransmitComplete,
|
||||
} cc2650_PhyState;
|
||||
|
||||
#endif /* CC2650_RADIO_H_ */
|
||||
|
||||
+251
-259
@@ -51,7 +51,6 @@
|
||||
|
||||
enum
|
||||
{
|
||||
IEEE802154_ACK_LENGTH = 5,
|
||||
CC2650_RECEIVE_SENSITIVITY = -100, // dBm
|
||||
};
|
||||
|
||||
@@ -77,55 +76,50 @@ static uint32_t sIEEEOverrides[] =
|
||||
};
|
||||
|
||||
/*
|
||||
* status of the pending bit of the last ack packet found by the
|
||||
* sTransmitRxAckCmd radio command
|
||||
* Number of retry counts left to the currently transmitting frame.
|
||||
*
|
||||
* used to pass data from the radio state ISR to the processing loop
|
||||
*/
|
||||
static volatile bool sReceivedAckPendingBit = false;
|
||||
|
||||
/*
|
||||
* number of retry counts left to the currently transmitting frame
|
||||
*
|
||||
* initialized when a frame is passed to be sent over the air, and decremented
|
||||
* Initialized when a frame is passed to be sent over the air, and decremented
|
||||
* by the radio ISR every time the transmit command string fails to receive a
|
||||
* corresponding ack
|
||||
* corresponding ack.
|
||||
*/
|
||||
static volatile unsigned int sTransmitRetryCount = 0;
|
||||
|
||||
/*
|
||||
* offset of the radio timer from the rtc
|
||||
* Offset of the radio timer from the rtc.
|
||||
*
|
||||
* used when we start and stop the RAT
|
||||
* Used when we start and stop the RAT on enabling and disabling of the rf
|
||||
* core.
|
||||
*/
|
||||
static uint32_t sRatOffset = 0;
|
||||
|
||||
/*
|
||||
* radio command structures that run on the CM0
|
||||
* Radio command structures that run on the CM0.
|
||||
*/
|
||||
static volatile rfc_CMD_SYNC_START_RAT_t sStartRatCmd;
|
||||
static volatile rfc_CMD_RADIO_SETUP_t sRadioSetupCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_SYNC_START_RAT_t sStartRatCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_RADIO_SETUP_t sRadioSetupCmd;
|
||||
|
||||
static volatile rfc_CMD_FS_POWERDOWN_t sFsPowerdownCmd;
|
||||
static volatile rfc_CMD_SYNC_STOP_RAT_t sStopRatCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_FS_POWERDOWN_t sFsPowerdownCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_SYNC_STOP_RAT_t sStopRatCmd;
|
||||
|
||||
static volatile rfc_CMD_CLEAR_RX_t sClearReceiveQueueCmd;
|
||||
static volatile rfc_CMD_IEEE_MOD_FILT_t sModifyReceiveFilterCmd;
|
||||
static volatile rfc_CMD_IEEE_MOD_SRC_MATCH_t sModifyReceiveSrcMatchCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_CLEAR_RX_t sClearReceiveQueueCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_MOD_FILT_t sModifyReceiveFilterCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_MOD_SRC_MATCH_t sModifyReceiveSrcMatchCmd;
|
||||
|
||||
static volatile rfc_CMD_IEEE_ED_SCAN_t sEdScanCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_ED_SCAN_t sEdScanCmd;
|
||||
|
||||
static volatile rfc_CMD_IEEE_RX_t sReceiveCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_RX_t sReceiveCmd;
|
||||
|
||||
static volatile rfc_CMD_IEEE_CSMA_t sCsmacaBackoffCmd;
|
||||
static volatile rfc_CMD_IEEE_TX_t sTransmitCmd;
|
||||
static volatile rfc_CMD_IEEE_RX_ACK_t sTransmitRxAckCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_CSMA_t sCsmacaBackoffCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_TX_t sTransmitCmd;
|
||||
static volatile __attribute__((aligned(4))) rfc_CMD_IEEE_RX_ACK_t sTransmitRxAckCmd;
|
||||
|
||||
static volatile ext_src_match_data_t sSrcMatchExtData;
|
||||
static volatile short_src_match_data_t sSrcMatchShortData;
|
||||
static volatile __attribute__((aligned(4))) ext_src_match_data_t sSrcMatchExtData;
|
||||
static volatile __attribute__((aligned(4))) short_src_match_data_t sSrcMatchShortData;
|
||||
|
||||
/* struct containing radio stats */
|
||||
static rfc_ieeeRxOutput_t sRfStats;
|
||||
/*
|
||||
* Structure containing radio statistics.
|
||||
*/
|
||||
static __attribute__((aligned(4))) rfc_ieeeRxOutput_t sRfStats;
|
||||
|
||||
#define RX_BUF_SIZE 144
|
||||
/* two receive buffers entries with room for 1 max IEEE802.15.4 frame in each */
|
||||
@@ -137,21 +131,20 @@ static dataQueue_t sRxDataQueue = { 0 };
|
||||
|
||||
/* openthread data primatives */
|
||||
static otRadioFrame sTransmitFrame;
|
||||
static otRadioFrame sReceiveFrame;
|
||||
static otError sTransmitError;
|
||||
static otError sReceiveError;
|
||||
|
||||
static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE] __attribute__((aligned(4))) ;
|
||||
static uint8_t sReceivePsdu[OT_RADIO_FRAME_MAX_SIZE] __attribute__((aligned(4))) ;
|
||||
static __attribute__((aligned(4))) uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
|
||||
/**
|
||||
* Interrupt handlers forward declared for register function
|
||||
static volatile bool sTxCmdChainDone = false;
|
||||
|
||||
/*
|
||||
* Interrupt handlers forward declared for register functions.
|
||||
*/
|
||||
void RFCCPE0IntHandler(void);
|
||||
void RFCCPE1IntHandler(void);
|
||||
|
||||
/**
|
||||
* @brief initialize the RX/TX buffers
|
||||
* Initialize the RX/TX buffers.
|
||||
*
|
||||
* Zeros out the receive and transmit buffers and sets up the data structures
|
||||
* of the receive queue.
|
||||
@@ -162,24 +155,22 @@ static void rfCoreInitBufs(void)
|
||||
memset(sRxBuf0, 0x00, RX_BUF_SIZE);
|
||||
memset(sRxBuf1, 0x00, RX_BUF_SIZE);
|
||||
|
||||
entry = (rfc_dataEntry_t *)sRxBuf0;
|
||||
entry->pNextEntry = sRxBuf1;
|
||||
entry = (rfc_dataEntry_t *)sRxBuf0;
|
||||
entry->pNextEntry = sRxBuf1;
|
||||
entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
|
||||
entry->length = sizeof(sRxBuf0) - sizeof(rfc_dataEntry_t);
|
||||
entry->length = sizeof(sRxBuf0) - sizeof(rfc_dataEntry_t);
|
||||
|
||||
entry = (rfc_dataEntry_t *)sRxBuf1;
|
||||
entry->pNextEntry = sRxBuf0;
|
||||
entry = (rfc_dataEntry_t *)sRxBuf1;
|
||||
entry->pNextEntry = sRxBuf0;
|
||||
entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
|
||||
entry->length = sizeof(sRxBuf0) - sizeof(rfc_dataEntry_t);
|
||||
entry->length = sizeof(sRxBuf1) - sizeof(rfc_dataEntry_t);
|
||||
|
||||
sTransmitFrame.mPsdu = sTransmitPsdu;
|
||||
sTransmitFrame.mPsdu = sTransmitPsdu;
|
||||
sTransmitFrame.mLength = 0;
|
||||
sReceiveFrame.mPsdu = sReceivePsdu;
|
||||
sReceiveFrame.mLength = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief initialize the RX command structure
|
||||
* Initialize the RX command structure.
|
||||
*
|
||||
* Sets the default values for the receive command structure.
|
||||
*/
|
||||
@@ -227,7 +218,7 @@ static void rfCoreInitReceiveParams(void)
|
||||
{
|
||||
.bAcceptFt0Beacon = 1,
|
||||
.bAcceptFt1Data = 1,
|
||||
.bAcceptFt2Ack = 0,
|
||||
.bAcceptFt2Ack = 1,
|
||||
.bAcceptFt3MacCmd = 1,
|
||||
.bAcceptFt4Reserved = 1,
|
||||
.bAcceptFt5Reserved = 1,
|
||||
@@ -263,10 +254,10 @@ static void rfCoreInitReceiveParams(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the direct abort command to the radio core
|
||||
* Sends the direct abort command to the radio core.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreExecuteAbortCmd(void)
|
||||
{
|
||||
@@ -274,12 +265,12 @@ static uint_fast8_t rfCoreExecuteAbortCmd(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the direct ping command to the radio core
|
||||
* Sends the direct ping command to the radio core.
|
||||
*
|
||||
* Check that the Radio core is alive and able to respond to commands.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreExecutePingCmd(void)
|
||||
{
|
||||
@@ -287,16 +278,16 @@ static uint_fast8_t rfCoreExecutePingCmd(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the immediate clear rx queue command to the radio core
|
||||
* Sends the immediate clear rx queue command to the radio core.
|
||||
*
|
||||
* Uses the radio core to mark all of the entries in the receive queue as
|
||||
* pending. This is used instead of clearing the entries manually to avoid race
|
||||
* conditions between the main processor and the radio core.
|
||||
*
|
||||
* @param [in] aQueue a pointer to the receive queue to be cleared
|
||||
* @param [in] aQueue A pointer to the receive queue to be cleared.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreClearReceiveQueue(dataQueue_t *aQueue)
|
||||
{
|
||||
@@ -308,7 +299,7 @@ static uint_fast8_t rfCoreClearReceiveQueue(dataQueue_t *aQueue)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enable/disable filtering
|
||||
* Enable/disable frame filtering.
|
||||
*
|
||||
* Uses the radio core to alter the current running RX command filtering
|
||||
* options. This ensures there is no access fault between the CM3 and CM0 for
|
||||
@@ -319,10 +310,11 @@ static uint_fast8_t rfCoreClearReceiveQueue(dataQueue_t *aQueue)
|
||||
*
|
||||
* @note An IEEE RX command *must* be running while this command executes.
|
||||
*
|
||||
* @param [in] aEnable TRUE: enable frame filtering, FALSE: disable frame filtering
|
||||
* @param [in] aEnable TRUE: enable frame filtering,
|
||||
* FALSE: disable frame filtering.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreModifyRxFrameFilter(bool aEnable)
|
||||
{
|
||||
@@ -340,7 +332,7 @@ static uint_fast8_t rfCoreModifyRxFrameFilter(bool aEnable)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enable/disable autoPend
|
||||
* Enable/disable autoPend feature.
|
||||
*
|
||||
* Uses the radio core to alter the current running RX command filtering
|
||||
* options. This ensures there is no access fault between the CM3 and CM0 for
|
||||
@@ -351,10 +343,11 @@ static uint_fast8_t rfCoreModifyRxFrameFilter(bool aEnable)
|
||||
*
|
||||
* @note An IEEE RX command *must* be running while this command executes.
|
||||
*
|
||||
* @param [in] aEnable TRUE: enable autoPend, FALSE: disable autoPend
|
||||
* @param [in] aEnable TRUE: enable autoPend,
|
||||
* FALSE: disable autoPend.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreModifyRxAutoPend(bool aEnable)
|
||||
{
|
||||
@@ -372,7 +365,7 @@ static uint_fast8_t rfCoreModifyRxAutoPend(bool aEnable)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the immediate modify source matching command to the radio core
|
||||
* Sends the immediate modify source matching command to the radio core.
|
||||
*
|
||||
* Uses the radio core to alter the current source matching parameters used by
|
||||
* the running RX command. This ensures there is no access fault between the
|
||||
@@ -382,12 +375,13 @@ static uint_fast8_t rfCoreModifyRxAutoPend(bool aEnable)
|
||||
*
|
||||
* @note An IEEE RX command *must* be running while this command executes.
|
||||
*
|
||||
* @param [in] aEntryNo the index of the entry to alter
|
||||
* @param [in] aType TRUE: the entry is a short address, FALSE: the entry is an extended address
|
||||
* @param [in] aEnable whether the given entry is to be enabled or disabled
|
||||
* @param [in] aEntryNo The index of the entry to alter.
|
||||
* @param [in] aType TRUE: the entry is a short address,
|
||||
* FALSE: the entry is an extended address.
|
||||
* @param [in] aEnable Whether the given entry is to be enabled or disabled.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreModifySourceMatchEntry(uint8_t aEntryNo, cc2650_address_t aType, bool aEnable)
|
||||
{
|
||||
@@ -420,105 +414,113 @@ static uint_fast8_t rfCoreModifySourceMatchEntry(uint8_t aEntryNo, cc2650_addres
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief walks the short address source match list to find an address
|
||||
* Walks the short address source match list to find an address.
|
||||
*
|
||||
* @param [in] address the short address to search for
|
||||
* @param [in] aAddress The short address to search for.
|
||||
*
|
||||
* @return the index where the address was found
|
||||
* @retval CC2650_SRC_MATCH_NONE the address was not found
|
||||
* @return The index where the address was found.
|
||||
* @retval CC2650_SRC_MATCH_NONE The address was not found.
|
||||
*/
|
||||
static uint8_t rfCoreFindShortSrcMatchIdx(const uint16_t aAddress)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t ret = CC2650_SRC_MATCH_NONE;
|
||||
|
||||
for (i = 0; i < CC2650_SHORTADD_SRC_MATCH_NUM; i++)
|
||||
{
|
||||
if (sSrcMatchShortData.extAddrEnt[i].shortAddr == aAddress)
|
||||
{
|
||||
return i;
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CC2650_SRC_MATCH_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief walks the short address source match list to find an empty slot
|
||||
* Walks the short address source match list to find an empty slot.
|
||||
*
|
||||
* @return the index of an unused address slot
|
||||
* @retval CC2650_SRC_MATCH_NONE no unused slots available
|
||||
* @return The index of an unused address slot.
|
||||
* @retval CC2650_SRC_MATCH_NONE No unused slots available.
|
||||
*/
|
||||
static uint8_t rfCoreFindEmptyShortSrcMatchIdx(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t ret = CC2650_SRC_MATCH_NONE;
|
||||
|
||||
for (i = 0; i < CC2650_SHORTADD_SRC_MATCH_NUM; i++)
|
||||
{
|
||||
if ((sSrcMatchShortData.srcMatchEn[i / 32] & (1 << (i % 32))) == 0u)
|
||||
{
|
||||
return i;
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CC2650_SRC_MATCH_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief walks the ext address source match list to find an address
|
||||
* Walks the extended address source match list to find an address.
|
||||
*
|
||||
* @param [in] address the ext address to search for
|
||||
* @param [in] aAddress The extended address to search for.
|
||||
*
|
||||
* @return the index where the address was found
|
||||
* @retval CC2650_SRC_MATCH_NONE the address was not found
|
||||
* @return The index where the address was found.
|
||||
* @retval CC2650_SRC_MATCH_NONE The address was not found.
|
||||
*/
|
||||
static uint8_t rfCoreFindExtSrcMatchIdx(const uint64_t *aAddress)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t ret = CC2650_SRC_MATCH_NONE;
|
||||
|
||||
for (i = 0; i < CC2650_EXTADD_SRC_MATCH_NUM; i++)
|
||||
{
|
||||
if (sSrcMatchExtData.extAddrEnt[i] == *aAddress)
|
||||
{
|
||||
return i;
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CC2650_SRC_MATCH_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief walks the ext address source match list to find an empty slot
|
||||
* Walks the extended address source match list to find an empty slot.
|
||||
*
|
||||
* @return the index of an unused address slot
|
||||
* @retval CC2650_SRC_MATCH_NONE no unused slots available
|
||||
* @return The index of an unused address slot.
|
||||
* @retval CC2650_SRC_MATCH_NONE No unused slots available.
|
||||
*/
|
||||
static uint8_t rfCoreFindEmptyExtSrcMatchIdx(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t ret = CC2650_SRC_MATCH_NONE;
|
||||
|
||||
for (i = 0; i < CC2650_EXTADD_SRC_MATCH_NUM; i++)
|
||||
{
|
||||
if ((sSrcMatchExtData.srcMatchEn[i / 32] & (1 << (i % 32))) != 0u)
|
||||
{
|
||||
return i;
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CC2650_SRC_MATCH_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the tx command to the radio core
|
||||
* Sends the tx command to the radio core.
|
||||
*
|
||||
* Sends the packet to the radio core to be sent asynchronously.
|
||||
*
|
||||
* @param [in] aPsdu a pointer to the data to be sent
|
||||
* @note this *must* be 4 byte aligned and not include the FCS, that is
|
||||
* calculated in hardware.
|
||||
* @param [in] aLen the length in bytes of data pointed to by psdu.
|
||||
* @note @ref aPsdu *must* be 4 byte aligned and not include the FCS.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @param [in] aPsdu A pointer to the data to be sent.
|
||||
* @param [in] aLen The length in bytes of data pointed to by PSDU.
|
||||
*
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreSendTransmitCmd(uint8_t *aPsdu, uint8_t aLen)
|
||||
{
|
||||
@@ -612,7 +614,7 @@ static uint_fast8_t rfCoreSendTransmitCmd(uint8_t *aPsdu, uint8_t aLen)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the rx command to the radio core
|
||||
* Sends the rx command to the radio core.
|
||||
*
|
||||
* Sends the pre-built receive command to the radio core. This sets up the
|
||||
* radio to receive packets according to the settings in the global rx command.
|
||||
@@ -621,8 +623,8 @@ static uint_fast8_t rfCoreSendTransmitCmd(uint8_t *aPsdu, uint8_t aLen)
|
||||
* It is only concerned with sending the command to the radio core. See @ref
|
||||
* otPlatRadioSetPanId for an example of how the rx settings are set changed.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command completed correctly
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command completed correctly.
|
||||
*/
|
||||
static uint_fast8_t rfCoreSendReceiveCmd(void)
|
||||
{
|
||||
@@ -669,7 +671,7 @@ static uint_fast8_t rfCoreSendEdScanCmd(uint8_t aChannel, uint16_t aDurration)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief enables the cpe0 and cpe1 radio interrupts
|
||||
* Enables the cpe0 and cpe1 radio interrupts.
|
||||
*
|
||||
* Enables the @ref IRQ_LAST_COMMAND_DONE and @ref IRQ_LAST_FG_COMMAND_DONE to
|
||||
* be handled by the @ref RFCCPE0IntHandler interrupt handler.
|
||||
@@ -678,11 +680,7 @@ static void rfCoreSetupInt(void)
|
||||
{
|
||||
bool interruptsWereDisabled;
|
||||
|
||||
/* We are already turned on by the caller, so this should not happen */
|
||||
if (!PRCMRfReady())
|
||||
{
|
||||
return;
|
||||
}
|
||||
otEXPECT(PRCMRfReady());
|
||||
|
||||
interruptsWereDisabled = IntMasterDisable();
|
||||
|
||||
@@ -701,10 +699,13 @@ static void rfCoreSetupInt(void)
|
||||
{
|
||||
IntMasterEnable();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disables and clears the cpe0 and cpe1 radio interrupts
|
||||
* Disables and clears the cpe0 and cpe1 radio interrupts.
|
||||
*/
|
||||
static void rfCoreStopInt(void)
|
||||
{
|
||||
@@ -730,7 +731,7 @@ static void rfCoreStopInt(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the mode for the radio core to IEEE 802.15.4
|
||||
* Sets the mode for the radio core to IEEE 802.15.4
|
||||
*/
|
||||
static void rfCoreSetModeSelect(void)
|
||||
{
|
||||
@@ -752,7 +753,7 @@ static void rfCoreSetModeSelect(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief turns on the radio core
|
||||
* Turns on the radio core.
|
||||
*
|
||||
* Sets up the power and resources for the radio core.
|
||||
* - switches the high frequency clock to the xosc crystal
|
||||
@@ -763,8 +764,8 @@ static void rfCoreSetModeSelect(void)
|
||||
* - sets up the interrupts
|
||||
* - sends the ping command to the radio core to make sure it is running
|
||||
*
|
||||
* @return the value from the ping command to the radio core
|
||||
* @retval CMDSTA_Done the radio core is alive and responding
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command was received.
|
||||
*/
|
||||
static uint_fast8_t rfCorePowerOn(void)
|
||||
{
|
||||
@@ -830,7 +831,7 @@ static uint_fast8_t rfCorePowerOn(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief turns off the radio core
|
||||
* Turns off the radio core.
|
||||
*
|
||||
* Switches off the power and resources for the radio core.
|
||||
* - disables the interrupts
|
||||
@@ -861,18 +862,20 @@ static void rfCorePowerOff(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the setup command string to the radio core
|
||||
* Sends the setup command string to the radio core.
|
||||
*
|
||||
* Enables the clock line from the RTC to the RF core RAT. Enables the RAT
|
||||
* timer and sets up the radio in IEEE mode.
|
||||
*
|
||||
* @return the value from the command status register
|
||||
* @retval CMDSTA_Done the command was received
|
||||
* @return The value from the command status register.
|
||||
* @retval CMDSTA_Done The command was received.
|
||||
*/
|
||||
static uint_fast16_t rfCoreSendEnableCmd(void)
|
||||
{
|
||||
uint8_t ret;
|
||||
bool interruptsWereDisabled;
|
||||
uint8_t doorbellRet;
|
||||
bool interruptsWereDisabled;
|
||||
uint_fast16_t ret;
|
||||
|
||||
static const rfc_CMD_SYNC_START_RAT_t cStartRatCmd =
|
||||
{
|
||||
.commandNo = CMD_SYNC_START_RAT,
|
||||
@@ -912,41 +915,40 @@ static uint_fast16_t rfCoreSendEnableCmd(void)
|
||||
|
||||
interruptsWereDisabled = IntMasterDisable();
|
||||
|
||||
if ((ret = (RFCDoorbellSendTo((uint32_t)&sStartRatCmd) & 0xFF)) != CMDSTA_Done)
|
||||
{
|
||||
if (!interruptsWereDisabled)
|
||||
{
|
||||
IntMasterEnable();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
doorbellRet = (RFCDoorbellSendTo((uint32_t)&sStartRatCmd) & 0xFF);
|
||||
otEXPECT_ACTION(CMDSTA_Done == doorbellRet, ret = doorbellRet);
|
||||
|
||||
/* synchronously wait for the CM0 to stop executing */
|
||||
while ((HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_LAST_COMMAND_DONE) == 0x00);
|
||||
|
||||
ret = sRadioSetupCmd.status;
|
||||
|
||||
exit:
|
||||
|
||||
if (!interruptsWereDisabled)
|
||||
{
|
||||
IntMasterEnable();
|
||||
}
|
||||
|
||||
return sRadioSetupCmd.status;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sends the shutdown command string to the radio core
|
||||
* Sends the shutdown command string to the radio core.
|
||||
*
|
||||
* Powers down the frequency synthesizer and stops the RAT.
|
||||
*
|
||||
* @note synchronously waits until the command string completes.
|
||||
*
|
||||
* @return the status of the RAT stop command
|
||||
* @retval DONE_OK the command string executed properly
|
||||
* @return The status of the RAT stop command.
|
||||
* @retval DONE_OK The command string executed properly.
|
||||
*/
|
||||
static uint_fast16_t rfCoreSendDisableCmd(void)
|
||||
{
|
||||
uint8_t doorbellRet;
|
||||
bool interruptsWereDisabled;
|
||||
uint8_t doorbellRet;
|
||||
bool interruptsWereDisabled;
|
||||
uint_fast16_t ret;
|
||||
|
||||
static const rfc_CMD_FS_POWERDOWN_t cFsPowerdownCmd =
|
||||
{
|
||||
.commandNo = CMD_FS_POWERDOWN,
|
||||
@@ -983,35 +985,31 @@ static uint_fast16_t rfCoreSendDisableCmd(void)
|
||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~IRQ_LAST_COMMAND_DONE;
|
||||
|
||||
doorbellRet = (RFCDoorbellSendTo((uint32_t)&sFsPowerdownCmd) & 0xFF);
|
||||
otEXPECT_ACTION(CMDSTA_Done == doorbellRet, ret = doorbellRet);
|
||||
|
||||
if (doorbellRet != CMDSTA_Done)
|
||||
{
|
||||
if (!interruptsWereDisabled)
|
||||
{
|
||||
IntMasterEnable();
|
||||
}
|
||||
|
||||
return doorbellRet;
|
||||
}
|
||||
|
||||
/* synchronously wait for the CM0 to stop */
|
||||
while ((HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_LAST_COMMAND_DONE) == 0x00);
|
||||
|
||||
if (!interruptsWereDisabled)
|
||||
{
|
||||
IntMasterEnable();
|
||||
}
|
||||
ret = sStopRatCmd.status;
|
||||
|
||||
if (sStopRatCmd.status == DONE_OK)
|
||||
{
|
||||
sRatOffset = sStopRatCmd.rat0;
|
||||
}
|
||||
|
||||
return sStopRatCmd.status;
|
||||
exit:
|
||||
|
||||
if (!interruptsWereDisabled)
|
||||
{
|
||||
IntMasterEnable();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* error interrupt handler
|
||||
* Error interrupt handler.
|
||||
*/
|
||||
void RFCCPE1IntHandler(void)
|
||||
{
|
||||
@@ -1020,7 +1018,7 @@ void RFCCPE1IntHandler(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* command done handler
|
||||
* Command done handler.
|
||||
*/
|
||||
void RFCCPE0IntHandler(void)
|
||||
{
|
||||
@@ -1063,29 +1061,27 @@ void RFCCPE0IntHandler(void)
|
||||
{
|
||||
sTransmitError = OT_ERROR_NO_ACK;
|
||||
/* signal polling function we are done transmitting, we failed to send the packet */
|
||||
sState = cc2650_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IEEE_DONE_ACK:
|
||||
sReceivedAckPendingBit = false;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2650_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
break;
|
||||
|
||||
case IEEE_DONE_ACKPEND:
|
||||
sReceivedAckPendingBit = true;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2650_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
sTransmitError = OT_ERROR_FAILED;
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2650_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1096,7 +1092,6 @@ void RFCCPE0IntHandler(void)
|
||||
switch (sTransmitCmd.status)
|
||||
{
|
||||
case IEEE_DONE_OK:
|
||||
sReceivedAckPendingBit = false;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
break;
|
||||
|
||||
@@ -1115,12 +1110,12 @@ void RFCCPE0IntHandler(void)
|
||||
break;
|
||||
|
||||
default:
|
||||
sTransmitError = OT_ERROR_GENERIC;
|
||||
sTransmitError = OT_ERROR_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2650_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1313,11 +1308,11 @@ otError otPlatRadioSleep(otInstance *aInstance)
|
||||
if (rfCoreExecuteAbortCmd() != CMDSTA_Done)
|
||||
{
|
||||
error = OT_ERROR_BUSY;
|
||||
return error;
|
||||
}
|
||||
|
||||
sState = cc2650_stateSleep;
|
||||
return error;
|
||||
else
|
||||
{
|
||||
sState = cc2650_stateSleep;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
@@ -1341,27 +1336,18 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
|
||||
|
||||
if (sState == cc2650_stateReceive)
|
||||
{
|
||||
/*
|
||||
* This is the easiest way to setup the frequency synthesizer.
|
||||
* And we are supposed to fall into the receive state afterwards.
|
||||
*/
|
||||
error = otPlatRadioReceive(aInstance, aFrame->mChannel);
|
||||
sState = cc2650_stateTransmit;
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
sState = cc2650_stateTransmit;
|
||||
|
||||
/* removing 2 bytes of CRC placeholder because we generate that in hardware */
|
||||
otEXPECT_ACTION(rfCoreSendTransmitCmd(aFrame->mPsdu, aFrame->mLength - 2) == CMDSTA_Done,
|
||||
error = OT_ERROR_FAILED);
|
||||
error = OT_ERROR_NONE;
|
||||
|
||||
otPlatRadioTxStarted(aInstance, aFrame);
|
||||
}
|
||||
/* removing 2 bytes of CRC placeholder because we generate that in hardware */
|
||||
otEXPECT_ACTION(rfCoreSendTransmitCmd(aFrame->mPsdu, aFrame->mLength - 2) == CMDSTA_Done,
|
||||
error = OT_ERROR_FAILED);
|
||||
error = OT_ERROR_NONE;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
sTxCmdChainDone = false;
|
||||
otPlatRadioTxStarted(aInstance, aFrame);
|
||||
}
|
||||
|
||||
exit:
|
||||
sTransmitError = error;
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1663,7 +1649,7 @@ void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
|
||||
* Function documented in platform/radio.h
|
||||
*
|
||||
* @note it is entirely possible for this function to fail, but there is no
|
||||
* valid way to return that error since the funciton prototype was changed.
|
||||
* valid way to return that error since the function prototype was changed.
|
||||
*/
|
||||
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanid)
|
||||
{
|
||||
@@ -1694,7 +1680,7 @@ exit:
|
||||
* Function documented in platform/radio.h
|
||||
*
|
||||
* @note it is entirely possible for this function to fail, but there is no
|
||||
* valid way to return that error since the funciton prototype was changed.
|
||||
* valid way to return that error since the function prototype was changed.
|
||||
*/
|
||||
void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
|
||||
{
|
||||
@@ -1723,7 +1709,7 @@ exit:
|
||||
* Function documented in platform/radio.h
|
||||
*
|
||||
* @note it is entirely possible for this function to fail, but there is no
|
||||
* valid way to return that error since the funciton prototype was changed.
|
||||
* valid way to return that error since the function prototype was changed.
|
||||
*/
|
||||
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress)
|
||||
{
|
||||
@@ -1747,53 +1733,97 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief search the receive queue for unprocessed messages
|
||||
*
|
||||
* Loop through the receive queue structure looking for data entries that the
|
||||
* radio core has marked as finished. Then place those in @ref sReceiveFrame
|
||||
* and mark any errors in @ref sReceiveError.
|
||||
*/
|
||||
static void readFrame(void)
|
||||
static void cc2650RadioProcessTransmitDone(otInstance *aInstance, otRadioFrame *aTransmitFrame, otRadioFrame *aAckFrame,
|
||||
otError aTransmitError)
|
||||
{
|
||||
rfc_ieeeRxCorrCrc_t *crcCorr;
|
||||
uint8_t rssi;
|
||||
rfc_dataEntryGeneral_t *startEntry = (rfc_dataEntryGeneral_t *)sRxDataQueue.pCurrEntry;
|
||||
rfc_dataEntryGeneral_t *curEntry = startEntry;
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, aTransmitFrame, aTransmitError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
otPlatRadioTxDone(aInstance, aTransmitFrame, aAckFrame, aTransmitError);
|
||||
}
|
||||
}
|
||||
|
||||
static void cc2650RadioProcessReceiveDone(otInstance *aInstance, otRadioFrame *aReceiveFrame, otError aReceiveError)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, aReceiveFrame, aReceiveError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, aReceiveFrame, aReceiveError);
|
||||
}
|
||||
}
|
||||
|
||||
static void cc2650RadioProcessReceiveQueue(otInstance *aInstance)
|
||||
{
|
||||
rfc_ieeeRxCorrCrc_t *crcCorr;
|
||||
rfc_dataEntryGeneral_t *curEntry, *startEntry;
|
||||
uint8_t rssi;
|
||||
|
||||
startEntry = (rfc_dataEntryGeneral_t *)sRxDataQueue.pCurrEntry;
|
||||
curEntry = startEntry;
|
||||
|
||||
/* loop through receive queue */
|
||||
do
|
||||
{
|
||||
uint8_t *payload = &(curEntry->data);
|
||||
|
||||
if (sReceiveFrame.mLength == 0 && curEntry->status == DATA_ENTRY_FINISHED)
|
||||
if (curEntry->status == DATA_ENTRY_FINISHED)
|
||||
{
|
||||
uint8_t len = payload[0];
|
||||
uint8_t len;
|
||||
otError receiveError;
|
||||
otRadioFrame receiveFrame;
|
||||
|
||||
/* get the information appended to the end of the frame.
|
||||
* This array access looks like it is a fencepost error, but the
|
||||
* first byte is the number of bytes that follow.
|
||||
*/
|
||||
len = payload[0];
|
||||
crcCorr = (rfc_ieeeRxCorrCrc_t *)&payload[len];
|
||||
rssi = payload[len - 1];
|
||||
rssi = payload[len - 1];
|
||||
|
||||
if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_RAW_LINK_API
|
||||
// Timestamp
|
||||
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
|
||||
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
|
||||
// TODO: Propagate CM0 timestamp
|
||||
receiveFrame.mMsec = otPlatAlarmMilliGetNow();
|
||||
receiveFrame.mUsec = 0; // Don't support microsecond timer for now.
|
||||
#endif
|
||||
|
||||
sReceiveFrame.mLength = len;
|
||||
memcpy(sReceiveFrame.mPsdu, &(payload[1]), len - 2);
|
||||
sReceiveFrame.mChannel = sReceiveCmd.channel;
|
||||
sReceiveFrame.mPower = rssi;
|
||||
sReceiveFrame.mLqi = crcCorr->status.corr;
|
||||
sReceiveError = OT_ERROR_NONE;
|
||||
receiveFrame.mLength = len;
|
||||
receiveFrame.mPsdu = &(payload[1]);
|
||||
receiveFrame.mChannel = sReceiveCmd.channel;
|
||||
receiveFrame.mPower = rssi;
|
||||
receiveFrame.mLqi = crcCorr->status.corr;
|
||||
|
||||
receiveError = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sReceiveError = OT_ERROR_FCS;
|
||||
receiveError = OT_ERROR_FCS;
|
||||
}
|
||||
|
||||
if ((receiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK)
|
||||
{
|
||||
if (receiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
|
||||
{
|
||||
sState = cc2650_stateReceive;
|
||||
cc2650RadioProcessTransmitDone(aInstance, &sTransmitFrame, &receiveFrame, receiveError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cc2650RadioProcessReceiveDone(aInstance, &receiveFrame, receiveError);
|
||||
}
|
||||
|
||||
curEntry->status = DATA_ENTRY_PENDING;
|
||||
@@ -1807,8 +1837,6 @@ static void readFrame(void)
|
||||
curEntry = (rfc_dataEntryGeneral_t *)(curEntry->pNextEntry);
|
||||
}
|
||||
while (curEntry != startEntry);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1828,59 +1856,23 @@ void cc2650RadioProcess(otInstance *aInstance)
|
||||
}
|
||||
}
|
||||
|
||||
if (sState == cc2650_stateTransmitComplete || (sState == cc2650_stateTransmit && sTransmitError != OT_ERROR_NONE))
|
||||
if (sState == cc2650_stateReceive
|
||||
|| sState == cc2650_stateTransmit)
|
||||
{
|
||||
/* we are not looking for an ACK packet, or failed */
|
||||
sState = cc2650_stateReceive;
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
// TODO: pass received ACK frame instead of generating one.
|
||||
otRadioFrame ackFrame;
|
||||
uint8_t psdu[IEEE802154_ACK_LENGTH];
|
||||
|
||||
ackFrame.mPsdu = psdu;
|
||||
ackFrame.mLength = IEEE802154_ACK_LENGTH;
|
||||
ackFrame.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
|
||||
|
||||
if (sReceivedAckPendingBit)
|
||||
{
|
||||
ackFrame.mPsdu[0] |= IEEE802154_FRAME_PENDING;
|
||||
}
|
||||
|
||||
ackFrame.mPsdu[1] = 0;
|
||||
ackFrame.mPsdu[2] = sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET];
|
||||
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, &ackFrame, sTransmitError);
|
||||
}
|
||||
cc2650RadioProcessReceiveQueue(aInstance);
|
||||
}
|
||||
|
||||
if (sState == cc2650_stateReceive || sState == cc2650_stateTransmit)
|
||||
if (sTxCmdChainDone)
|
||||
{
|
||||
readFrame();
|
||||
|
||||
if (sReceiveFrame.mLength > 0)
|
||||
if (sState == cc2650_stateTransmit)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
|
||||
}
|
||||
/* we are not looking for an ACK packet, or failed */
|
||||
sState = cc2650_stateReceive;
|
||||
cc2650RadioProcessTransmitDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
|
||||
}
|
||||
|
||||
sReceiveFrame.mLength = 0;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
sTxCmdChainDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ enum
|
||||
{
|
||||
IEEE802154_FRAME_TYPE_MASK = 0x7, ///< (IEEE 802.15.4-2006) PSDU.FCF.frameType
|
||||
IEEE802154_FRAME_TYPE_ACK = 0x2, ///< (IEEE 802.15.4-2006) frame type: ACK
|
||||
IEEE802154_FRAME_PENDING = (1<<4), ///< (IEEE 802.15.4-2006) PSDU.FCF.bFramePending
|
||||
IEEE802154_ACK_REQUEST = (1<<5), ///< (IEEE 802.15.4-2006) PSDU.FCF.bAR
|
||||
IEEE802154_DSN_OFFSET = 2, ///< (IEEE 802.15.4-2006) PSDU.sequenceNumber
|
||||
IEEE802154_MAC_MIN_BE = 1, ///< (IEEE 802.15.4-2006) macMinBE
|
||||
@@ -156,19 +155,19 @@ typedef enum cc2652_address
|
||||
* The following are valid radio state transitions for the cc2652:
|
||||
*
|
||||
* (Radio ON)
|
||||
* +----------+ Enable() +-------+ Receive() +---------+ Transmit() +----------+
|
||||
* | |----------->| |------------->| |-------------->| |
|
||||
* | Disabled | | Sleep | | Receive | | Transmit |
|
||||
* | |<-----------| |<-------------| |<--------------| |
|
||||
* +----------+ Disable() | | Sleep() | |<-- Receive() +----------+
|
||||
* | | (Radio OFF) +---------+ \ | transmit
|
||||
* | | \-----\ | complete
|
||||
* | | EnergyScan() +--------+ | V
|
||||
* | |------------->| | +------------------+
|
||||
* | | | EdScan | | |
|
||||
* | |<-------------| | | TransmitComplete |
|
||||
* | | signal ED | | | |
|
||||
* +-------+ scan done +--------+ +------------------+
|
||||
* +----------+ Enable() +-------+ Receive() +---------+ Transmit() +----------+
|
||||
* | |----------->| |------------->| |--------------->| |
|
||||
* | Disabled | | Sleep | | Receive | | Transmit |
|
||||
* | |<-----------| |<-------------| |<---------------| |
|
||||
* +----------+ Disable() | | Sleep() | | AckFrame RX or +----------+
|
||||
* | | (Radio OFF) +---------+ sTxCmdChainDone == true
|
||||
* | |
|
||||
* | | EnergyScan() +--------+
|
||||
* | |------------->| |
|
||||
* | | | EdScan |
|
||||
* | |<-------------| |
|
||||
* | | signal ED | |
|
||||
* +-------+ scan done +--------+
|
||||
*
|
||||
* These states slightly differ from the states in \ref include/platform/radio.h.
|
||||
* The additional states the phy can be in are due to the asynchronous nature
|
||||
@@ -193,7 +192,6 @@ typedef enum cc2652_PhyState
|
||||
cc2652_stateReceive,
|
||||
cc2652_stateEdScan,
|
||||
cc2652_stateTransmit,
|
||||
cc2652_stateTransmitComplete,
|
||||
} cc2652_PhyState_t;
|
||||
|
||||
#endif /* CC2652_RADIO_H_ */
|
||||
|
||||
+108
-102
@@ -61,7 +61,6 @@
|
||||
|
||||
enum
|
||||
{
|
||||
IEEE802154_ACK_LENGTH = 5,
|
||||
CC2652_RECEIVE_SENSITIVITY = -100, // dBm
|
||||
};
|
||||
|
||||
@@ -81,14 +80,6 @@ static uint32_t sIEEEOverrides[] =
|
||||
0xFFFFFFFF, // END_OVERRIDE
|
||||
};
|
||||
|
||||
/*
|
||||
* Status of the pending bit of the last ack packet found by the
|
||||
* sTransmitRxAckCmd radio command.
|
||||
*
|
||||
* Used to pass data from the radio state ISR to the processing loop.
|
||||
*/
|
||||
static volatile bool sReceivedAckPendingBit = false;
|
||||
|
||||
/*
|
||||
* Number of retry counts left to the currently transmitting frame.
|
||||
*
|
||||
@@ -143,6 +134,8 @@ static __attribute__((aligned(4))) rfc_ieeeRxOutput_t sRfStats;
|
||||
#define RX_BUF_SIZE 144
|
||||
static __attribute__((aligned(4))) uint8_t sRxBuf0[RX_BUF_SIZE];
|
||||
static __attribute__((aligned(4))) uint8_t sRxBuf1[RX_BUF_SIZE];
|
||||
static __attribute__((aligned(4))) uint8_t sRxBuf2[RX_BUF_SIZE];
|
||||
static __attribute__((aligned(4))) uint8_t sRxBuf3[RX_BUF_SIZE];
|
||||
|
||||
/*
|
||||
* The RX Data Queue used by @ref sReceiveCmd.
|
||||
@@ -153,12 +146,11 @@ static __attribute__((aligned(4))) dataQueue_t sRxDataQueue = { 0 };
|
||||
* OpenThread data primitives
|
||||
*/
|
||||
static otRadioFrame sTransmitFrame;
|
||||
static otRadioFrame sReceiveFrame;
|
||||
static otError sTransmitError;
|
||||
static otError sReceiveError;
|
||||
|
||||
static __attribute__((aligned(4))) uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
static __attribute__((aligned(4))) uint8_t sReceivePsdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
|
||||
static volatile bool sTxCmdChainDone = false;
|
||||
|
||||
/*
|
||||
* Interrupt handlers forward declared for register functions.
|
||||
@@ -175,8 +167,10 @@ void RFCCPE1IntHandler(void);
|
||||
static void rfCoreInitBufs(void)
|
||||
{
|
||||
rfc_dataEntry_t *entry;
|
||||
memset(sRxBuf0, 0x00, RX_BUF_SIZE);
|
||||
memset(sRxBuf1, 0x00, RX_BUF_SIZE);
|
||||
memset(sRxBuf0, 0x00, sizeof(sRxBuf0));
|
||||
memset(sRxBuf1, 0x00, sizeof(sRxBuf1));
|
||||
memset(sRxBuf2, 0x00, sizeof(sRxBuf2));
|
||||
memset(sRxBuf3, 0x00, sizeof(sRxBuf3));
|
||||
|
||||
entry = (rfc_dataEntry_t *)sRxBuf0;
|
||||
entry->pNextEntry = sRxBuf1;
|
||||
@@ -184,14 +178,22 @@ static void rfCoreInitBufs(void)
|
||||
entry->length = sizeof(sRxBuf0) - sizeof(rfc_dataEntry_t);
|
||||
|
||||
entry = (rfc_dataEntry_t *)sRxBuf1;
|
||||
entry->pNextEntry = sRxBuf2;
|
||||
entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
|
||||
entry->length = sizeof(sRxBuf1) - sizeof(rfc_dataEntry_t);
|
||||
|
||||
entry = (rfc_dataEntry_t *)sRxBuf2;
|
||||
entry->pNextEntry = sRxBuf3;
|
||||
entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
|
||||
entry->length = sizeof(sRxBuf2) - sizeof(rfc_dataEntry_t);
|
||||
|
||||
entry = (rfc_dataEntry_t *)sRxBuf3;
|
||||
entry->pNextEntry = sRxBuf0;
|
||||
entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
|
||||
entry->length = sizeof(sRxBuf0) - sizeof(rfc_dataEntry_t);
|
||||
entry->length = sizeof(sRxBuf3) - sizeof(rfc_dataEntry_t);
|
||||
|
||||
sTransmitFrame.mPsdu = sTransmitPsdu;
|
||||
sTransmitFrame.mLength = 0;
|
||||
sReceiveFrame.mPsdu = sReceivePsdu;
|
||||
sReceiveFrame.mLength = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,7 +245,7 @@ static void rfCoreInitReceiveParams(void)
|
||||
{
|
||||
.bAcceptFt0Beacon = 1,
|
||||
.bAcceptFt1Data = 1,
|
||||
.bAcceptFt2Ack = 0,
|
||||
.bAcceptFt2Ack = 1,
|
||||
.bAcceptFt3MacCmd = 1,
|
||||
.bAcceptFt4Reserved = 1,
|
||||
.bAcceptFt5Reserved = 1,
|
||||
@@ -696,7 +698,7 @@ static uint_fast8_t rfCoreSendEdScanCmd(uint8_t aChannel, uint16_t aDurration)
|
||||
}
|
||||
|
||||
/**
|
||||
* enables the cpe0 and cpe1 radio interrupts
|
||||
* Enables the cpe0 and cpe1 radio interrupts.
|
||||
*
|
||||
* Enables the @ref IRQ_LAST_COMMAND_DONE and @ref IRQ_LAST_FG_COMMAND_DONE to
|
||||
* be handled by the @ref RFCCPE0IntHandler interrupt handler.
|
||||
@@ -1067,29 +1069,27 @@ void RFCCPE0IntHandler(void)
|
||||
{
|
||||
sTransmitError = OT_ERROR_NO_ACK;
|
||||
/* signal polling function we are done transmitting, we failed to send the packet */
|
||||
sState = cc2652_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IEEE_DONE_ACK:
|
||||
sReceivedAckPendingBit = false;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2652_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
break;
|
||||
|
||||
case IEEE_DONE_ACKPEND:
|
||||
sReceivedAckPendingBit = true;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2652_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
sTransmitError = OT_ERROR_FAILED;
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2652_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1100,7 +1100,6 @@ void RFCCPE0IntHandler(void)
|
||||
switch (sTransmitCmd.status)
|
||||
{
|
||||
case IEEE_DONE_OK:
|
||||
sReceivedAckPendingBit = false;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
break;
|
||||
|
||||
@@ -1124,7 +1123,7 @@ void RFCCPE0IntHandler(void)
|
||||
}
|
||||
|
||||
/* signal polling function we are done transmitting */
|
||||
sState = cc2652_stateTransmitComplete;
|
||||
sTxCmdChainDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1344,7 +1343,6 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
|
||||
*/
|
||||
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
|
||||
{
|
||||
(void)aInstance;
|
||||
otError error = OT_ERROR_BUSY;
|
||||
|
||||
if (sState == cc2652_stateReceive)
|
||||
@@ -1355,10 +1353,12 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
|
||||
otEXPECT_ACTION(rfCoreSendTransmitCmd(aFrame->mPsdu, aFrame->mLength - 2) == CMDSTA_Done,
|
||||
error = OT_ERROR_FAILED);
|
||||
error = OT_ERROR_NONE;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
sTxCmdChainDone = false;
|
||||
otPlatRadioTxStarted(aInstance, aFrame);
|
||||
}
|
||||
|
||||
exit:
|
||||
sTransmitError = error;
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1745,53 +1745,97 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the receive queue for unprocessed messages.
|
||||
*
|
||||
* Loop through the receive queue structure looking for data entries that the
|
||||
* radio core has marked as finished. Then place those in @ref sReceiveFrame
|
||||
* and mark any errors in @ref sReceiveError.
|
||||
*/
|
||||
static void readFrame(void)
|
||||
static void cc2652RadioProcessTransmitDone(otInstance *aInstance, otRadioFrame *aTransmitFrame, otRadioFrame *aAckFrame,
|
||||
otError aTransmitError)
|
||||
{
|
||||
rfc_ieeeRxCorrCrc_t *crcCorr;
|
||||
uint8_t rssi;
|
||||
rfc_dataEntryGeneral_t *startEntry = (rfc_dataEntryGeneral_t *)sRxDataQueue.pCurrEntry;
|
||||
rfc_dataEntryGeneral_t *curEntry = startEntry;
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, aTransmitFrame, aTransmitError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
otPlatRadioTxDone(aInstance, aTransmitFrame, aAckFrame, aTransmitError);
|
||||
}
|
||||
}
|
||||
|
||||
static void cc2652RadioProcessReceiveDone(otInstance *aInstance, otRadioFrame *aReceiveFrame, otError aReceiveError)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, aReceiveFrame, aReceiveError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, aReceiveFrame, aReceiveError);
|
||||
}
|
||||
}
|
||||
|
||||
static void cc2652RadioProcessReceiveQueue(otInstance *aInstance)
|
||||
{
|
||||
rfc_ieeeRxCorrCrc_t *crcCorr;
|
||||
rfc_dataEntryGeneral_t *curEntry, *startEntry;
|
||||
uint8_t rssi;
|
||||
|
||||
startEntry = (rfc_dataEntryGeneral_t *)sRxDataQueue.pCurrEntry;
|
||||
curEntry = startEntry;
|
||||
|
||||
/* loop through receive queue */
|
||||
do
|
||||
{
|
||||
uint8_t *payload = &(curEntry->data);
|
||||
|
||||
if (sReceiveFrame.mLength == 0 && curEntry->status == DATA_ENTRY_FINISHED)
|
||||
if (curEntry->status == DATA_ENTRY_FINISHED)
|
||||
{
|
||||
uint8_t len = payload[0];
|
||||
uint8_t len;
|
||||
otError receiveError;
|
||||
otRadioFrame receiveFrame;
|
||||
|
||||
/* get the information appended to the end of the frame.
|
||||
* This array access looks like it is a fencepost error, but the
|
||||
* first byte is the number of bytes that follow.
|
||||
*/
|
||||
len = payload[0];
|
||||
crcCorr = (rfc_ieeeRxCorrCrc_t *)&payload[len];
|
||||
rssi = payload[len - 1];
|
||||
rssi = payload[len - 1];
|
||||
|
||||
if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_RAW_LINK_API
|
||||
// Timestamp
|
||||
sReceiveFrame.mMsec = otPlatAlarmMilliGetNow();
|
||||
sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now.
|
||||
// TODO: Propagate CM0 timestamp
|
||||
receiveFrame.mMsec = otPlatAlarmMilliGetNow();
|
||||
receiveFrame.mUsec = 0; // Don't support microsecond timer for now.
|
||||
#endif
|
||||
|
||||
sReceiveFrame.mLength = len;
|
||||
memcpy(sReceiveFrame.mPsdu, &(payload[1]), len - 2);
|
||||
sReceiveFrame.mChannel = sReceiveCmd.channel;
|
||||
sReceiveFrame.mPower = rssi;
|
||||
sReceiveFrame.mLqi = crcCorr->status.corr;
|
||||
sReceiveError = OT_ERROR_NONE;
|
||||
receiveFrame.mLength = len;
|
||||
receiveFrame.mPsdu = &(payload[1]);
|
||||
receiveFrame.mChannel = sReceiveCmd.channel;
|
||||
receiveFrame.mPower = rssi;
|
||||
receiveFrame.mLqi = crcCorr->status.corr;
|
||||
|
||||
receiveError = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sReceiveError = OT_ERROR_FCS;
|
||||
receiveError = OT_ERROR_FCS;
|
||||
}
|
||||
|
||||
if ((receiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK)
|
||||
{
|
||||
if (receiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
|
||||
{
|
||||
sState = cc2652_stateReceive;
|
||||
cc2652RadioProcessTransmitDone(aInstance, &sTransmitFrame, &receiveFrame, receiveError);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cc2652RadioProcessReceiveDone(aInstance, &receiveFrame, receiveError);
|
||||
}
|
||||
|
||||
curEntry->status = DATA_ENTRY_PENDING;
|
||||
@@ -1805,8 +1849,6 @@ static void readFrame(void)
|
||||
curEntry = (rfc_dataEntryGeneral_t *)(curEntry->pNextEntry);
|
||||
}
|
||||
while (curEntry != startEntry);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1826,59 +1868,23 @@ void cc2652RadioProcess(otInstance *aInstance)
|
||||
}
|
||||
}
|
||||
|
||||
if (sState == cc2652_stateTransmitComplete || (sState == cc2652_stateTransmit && sTransmitError != OT_ERROR_NONE))
|
||||
if (sState == cc2652_stateReceive
|
||||
|| sState == cc2652_stateTransmit)
|
||||
{
|
||||
/* we are not looking for an ACK packet, or failed */
|
||||
sState = cc2652_stateReceive;
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
// TODO: pass received ACK frame instead of generating one.
|
||||
otRadioFrame ackFrame;
|
||||
uint8_t psdu[IEEE802154_ACK_LENGTH];
|
||||
|
||||
ackFrame.mPsdu = psdu;
|
||||
ackFrame.mLength = IEEE802154_ACK_LENGTH;
|
||||
ackFrame.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
|
||||
|
||||
if (sReceivedAckPendingBit)
|
||||
{
|
||||
ackFrame.mPsdu[0] |= IEEE802154_FRAME_PENDING;
|
||||
}
|
||||
|
||||
ackFrame.mPsdu[1] = 0;
|
||||
ackFrame.mPsdu[2] = sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET];
|
||||
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, &ackFrame, sTransmitError);
|
||||
}
|
||||
cc2652RadioProcessReceiveQueue(aInstance);
|
||||
}
|
||||
|
||||
if (sState == cc2652_stateReceive || sState == cc2652_stateTransmit)
|
||||
if (sTxCmdChainDone)
|
||||
{
|
||||
readFrame();
|
||||
|
||||
if (sReceiveFrame.mLength > 0)
|
||||
if (sState == cc2652_stateTransmit)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
|
||||
}
|
||||
else
|
||||
#endif /* OPENTHREAD_ENABLE_DIAG */
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
|
||||
}
|
||||
/* we are not looking for an ACK packet, or failed */
|
||||
sState = cc2652_stateReceive;
|
||||
cc2652RadioProcessTransmitDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
|
||||
}
|
||||
|
||||
sReceiveFrame.mLength = 0;
|
||||
sTransmitError = OT_ERROR_NONE;
|
||||
sTxCmdChainDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user