9bdd4719ea06d97929d6702bd55d373ffc579d82
[platform/upstream/connectedhomeip.git] / third_party / openthread / repo / examples / platforms / efr32mg21 / radio.c
1 /*
2  *  Copyright (c) 2019, The OpenThread Authors.
3  *  All rights reserved.
4  *
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.
15  *
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.
27  */
28
29 /**
30  * @file
31  *   This file implements the OpenThread platform abstraction for radio communication.
32  *
33  */
34
35 #include <openthread-core-config.h>
36 #include <openthread/config.h>
37
38 #include <assert.h>
39
40 #include "openthread-system.h"
41 #include <openthread/platform/alarm-milli.h>
42 #include <openthread/platform/diag.h>
43 #include <openthread/platform/radio.h>
44
45 #include "common/logging.hpp"
46 #include "utils/code_utils.h"
47
48 #include "utils/soft_source_match_table.h"
49
50 #include "board_config.h"
51 #include "em_cmu.h"
52 #include "em_core.h"
53 #include "em_system.h"
54 #include "pa_conversions_efr32.h"
55 #include "platform-band.h"
56 #include "rail.h"
57 #include "rail_config.h"
58 #include "rail_ieee802154.h"
59
60 enum
61 {
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,
70 };
71
72 enum
73 {
74     EFR32_RECEIVE_SENSITIVITY    = -100, // dBm
75     EFR32_RSSI_AVERAGING_TIME    = 16,   // us
76     EFR32_RSSI_AVERAGING_TIMEOUT = 300,  // us
77 };
78
79 enum
80 {
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
84 };
85
86 enum
87 {
88     EFR32_NUM_BAND_CONFIGS = 1,
89 };
90
91 typedef enum
92 {
93     ENERGY_SCAN_STATUS_IDLE,
94     ENERGY_SCAN_STATUS_IN_PROGRESS,
95     ENERGY_SCAN_STATUS_COMPLETED
96 } energyScanStatus;
97
98 typedef enum
99 {
100     ENERGY_SCAN_MODE_SYNC,
101     ENERGY_SCAN_MODE_ASYNC
102 } energyScanMode;
103
104 RAIL_Handle_t gRailHandle;
105
106 static volatile bool sTransmitBusy      = false;
107 static bool          sPromiscuous       = false;
108 static bool          sIsSrcMatchEnabled = false;
109 static otRadioState  sState             = OT_RADIO_STATE_DISABLED;
110
111 static uint8_t      sReceivePsdu[IEEE802154_MAX_LENGTH];
112 static otRadioFrame sReceiveFrame;
113 static otError      sReceiveError;
114
115 static otRadioFrame     sTransmitFrame;
116 static uint8_t          sTransmitPsdu[IEEE802154_MAX_LENGTH];
117 static volatile otError sTransmitError;
118
119 static efr32BandConfig sBandConfigs[EFR32_NUM_BAND_CONFIGS];
120
121 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
122 static efr32RadioCounters sRailDebugCounters;
123 #endif
124
125 static volatile energyScanStatus sEnergyScanStatus;
126 static volatile int8_t           sEnergyScanResultDbm;
127 static energyScanMode            sEnergyScanMode;
128
129 #define QUARTER_DBM_IN_DBM 4
130 #define US_IN_MS 1000
131
132 static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents);
133
134 static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
135     NULL, // addresses
136     {
137         // ackConfig
138         true, // ackConfig.enable
139         894,  // ackConfig.ackTimeout
140         {
141             // ackConfig.rxTransitions
142             RAIL_RF_STATE_RX, // ackConfig.rxTransitions.success
143             RAIL_RF_STATE_RX, // ackConfig.rxTransitions.error
144         },
145         {
146             // ackConfig.txTransitions
147             RAIL_RF_STATE_RX, // ackConfig.txTransitions.success
148             RAIL_RF_STATE_RX, // ackConfig.txTransitions.error
149         },
150     },
151     {
152         // timings
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
159     },
160     RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES, // framesMask
161     false,                                  // promiscuousMode
162     false,                                  // isPanCoordinator
163 };
164
165 RAIL_DECLARE_TX_POWER_VBAT_CURVES_ALT;
166
167 static int8_t sTxPowerDbm = OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER;
168
169 static efr32BandConfig *sTxBandConfig = NULL;
170 static efr32BandConfig *sRxBandConfig = NULL;
171
172 static RAIL_Handle_t efr32RailConfigInit(efr32BandConfig *aBandConfig)
173 {
174     RAIL_Status_t     status;
175     RAIL_Handle_t     handle;
176     RAIL_DataConfig_t railDataConfig = {
177         TX_PACKET_DATA,
178         RX_PACKET_DATA,
179         PACKET_MODE,
180         PACKET_MODE,
181     };
182
183     handle = RAIL_Init(&aBandConfig->mRailConfig, NULL);
184     assert(handle != NULL);
185
186     status = RAIL_ConfigData(handle, &railDataConfig);
187     assert(status == RAIL_STATUS_NO_ERROR);
188
189     RAIL_Idle(handle, RAIL_IDLE, true);
190
191     status = RAIL_ConfigCal(handle, RAIL_CAL_ALL);
192     assert(status == RAIL_STATUS_NO_ERROR);
193
194     if (aBandConfig->mChannelConfig != NULL)
195     {
196         RAIL_ConfigChannels(handle, aBandConfig->mChannelConfig, NULL);
197     }
198     else
199     {
200         status = RAIL_IEEE802154_Config2p4GHzRadio(handle);
201         assert(status == RAIL_STATUS_NO_ERROR);
202     }
203
204     status = RAIL_IEEE802154_Init(handle, &sRailIeee802154Config);
205     assert(status == RAIL_STATUS_NO_ERROR);
206
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 | //
217 #endif
218                                    RAIL_EVENT_SCHEDULER_STATUS //
219     );
220     assert(status == RAIL_STATUS_NO_ERROR);
221
222     uint16_t actualLength = RAIL_SetTxFifo(handle, aBandConfig->mRailTxFifo, 0, sizeof(aBandConfig->mRailTxFifo));
223     assert(actualLength == sizeof(aBandConfig->mRailTxFifo));
224
225     return handle;
226 }
227
228 static void efr32RadioSetTxPower(RAIL_Handle_t               aRailHandle,
229                                  const RAIL_ChannelConfig_t *aChannelConfig,
230                                  int8_t                      aPowerDbm)
231 {
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};
235
236     status = RAIL_InitTxPowerCurvesAlt(&txPowerCurvesConfig);
237     assert(status == RAIL_STATUS_NO_ERROR);
238
239     status = RAIL_ConfigTxPower(aRailHandle, &txPowerConfig);
240     assert(status == RAIL_STATUS_NO_ERROR);
241
242     status = RAIL_SetTxPowerDbm(aRailHandle, ((RAIL_TxPower_t)aPowerDbm) * 10);
243     assert(status == RAIL_STATUS_NO_ERROR);
244 }
245
246 static efr32BandConfig *efr32RadioGetBandConfig(uint8_t aChannel)
247 {
248     efr32BandConfig *config = NULL;
249
250     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
251     {
252         if ((sBandConfigs[i].mChannelMin <= aChannel) && (aChannel <= sBandConfigs[i].mChannelMax))
253         {
254             config = &sBandConfigs[i];
255             break;
256         }
257     }
258
259     return config;
260 }
261
262 static void efr32BandConfigInit(void (*aEventCallback)(RAIL_Handle_t railHandle, RAIL_Events_t events))
263 {
264     uint8_t index = 0;
265
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;
273
274     assert((sBandConfigs[index].mRailHandle = efr32RailConfigInit(&sBandConfigs[index])) != NULL);
275     index++;
276 #endif
277 }
278
279 void efr32RadioInit(void)
280 {
281     efr32BandConfigInit(RAILCb_Generic);
282
283     sReceiveFrame.mLength  = 0;
284     sReceiveFrame.mPsdu    = sReceivePsdu;
285     sTransmitFrame.mLength = 0;
286     sTransmitFrame.mPsdu   = sTransmitPsdu;
287
288     sRxBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL);
289     assert(sRxBandConfig != NULL);
290
291     sTxBandConfig = sRxBandConfig;
292     efr32RadioSetTxPower(sTxBandConfig->mRailHandle, sTxBandConfig->mChannelConfig, sTxPowerDbm);
293
294     gRailHandle = sTxBandConfig->mRailHandle; // global handle for alarms.
295
296     sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
297     sTransmitError    = OT_ERROR_NONE;
298     sTransmitBusy     = false;
299
300     otLogInfoPlat("Initialized", NULL);
301 }
302
303 void efr32RadioDeinit(void)
304 {
305     RAIL_Status_t status;
306
307     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
308     {
309         RAIL_Idle(sBandConfigs[i].mRailHandle, RAIL_IDLE_FORCE_SHUTDOWN_CLEAR_FLAGS, true);
310
311         status = RAIL_IEEE802154_Deinit(sBandConfigs[i].mRailHandle);
312         assert(status == RAIL_STATUS_NO_ERROR);
313
314         sBandConfigs[i].mRailHandle = NULL;
315     }
316
317     sTxBandConfig = NULL;
318     sRxBandConfig = NULL;
319 }
320
321 static otError efr32StartEnergyScan(energyScanMode aMode, uint16_t aChannel, RAIL_Time_t aAveragingTimeUs)
322 {
323     RAIL_Status_t status;
324     otError       error = OT_ERROR_NONE;
325
326     otEXPECT_ACTION(sEnergyScanStatus == ENERGY_SCAN_STATUS_IDLE, error = OT_ERROR_BUSY);
327
328     sEnergyScanStatus = ENERGY_SCAN_STATUS_IN_PROGRESS;
329     sEnergyScanMode   = aMode;
330
331     RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, true);
332
333     RAIL_SchedulerInfo_t scanSchedulerInfo = {.priority        = RADIO_SCHEDULER_CHANNEL_SCAN_PRIORITY,
334                                               .slipTime        = RADIO_SCHEDULER_CHANNEL_SLIP_TIME,
335                                               .transactionTime = aAveragingTimeUs};
336
337     status = RAIL_StartAverageRssi(sRxBandConfig->mRailHandle, aChannel, aAveragingTimeUs, &scanSchedulerInfo);
338     otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
339
340 exit:
341     return error;
342 }
343
344 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
345 {
346     OT_UNUSED_VARIABLE(aInstance);
347
348     uint64_t eui64;
349     uint8_t *eui64Ptr = NULL;
350
351     eui64    = SYSTEM_GetUnique();
352     eui64Ptr = (uint8_t *)&eui64;
353
354     for (uint8_t i = 0; i < OT_EXT_ADDRESS_SIZE; i++)
355     {
356         aIeeeEui64[i] = eui64Ptr[(OT_EXT_ADDRESS_SIZE - 1) - i];
357     }
358 }
359
360 void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
361 {
362     OT_UNUSED_VARIABLE(aInstance);
363
364     RAIL_Status_t status;
365
366     otLogInfoPlat("PANID=%X", aPanId);
367
368     utilsSoftSrcMatchSetPanId(aPanId);
369
370     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
371     {
372         status = RAIL_IEEE802154_SetPanId(sBandConfigs[i].mRailHandle, aPanId, 0);
373         assert(status == RAIL_STATUS_NO_ERROR);
374     }
375 }
376
377 void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
378 {
379     OT_UNUSED_VARIABLE(aInstance);
380
381     RAIL_Status_t status;
382
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]);
385
386     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
387     {
388         status = RAIL_IEEE802154_SetLongAddress(sBandConfigs[i].mRailHandle, (uint8_t *)aAddress->m8, 0);
389         assert(status == RAIL_STATUS_NO_ERROR);
390     }
391 }
392
393 void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aAddress)
394 {
395     OT_UNUSED_VARIABLE(aInstance);
396
397     RAIL_Status_t status;
398
399     otLogInfoPlat("ShortAddr=%X", aAddress);
400
401     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
402     {
403         status = RAIL_IEEE802154_SetShortAddress(sBandConfigs[i].mRailHandle, aAddress, 0);
404         assert(status == RAIL_STATUS_NO_ERROR);
405     }
406 }
407
408 bool otPlatRadioIsEnabled(otInstance *aInstance)
409 {
410     OT_UNUSED_VARIABLE(aInstance);
411
412     return (sState != OT_RADIO_STATE_DISABLED);
413 }
414
415 otError otPlatRadioEnable(otInstance *aInstance)
416 {
417     otEXPECT(!otPlatRadioIsEnabled(aInstance));
418
419     otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
420     sState = OT_RADIO_STATE_SLEEP;
421
422 exit:
423     return OT_ERROR_NONE;
424 }
425
426 otError otPlatRadioDisable(otInstance *aInstance)
427 {
428     otEXPECT(otPlatRadioIsEnabled(aInstance));
429
430     otLogInfoPlat("State=OT_RADIO_STATE_DISABLED", NULL);
431     sState = OT_RADIO_STATE_DISABLED;
432
433 exit:
434     return OT_ERROR_NONE;
435 }
436
437 otError otPlatRadioSleep(otInstance *aInstance)
438 {
439     OT_UNUSED_VARIABLE(aInstance);
440
441     otError error = OT_ERROR_NONE;
442
443     otEXPECT_ACTION((sState != OT_RADIO_STATE_TRANSMIT) && (sState != OT_RADIO_STATE_DISABLED),
444                     error = OT_ERROR_INVALID_STATE);
445
446     otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
447
448     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
449     {
450         RAIL_Idle(sBandConfigs[i].mRailHandle, RAIL_IDLE, true);
451     }
452     sState = OT_RADIO_STATE_SLEEP;
453
454 exit:
455     return error;
456 }
457
458 otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
459 {
460     otError          error = OT_ERROR_NONE;
461     RAIL_Status_t    status;
462     efr32BandConfig *config;
463
464     OT_UNUSED_VARIABLE(aInstance);
465     otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, error = OT_ERROR_INVALID_STATE);
466
467     config = efr32RadioGetBandConfig(aChannel);
468     otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
469
470     if (sRxBandConfig != config)
471     {
472         RAIL_Idle(sRxBandConfig->mRailHandle, RAIL_IDLE, false);
473         sRxBandConfig = config;
474     }
475
476     RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
477         .priority = RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY,
478         // sliptime/transaction time is not used for bg rx
479     };
480
481     status = RAIL_StartRx(sRxBandConfig->mRailHandle, aChannel, &bgRxSchedulerInfo);
482     otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
483
484     otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL);
485     sState                 = OT_RADIO_STATE_RECEIVE;
486     sReceiveFrame.mChannel = aChannel;
487
488 exit:
489     return error;
490 }
491
492 otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
493 {
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;
499     uint8_t           frameLength;
500
501 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
502     sRailDebugCounters.mRailPlatTxTriggered++;
503 #endif
504
505     assert(sTransmitBusy == false);
506
507     otEXPECT_ACTION((sState != OT_RADIO_STATE_DISABLED) && (sState != OT_RADIO_STATE_TRANSMIT),
508                     error = OT_ERROR_INVALID_STATE);
509
510     config = efr32RadioGetBandConfig(aFrame->mChannel);
511     otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
512
513     sState         = OT_RADIO_STATE_TRANSMIT;
514     sTransmitError = OT_ERROR_NONE;
515     sTransmitBusy  = true;
516
517     if (sTxBandConfig != config)
518     {
519         efr32RadioSetTxPower(config->mRailHandle, config->mChannelConfig, sTxPowerDbm);
520         sTxBandConfig = config;
521     }
522
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);
526
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
531     };
532
533     if (aFrame->mPsdu[0] & IEEE802154_ACK_REQUEST)
534     {
535         txOptions |= RAIL_TX_OPTION_WAIT_FOR_ACK;
536
537 #if RADIO_CONFIG_DMP_SUPPORT
538         // time we wait for ACK
539         if (RAIL_GetSymbolRate(gRailHandle) > 0)
540         {
541             txSchedulerInfo.transactionTime += 12 * 1e6 / RAIL_GetSymbolRate(gRailHandle);
542         }
543         else
544         {
545             txSchedulerInfo.transactionTime += 12 * RADIO_TIMING_DEFAULT_SYMBOLTIME_US;
546         }
547 #endif
548     }
549
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)
554     {
555         txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * 8 * 1e6 / RAIL_GetBitRate(gRailHandle);
556     }
557     else
558     { // assume 250kbps
559         txSchedulerInfo.transactionTime = (frameLength + 4 + 1 + 1) * RADIO_TIMING_DEFAULT_BYTETIME_US;
560     }
561 #endif
562
563     if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
564     {
565 #if RADIO_CONFIG_DMP_SUPPORT
566         // time needed for CSMA/CA
567         txSchedulerInfo.transactionTime += RADIO_TIMING_CSMA_OVERHEAD_US;
568 #endif
569         status =
570             RAIL_StartCcaCsmaTx(sTxBandConfig->mRailHandle, aFrame->mChannel, txOptions, &csmaConfig, &txSchedulerInfo);
571     }
572     else
573     {
574         status = RAIL_StartTx(sTxBandConfig->mRailHandle, aFrame->mChannel, txOptions, &txSchedulerInfo);
575     }
576
577     if (status == RAIL_STATUS_NO_ERROR)
578     {
579 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
580         sRailDebugCounters.mRailTxStarted++;
581 #endif
582         otPlatRadioTxStarted(aInstance, aFrame);
583     }
584     else
585     {
586 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
587         sRailDebugCounters.mRailTxStartFailed++;
588 #endif
589         sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
590         sTransmitBusy  = false;
591     }
592
593 exit:
594     return error;
595 }
596
597 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
598 {
599     OT_UNUSED_VARIABLE(aInstance);
600
601     return &sTransmitFrame;
602 }
603
604 int8_t otPlatRadioGetRssi(otInstance *aInstance)
605 {
606     otError  error;
607     uint32_t start;
608     int8_t   rssi = OT_RADIO_RSSI_INVALID;
609
610     OT_UNUSED_VARIABLE(aInstance);
611
612     error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME);
613     otEXPECT(error == OT_ERROR_NONE);
614
615     start = RAIL_GetTime();
616
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))
620         ;
621
622     if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
623     {
624         rssi = sEnergyScanResultDbm;
625     }
626
627     sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
628 exit:
629     return rssi;
630 }
631
632 otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
633 {
634     OT_UNUSED_VARIABLE(aInstance);
635
636     return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN;
637 }
638
639 bool otPlatRadioGetPromiscuous(otInstance *aInstance)
640 {
641     OT_UNUSED_VARIABLE(aInstance);
642
643     return sPromiscuous;
644 }
645
646 void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
647 {
648     OT_UNUSED_VARIABLE(aInstance);
649
650     RAIL_Status_t status;
651
652     sPromiscuous = aEnable;
653
654     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
655     {
656         status = RAIL_IEEE802154_SetPromiscuousMode(sBandConfigs[i].mRailHandle, aEnable);
657         assert(status == RAIL_STATUS_NO_ERROR);
658     }
659 }
660
661 void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
662 {
663     OT_UNUSED_VARIABLE(aInstance);
664
665     // set Frame Pending bit for all outgoing ACKs if aEnable is false
666     sIsSrcMatchEnabled = aEnable;
667 }
668
669 static void processNextRxPacket(otInstance *aInstance, RAIL_Handle_t aRailHandle)
670 {
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;
675     uint16_t               length;
676
677     packetHandle = RAIL_GetRxPacketInfo(aRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST, &packetInfo);
678
679     otEXPECT_ACTION(packetHandle != RAIL_RX_PACKET_HANDLE_INVALID &&
680                         packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS,
681                     packetHandle = RAIL_RX_PACKET_HANDLE_INVALID);
682
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);
687
688     length = packetInfo.packetBytes + 1;
689
690     // check the length in recv packet info structure
691     otEXPECT(length == packetInfo.firstPortionData[0]);
692
693     // check the length validity of recv packet
694     otEXPECT(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH);
695
696     otLogInfoPlat("Received data:%d", length);
697
698     // skip length byte
699     assert(packetInfo.firstPortionBytes > 0);
700     packetInfo.firstPortionData++;
701     packetInfo.firstPortionBytes--;
702     packetInfo.packetBytes--;
703
704     // read packet
705     memcpy(sReceiveFrame.mPsdu, packetInfo.firstPortionData, packetInfo.firstPortionBytes);
706     memcpy(sReceiveFrame.mPsdu + packetInfo.firstPortionBytes, packetInfo.lastPortionData,
707            packetInfo.packetBytes - packetInfo.firstPortionBytes);
708
709     status = RAIL_ReleaseRxPacket(aRailHandle, packetHandle);
710     if (status == RAIL_STATUS_NO_ERROR)
711     {
712         packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
713     }
714
715     sReceiveFrame.mLength = length;
716
717     if (packetDetails.isAck)
718     {
719         assert((length == IEEE802154_ACK_LENGTH) &&
720                (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK);
721
722         RAIL_YieldRadio(gRailHandle);
723         sTransmitBusy = false;
724
725         if (sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
726         {
727             sTransmitError = OT_ERROR_NONE;
728         }
729         else
730         {
731             sTransmitError = OT_ERROR_NO_ACK;
732         }
733     }
734     else
735     {
736         otEXPECT(length != IEEE802154_ACK_LENGTH);
737
738         sReceiveError = OT_ERROR_NONE;
739
740         sReceiveFrame.mInfo.mRxInfo.mRssi = packetDetails.rssi;
741         sReceiveFrame.mInfo.mRxInfo.mLqi  = packetDetails.lqi;
742
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;
746
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;
750
751 #if OPENTHREAD_CONFIG_DIAG_ENABLE
752
753         if (otPlatDiagModeGet())
754         {
755             otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
756         }
757         else
758 #endif
759         {
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)
763             {
764                 otLogInfoPlat("Received %d bytes", sReceiveFrame.mLength);
765                 otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
766 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
767                 sRailDebugCounters.mRailPlatRadioReceiveDoneCbCount++;
768 #endif
769             }
770         }
771     }
772
773     otSysEventSignalPending();
774
775 exit:
776
777     if (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID)
778     {
779         RAIL_ReleaseRxPacket(aRailHandle, packetHandle);
780     }
781 }
782
783 static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
784 {
785     RAIL_Status_t status;
786
787     if (sIsSrcMatchEnabled)
788     {
789         RAIL_IEEE802154_Address_t sourceAddress;
790
791         status = RAIL_IEEE802154_GetAddress(aRailHandle, &sourceAddress);
792         assert(status == RAIL_STATUS_NO_ERROR);
793
794         if ((sourceAddress.length == RAIL_IEEE802154_LongAddress &&
795              utilsSoftSrcMatchExtFindEntry((otExtAddress *)sourceAddress.longAddress) >= 0) ||
796             (sourceAddress.length == RAIL_IEEE802154_ShortAddress &&
797              utilsSoftSrcMatchShortFindEntry(sourceAddress.shortAddress) >= 0))
798         {
799             status = RAIL_IEEE802154_SetFramePending(aRailHandle);
800             assert(status == RAIL_STATUS_NO_ERROR);
801         }
802     }
803     else
804     {
805         status = RAIL_IEEE802154_SetFramePending(aRailHandle);
806         assert(status == RAIL_STATUS_NO_ERROR);
807     }
808 }
809
810 static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
811 {
812 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
813     if (aEvents & RAIL_EVENT_CONFIG_SCHEDULED)
814     {
815         sRailDebugCounters.mRailEventConfigScheduled++;
816     }
817     if (aEvents & RAIL_EVENT_CONFIG_UNSCHEDULED)
818     {
819         sRailDebugCounters.mRailEventConfigUnScheduled++;
820     }
821 #endif
822     if (aEvents & RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND)
823     {
824         ieee802154DataRequestCommand(aRailHandle);
825     }
826     if (aEvents & RAIL_EVENTS_TX_COMPLETION)
827     {
828         if (aEvents & RAIL_EVENT_TX_PACKET_SENT)
829         {
830             if ((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
831             {
832                 RAIL_YieldRadio(aRailHandle);
833                 sTransmitError = OT_ERROR_NONE;
834                 sTransmitBusy  = false;
835             }
836 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
837             sRailDebugCounters.mRailEventPacketSent++;
838 #endif
839         }
840         else if (aEvents & RAIL_EVENT_TX_CHANNEL_BUSY)
841         {
842             RAIL_YieldRadio(aRailHandle);
843             sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
844             sTransmitBusy  = false;
845 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
846             sRailDebugCounters.mRailEventChannelBusy++;
847 #endif
848         }
849         else
850         {
851             RAIL_YieldRadio(aRailHandle);
852             sTransmitError = OT_ERROR_ABORT;
853             sTransmitBusy  = false;
854 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
855             sRailDebugCounters.mRailEventTxAbort++;
856 #endif
857         }
858     }
859
860     if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT)
861     {
862         RAIL_YieldRadio(aRailHandle);
863         sTransmitError = OT_ERROR_NO_ACK;
864         sTransmitBusy  = false;
865 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
866         sRailDebugCounters.mRailEventNoAck++;
867 #endif
868     }
869
870     if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED)
871     {
872         RAIL_HoldRxPacket(aRailHandle);
873 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
874         sRailDebugCounters.mRailEventPacketReceived++;
875 #endif
876     }
877
878     if (aEvents & RAIL_EVENT_CAL_NEEDED)
879     {
880         RAIL_Status_t status;
881
882         status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING);
883         assert(status == RAIL_STATUS_NO_ERROR);
884
885 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
886         sRailDebugCounters.mRailEventCalNeeded++;
887 #endif
888     }
889
890     if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
891     {
892         const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
893         RAIL_YieldRadio(aRailHandle);
894
895         sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
896
897         if (energyScanResultQuarterDbm == RAIL_RSSI_INVALID)
898         {
899             sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
900         }
901         else
902         {
903             sEnergyScanResultDbm = energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM;
904         }
905
906 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
907         sRailDebugCounters.mRailPlatRadioEnergyScanDoneCbCount++;
908 #endif
909     }
910     if (aEvents & RAIL_EVENT_SCHEDULER_STATUS)
911     {
912         RAIL_SchedulerStatus_t status = RAIL_GetSchedulerStatus(aRailHandle);
913
914         assert(status != RAIL_SCHEDULER_STATUS_INTERNAL_ERROR);
915
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))
920         {
921             sTransmitError = OT_ERROR_ABORT;
922             sTransmitBusy  = false;
923 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
924             sRailDebugCounters.mRailEventSchedulerStatusError++;
925 #endif
926         }
927         else if (status == RAIL_SCHEDULER_STATUS_AVERAGE_RSSI_FAIL)
928         {
929             sEnergyScanStatus    = ENERGY_SCAN_STATUS_COMPLETED;
930             sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
931         }
932 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
933         else if (sTransmitBusy)
934         {
935             sRailDebugCounters.mRailEventsSchedulerStatusLastStatus = status;
936             sRailDebugCounters.mRailEventsSchedulerStatusTransmitBusy++;
937         }
938 #endif
939     }
940
941     otSysEventSignalPending();
942 }
943
944 otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
945 {
946     OT_UNUSED_VARIABLE(aInstance);
947
948     return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
949 }
950
951 void efr32RadioProcess(otInstance *aInstance)
952 {
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);
956
957     if (sState == OT_RADIO_STATE_TRANSMIT && sTransmitBusy == false)
958     {
959         if (sTransmitError != OT_ERROR_NONE)
960         {
961             otLogDebgPlat("Transmit failed ErrorCode=%d", sTransmitError);
962         }
963
964         sState = OT_RADIO_STATE_RECEIVE;
965 #if OPENTHREAD_CONFIG_DIAG_ENABLE
966         if (otPlatDiagModeGet())
967         {
968             otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
969         }
970         else
971 #endif
972             if (((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0) || (sTransmitError != OT_ERROR_NONE))
973         {
974             otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
975         }
976         else
977         {
978             otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveFrame, sTransmitError);
979         }
980
981 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
982         sRailDebugCounters.mRailPlatRadioTxDoneCbCount++;
983 #endif
984
985         otSysEventSignalPending();
986     }
987     else if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
988     {
989         sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
990         otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
991         otSysEventSignalPending();
992
993 #if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
994         sRailDebugCounters.mRailEventEnergyScanCompleted++;
995 #endif
996     }
997 }
998
999 otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
1000 {
1001     OT_UNUSED_VARIABLE(aInstance);
1002
1003     otError error = OT_ERROR_NONE;
1004
1005     otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS);
1006     *aPower = sTxPowerDbm;
1007
1008 exit:
1009     return error;
1010 }
1011
1012 otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
1013 {
1014     OT_UNUSED_VARIABLE(aInstance);
1015
1016     RAIL_Status_t status;
1017
1018     for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
1019     {
1020         status = RAIL_SetTxPowerDbm(sBandConfigs[i].mRailHandle, ((RAIL_TxPower_t)aPower) * 10);
1021         assert(status == RAIL_STATUS_NO_ERROR);
1022     }
1023
1024     sTxPowerDbm = aPower;
1025
1026     return OT_ERROR_NONE;
1027 }
1028
1029 otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
1030 {
1031     OT_UNUSED_VARIABLE(aInstance);
1032     OT_UNUSED_VARIABLE(aThreshold);
1033
1034     return OT_ERROR_NOT_IMPLEMENTED;
1035 }
1036
1037 otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
1038 {
1039     OT_UNUSED_VARIABLE(aInstance);
1040     OT_UNUSED_VARIABLE(aThreshold);
1041
1042     return OT_ERROR_NOT_IMPLEMENTED;
1043 }
1044
1045 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
1046 {
1047     OT_UNUSED_VARIABLE(aInstance);
1048
1049     return EFR32_RECEIVE_SENSITIVITY;
1050 }