2 * Copyright (c) 2020, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
31 * This file implements the OpenThread platform abstraction for radio communication.
35 #include <openthread-core-config.h>
36 #include <openthread/config.h>
40 #include "openthread-system.h"
41 #include <openthread/config.h>
42 #include <openthread/platform/alarm-milli.h>
43 #include <openthread/platform/diag.h>
44 #include <openthread/platform/radio.h>
46 #include "common/logging.hpp"
47 #include "utils/code_utils.h"
49 #include "utils/soft_source_match_table.h"
51 #include "board_config.h"
54 #include "em_system.h"
55 #include "hal-config.h"
56 #include "pa_conversions_efr32.h"
57 #include "platform-band.h"
59 #include "rail_config.h"
60 #include "rail_ieee802154.h"
64 IEEE802154_MIN_LENGTH = 5,
65 IEEE802154_MAX_LENGTH = 127,
66 IEEE802154_ACK_LENGTH = 5,
68 // FCF + DSN + dest PANID + dest addr + src PANID + src addr (without security header)
69 IEEE802154_MAX_MHR_LENGTH = 2 + 1 + 2 + 8 + 2 + 8,
71 IEEE802154_FRAME_TYPE_MASK = 0x7,
72 IEEE802154_FRAME_TYPE_ACK = 0x2,
73 IEEE802154_FRAME_TYPE_MAC_COMMAND = 0x3,
74 IEEE802154_ACK_REQUEST = 1 << 5,
75 IEEE802154_DSN_OFFSET = 2,
76 IEEE802154_FCF_OFFSET = 0,
81 EFR32_RECEIVE_SENSITIVITY = -100, // dBm
82 EFR32_RSSI_AVERAGING_TIME = 16, // us
83 EFR32_RSSI_AVERAGING_TIMEOUT = 300, // us
88 EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY = 10, // High priority
89 EFR32_SCHEDULER_TX_PRIORITY = 10, // High priority
90 EFR32_SCHEDULER_RX_PRIORITY = 20, // Low priority
95 #if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT && RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
96 EFR32_NUM_BAND_CONFIGS = 2,
98 EFR32_NUM_BAND_CONFIGS = 1,
104 ENERGY_SCAN_STATUS_IDLE,
105 ENERGY_SCAN_STATUS_IN_PROGRESS,
106 ENERGY_SCAN_STATUS_COMPLETED
111 ENERGY_SCAN_MODE_SYNC,
112 ENERGY_SCAN_MODE_ASYNC
115 RAIL_Handle_t gRailHandle;
117 static volatile bool sTransmitBusy = false;
118 static bool sPromiscuous = false;
119 static otRadioState sState = OT_RADIO_STATE_DISABLED;
123 ACKED_WITH_FP_MATCH_LENGTH = 1 + IEEE802154_MAX_MHR_LENGTH, // PHR and MHR
124 ACKED_WITH_FP_SLOTS = 16, // maximum number of Data Request packets in the RX FIFO. Length should be a power of 2.
127 typedef struct efr32AckedWithFP
130 uint8_t mPacket[ACKED_WITH_FP_MATCH_LENGTH];
132 static bool sIsSrcMatchEnabled = false;
133 static efr32AckedWithFP sAckedWithFPFifo[ACKED_WITH_FP_SLOTS];
134 static uint32_t sAckedWithFPReadIndex;
135 static volatile uint32_t sAckedWithFPWriteIndex;
137 static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH];
138 static otRadioFrame sReceiveFrame;
139 static otError sReceiveError;
141 static otRadioFrame sTransmitFrame;
142 static uint8_t sTransmitPsdu[IEEE802154_MAX_LENGTH];
143 static volatile otError sTransmitError;
145 static efr32CommonConfig sCommonConfig;
146 static efr32BandConfig sBandConfigs[EFR32_NUM_BAND_CONFIGS];
148 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
149 static efr32RadioCounters sRailDebugCounters;
152 static volatile energyScanStatus sEnergyScanStatus;
153 static volatile int8_t sEnergyScanResultDbm;
154 static energyScanMode sEnergyScanMode;
156 #define QUARTER_DBM_IN_DBM 4
157 #define US_IN_MS 1000
159 static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents);
161 static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
169 .success = RAIL_RF_STATE_RX,
170 .error = RAIL_RF_STATE_RX,
174 .success = RAIL_RF_STATE_RX,
175 .error = RAIL_RF_STATE_RX,
184 .rxSearchTimeout = 0,
185 .txToRxSearchTimeout = 0,
187 .framesMask = RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES,
188 .promiscuousMode = false,
189 .isPanCoordinator = false,
192 #if RADIO_CONFIG_PA_USES_DCDC
193 RAIL_DECLARE_TX_POWER_DCDC_CURVES(piecewiseSegments, curvesSg, curves24Hp, curves24Lp);
195 RAIL_DECLARE_TX_POWER_VBAT_CURVES(piecewiseSegments, curvesSg, curves24Hp, curves24Lp);
198 static int8_t sTxPowerDbm = OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER;
200 static int8_t sCcaThresholdDbm = -75; // default -75dBm energy detect threshold
202 static efr32BandConfig *sCurrentBandConfig = NULL;
204 static RAIL_Handle_t efr32RailInit(efr32CommonConfig *aCommonConfig)
206 RAIL_Status_t status;
207 RAIL_Handle_t handle;
209 handle = RAIL_Init(&aCommonConfig->mRailConfig, NULL);
210 assert(handle != NULL);
212 status = RAIL_ConfigCal(handle, RAIL_CAL_ALL);
213 assert(status == RAIL_STATUS_NO_ERROR);
215 status = RAIL_IEEE802154_Init(handle, &sRailIeee802154Config);
216 assert(status == RAIL_STATUS_NO_ERROR);
218 status = RAIL_ConfigEvents(handle, RAIL_EVENTS_ALL,
219 RAIL_EVENT_RX_ACK_TIMEOUT | //
220 RAIL_EVENTS_TX_COMPLETION | //
221 RAIL_EVENT_RX_PACKET_RECEIVED | //
222 RAIL_EVENT_RSSI_AVERAGE_DONE | //
223 RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND | //
224 RAIL_EVENT_CAL_NEEDED | //
225 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
226 RAIL_EVENT_CONFIG_SCHEDULED | //
227 RAIL_EVENT_CONFIG_UNSCHEDULED | //
229 RAIL_EVENT_SCHEDULER_STATUS //
231 assert(status == RAIL_STATUS_NO_ERROR);
233 uint16_t actualLenth = RAIL_SetTxFifo(handle, aCommonConfig->mRailTxFifo, 0, sizeof(aCommonConfig->mRailTxFifo));
234 assert(actualLenth == sizeof(aCommonConfig->mRailTxFifo));
239 static void efr32RailConfigLoad(efr32BandConfig *aBandConfig)
241 RAIL_Status_t status;
242 #if HAL_PA_2P4_LOWPOWER == 1
243 RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_LP, BSP_PA_VOLTAGE, 10};
245 RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_HP, BSP_PA_VOLTAGE, 10};
247 if (aBandConfig->mChannelConfig != NULL)
249 uint16_t firstChannel = RAIL_ConfigChannels(gRailHandle, aBandConfig->mChannelConfig, NULL);
250 assert(firstChannel == aBandConfig->mChannelMin);
252 txPowerConfig.mode = RAIL_TX_POWER_MODE_SUBGIG;
256 status = RAIL_IEEE802154_Config2p4GHzRadio(gRailHandle);
257 assert(status == RAIL_STATUS_NO_ERROR);
259 status = RAIL_ConfigTxPower(gRailHandle, &txPowerConfig);
260 assert(status == RAIL_STATUS_NO_ERROR);
263 static void efr32RadioSetTxPower(int8_t aPowerDbm)
265 RAIL_Status_t status;
266 RAIL_TxPowerCurvesConfig_t txPowerCurvesConfig = {curves24Hp, curvesSg, curves24Lp, piecewiseSegments};
268 status = RAIL_InitTxPowerCurves(&txPowerCurvesConfig);
269 assert(status == RAIL_STATUS_NO_ERROR);
271 status = RAIL_SetTxPowerDbm(gRailHandle, ((RAIL_TxPower_t)aPowerDbm) * 10);
272 assert(status == RAIL_STATUS_NO_ERROR);
275 static efr32BandConfig *efr32RadioGetBandConfig(uint8_t aChannel)
277 efr32BandConfig *config = NULL;
279 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
281 if ((sBandConfigs[i].mChannelMin <= aChannel) && (aChannel <= sBandConfigs[i].mChannelMax))
283 config = &sBandConfigs[i];
291 static void efr32ConfigInit(void (*aEventCallback)(RAIL_Handle_t railHandle, RAIL_Events_t events))
293 sCommonConfig.mRailConfig.eventsCallback = aEventCallback;
294 sCommonConfig.mRailConfig.protocol = NULL; // only used by Bluetooth stack
295 #if RADIO_CONFIG_DMP_SUPPORT
296 sCommonConfig.mRailConfig.scheduler = &(sCommonConfig.railSchedState);
298 sCommonConfig.mRailConfig.scheduler = NULL; // only needed for DMP
303 #if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT
304 sBandConfigs[index].mChannelConfig = NULL;
305 sBandConfigs[index].mChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
306 sBandConfigs[index].mChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
311 #if RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
312 sBandConfigs[index].mChannelConfig = channelConfigs[0];
313 sBandConfigs[index].mChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
314 sBandConfigs[index].mChannelMax = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
317 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
318 memset(&sRailDebugCounters, 0x00, sizeof(efr32RadioCounters));
321 gRailHandle = efr32RailInit(&sCommonConfig);
322 assert(gRailHandle != NULL);
323 efr32RailConfigLoad(&(sBandConfigs[0]));
326 void efr32RadioInit(void)
328 RAIL_Status_t status;
330 // check if RAIL_TX_FIFO_SIZE is power of two..
331 assert((RAIL_TX_FIFO_SIZE & (RAIL_TX_FIFO_SIZE - 1)) == 0);
333 // check the limits of the RAIL_TX_FIFO_SIZE.
334 assert((RAIL_TX_FIFO_SIZE >= 64) || (RAIL_TX_FIFO_SIZE <= 4096));
336 efr32ConfigInit(RAILCb_Generic);
338 CMU_ClockEnable(cmuClock_PRS, true);
340 status = RAIL_ConfigSleep(gRailHandle, RAIL_SLEEP_CONFIG_TIMERSYNC_ENABLED);
341 assert(status == RAIL_STATUS_NO_ERROR);
343 sReceiveFrame.mLength = 0;
344 sReceiveFrame.mPsdu = sReceivePsdu;
345 sTransmitFrame.mLength = 0;
346 sTransmitFrame.mPsdu = sTransmitPsdu;
348 sCurrentBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL);
349 assert(sCurrentBandConfig != NULL);
351 memset(sAckedWithFPFifo, 0, sizeof(sAckedWithFPFifo));
352 sAckedWithFPWriteIndex = 0;
353 sAckedWithFPReadIndex = 0;
355 efr32RadioSetTxPower(sTxPowerDbm);
357 sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
358 sTransmitError = OT_ERROR_NONE;
359 sTransmitBusy = false;
361 otLogInfoPlat("Initialized", NULL);
364 void efr32RadioDeinit(void)
366 RAIL_Status_t status;
368 RAIL_Idle(gRailHandle, RAIL_IDLE_ABORT, true);
369 status = RAIL_ConfigEvents(gRailHandle, RAIL_EVENTS_ALL, 0);
370 assert(status == RAIL_STATUS_NO_ERROR);
372 sCurrentBandConfig = NULL;
375 static otError efr32StartEnergyScan(energyScanMode aMode, uint16_t aChannel, RAIL_Time_t aAveragingTimeUs)
377 RAIL_Status_t status;
378 otError error = OT_ERROR_NONE;
379 efr32BandConfig *config = NULL;
381 otEXPECT_ACTION(sEnergyScanStatus == ENERGY_SCAN_STATUS_IDLE, error = OT_ERROR_BUSY);
383 sEnergyScanStatus = ENERGY_SCAN_STATUS_IN_PROGRESS;
384 sEnergyScanMode = aMode;
386 RAIL_Idle(gRailHandle, RAIL_IDLE, true);
388 config = efr32RadioGetBandConfig(aChannel);
389 otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
391 if (sCurrentBandConfig != config)
393 efr32RailConfigLoad(config);
394 sCurrentBandConfig = config;
397 RAIL_SchedulerInfo_t scanSchedulerInfo = {.priority = RADIO_SCHEDULER_CHANNEL_SCAN_PRIORITY,
398 .slipTime = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
399 .transactionTime = aAveragingTimeUs};
401 status = RAIL_StartAverageRssi(gRailHandle, aChannel, aAveragingTimeUs, &scanSchedulerInfo);
402 otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
408 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
410 OT_UNUSED_VARIABLE(aInstance);
413 uint8_t *eui64Ptr = NULL;
415 eui64 = SYSTEM_GetUnique();
416 eui64Ptr = (uint8_t *)&eui64;
418 for (uint8_t i = 0; i < OT_EXT_ADDRESS_SIZE; i++)
420 aIeeeEui64[i] = eui64Ptr[(OT_EXT_ADDRESS_SIZE - 1) - i];
424 void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
426 OT_UNUSED_VARIABLE(aInstance);
428 RAIL_Status_t status;
430 otLogInfoPlat("PANID=%X", aPanId);
432 utilsSoftSrcMatchSetPanId(aPanId);
434 status = RAIL_IEEE802154_SetPanId(gRailHandle, aPanId, 0);
435 assert(status == RAIL_STATUS_NO_ERROR);
438 void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
440 OT_UNUSED_VARIABLE(aInstance);
442 RAIL_Status_t status;
444 otLogInfoPlat("ExtAddr=%X%X%X%X%X%X%X%X", aAddress->m8[7], aAddress->m8[6], aAddress->m8[5], aAddress->m8[4],
445 aAddress->m8[3], aAddress->m8[2], aAddress->m8[1], aAddress->m8[0]);
447 status = RAIL_IEEE802154_SetLongAddress(gRailHandle, (uint8_t *)aAddress->m8, 0);
448 assert(status == RAIL_STATUS_NO_ERROR);
451 void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress)
453 OT_UNUSED_VARIABLE(aInstance);
455 RAIL_Status_t status;
457 otLogInfoPlat("ShortAddr=%X", aAddress);
459 status = RAIL_IEEE802154_SetShortAddress(gRailHandle, aAddress, 0);
460 assert(status == RAIL_STATUS_NO_ERROR);
463 bool otPlatRadioIsEnabled(otInstance *aInstance)
465 OT_UNUSED_VARIABLE(aInstance);
467 return (sState != OT_RADIO_STATE_DISABLED);
470 otError otPlatRadioEnable(otInstance *aInstance)
472 otEXPECT(!otPlatRadioIsEnabled(aInstance));
474 otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
475 sState = OT_RADIO_STATE_SLEEP;
478 return OT_ERROR_NONE;
481 otError otPlatRadioDisable(otInstance *aInstance)
483 otEXPECT(otPlatRadioIsEnabled(aInstance));
485 otLogInfoPlat("State=OT_RADIO_STATE_DISABLED", NULL);
486 sState = OT_RADIO_STATE_DISABLED;
489 return OT_ERROR_NONE;
492 otError otPlatRadioSleep(otInstance *aInstance)
494 OT_UNUSED_VARIABLE(aInstance);
496 otError error = OT_ERROR_NONE;
498 otEXPECT_ACTION((sState != OT_RADIO_STATE_TRANSMIT) && (sState != OT_RADIO_STATE_DISABLED),
499 error = OT_ERROR_INVALID_STATE);
501 otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
503 RAIL_Idle(gRailHandle, RAIL_IDLE, true);
504 sState = OT_RADIO_STATE_SLEEP;
510 otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
512 otError error = OT_ERROR_NONE;
513 RAIL_Status_t status;
514 efr32BandConfig *config;
516 OT_UNUSED_VARIABLE(aInstance);
517 otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, error = OT_ERROR_INVALID_STATE);
519 config = efr32RadioGetBandConfig(aChannel);
520 otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
522 if (sCurrentBandConfig != config)
524 RAIL_Idle(gRailHandle, RAIL_IDLE, true);
525 efr32RailConfigLoad(config);
526 sCurrentBandConfig = config;
529 RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
530 .priority = RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY,
531 // sliptime/transaction time is not used for bg rx
534 status = RAIL_StartRx(gRailHandle, aChannel, &bgRxSchedulerInfo);
535 otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
537 otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL);
538 sState = OT_RADIO_STATE_RECEIVE;
539 sReceiveFrame.mChannel = aChannel;
545 otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
547 otError error = OT_ERROR_NONE;
548 RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
549 RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_DEFAULT;
550 efr32BandConfig * config;
551 RAIL_Status_t status;
554 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
555 sRailDebugCounters.mRailPlatTxTriggered++;
558 assert(sTransmitBusy == false);
560 otEXPECT_ACTION((sState != OT_RADIO_STATE_DISABLED) && (sState != OT_RADIO_STATE_TRANSMIT),
561 error = OT_ERROR_INVALID_STATE);
563 config = efr32RadioGetBandConfig(aFrame->mChannel);
564 otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
566 sState = OT_RADIO_STATE_TRANSMIT;
567 sTransmitError = OT_ERROR_NONE;
568 sTransmitBusy = true;
570 if (sCurrentBandConfig != config)
572 RAIL_Idle(gRailHandle, RAIL_IDLE, true);
573 efr32RailConfigLoad(config);
574 sCurrentBandConfig = config;
577 frameLength = (uint8_t)aFrame->mLength;
578 RAIL_WriteTxFifo(gRailHandle, &frameLength, sizeof frameLength, true);
579 RAIL_WriteTxFifo(gRailHandle, aFrame->mPsdu, frameLength - 2, false);
581 RAIL_SchedulerInfo_t txSchedulerInfo = {
582 .priority = RADIO_SCHEDULER_TX_PRIORITY,
583 .slipTime = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
584 .transactionTime = 0, // will be calculated later if DMP is used
587 if (aFrame->mPsdu[0] & IEEE802154_ACK_REQUEST)
589 txOptions |= RAIL_TX_OPTION_WAIT_FOR_ACK;
591 #if RADIO_CONFIG_DMP_SUPPORT
592 // time we wait for ACK
593 if (RAIL_GetSymbolRate(gRailHandle) > 0)
595 txSchedulerInfo.transactionTime += 12 * 1e6 / RAIL_GetSymbolRate(gRailHandle);
599 txSchedulerInfo.transactionTime += 12 * RADIO_TIMING_DEFAULT_SYMBOLTIME_US;
604 #if RADIO_CONFIG_DMP_SUPPORT
605 // time needed for the frame itself
606 // 4B preamble, 1B SFD, 1B PHR is not counted in frameLength
607 if (RAIL_GetBitRate(gRailHandle) > 0)
609 txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * 8 * 1e6 / RAIL_GetBitRate(gRailHandle);
613 txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * RADIO_TIMING_DEFAULT_BYTETIME_US;
617 if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
619 #if RADIO_CONFIG_DMP_SUPPORT
620 // time needed for CSMA/CA
621 txSchedulerInfo.transactionTime += RADIO_TIMING_CSMA_OVERHEAD_US;
623 csmaConfig.csmaTries = aFrame->mInfo.mTxInfo.mMaxCsmaBackoffs;
624 csmaConfig.ccaThreshold = sCcaThresholdDbm;
626 status = RAIL_StartCcaCsmaTx(gRailHandle, aFrame->mChannel, txOptions, &csmaConfig, &txSchedulerInfo);
630 status = RAIL_StartTx(gRailHandle, aFrame->mChannel, txOptions, &txSchedulerInfo);
633 if (status == RAIL_STATUS_NO_ERROR)
635 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
636 sRailDebugCounters.mRailTxStarted++;
638 otPlatRadioTxStarted(aInstance, aFrame);
642 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
643 sRailDebugCounters.mRailTxStartFailed++;
645 sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
646 sTransmitBusy = false;
647 otSysEventSignalPending();
654 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
656 OT_UNUSED_VARIABLE(aInstance);
658 return &sTransmitFrame;
661 int8_t otPlatRadioGetRssi(otInstance *aInstance)
665 int8_t rssi = OT_RADIO_RSSI_INVALID;
667 OT_UNUSED_VARIABLE(aInstance);
669 error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME);
670 otEXPECT(error == OT_ERROR_NONE);
672 start = RAIL_GetTime();
674 // waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE
675 while (sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS &&
676 ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT))
679 if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
681 rssi = sEnergyScanResultDbm;
684 sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
689 otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
691 OT_UNUSED_VARIABLE(aInstance);
693 return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN;
696 bool otPlatRadioGetPromiscuous(otInstance *aInstance)
698 OT_UNUSED_VARIABLE(aInstance);
703 void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
705 OT_UNUSED_VARIABLE(aInstance);
707 RAIL_Status_t status;
709 sPromiscuous = aEnable;
711 status = RAIL_IEEE802154_SetPromiscuousMode(gRailHandle, aEnable);
712 assert(status == RAIL_STATUS_NO_ERROR);
715 void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
717 OT_UNUSED_VARIABLE(aInstance);
719 // set Frame Pending bit for all outgoing ACKs if aEnable is false
720 sIsSrcMatchEnabled = aEnable;
723 static bool sAckedWithFPFifoIsFull(void)
725 return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == otARRAY_LENGTH(sAckedWithFPFifo);
728 static bool sAckedWithFPFifoIsEmpty(void)
730 return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == 0;
733 static efr32AckedWithFP *sAckedWithFPFifoGetWriteSlot(void)
735 uint32_t idx = sAckedWithFPWriteIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1);
736 return &sAckedWithFPFifo[idx];
739 static const efr32AckedWithFP *sAckedWithFPFifoGetReadSlot(void)
741 uint32_t idx = sAckedWithFPReadIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1);
742 return &sAckedWithFPFifo[idx];
745 static void insertIeee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
747 assert(!sAckedWithFPFifoIsFull());
748 efr32AckedWithFP *const slot = sAckedWithFPFifoGetWriteSlot();
750 RAIL_RxPacketInfo_t packetInfo;
752 RAIL_GetRxIncomingPacketInfo(aRailHandle, &packetInfo);
753 assert(packetInfo.packetBytes >= 4); // PHR + FCF + DSN
755 if (packetInfo.packetBytes > sizeof(slot->mPacket))
757 packetInfo.packetBytes = sizeof(slot->mPacket);
758 if (packetInfo.firstPortionBytes >= sizeof(slot->mPacket))
760 packetInfo.firstPortionBytes = sizeof(slot->mPacket);
761 packetInfo.lastPortionData = NULL;
764 slot->mLength = packetInfo.packetBytes;
765 RAIL_CopyRxPacket(slot->mPacket, &packetInfo);
767 ++sAckedWithFPWriteIndex;
770 static bool wasAckedWithFramePending(const uint8_t *aPsdu, uint8_t aPsduLength)
772 bool ackedWithFramePending = false;
773 uint16_t fcf = aPsdu[IEEE802154_FCF_OFFSET] | (aPsdu[IEEE802154_FCF_OFFSET + 1] << 8);
775 otEXPECT((fcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_MAC_COMMAND);
777 while (!(ackedWithFramePending || sAckedWithFPFifoIsEmpty()))
779 const efr32AckedWithFP *const slot = sAckedWithFPFifoGetReadSlot();
780 if ((slot->mPacket[0] == aPsduLength) && (memcmp(slot->mPacket + 1, aPsdu, slot->mLength - 1) == 0))
782 ackedWithFramePending = true;
784 ++sAckedWithFPReadIndex;
788 return ackedWithFramePending;
791 static void processNextRxPacket(otInstance *aInstance)
793 RAIL_RxPacketHandle_t packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
794 RAIL_RxPacketInfo_t packetInfo;
795 RAIL_RxPacketDetails_t packetDetails;
796 RAIL_Status_t status;
799 packetHandle = RAIL_GetRxPacketInfo(gRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST, &packetInfo);
801 otEXPECT_ACTION(packetHandle != RAIL_RX_PACKET_HANDLE_INVALID &&
802 packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS,
803 packetHandle = RAIL_RX_PACKET_HANDLE_INVALID);
805 status = RAIL_GetRxPacketDetailsAlt(gRailHandle, packetHandle, &packetDetails);
806 otEXPECT(status == RAIL_STATUS_NO_ERROR);
808 length = packetInfo.packetBytes + 1;
810 // check the length in recv packet info structure; RAIL should take care of this.
811 assert(length == packetInfo.firstPortionData[0]);
813 // check the length validity of recv packet; RAIL should take care of this.
814 assert(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH);
816 otLogInfoPlat("Received data:%d", length);
819 assert(packetInfo.firstPortionBytes > 0);
820 packetInfo.firstPortionData++;
821 packetInfo.firstPortionBytes--;
822 packetInfo.packetBytes--;
825 RAIL_CopyRxPacket(sReceiveFrame.mPsdu, &packetInfo);
827 status = RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
828 if (status == RAIL_STATUS_NO_ERROR)
830 packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
833 sReceiveFrame.mLength = length;
835 if (packetDetails.isAck)
837 assert((length == IEEE802154_ACK_LENGTH) &&
838 (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK);
840 RAIL_YieldRadio(gRailHandle);
841 sTransmitBusy = false;
843 if (sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
845 sTransmitError = OT_ERROR_NONE;
849 sTransmitError = OT_ERROR_NO_ACK;
854 // signal MAC layer for each received frame if promiscuous is enabled
855 // otherwise only signal MAC layer for non-ACK frame
856 otEXPECT(sPromiscuous || (length != IEEE802154_ACK_LENGTH));
858 sReceiveError = OT_ERROR_NONE;
860 sReceiveFrame.mInfo.mRxInfo.mRssi = packetDetails.rssi;
861 sReceiveFrame.mInfo.mRxInfo.mLqi = packetDetails.lqi;
863 // Get the timestamp when the SFD was received
864 assert(packetDetails.timeReceived.timePosition != RAIL_PACKET_TIME_INVALID);
865 packetDetails.timeReceived.totalPacketBytes = length + 1;
867 status = RAIL_GetRxTimeSyncWordEndAlt(gRailHandle, &packetDetails);
868 assert(status == RAIL_STATUS_NO_ERROR);
869 sReceiveFrame.mInfo.mRxInfo.mTimestamp = packetDetails.timeReceived.packetTime;
871 // Set this flag only when the packet is really acknowledged with frame pending set.
872 sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending =
873 wasAckedWithFramePending(sReceiveFrame.mPsdu, sReceiveFrame.mLength);
875 #if OPENTHREAD_CONFIG_DIAG_ENABLE
877 if (otPlatDiagModeGet())
879 otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
884 otLogInfoPlat("Received %d bytes", sReceiveFrame.mLength);
885 otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
886 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
887 sRailDebugCounters.mRailPlatRadioReceiveDoneCbCount++;
892 otSysEventSignalPending();
896 if (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID)
898 RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
902 static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
904 RAIL_Status_t status;
906 if (sIsSrcMatchEnabled)
908 RAIL_IEEE802154_Address_t sourceAddress;
910 status = RAIL_IEEE802154_GetAddress(aRailHandle, &sourceAddress);
911 assert(status == RAIL_STATUS_NO_ERROR);
913 if ((sourceAddress.length == RAIL_IEEE802154_LongAddress &&
914 utilsSoftSrcMatchExtFindEntry((otExtAddress *)sourceAddress.longAddress) >= 0) ||
915 (sourceAddress.length == RAIL_IEEE802154_ShortAddress &&
916 utilsSoftSrcMatchShortFindEntry(sourceAddress.shortAddress) >= 0))
918 status = RAIL_IEEE802154_SetFramePending(aRailHandle);
919 assert(status == RAIL_STATUS_NO_ERROR);
920 insertIeee802154DataRequestCommand(aRailHandle);
925 status = RAIL_IEEE802154_SetFramePending(aRailHandle);
926 assert(status == RAIL_STATUS_NO_ERROR);
927 insertIeee802154DataRequestCommand(aRailHandle);
931 static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
933 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
934 if (aEvents & RAIL_EVENT_CONFIG_SCHEDULED)
936 sRailDebugCounters.mRailEventConfigScheduled++;
938 if (aEvents & RAIL_EVENT_CONFIG_UNSCHEDULED)
940 sRailDebugCounters.mRailEventConfigUnScheduled++;
943 if (aEvents & RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND)
945 ieee802154DataRequestCommand(aRailHandle);
948 if (aEvents & RAIL_EVENTS_TX_COMPLETION)
950 if (aEvents & RAIL_EVENT_TX_PACKET_SENT)
952 if ((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
954 RAIL_YieldRadio(aRailHandle);
955 sTransmitError = OT_ERROR_NONE;
956 sTransmitBusy = false;
958 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
959 sRailDebugCounters.mRailEventPacketSent++;
962 else if (aEvents & RAIL_EVENT_TX_CHANNEL_BUSY)
964 RAIL_YieldRadio(aRailHandle);
965 sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
966 sTransmitBusy = false;
967 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
968 sRailDebugCounters.mRailEventChannelBusy++;
973 RAIL_YieldRadio(aRailHandle);
974 sTransmitError = OT_ERROR_ABORT;
975 sTransmitBusy = false;
976 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
977 sRailDebugCounters.mRailEventTxAbort++;
982 if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT)
984 RAIL_YieldRadio(aRailHandle);
985 sTransmitError = OT_ERROR_NO_ACK;
986 sTransmitBusy = false;
987 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
988 sRailDebugCounters.mRailEventNoAck++;
992 if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED)
994 RAIL_HoldRxPacket(aRailHandle);
995 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
996 sRailDebugCounters.mRailEventPacketReceived++;
1000 if (aEvents & RAIL_EVENT_CAL_NEEDED)
1002 RAIL_Status_t status;
1004 status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING);
1005 assert(status == RAIL_STATUS_NO_ERROR);
1007 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
1008 sRailDebugCounters.mRailEventCalNeeded++;
1012 if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
1014 const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
1015 RAIL_YieldRadio(aRailHandle);
1017 sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
1019 if (energyScanResultQuarterDbm == RAIL_RSSI_INVALID)
1021 sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
1025 sEnergyScanResultDbm = energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM;
1028 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
1029 sRailDebugCounters.mRailPlatRadioEnergyScanDoneCbCount++;
1032 if (aEvents & RAIL_EVENT_SCHEDULER_STATUS)
1034 RAIL_SchedulerStatus_t status = RAIL_GetSchedulerStatus(aRailHandle);
1036 assert(status != RAIL_SCHEDULER_STATUS_INTERNAL_ERROR);
1038 if (status == RAIL_SCHEDULER_STATUS_CCA_CSMA_TX_FAIL || status == RAIL_SCHEDULER_STATUS_SINGLE_TX_FAIL ||
1039 status == RAIL_SCHEDULER_STATUS_SCHEDULED_TX_FAIL ||
1040 (status == RAIL_SCHEDULER_STATUS_SCHEDULE_FAIL && sTransmitBusy) ||
1041 (status == RAIL_SCHEDULER_STATUS_EVENT_INTERRUPTED && sTransmitBusy))
1043 sTransmitError = OT_ERROR_ABORT;
1044 sTransmitBusy = false;
1045 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
1046 sRailDebugCounters.mRailEventSchedulerStatusError++;
1049 else if (status == RAIL_SCHEDULER_STATUS_AVERAGE_RSSI_FAIL)
1051 sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
1052 sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
1054 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
1055 else if (sTransmitBusy)
1057 sRailDebugCounters.mRailEventsSchedulerStatusLastStatus = status;
1058 sRailDebugCounters.mRailEventsSchedulerStatusTransmitBusy++;
1063 otSysEventSignalPending();
1066 otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
1068 OT_UNUSED_VARIABLE(aInstance);
1070 return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
1073 void efr32RadioProcess(otInstance *aInstance)
1075 // We should process the received packet first. Adding it at the end of this function,
1076 // will delay the stack notification until the next call to efr32RadioProcess()
1077 processNextRxPacket(aInstance);
1079 if (sState == OT_RADIO_STATE_TRANSMIT && sTransmitBusy == false)
1081 if (sTransmitError != OT_ERROR_NONE)
1083 otLogDebgPlat("Transmit failed ErrorCode=%d", sTransmitError);
1086 sState = OT_RADIO_STATE_RECEIVE;
1087 #if OPENTHREAD_CONFIG_DIAG_ENABLE
1088 if (otPlatDiagModeGet())
1090 otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
1094 if (((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0) || (sTransmitError != OT_ERROR_NONE))
1096 otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
1100 otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveFrame, sTransmitError);
1103 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
1104 sRailDebugCounters.mRailPlatRadioTxDoneCbCount++;
1107 otSysEventSignalPending();
1109 else if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
1111 sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
1112 otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
1113 otSysEventSignalPending();
1115 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
1116 sRailDebugCounters.mRailEventEnergyScanCompleted++;
1121 otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
1123 OT_UNUSED_VARIABLE(aInstance);
1125 otError error = OT_ERROR_NONE;
1127 otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS);
1128 *aPower = sTxPowerDbm;
1134 otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
1136 OT_UNUSED_VARIABLE(aInstance);
1138 RAIL_Status_t status;
1140 status = RAIL_SetTxPowerDbm(gRailHandle, ((RAIL_TxPower_t)aPower) * 10);
1141 assert(status == RAIL_STATUS_NO_ERROR);
1143 sTxPowerDbm = aPower;
1145 return OT_ERROR_NONE;
1148 otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
1150 OT_UNUSED_VARIABLE(aInstance);
1152 otError error = OT_ERROR_NONE;
1153 otEXPECT_ACTION(aThreshold != NULL, error = OT_ERROR_INVALID_ARGS);
1155 *aThreshold = sCcaThresholdDbm;
1161 otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
1163 OT_UNUSED_VARIABLE(aInstance);
1165 sCcaThresholdDbm = aThreshold;
1167 return OT_ERROR_NONE;
1170 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
1172 OT_UNUSED_VARIABLE(aInstance);
1174 return EFR32_RECEIVE_SENSITIVITY;