[low-power] add CSL implementations on nrf52840 (#5449)

This commit is contained in:
Li Cao
2020-09-02 22:32:16 -07:00
committed by GitHub
parent 00c6d7b41e
commit b940baf9b6
8 changed files with 175 additions and 32 deletions
@@ -268,6 +268,16 @@
#define RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM 0
#endif
/**
* @def OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW
*
* CSL sample window in units of 10 symbols.
*
*/
#ifndef OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW
#define OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW 30
#endif
/*
* Suppress the ARMCC warning on unreachable statement,
* e.g. break after assert(false) or ExitNow() macro.
+101 -2
View File
@@ -41,6 +41,8 @@
#include <stdint.h>
#include <string.h>
#include <openthread/link.h>
#include "utils/code_utils.h"
#include "utils/mac_frame.h"
@@ -56,6 +58,7 @@
#include <nrf.h>
#include <nrf_802154.h>
#include <nrf_802154_pib.h>
#include <openthread-core-config.h>
#include <openthread/config.h>
@@ -109,6 +112,12 @@ static uint32_t sEnergyDetectionTime;
static uint8_t sEnergyDetectionChannel;
static int8_t sEnergyDetected;
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static uint32_t sCslPeriod;
static uint32_t sCslSampleTime;
static const uint8_t sCslIeHeader[OT_IE_HEADER_SIZE] = {CSL_IE_HEADER_BYTES_LO, CSL_IE_HEADER_BYTES_HI};
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
typedef enum
{
kPendingEventSleep, // Requested to enter Sleep state.
@@ -413,7 +422,7 @@ otError otPlatRadioSleep(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
if (nrf_802154_sleep())
if (nrf_802154_sleep_if_idle())
{
clearPendingEvents();
}
@@ -818,7 +827,7 @@ void nrf5RadioProcess(otInstance *aInstance)
if (isPendingEventSet(kPendingEventSleep))
{
if (nrf_802154_sleep())
if (nrf_802154_sleep_if_idle())
{
resetPendingEvent(kPendingEventSleep);
}
@@ -943,6 +952,17 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error)
setPendingEvent(kPendingEventReceiveFailed);
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static uint16_t getCslPhase()
{
uint32_t curTime = otPlatAlarmMicroGetNow();
uint32_t cslPeriodInUs = sCslPeriod * OT_US_PER_TEN_SYMBOLS;
uint32_t diff = ((sCslSampleTime % cslPeriodInUs) - (curTime % cslPeriodInUs) + cslPeriodInUs) % cslPeriodInUs;
return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS);
}
#endif
void nrf_802154_tx_ack_started(uint8_t *p_data)
{
// Check if the frame pending bit is set in ACK frame.
@@ -950,6 +970,16 @@ void nrf_802154_tx_ack_started(uint8_t *p_data)
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
// Update IE and secure Enh-ACK.
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
{
otRadioFrame ackFrame;
ackFrame.mPsdu = (uint8_t *)(p_data + 1);
ackFrame.mLength = p_data[0];
otMacFrameSetCslIe(&ackFrame, sCslPeriod, getCslPhase());
}
#endif
txAckProcessSecurity(p_data);
#endif
}
@@ -1046,6 +1076,13 @@ void nrf_802154_tx_started(const uint8_t *aFrame)
}
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
{
otMacFrameSetCslIe(&sTransmitFrame, (uint16_t)sCslPeriod, getCslPhase());
}
#endif
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
otEXPECT(otMacFrameIsSecurityEnabled(&sTransmitFrame) && otMacFrameIsKeyIdMode1(&sTransmitFrame) &&
!sTransmitFrame.mInfo.mTxInfo.mIsSecurityProcessed);
@@ -1084,6 +1121,13 @@ uint32_t nrf_802154_random_get(void)
return otRandomNonCryptoGetUint32();
}
uint64_t otPlatRadioGetNow(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return otPlatTimeGet();
}
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
void otPlatRadioSetMacKey(otInstance * aInstance,
uint8_t aKeyIdMode,
@@ -1118,3 +1162,58 @@ void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCoun
CRITICAL_REGION_EXIT();
}
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static void updateIeData(otInstance *aInstance, const uint8_t *aShortAddr, const uint8_t *aExtAddr)
{
int8_t offset = 0;
uint8_t ackIeData[OT_ACK_IE_MAX_SIZE];
if (sCslPeriod > 0)
{
memcpy(ackIeData, sCslIeHeader, OT_IE_HEADER_SIZE);
offset += OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE; // reserve space for CSL IE
}
if (offset > 0)
{
nrf_802154_ack_data_set(aShortAddr, false, ackIeData, offset, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_set(aExtAddr, true, ackIeData, offset, NRF_802154_ACK_DATA_IE);
}
else
{
nrf_802154_ack_data_clear(aShortAddr, false, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_clear(aExtAddr, true, NRF_802154_ACK_DATA_IE);
}
}
otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, const otExtAddress *aExtAddr)
{
otError error = OT_ERROR_NONE;
uint8_t parentExtAddr[OT_EXT_ADDRESS_SIZE];
uint8_t parentShortAddress[SHORT_ADDRESS_SIZE];
const uint8_t *shortAddress;
sCslPeriod = aCslPeriod;
for (uint32_t i = 0; i < sizeof(parentExtAddr); i++)
{
parentExtAddr[i] = aExtAddr->m8[sizeof(parentExtAddr) - i - 1];
}
shortAddress = nrf_802154_pib_short_address_get();
memcpy(parentShortAddress, shortAddress, SHORT_ADDRESS_SIZE);
parentShortAddress[0] &= 0xfc;
updateIeData(aInstance, parentShortAddress, parentExtAddr);
return error;
}
void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime)
{
OT_UNUSED_VARIABLE(aInstance);
sCslSampleTime = aCslSampleTime;
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+3 -3
View File
@@ -120,7 +120,7 @@ static uint8_t sAckIeDataLength = 0;
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static const uint8_t sCslIeHeader[OT_IE_HEADER_IE_SIZE] = {0x04, 0x0d};
static const uint8_t sCslIeHeader[OT_IE_HEADER_SIZE] = {CSL_IE_HEADER_BYTES_LO, CSL_IE_HEADER_BYTES_HI};
static uint32_t sCslSampleTime;
static uint32_t sCslPeriod;
#endif
@@ -1073,8 +1073,8 @@ static otError updateIeData(otInstance *aInstance)
if (sCslPeriod > 0)
{
memcpy(sAckIeData, sCslIeHeader, OT_IE_HEADER_IE_SIZE);
offset += OT_IE_HEADER_IE_SIZE + OT_CSL_IE_SIZE; // reserve space for CSL IE
memcpy(sAckIeData, sCslIeHeader, OT_IE_HEADER_SIZE);
offset += OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE; // reserve space for CSL IE
}
sAckIeDataLength = offset;