2 * Copyright (c) 2019, 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/platform/alarm-milli.h>
42 #include <openthread/platform/diag.h>
43 #include <openthread/platform/radio.h>
45 #include "common/logging.hpp"
46 #include "utils/code_utils.h"
48 #include "utils/soft_source_match_table.h"
50 #include "board_config.h"
53 #include "em_system.h"
54 #include "pa_conversions_efr32.h"
55 #include "platform-band.h"
57 #include "rail_config.h"
58 #include "rail_ieee802154.h"
62 IEEE802154_MIN_LENGTH = 5,
63 IEEE802154_MAX_LENGTH = 127,
64 IEEE802154_ACK_LENGTH = 5,
65 IEEE802154_FRAME_TYPE_MASK = 0x7,
66 IEEE802154_FRAME_TYPE_ACK = 0x2,
67 IEEE802154_FRAME_PENDING = 1 << 4,
68 IEEE802154_ACK_REQUEST = 1 << 5,
69 IEEE802154_DSN_OFFSET = 2,
74 EFR32_RECEIVE_SENSITIVITY = -100, // dBm
75 EFR32_RSSI_AVERAGING_TIME = 16, // us
76 EFR32_RSSI_AVERAGING_TIMEOUT = 300, // us
81 EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY = 10, // High priority
82 EFR32_SCHEDULER_TX_PRIORITY = 10, // High priority
83 EFR32_SCHEDULER_RX_PRIORITY = 20, // Low priority
88 EFR32_NUM_BAND_CONFIGS = 1,
93 ENERGY_SCAN_STATUS_IDLE,
94 ENERGY_SCAN_STATUS_IN_PROGRESS,
95 ENERGY_SCAN_STATUS_COMPLETED
100 ENERGY_SCAN_MODE_SYNC,
101 ENERGY_SCAN_MODE_ASYNC
104 RAIL_Handle_t gRailHandle;
106 static volatile bool sTransmitBusy = false;
107 static bool sPromiscuous = false;
108 static bool sIsSrcMatchEnabled = false;
109 static otRadioState sState = OT_RADIO_STATE_DISABLED;
111 static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH];
112 static otRadioFrame sReceiveFrame;
113 static otError sReceiveError;
115 static otRadioFrame sTransmitFrame;
116 static uint8_t sTransmitPsdu[IEEE802154_MAX_LENGTH];
117 static volatile otError sTransmitError;
119 static efr32BandConfig sBandConfigs[EFR32_NUM_BAND_CONFIGS];
121 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
122 static efr32RadioCounters sRailDebugCounters;
125 static volatile energyScanStatus sEnergyScanStatus;
126 static volatile int8_t sEnergyScanResultDbm;
127 static energyScanMode sEnergyScanMode;
129 #define QUARTER_DBM_IN_DBM 4
130 #define US_IN_MS 1000
132 static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents);
134 static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
138 true, // ackConfig.enable
139 894, // ackConfig.ackTimeout
141 // ackConfig.rxTransitions
142 RAIL_RF_STATE_RX, // ackConfig.rxTransitions.success
143 RAIL_RF_STATE_RX, // ackConfig.rxTransitions.error
146 // ackConfig.txTransitions
147 RAIL_RF_STATE_RX, // ackConfig.txTransitions.success
148 RAIL_RF_STATE_RX, // ackConfig.txTransitions.error
153 100, // timings.idleToRx
154 192 - 10, // timings.txToRx
155 100, // timings.idleToTx
156 192, // timings.rxToTx
157 0, // timings.rxSearchTimeout
158 0, // timings.txToRxSearchTimeout
160 RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES, // framesMask
161 false, // promiscuousMode
162 false, // isPanCoordinator
165 RAIL_DECLARE_TX_POWER_VBAT_CURVES_ALT;
167 static int8_t sTxPowerDbm = OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER;
169 static efr32BandConfig *sTxBandConfig = NULL;
170 static efr32BandConfig *sRxBandConfig = NULL;
172 static RAIL_Handle_t efr32RailConfigInit(efr32BandConfig *aBandConfig)
174 RAIL_Status_t status;
175 RAIL_Handle_t handle;
176 RAIL_DataConfig_t railDataConfig = {
183 handle = RAIL_Init(&aBandConfig->mRailConfig, NULL);
184 assert(handle != NULL);
186 status = RAIL_ConfigData(handle, &railDataConfig);
187 assert(status == RAIL_STATUS_NO_ERROR);
189 RAIL_Idle(handle, RAIL_IDLE, true);
191 status = RAIL_ConfigCal(handle, RAIL_CAL_ALL);
192 assert(status == RAIL_STATUS_NO_ERROR);
194 if (aBandConfig->mChannelConfig != NULL)
196 RAIL_ConfigChannels(handle, aBandConfig->mChannelConfig, NULL);
200 status = RAIL_IEEE802154_Config2p4GHzRadio(handle);
201 assert(status == RAIL_STATUS_NO_ERROR);
204 status = RAIL_IEEE802154_Init(handle, &sRailIeee802154Config);
205 assert(status == RAIL_STATUS_NO_ERROR);
207 status = RAIL_ConfigEvents(handle, RAIL_EVENTS_ALL,
208 RAIL_EVENT_RX_ACK_TIMEOUT | //
209 RAIL_EVENTS_TX_COMPLETION | //
210 RAIL_EVENT_RX_PACKET_RECEIVED | //
211 RAIL_EVENT_RSSI_AVERAGE_DONE | //
212 RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND | //
213 RAIL_EVENT_CAL_NEEDED | //
214 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
215 RAIL_EVENT_CONFIG_SCHEDULED | //
216 RAIL_EVENT_CONFIG_UNSCHEDULED | //
218 RAIL_EVENT_SCHEDULER_STATUS //
220 assert(status == RAIL_STATUS_NO_ERROR);
222 uint16_t actualLength = RAIL_SetTxFifo(handle, aBandConfig->mRailTxFifo, 0, sizeof(aBandConfig->mRailTxFifo));
223 assert(actualLength == sizeof(aBandConfig->mRailTxFifo));
228 static void efr32RadioSetTxPower(RAIL_Handle_t aRailHandle,
229 const RAIL_ChannelConfig_t *aChannelConfig,
232 RAIL_Status_t status;
233 const RAIL_TxPowerCurvesConfigAlt_t txPowerCurvesConfig = RAIL_DECLARE_TX_POWER_CURVES_CONFIG_ALT;
234 RAIL_TxPowerConfig_t txPowerConfig = {RAIL_TX_POWER_MODE_2P4_HP, 3300, 10};
236 status = RAIL_InitTxPowerCurvesAlt(&txPowerCurvesConfig);
237 assert(status == RAIL_STATUS_NO_ERROR);
239 status = RAIL_ConfigTxPower(aRailHandle, &txPowerConfig);
240 assert(status == RAIL_STATUS_NO_ERROR);
242 status = RAIL_SetTxPowerDbm(aRailHandle, ((RAIL_TxPower_t)aPowerDbm) * 10);
243 assert(status == RAIL_STATUS_NO_ERROR);
246 static efr32BandConfig *efr32RadioGetBandConfig(uint8_t aChannel)
248 efr32BandConfig *config = NULL;
250 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
252 if ((sBandConfigs[i].mChannelMin <= aChannel) && (aChannel <= sBandConfigs[i].mChannelMax))
254 config = &sBandConfigs[i];
262 static void efr32BandConfigInit(void (*aEventCallback)(RAIL_Handle_t railHandle, RAIL_Events_t events))
266 #if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT
267 sBandConfigs[index].mRailConfig.eventsCallback = aEventCallback;
268 sBandConfigs[index].mRailConfig.protocol = NULL;
269 sBandConfigs[index].mRailConfig.scheduler = &sBandConfigs[index].mRailSchedState;
270 sBandConfigs[index].mChannelConfig = NULL;
271 sBandConfigs[index].mChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
272 sBandConfigs[index].mChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
274 assert((sBandConfigs[index].mRailHandle = efr32RailConfigInit(&sBandConfigs[index])) != NULL);
279 void efr32RadioInit(void)
281 efr32BandConfigInit(RAILCb_Generic);
283 sReceiveFrame.mLength = 0;
284 sReceiveFrame.mPsdu = sReceivePsdu;
285 sTransmitFrame.mLength = 0;
286 sTransmitFrame.mPsdu = sTransmitPsdu;
288 sRxBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL);
289 assert(sRxBandConfig != NULL);
291 sTxBandConfig = sRxBandConfig;
292 efr32RadioSetTxPower(sTxBandConfig->mRailHandle, sTxBandConfig->mChannelConfig, sTxPowerDbm);
294 gRailHandle = sTxBandConfig->mRailHandle; // global handle for alarms.
296 sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
297 sTransmitError = OT_ERROR_NONE;
298 sTransmitBusy = false;
300 otLogInfoPlat("Initialized", NULL);
303 void efr32RadioDeinit(void)
305 RAIL_Status_t status;
307 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
309 RAIL_Idle(sBandConfigs[i].mRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true);
311 status = RAIL_IEEE802154_Deinit(sBandConfigs[i].mRailHandle);
312 assert(status == RAIL_STATUS_NO_ERROR);
314 sBandConfigs[i].mRailHandle = NULL;
317 sTxBandConfig = NULL;
318 sRxBandConfig = NULL;
321 static otError efr32StartEnergyScan(energyScanMode aMode, uint16_t aChannel, RAIL_Time_t aAveragingTimeUs)
323 RAIL_Status_t status;
324 otError error = OT_ERROR_NONE;
326 otEXPECT_ACTION(sEnergyScanStatus == ENERGY_SCAN_STATUS_IDLE, error = OT_ERROR_BUSY);
328 sEnergyScanStatus = ENERGY_SCAN_STATUS_IN_PROGRESS;
329 sEnergyScanMode = aMode;
331 RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, true);
333 RAIL_SchedulerInfo_t scanSchedulerInfo = {.priority = RADIO_SCHEDULER_CHANNEL_SCAN_PRIORITY,
334 .slipTime = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
335 .transactionTime = aAveragingTimeUs};
337 status = RAIL_StartAverageRssi(sRxBandConfig->mRailHandle, aChannel, aAveragingTimeUs, &scanSchedulerInfo);
338 otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
344 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
346 OT_UNUSED_VARIABLE(aInstance);
349 uint8_t *eui64Ptr = NULL;
351 eui64 = SYSTEM_GetUnique();
352 eui64Ptr = (uint8_t *)&eui64;
354 for (uint8_t i = 0; i < OT_EXT_ADDRESS_SIZE; i++)
356 aIeeeEui64[i] = eui64Ptr[(OT_EXT_ADDRESS_SIZE - 1) - i];
360 void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
362 OT_UNUSED_VARIABLE(aInstance);
364 RAIL_Status_t status;
366 otLogInfoPlat("PANID=%X", aPanId);
368 utilsSoftSrcMatchSetPanId(aPanId);
370 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
372 status = RAIL_IEEE802154_SetPanId(sBandConfigs[i].mRailHandle, aPanId, 0);
373 assert(status == RAIL_STATUS_NO_ERROR);
377 void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
379 OT_UNUSED_VARIABLE(aInstance);
381 RAIL_Status_t status;
383 otLogInfoPlat("ExtAddr=%X%X%X%X%X%X%X%X", aAddress->m8[7], aAddress->m8[6], aAddress->m8[5], aAddress->m8[4],
384 aAddress->m8[3], aAddress->m8[2], aAddress->m8[1], aAddress->m8[0]);
386 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
388 status = RAIL_IEEE802154_SetLongAddress(sBandConfigs[i].mRailHandle, (uint8_t *)aAddress->m8, 0);
389 assert(status == RAIL_STATUS_NO_ERROR);
393 void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress)
395 OT_UNUSED_VARIABLE(aInstance);
397 RAIL_Status_t status;
399 otLogInfoPlat("ShortAddr=%X", aAddress);
401 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
403 status = RAIL_IEEE802154_SetShortAddress(sBandConfigs[i].mRailHandle, aAddress, 0);
404 assert(status == RAIL_STATUS_NO_ERROR);
408 bool otPlatRadioIsEnabled(otInstance *aInstance)
410 OT_UNUSED_VARIABLE(aInstance);
412 return (sState != OT_RADIO_STATE_DISABLED);
415 otError otPlatRadioEnable(otInstance *aInstance)
417 otEXPECT(!otPlatRadioIsEnabled(aInstance));
419 otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
420 sState = OT_RADIO_STATE_SLEEP;
423 return OT_ERROR_NONE;
426 otError otPlatRadioDisable(otInstance *aInstance)
428 otEXPECT(otPlatRadioIsEnabled(aInstance));
430 otLogInfoPlat("State=OT_RADIO_STATE_DISABLED", NULL);
431 sState = OT_RADIO_STATE_DISABLED;
434 return OT_ERROR_NONE;
437 otError otPlatRadioSleep(otInstance *aInstance)
439 OT_UNUSED_VARIABLE(aInstance);
441 otError error = OT_ERROR_NONE;
443 otEXPECT_ACTION((sState != OT_RADIO_STATE_TRANSMIT) && (sState != OT_RADIO_STATE_DISABLED),
444 error = OT_ERROR_INVALID_STATE);
446 otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
448 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
450 RAIL_Idle(sBandConfigs[i].mRailHandle, RAIL_IDLE, true);
452 sState = OT_RADIO_STATE_SLEEP;
458 otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
460 otError error = OT_ERROR_NONE;
461 RAIL_Status_t status;
462 efr32BandConfig *config;
464 OT_UNUSED_VARIABLE(aInstance);
465 otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, error = OT_ERROR_INVALID_STATE);
467 config = efr32RadioGetBandConfig(aChannel);
468 otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
470 if (sRxBandConfig != config)
472 RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, false);
473 sRxBandConfig = config;
476 RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
477 .priority = RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY,
478 // sliptime/transaction time is not used for bg rx
481 status = RAIL_StartRx(sRxBandConfig->mRailHandle, aChannel, &bgRxSchedulerInfo);
482 otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
484 otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL);
485 sState = OT_RADIO_STATE_RECEIVE;
486 sReceiveFrame.mChannel = aChannel;
492 otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
494 otError error = OT_ERROR_NONE;
495 RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
496 RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_NONE;
497 efr32BandConfig * config;
498 RAIL_Status_t status;
501 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
502 sRailDebugCounters.mRailPlatTxTriggered++;
505 assert(sTransmitBusy == false);
507 otEXPECT_ACTION((sState != OT_RADIO_STATE_DISABLED) && (sState != OT_RADIO_STATE_TRANSMIT),
508 error = OT_ERROR_INVALID_STATE);
510 config = efr32RadioGetBandConfig(aFrame->mChannel);
511 otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
513 sState = OT_RADIO_STATE_TRANSMIT;
514 sTransmitError = OT_ERROR_NONE;
515 sTransmitBusy = true;
517 if (sTxBandConfig != config)
519 efr32RadioSetTxPower(config->mRailHandle, config->mChannelConfig, sTxPowerDbm);
520 sTxBandConfig = config;
523 frameLength = (uint8_t)aFrame->mLength;
524 RAIL_WriteTxFifo(sTxBandConfig->mRailHandle, &frameLength, sizeof frameLength, true);
525 RAIL_WriteTxFifo(sTxBandConfig->mRailHandle, aFrame->mPsdu, frameLength - 2, false);
527 RAIL_SchedulerInfo_t txSchedulerInfo = {
528 .priority = RADIO_SCHEDULER_TX_PRIORITY,
529 .slipTime = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
530 .transactionTime = 0, // will be calculated later if DMP is used
533 if (aFrame->mPsdu[0] & IEEE802154_ACK_REQUEST)
535 txOptions |= RAIL_TX_OPTION_WAIT_FOR_ACK;
537 #if RADIO_CONFIG_DMP_SUPPORT
538 // time we wait for ACK
539 if (RAIL_GetSymbolRate(gRailHandle) > 0)
541 txSchedulerInfo.transactionTime += 12 * 1e6 / RAIL_GetSymbolRate(gRailHandle);
545 txSchedulerInfo.transactionTime += 12 * RADIO_TIMING_DEFAULT_SYMBOLTIME_US;
550 #if RADIO_CONFIG_DMP_SUPPORT
551 // time needed for the frame itself
552 // 4B preamble, 1B SFD, 1B PHR is not counted in frameLength
553 if (RAIL_GetBitRate(gRailHandle) > 0)
555 txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * 8 * 1e6 / RAIL_GetBitRate(gRailHandle);
559 txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * RADIO_TIMING_DEFAULT_BYTETIME_US;
563 if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
565 #if RADIO_CONFIG_DMP_SUPPORT
566 // time needed for CSMA/CA
567 txSchedulerInfo.transactionTime += RADIO_TIMING_CSMA_OVERHEAD_US;
570 RAIL_StartCcaCsmaTx(sTxBandConfig->mRailHandle, aFrame->mChannel, txOptions, &csmaConfig, &txSchedulerInfo);
574 status = RAIL_StartTx(sTxBandConfig->mRailHandle, aFrame->mChannel, txOptions, &txSchedulerInfo);
577 if (status == RAIL_STATUS_NO_ERROR)
579 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
580 sRailDebugCounters.mRailTxStarted++;
582 otPlatRadioTxStarted(aInstance, aFrame);
586 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
587 sRailDebugCounters.mRailTxStartFailed++;
589 sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
590 sTransmitBusy = false;
597 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
599 OT_UNUSED_VARIABLE(aInstance);
601 return &sTransmitFrame;
604 int8_t otPlatRadioGetRssi(otInstance *aInstance)
608 int8_t rssi = OT_RADIO_RSSI_INVALID;
610 OT_UNUSED_VARIABLE(aInstance);
612 error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME);
613 otEXPECT(error == OT_ERROR_NONE);
615 start = RAIL_GetTime();
617 // waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE
618 while (sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS &&
619 ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT))
622 if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
624 rssi = sEnergyScanResultDbm;
627 sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
632 otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
634 OT_UNUSED_VARIABLE(aInstance);
636 return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN;
639 bool otPlatRadioGetPromiscuous(otInstance *aInstance)
641 OT_UNUSED_VARIABLE(aInstance);
646 void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
648 OT_UNUSED_VARIABLE(aInstance);
650 RAIL_Status_t status;
652 sPromiscuous = aEnable;
654 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
656 status = RAIL_IEEE802154_SetPromiscuousMode(sBandConfigs[i].mRailHandle, aEnable);
657 assert(status == RAIL_STATUS_NO_ERROR);
661 void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
663 OT_UNUSED_VARIABLE(aInstance);
665 // set Frame Pending bit for all outgoing ACKs if aEnable is false
666 sIsSrcMatchEnabled = aEnable;
669 static void processNextRxPacket(otInstance *aInstance, RAIL_Handle_t aRailHandle)
671 RAIL_RxPacketHandle_t packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
672 RAIL_RxPacketInfo_t packetInfo;
673 RAIL_RxPacketDetails_t packetDetails;
674 RAIL_Status_t status;
677 packetHandle = RAIL_GetRxPacketInfo(aRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST, &packetInfo);
679 otEXPECT_ACTION(packetHandle != RAIL_RX_PACKET_HANDLE_INVALID &&
680 packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS,
681 packetHandle = RAIL_RX_PACKET_HANDLE_INVALID);
683 packetDetails.timeReceived.timePosition = RAIL_PACKET_TIME_INVALID;
684 packetDetails.timeReceived.totalPacketBytes = 0;
685 status = RAIL_GetRxPacketDetails(aRailHandle, packetHandle, &packetDetails);
686 otEXPECT(status == RAIL_STATUS_NO_ERROR);
688 length = packetInfo.packetBytes + 1;
690 // check the length in recv packet info structure
691 otEXPECT(length == packetInfo.firstPortionData[0]);
693 // check the length validity of recv packet
694 otEXPECT(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH);
696 otLogInfoPlat("Received data:%d", length);
699 assert(packetInfo.firstPortionBytes > 0);
700 packetInfo.firstPortionData++;
701 packetInfo.firstPortionBytes--;
702 packetInfo.packetBytes--;
705 memcpy(sReceiveFrame.mPsdu, packetInfo.firstPortionData, packetInfo.firstPortionBytes);
706 memcpy(sReceiveFrame.mPsdu + packetInfo.firstPortionBytes, packetInfo.lastPortionData,
707 packetInfo.packetBytes - packetInfo.firstPortionBytes);
709 status = RAIL_ReleaseRxPacket(aRailHandle, packetHandle);
710 if (status == RAIL_STATUS_NO_ERROR)
712 packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
715 sReceiveFrame.mLength = length;
717 if (packetDetails.isAck)
719 assert((length == IEEE802154_ACK_LENGTH) &&
720 (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK);
722 RAIL_YieldRadio(gRailHandle);
723 sTransmitBusy = false;
725 if (sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
727 sTransmitError = OT_ERROR_NONE;
731 sTransmitError = OT_ERROR_NO_ACK;
736 otEXPECT(length != IEEE802154_ACK_LENGTH);
738 sReceiveError = OT_ERROR_NONE;
740 sReceiveFrame.mInfo.mRxInfo.mRssi = packetDetails.rssi;
741 sReceiveFrame.mInfo.mRxInfo.mLqi = packetDetails.lqi;
743 // TODO: grab timestamp and handle conversion to msec/usec and RAIL_GetRxTimeSyncWordEndAlt
744 // sReceiveFrame.mInfo.mRxInfo.mMsec = packetDetails.packetTime;
745 // sReceiveFrame.mInfo.mRxInfo.mUsec = packetDetails.packetTime;
747 // TODO Set this flag only when the packet is really acknowledged with frame pending set.
748 // See https://github.com/openthread/openthread/pull/3785
749 sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = true;
751 #if OPENTHREAD_CONFIG_DIAG_ENABLE
753 if (otPlatDiagModeGet())
755 otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
760 // signal MAC layer for each received frame if promiscuous is enabled
761 // otherwise only signal MAC layer for non-ACK frame
762 if (sPromiscuous || sReceiveFrame.mLength > IEEE802154_ACK_LENGTH)
764 otLogInfoPlat("Received %d bytes", sReceiveFrame.mLength);
765 otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
766 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
767 sRailDebugCounters.mRailPlatRadioReceiveDoneCbCount++;
773 otSysEventSignalPending();
777 if (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID)
779 RAIL_ReleaseRxPacket(aRailHandle, packetHandle);
783 static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
785 RAIL_Status_t status;
787 if (sIsSrcMatchEnabled)
789 RAIL_IEEE802154_Address_t sourceAddress;
791 status = RAIL_IEEE802154_GetAddress(aRailHandle, &sourceAddress);
792 assert(status == RAIL_STATUS_NO_ERROR);
794 if ((sourceAddress.length == RAIL_IEEE802154_LongAddress &&
795 utilsSoftSrcMatchExtFindEntry((otExtAddress *)sourceAddress.longAddress) >= 0) ||
796 (sourceAddress.length == RAIL_IEEE802154_ShortAddress &&
797 utilsSoftSrcMatchShortFindEntry(sourceAddress.shortAddress) >= 0))
799 status = RAIL_IEEE802154_SetFramePending(aRailHandle);
800 assert(status == RAIL_STATUS_NO_ERROR);
805 status = RAIL_IEEE802154_SetFramePending(aRailHandle);
806 assert(status == RAIL_STATUS_NO_ERROR);
810 static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
812 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
813 if (aEvents & RAIL_EVENT_CONFIG_SCHEDULED)
815 sRailDebugCounters.mRailEventConfigScheduled++;
817 if (aEvents & RAIL_EVENT_CONFIG_UNSCHEDULED)
819 sRailDebugCounters.mRailEventConfigUnScheduled++;
822 if (aEvents & RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND)
824 ieee802154DataRequestCommand(aRailHandle);
826 if (aEvents & RAIL_EVENTS_TX_COMPLETION)
828 if (aEvents & RAIL_EVENT_TX_PACKET_SENT)
830 if ((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
832 RAIL_YieldRadio(aRailHandle);
833 sTransmitError = OT_ERROR_NONE;
834 sTransmitBusy = false;
836 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
837 sRailDebugCounters.mRailEventPacketSent++;
840 else if (aEvents & RAIL_EVENT_TX_CHANNEL_BUSY)
842 RAIL_YieldRadio(aRailHandle);
843 sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
844 sTransmitBusy = false;
845 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
846 sRailDebugCounters.mRailEventChannelBusy++;
851 RAIL_YieldRadio(aRailHandle);
852 sTransmitError = OT_ERROR_ABORT;
853 sTransmitBusy = false;
854 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
855 sRailDebugCounters.mRailEventTxAbort++;
860 if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT)
862 RAIL_YieldRadio(aRailHandle);
863 sTransmitError = OT_ERROR_NO_ACK;
864 sTransmitBusy = false;
865 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
866 sRailDebugCounters.mRailEventNoAck++;
870 if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED)
872 RAIL_HoldRxPacket(aRailHandle);
873 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
874 sRailDebugCounters.mRailEventPacketReceived++;
878 if (aEvents & RAIL_EVENT_CAL_NEEDED)
880 RAIL_Status_t status;
882 status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING);
883 assert(status == RAIL_STATUS_NO_ERROR);
885 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
886 sRailDebugCounters.mRailEventCalNeeded++;
890 if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
892 const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
893 RAIL_YieldRadio(aRailHandle);
895 sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
897 if (energyScanResultQuarterDbm == RAIL_RSSI_INVALID)
899 sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
903 sEnergyScanResultDbm = energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM;
906 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
907 sRailDebugCounters.mRailPlatRadioEnergyScanDoneCbCount++;
910 if (aEvents & RAIL_EVENT_SCHEDULER_STATUS)
912 RAIL_SchedulerStatus_t status = RAIL_GetSchedulerStatus(aRailHandle);
914 assert(status != RAIL_SCHEDULER_STATUS_INTERNAL_ERROR);
916 if (status == RAIL_SCHEDULER_STATUS_CCA_CSMA_TX_FAIL || status == RAIL_SCHEDULER_STATUS_SINGLE_TX_FAIL ||
917 status == RAIL_SCHEDULER_STATUS_SCHEDULED_TX_FAIL ||
918 (status == RAIL_SCHEDULER_STATUS_SCHEDULE_FAIL && sTransmitBusy) ||
919 (status == RAIL_SCHEDULER_STATUS_EVENT_INTERRUPTED && sTransmitBusy))
921 sTransmitError = OT_ERROR_ABORT;
922 sTransmitBusy = false;
923 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
924 sRailDebugCounters.mRailEventSchedulerStatusError++;
927 else if (status == RAIL_SCHEDULER_STATUS_AVERAGE_RSSI_FAIL)
929 sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
930 sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
932 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
933 else if (sTransmitBusy)
935 sRailDebugCounters.mRailEventsSchedulerStatusLastStatus = status;
936 sRailDebugCounters.mRailEventsSchedulerStatusTransmitBusy++;
941 otSysEventSignalPending();
944 otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
946 OT_UNUSED_VARIABLE(aInstance);
948 return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
951 void efr32RadioProcess(otInstance *aInstance)
953 // We should process the received packet first. Adding it at the end of this function,
954 // will delay the stack notification until the next call to efr32RadioProcess()
955 processNextRxPacket(aInstance, sRxBandConfig->mRailHandle);
957 if (sState == OT_RADIO_STATE_TRANSMIT && sTransmitBusy == false)
959 if (sTransmitError != OT_ERROR_NONE)
961 otLogDebgPlat("Transmit failed ErrorCode=%d", sTransmitError);
964 sState = OT_RADIO_STATE_RECEIVE;
965 #if OPENTHREAD_CONFIG_DIAG_ENABLE
966 if (otPlatDiagModeGet())
968 otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
972 if (((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0) || (sTransmitError != OT_ERROR_NONE))
974 otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
978 otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveFrame, sTransmitError);
981 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
982 sRailDebugCounters.mRailPlatRadioTxDoneCbCount++;
985 otSysEventSignalPending();
987 else if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
989 sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
990 otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
991 otSysEventSignalPending();
993 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
994 sRailDebugCounters.mRailEventEnergyScanCompleted++;
999 otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
1001 OT_UNUSED_VARIABLE(aInstance);
1003 otError error = OT_ERROR_NONE;
1005 otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS);
1006 *aPower = sTxPowerDbm;
1012 otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
1014 OT_UNUSED_VARIABLE(aInstance);
1016 RAIL_Status_t status;
1018 for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
1020 status = RAIL_SetTxPowerDbm(sBandConfigs[i].mRailHandle, ((RAIL_TxPower_t)aPower) * 10);
1021 assert(status == RAIL_STATUS_NO_ERROR);
1024 sTxPowerDbm = aPower;
1026 return OT_ERROR_NONE;
1029 otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
1031 OT_UNUSED_VARIABLE(aInstance);
1032 OT_UNUSED_VARIABLE(aThreshold);
1034 return OT_ERROR_NOT_IMPLEMENTED;
1037 otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
1039 OT_UNUSED_VARIABLE(aInstance);
1040 OT_UNUSED_VARIABLE(aThreshold);
1042 return OT_ERROR_NOT_IMPLEMENTED;
1045 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
1047 OT_UNUSED_VARIABLE(aInstance);
1049 return EFR32_RECEIVE_SENSITIVITY;