mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 01:17:46 +00:00
[posix-host] die on RCP timeout (#4591)
When RCP fails to respond in time, it usually means RCP is stuck or in some bad situations that can only recover by hardware resetting. This commit changes the behavior on RCP timeout so that RCP can be reset during the host daemon restarting.
This commit is contained in:
@@ -250,13 +250,12 @@ exit:
|
||||
|
||||
otError HdlcInterface::WaitForFrame(const struct timeval &aTimeout)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
struct timeval timeout = aTimeout;
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
struct Event event;
|
||||
uint64_t delay = static_cast<uint64_t>(aTimeout.tv_sec) * US_PER_S + static_cast<uint64_t>(aTimeout.tv_usec);
|
||||
|
||||
virtualTimeSendSleepEvent(&timeout);
|
||||
virtualTimeSendSleepEvent(&aTimeout);
|
||||
virtualTimeReceiveEvent(&event);
|
||||
|
||||
switch (event.mEvent)
|
||||
@@ -266,7 +265,7 @@ otError HdlcInterface::WaitForFrame(const struct timeval &aTimeout)
|
||||
break;
|
||||
|
||||
case OT_SIM_EVENT_ALARM_FIRED:
|
||||
ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
VerifyOrExit(event.mDelay <= delay, error = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -274,6 +273,8 @@ otError HdlcInterface::WaitForFrame(const struct timeval &aTimeout)
|
||||
break;
|
||||
}
|
||||
#else // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
struct timeval timeout = aTimeout;
|
||||
|
||||
fd_set read_fds;
|
||||
fd_set error_fds;
|
||||
int rval;
|
||||
|
||||
@@ -82,6 +82,11 @@ enum
|
||||
* System call or library function error.
|
||||
*/
|
||||
OT_EXIT_ERROR_ERRNO = 5,
|
||||
|
||||
/**
|
||||
* No response from radio spinel.
|
||||
*/
|
||||
OT_EXIT_RADIO_SPINEL_NO_RESPONSE = 6,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -133,6 +133,10 @@ const char *otExitCodeToString(uint8_t aExitCode)
|
||||
retval = "RadioSpinelReset";
|
||||
break;
|
||||
|
||||
case OT_EXIT_RADIO_SPINEL_NO_RESPONSE:
|
||||
retval = "RadioSpinelNoResponse";
|
||||
break;
|
||||
|
||||
case OT_EXIT_ERROR_ERRNO:
|
||||
retval = strerror(errno);
|
||||
break;
|
||||
|
||||
@@ -1237,36 +1237,26 @@ otError RadioSpinel::Remove(spinel_prop_key_t aKey, const char *aFormat, ...)
|
||||
|
||||
otError RadioSpinel::WaitResponse(void)
|
||||
{
|
||||
uint64_t now = platformGetTime();
|
||||
uint64_t end = now + kMaxWaitTime * US_PER_MS;
|
||||
struct timeval timeout = {kMaxWaitTime / 1000, (kMaxWaitTime % 1000) * 1000};
|
||||
uint64_t end = platformGetTime() + kMaxWaitTime * US_PER_MS;
|
||||
|
||||
otLogInfoPlat("Wait response: tid=%u key=%u", mWaitingTid, mWaitingKey);
|
||||
|
||||
do
|
||||
{
|
||||
if (mSpinelInterface.WaitForFrame(timeout) == OT_ERROR_RESPONSE_TIMEOUT)
|
||||
{
|
||||
FreeTid(mWaitingTid);
|
||||
mWaitingTid = 0;
|
||||
ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT);
|
||||
}
|
||||
uint64_t now;
|
||||
uint64_t remain;
|
||||
struct timeval timeout;
|
||||
|
||||
now = platformGetTime();
|
||||
VerifyOrDie(end > now, OT_EXIT_RADIO_SPINEL_NO_RESPONSE);
|
||||
remain = end - now;
|
||||
|
||||
if (end > now)
|
||||
{
|
||||
uint64_t remain = end - now;
|
||||
timeout.tv_sec = static_cast<time_t>(remain / US_PER_S);
|
||||
timeout.tv_usec = static_cast<suseconds_t>(remain % US_PER_S);
|
||||
|
||||
timeout.tv_sec = static_cast<time_t>(remain / US_PER_S);
|
||||
timeout.tv_usec = static_cast<suseconds_t>(remain % US_PER_S);
|
||||
}
|
||||
else
|
||||
{
|
||||
mWaitingTid = 0;
|
||||
mError = OT_ERROR_RESPONSE_TIMEOUT;
|
||||
}
|
||||
VerifyOrDie(mSpinelInterface.WaitForFrame(timeout) == OT_ERROR_NONE, OT_EXIT_RADIO_SPINEL_NO_RESPONSE);
|
||||
} while (mWaitingTid || !mIsReady);
|
||||
|
||||
exit:
|
||||
LogIfFail("Error waiting response", mError);
|
||||
// This indicates end of waiting repsonse.
|
||||
mWaitingKey = SPINEL_PROP_LAST_STATUS;
|
||||
|
||||
Reference in New Issue
Block a user