mirror of
https://github.com/espressif/openthread.git
synced 2026-06-21 05:03:51 +00:00
[efr32] fallback to use relative timer if absolute timer fails to start (#4081)
Added a fallback to the efr32mg12 where if an alarm set with an absolute expiry time (t0 + dt) has failed to start then we fallback to using a relative timer (dt). It has been observed in testing that alarms have stopped working on the efr32mg12. This has caused other issues such as buffers not being freed or the network splitting as no further alarms are scheduled. The cause is due to an alarm being set to expire slightly in the past. In this case we fallback to using a relative timer using only the dt value. For the cases where it fails it will be set to 1ms into the future from the time the RAIL_SetTimer is called. RAIL maintains time in microseconds but is being rounded down for the time returned in milliseconds by otPlatAlarmMilliGetNow. We used a 1ms minimum delta to ensure that the absolute time would be in the next millisecond but this could still fail. We therefore use a relative timer in this case which on the cases where it fails should be 1ms ahead of current time.
This commit is contained in:
committed by
Jonathan Hui
parent
0dde90edcb
commit
89dca58915
@@ -137,15 +137,23 @@ void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t t0, uint32_t dt)
|
||||
expires_microsec = (t0 + dt) * US_IN_MS;
|
||||
status = RAIL_SetTimer(gRailHandle, expires_microsec, RAIL_TIME_ABSOLUTE, RAILCb_TimerExpired);
|
||||
|
||||
if (status == RAIL_STATUS_NO_ERROR)
|
||||
if (status != RAIL_STATUS_NO_ERROR)
|
||||
{
|
||||
sIsRunning = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIsRunning = false;
|
||||
otLogCritPlat("Alarm set timer, status: %d, dt: %u, t0: %u", status, dt, t0);
|
||||
// The RAIL timer could not be set due to expiration time being in the past with respect to RAIL's current
|
||||
// time which is in microseconds. We fallback to using a relative timer from the current time.
|
||||
|
||||
expires_microsec = dt * US_IN_MS;
|
||||
status = RAIL_SetTimer(gRailHandle, expires_microsec, RAIL_TIME_DELAY, RAILCb_TimerExpired);
|
||||
|
||||
if (status != RAIL_STATUS_NO_ERROR)
|
||||
{
|
||||
otLogCritPlat("Alarm start timer failed, status: %d, dt: %u, t0: %u, now: %u", status, dt, t0,
|
||||
otPlatAlarmMilliGetNow());
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
sIsRunning = true;
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStop(otInstance *aInstance)
|
||||
@@ -175,6 +183,9 @@ void efr32AlarmProcess(otInstance *aInstance)
|
||||
|
||||
if (sAlarmDt > RAIL_TIMER_MAX_DELTA_MS)
|
||||
{
|
||||
// We split longer delays in two due to the maximum allowed timer in RAIL. Here we
|
||||
// re-arm the RAIL timer with the remaining part of the alarm.
|
||||
|
||||
now = otPlatAlarmMilliGetNow();
|
||||
dt = (sAlarmT0 + sAlarmDt) - now;
|
||||
|
||||
@@ -190,27 +201,33 @@ void efr32AlarmProcess(otInstance *aInstance)
|
||||
new_expires_microsec = (now + dt) * US_IN_MS;
|
||||
status = RAIL_SetTimer(gRailHandle, new_expires_microsec, RAIL_TIME_ABSOLUTE, RAILCb_TimerExpired);
|
||||
|
||||
if (status == RAIL_STATUS_NO_ERROR)
|
||||
if (status != RAIL_STATUS_NO_ERROR)
|
||||
{
|
||||
sIsRunning = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIsRunning = false;
|
||||
otLogCritPlat("Alarm set timer, status: %d, expires: %u, dt: %u, now: %u", status, sAlarmT0 + sAlarmDt,
|
||||
dt, now);
|
||||
}
|
||||
}
|
||||
new_expires_microsec = dt * US_IN_MS;
|
||||
status = RAIL_SetTimer(gRailHandle, new_expires_microsec, RAIL_TIME_DELAY, RAILCb_TimerExpired);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagAlarmFired(aInstance);
|
||||
if (status != RAIL_STATUS_NO_ERROR)
|
||||
{
|
||||
otLogCritPlat("Alarm extend timer failed, status: %d, dt: %u, now: %u", status, dt,
|
||||
otPlatAlarmMilliGetNow());
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
sIsRunning = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatAlarmMilliFired(aInstance);
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagAlarmFired(aInstance);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatAlarmMilliFired(aInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit:
|
||||
|
||||
Reference in New Issue
Block a user