[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)
This commit is contained in:
Mason Tran
2020-07-14 20:48:54 -07:00
committed by GitHub
parent 51f9d2cb9d
commit 5ce29eb89c
3 changed files with 57 additions and 24 deletions
+19 -8
View File
@@ -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;
}
+19 -8
View File
@@ -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;
}
+19 -8
View File
@@ -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;
}