mirror of
https://github.com/espressif/openthread.git
synced 2026-08-15 23:27:47 +00:00
[spinel] add coprocessor reset failure callback (#11284)
Add a coprocessor reset failure callback to handle the coprocessor reset failure instead of letting the program crash directly.
This commit is contained in:
@@ -261,6 +261,7 @@ ot_option(OT_UPTIME OPENTHREAD_CONFIG_UPTIME_ENABLE "uptime")
|
||||
ot_option(OT_VERHOEFF_CHECKSUM OPENTHREAD_CONFIG_VERHOEFF_CHECKSUM_ENABLE "verhoeff checksum")
|
||||
ot_option(OT_WAKEUP_COORDINATOR OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE "wake-up coordinator")
|
||||
ot_option(OT_WAKEUP_END_DEVICE OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE "wake-up end device")
|
||||
ot_option(OT_SPINEL_CP_RESET_FAIL_CALLBACK_ENABLE OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE "CP reset failure callback")
|
||||
|
||||
option(OT_DOC "build OpenThread documentation")
|
||||
message(STATUS "- - - - - - - - - - - - - - - - ")
|
||||
|
||||
@@ -76,7 +76,7 @@ main()
|
||||
fi
|
||||
|
||||
reset_source
|
||||
build -DOT_POSIX_RCP_VENDOR_BUS=ON "$@"
|
||||
build -DOT_POSIX_RCP_VENDOR_BUS=ON -DOT_SPINEL_CP_RESET_FAIL_CALLBACK_ENABLE=ON "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -163,4 +163,13 @@
|
||||
#define OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
*
|
||||
* Enables Co-processor reset failure callback in Spinel driver
|
||||
*/
|
||||
#ifndef OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
#define OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE 0
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_SPINEL_CONFIG_H_
|
||||
|
||||
@@ -52,6 +52,10 @@ SpinelDriver::SpinelDriver(void)
|
||||
, mSpinelVersionMajor(-1)
|
||||
, mSpinelVersionMinor(-1)
|
||||
, mIsCoprocessorReady(false)
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
, mCoprocessorResetFailureCallback(nullptr)
|
||||
, mCoprocessorResetFailureContext(nullptr)
|
||||
#endif
|
||||
{
|
||||
memset(mVersion, 0, sizeof(mVersion));
|
||||
|
||||
@@ -119,6 +123,15 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
void SpinelDriver::SetCoprocessorResetFailureCallback(otSpinelDriverCoprocessorResetFailureCallback aCallback,
|
||||
void *aContext)
|
||||
{
|
||||
mCoprocessorResetFailureCallback = aCallback;
|
||||
mCoprocessorResetFailureContext = aContext;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SpinelDriver::ResetCoprocessor(bool aSoftwareReset)
|
||||
{
|
||||
bool hardwareReset;
|
||||
@@ -129,7 +142,13 @@ void SpinelDriver::ResetCoprocessor(bool aSoftwareReset)
|
||||
VerifyOrExit(!mIsCoprocessorReady, resetDone = true);
|
||||
#endif
|
||||
|
||||
mWaitingKey = SPINEL_PROP_LAST_STATUS;
|
||||
// Before resetting the co-processor, mIsCoprocessorReady must be set to false.
|
||||
// Otherwise, in some cases, the host may misinterpret the reset result.
|
||||
// For example, if mIsCoprocessorReady is true when calling ResetCoprocessor,
|
||||
// and the reset fails but the co-processor sends some invalid data, `WaitResponse`
|
||||
// may mistakenly return OT_ERROR_NONE, causing the host to believe the reset succeeded.
|
||||
mIsCoprocessorReady = false;
|
||||
mWaitingKey = SPINEL_PROP_LAST_STATUS;
|
||||
|
||||
if (aSoftwareReset && (SendReset(SPINEL_RESET_STACK) == OT_ERROR_NONE) && (WaitResponse() == OT_ERROR_NONE))
|
||||
{
|
||||
@@ -160,6 +179,12 @@ exit:
|
||||
if (!resetDone)
|
||||
{
|
||||
LogCrit("Failed to reset co-processor!");
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
if (mCoprocessorResetFailureCallback)
|
||||
{
|
||||
mCoprocessorResetFailureCallback(mCoprocessorResetFailureContext);
|
||||
}
|
||||
#endif
|
||||
DieNow(OT_EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +215,27 @@ public:
|
||||
*/
|
||||
spinel_iid_t GetIid(void) { return mIid; }
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
/**
|
||||
* A callback type for handling Co-processor reset failure of spinel driver.
|
||||
*
|
||||
* @param[in] aContext A pointer to the user context.
|
||||
*/
|
||||
typedef void (*otSpinelDriverCoprocessorResetFailureCallback)(void *aContext);
|
||||
|
||||
/**
|
||||
* Registers a callback to handle Co-processor reset failure of Spinel driver.
|
||||
*
|
||||
* This function is used to register a callback to handle Co-processor reset failure.
|
||||
* When the Spinel driver fails to reset the Co-processor through both software and
|
||||
* hardware resets, the user can handle the error through the callback(such as OTA).
|
||||
*
|
||||
* @param[in] aCallback The callback.
|
||||
* @param[in] aContext A pointer to the user context.
|
||||
*/
|
||||
void SetCoprocessorResetFailureCallback(otSpinelDriverCoprocessorResetFailureCallback aCallback, void *aContext);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kMaxSpinelFrame = SPINEL_FRAME_MAX_SIZE;
|
||||
static constexpr uint16_t kVersionStringSize = 128;
|
||||
@@ -314,6 +335,11 @@ private:
|
||||
char mVersion[kVersionStringSize];
|
||||
|
||||
Array<unsigned int, kCapsBufferSize> mCoprocessorCaps;
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
otSpinelDriverCoprocessorResetFailureCallback mCoprocessorResetFailureCallback;
|
||||
void *mCoprocessorResetFailureContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace Spinel
|
||||
|
||||
@@ -444,6 +444,13 @@ void platformResolverUpdateFdSet(otSysMainloopContext *aContext);
|
||||
*/
|
||||
void platformResolverProcess(const otSysMainloopContext *aContext);
|
||||
|
||||
/**
|
||||
* The callback for coprocessor reset failure.
|
||||
*
|
||||
* @param[in] aContext A pointer to the mainloop context.
|
||||
*/
|
||||
void platformCoprocessorResetFailed(void *aContext);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -73,6 +73,10 @@ Radio::Radio(void)
|
||||
{
|
||||
}
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
OT_TOOL_WEAK void platformCoprocessorResetFailed(void *) {}
|
||||
#endif
|
||||
|
||||
void Radio::Init(const char *aUrl)
|
||||
{
|
||||
bool resetRadio;
|
||||
@@ -107,6 +111,10 @@ void Radio::Init(const char *aUrl)
|
||||
resetRadio = !mRadioUrl.HasParam("no-reset");
|
||||
skipCompatibilityCheck = mRadioUrl.HasParam("skip-rcp-compatibility-check");
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_COPROCESSOR_RESET_FAILURE_CALLBACK_ENABLE
|
||||
GetSpinelDriver().SetCoprocessorResetFailureCallback(platformCoprocessorResetFailed, this);
|
||||
#endif
|
||||
|
||||
mRadioSpinel.SetCallbacks(callbacks);
|
||||
mRadioSpinel.Init(skipCompatibilityCheck, resetRadio, &GetSpinelDriver(),
|
||||
(skipCompatibilityCheck ? 0 : kRequiredRadioCaps), aEnableRcpTimeSync);
|
||||
|
||||
Reference in New Issue
Block a user