From 5ce29eb89c3b7c288b41bb7d58a14781366f8b85 Mon Sep 17 00:00:00 2001 From: Mason Tran Date: Tue, 14 Jul 2020 23:48:54 -0400 Subject: [PATCH] [efr32] fix otPlatRadioGetRssi() for MG1, MG12, MG13 (#5238) This fixes an issue with Channel Monitoring for the EFR32 platform (MG1, MG12, MG13), where in, turning the radio to a new channel and immediately gathering background RSSI information was returning invalid results. A further investigation with the RAIL team indicated that this issue was occurring because the usage of `RAIL_GetRssi()` is incorrect. While the Rail_GetRssi API functions as documented, the problem is that the current implementation of this API returns valid results only in certain specified radio states and does not fit the use case for the OpenThread Channel Monitoring feature. (i.e computing RSSI value in the RxWarm radio state). To fix the issue, I am switching the affected platforms to the efr32mg21 implementation for `otPlatRadioGetRssi()`, which uses `RAIL_StartAverageRssi()` instead of `RAIL_GetRssi()`. `RAIL_StartAverageRssi()` uses hardware to trigger an interrupt once the RSSI is valid and should provide valid results. This approach was added by Marven when testing DMP support with OpenThread (https://github.com/openthread/openthread/pull/4321) --- examples/platforms/efr32mg1/radio.c | 27 +++++++++++++++++++-------- examples/platforms/efr32mg12/radio.c | 27 +++++++++++++++++++-------- examples/platforms/efr32mg13/radio.c | 27 +++++++++++++++++++-------- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/examples/platforms/efr32mg1/radio.c b/examples/platforms/efr32mg1/radio.c index c9a54d393..764be7183 100644 --- a/examples/platforms/efr32mg1/radio.c +++ b/examples/platforms/efr32mg1/radio.c @@ -77,6 +77,7 @@ enum enum { EFR32_RECEIVE_SENSITIVITY = -100, // dBm + EFR32_RSSI_AVERAGING_TIME = 16, // us EFR32_RSSI_AVERAGING_TIMEOUT = 300, // us }; @@ -657,19 +658,29 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) int8_t otPlatRadioGetRssi(otInstance *aInstance) { - int8_t rssi = OT_RADIO_RSSI_INVALID; + otError error; + uint32_t start; + int8_t rssi = OT_RADIO_RSSI_INVALID; + OT_UNUSED_VARIABLE(aInstance); - if ((RAIL_GetRadioState(gRailHandle) & RAIL_RF_STATE_RX)) + error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME); + otEXPECT(error == OT_ERROR_NONE); + + start = RAIL_GetTime(); + + // waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE + while (sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS && + ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT)) + ; + + if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED) { - int16_t railRssi = RAIL_RSSI_INVALID; - railRssi = RAIL_GetRssi(gRailHandle, true); - if (railRssi != RAIL_RSSI_INVALID) - { - rssi = railRssi / QUARTER_DBM_IN_DBM; - } + rssi = sEnergyScanResultDbm; } + sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE; +exit: return rssi; } diff --git a/examples/platforms/efr32mg12/radio.c b/examples/platforms/efr32mg12/radio.c index c9a54d393..764be7183 100644 --- a/examples/platforms/efr32mg12/radio.c +++ b/examples/platforms/efr32mg12/radio.c @@ -77,6 +77,7 @@ enum enum { EFR32_RECEIVE_SENSITIVITY = -100, // dBm + EFR32_RSSI_AVERAGING_TIME = 16, // us EFR32_RSSI_AVERAGING_TIMEOUT = 300, // us }; @@ -657,19 +658,29 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) int8_t otPlatRadioGetRssi(otInstance *aInstance) { - int8_t rssi = OT_RADIO_RSSI_INVALID; + otError error; + uint32_t start; + int8_t rssi = OT_RADIO_RSSI_INVALID; + OT_UNUSED_VARIABLE(aInstance); - if ((RAIL_GetRadioState(gRailHandle) & RAIL_RF_STATE_RX)) + error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME); + otEXPECT(error == OT_ERROR_NONE); + + start = RAIL_GetTime(); + + // waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE + while (sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS && + ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT)) + ; + + if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED) { - int16_t railRssi = RAIL_RSSI_INVALID; - railRssi = RAIL_GetRssi(gRailHandle, true); - if (railRssi != RAIL_RSSI_INVALID) - { - rssi = railRssi / QUARTER_DBM_IN_DBM; - } + rssi = sEnergyScanResultDbm; } + sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE; +exit: return rssi; } diff --git a/examples/platforms/efr32mg13/radio.c b/examples/platforms/efr32mg13/radio.c index 8207fa055..2f8bcdc30 100644 --- a/examples/platforms/efr32mg13/radio.c +++ b/examples/platforms/efr32mg13/radio.c @@ -77,6 +77,7 @@ enum enum { EFR32_RECEIVE_SENSITIVITY = -100, // dBm + EFR32_RSSI_AVERAGING_TIME = 16, // us EFR32_RSSI_AVERAGING_TIMEOUT = 300, // us }; @@ -657,19 +658,29 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) int8_t otPlatRadioGetRssi(otInstance *aInstance) { - int8_t rssi = OT_RADIO_RSSI_INVALID; + otError error; + uint32_t start; + int8_t rssi = OT_RADIO_RSSI_INVALID; + OT_UNUSED_VARIABLE(aInstance); - if ((RAIL_GetRadioState(gRailHandle) & RAIL_RF_STATE_RX)) + error = efr32StartEnergyScan(ENERGY_SCAN_MODE_SYNC, sReceiveFrame.mChannel, EFR32_RSSI_AVERAGING_TIME); + otEXPECT(error == OT_ERROR_NONE); + + start = RAIL_GetTime(); + + // waiting for the event RAIL_EVENT_RSSI_AVERAGE_DONE + while (sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS && + ((RAIL_GetTime() - start) < EFR32_RSSI_AVERAGING_TIMEOUT)) + ; + + if (sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED) { - int16_t railRssi = RAIL_RSSI_INVALID; - railRssi = RAIL_GetRssi(gRailHandle, true); - if (railRssi != RAIL_RSSI_INVALID) - { - rssi = railRssi / QUARTER_DBM_IN_DBM; - } + rssi = sEnergyScanResultDbm; } + sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE; +exit: return rssi; }