mirror of
https://github.com/espressif/openthread.git
synced 2026-09-04 16:20:05 +00:00
[api] add API to reset to bootloader mode (#9523)
This commit is contained in:
@@ -225,6 +225,7 @@ ot_option(OT_NETDIAG_CLIENT OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE "Network
|
||||
ot_option(OT_OPERATIONAL_DATASET_AUTO_INIT OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT "operational dataset auto init")
|
||||
ot_option(OT_OTNS OPENTHREAD_CONFIG_OTNS_ENABLE "OTNS")
|
||||
ot_option(OT_PING_SENDER OPENTHREAD_CONFIG_PING_SENDER_ENABLE "ping sender" ${OT_APP_CLI})
|
||||
ot_option(OT_PLATFORM_BOOTLOADER_MODE OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE "platform bootloader mode")
|
||||
ot_option(OT_PLATFORM_NETIF OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE "platform netif")
|
||||
ot_option(OT_PLATFORM_UDP OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE "platform UDP")
|
||||
ot_option(OT_REFERENCE_DEVICE OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE "test harness reference device")
|
||||
|
||||
@@ -60,6 +60,15 @@ void otPlatReset(otInstance *aInstance)
|
||||
#endif // OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
otError otPlatResetToBootloader(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return OT_ERROR_NOT_CAPABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (369)
|
||||
#define OPENTHREAD_API_VERSION (370)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
@@ -255,6 +255,20 @@ void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback a
|
||||
*/
|
||||
void otInstanceReset(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Triggers a platform reset to bootloader mode, if supported.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE`.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Reset to bootloader successfully.
|
||||
* @retval OT_ERROR_BUSY Failed due to another operation is ongoing.
|
||||
* @retval OT_ERROR_NOT_CAPABLE Not capable of resetting to bootloader.
|
||||
*
|
||||
*/
|
||||
otError otInstanceResetToBootloader(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Deletes all the settings stored on non-volatile memory, and then triggers a platform reset.
|
||||
*
|
||||
|
||||
@@ -61,6 +61,20 @@ extern "C" {
|
||||
*/
|
||||
void otPlatReset(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Performs a hardware reset on the platform to launch bootloader mode, if supported.
|
||||
*
|
||||
* Used when `OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE` is enabled.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Reset to bootloader successfully.
|
||||
* @retval OT_ERROR_BUSY Failed due to another operation is ongoing.
|
||||
* @retval OT_ERROR_NOT_CAPABLE Not capable of resetting to bootloader.
|
||||
*
|
||||
*/
|
||||
otError otPlatResetToBootloader(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Enumeration of possible reset reason codes.
|
||||
*
|
||||
|
||||
+17
-1
@@ -132,6 +132,17 @@ build_simulation()
|
||||
options+=("-DOT_LINK_METRICS_MANAGER=ON")
|
||||
fi
|
||||
|
||||
if [[ ${OT_NODE_TYPE} == cli* ]]; then
|
||||
# Only enable OT_PLATFORM_BOOTLOADER_MODE when testing cli.
|
||||
# This is intended to test that the "reset bootloader" CLI command returns a "NotCapable" error
|
||||
|
||||
# Note: Setting this option to ON for all OT_NODE_TYPEs will cause the posix/expects CI check to fail.
|
||||
# This is because the simulation RCP will have the SPINEL_CAP_RCP_RESET_TO_BOOTLOADER capability,
|
||||
# causing the ot-cli POSIX app to send the reset to simulation RCP successfully instead of printing
|
||||
# the expected error.
|
||||
options+=("-DOT_PLATFORM_BOOTLOADER_MODE=ON")
|
||||
fi
|
||||
|
||||
if [[ ${ot_extra_options[*]+x} ]]; then
|
||||
options+=("${ot_extra_options[@]}")
|
||||
fi
|
||||
@@ -158,7 +169,12 @@ build_simulation()
|
||||
build_posix()
|
||||
{
|
||||
local version="$1"
|
||||
local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
|
||||
local options=(
|
||||
"-DBUILD_TESTING=ON"
|
||||
"-DOT_MESSAGE_USE_HEAP=ON"
|
||||
"-DOT_PLATFORM_BOOTLOADER_MODE=ON"
|
||||
"-DOT_THREAD_VERSION=${version}"
|
||||
)
|
||||
|
||||
if [[ ${version} != "1.1" ]]; then
|
||||
options+=("-DOT_DUA=ON")
|
||||
|
||||
@@ -3075,6 +3075,17 @@ Signal a platform reset.
|
||||
> reset
|
||||
```
|
||||
|
||||
### reset bootloader
|
||||
|
||||
Signal a platform reset to bootloader mode, if supported.
|
||||
|
||||
Requires `OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE`.
|
||||
|
||||
```bash
|
||||
> reset bootloader
|
||||
Done
|
||||
```
|
||||
|
||||
### rloc16
|
||||
|
||||
Get the Thread RLOC16 value.
|
||||
|
||||
+26
-3
@@ -276,11 +276,34 @@ template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])
|
||||
|
||||
template <> otError Interpreter::Process<Cmd("reset")>(Arg aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgs);
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otInstanceReset(GetInstancePtr());
|
||||
if (aArgs[0].IsEmpty())
|
||||
{
|
||||
otInstanceReset(GetInstancePtr());
|
||||
}
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
/**
|
||||
* @cli reset bootloader
|
||||
* @code
|
||||
* reset bootloader
|
||||
* @endcode
|
||||
* @cparam reset bootloader
|
||||
* @par api_copy
|
||||
* #otInstanceResetToBootloader
|
||||
*/
|
||||
else if (aArgs[0] == "bootloader")
|
||||
{
|
||||
error = otInstanceResetToBootloader(GetInstancePtr());
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void Interpreter::ProcessLine(char *aBuf)
|
||||
|
||||
@@ -86,6 +86,10 @@ void otInstanceFinalize(otInstance *aInstance) { AsCoreType(aInstance).Finalize(
|
||||
|
||||
void otInstanceReset(otInstance *aInstance) { AsCoreType(aInstance).Reset(); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
otError otInstanceResetToBootloader(otInstance *aInstance) { return AsCoreType(aInstance).ResetToBootloader(); }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_UPTIME_ENABLE
|
||||
uint64_t otInstanceGetUptime(otInstance *aInstance) { return AsCoreType(aInstance).Get<Uptime>().GetUptime(); }
|
||||
|
||||
|
||||
@@ -312,6 +312,10 @@ exit:
|
||||
|
||||
void Instance::Reset(void) { otPlatReset(this); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
Error Instance::ResetToBootloader(void) { return otPlatResetToBootloader(this); }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_RADIO
|
||||
void Instance::ResetRadioStack(void)
|
||||
{
|
||||
|
||||
@@ -236,6 +236,18 @@ public:
|
||||
*/
|
||||
void Reset(void);
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
/**
|
||||
* Triggers a platform reset to bootloader mode, if supported.
|
||||
*
|
||||
* @retval kErrorNone Reset to bootloader successfully.
|
||||
* @retval kErrorBusy Failed due to another operation is ongoing.
|
||||
* @retval kErrorNotCapable Not capable of resetting to bootloader.
|
||||
*
|
||||
*/
|
||||
Error ResetToBootloader(void);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_RADIO
|
||||
/**
|
||||
* Resets the internal states of the radio.
|
||||
|
||||
@@ -72,6 +72,7 @@ RadioSpinel::RadioSpinel(void)
|
||||
, mIsPromiscuous(false)
|
||||
, mIsReady(false)
|
||||
, mSupportsLogStream(false)
|
||||
, mSupportsResetToBootloader(false)
|
||||
, mIsTimeSynced(false)
|
||||
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
|
||||
, mRcpFailureCount(0)
|
||||
@@ -236,6 +237,11 @@ bool RadioSpinel::IsRcp(bool &aSupportsRcpApiVersion, bool &aSupportsRcpMinHostA
|
||||
aSupportsRcpApiVersion = true;
|
||||
}
|
||||
|
||||
if (capability == SPINEL_CAP_RCP_RESET_TO_BOOTLOADER)
|
||||
{
|
||||
mSupportsResetToBootloader = true;
|
||||
}
|
||||
|
||||
if (capability == SPINEL_PROP_RCP_MIN_HOST_API_VERSION)
|
||||
{
|
||||
aSupportsRcpMinHostApiVersion = true;
|
||||
@@ -1469,6 +1475,11 @@ otError RadioSpinel::SendReset(uint8_t aResetType)
|
||||
uint8_t buffer[kMaxSpinelFrame];
|
||||
spinel_ssize_t packed;
|
||||
|
||||
if ((aResetType == SPINEL_RESET_BOOTLOADER) && !mSupportsResetToBootloader)
|
||||
{
|
||||
ExitNow(error = OT_ERROR_NOT_CAPABLE);
|
||||
}
|
||||
|
||||
// Pack the header, command and key
|
||||
packed = spinel_datatype_pack(buffer, sizeof(buffer), SPINEL_DATATYPE_COMMAND_S SPINEL_DATATYPE_UINT8_S,
|
||||
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_RESET, aResetType);
|
||||
|
||||
@@ -808,10 +808,11 @@ public:
|
||||
/**
|
||||
* Tries to reset the co-processor.
|
||||
*
|
||||
* @prarm[in] aResetType The reset type, SPINEL_RESET_PLATFORM or SPINEL_RESET_STACK.
|
||||
* @prarm[in] aResetType The reset type, SPINEL_RESET_PLATFORM, SPINEL_RESET_STACK, or SPINEL_RESET_BOOTLOADER.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully removed item from the property.
|
||||
* @retval OT_ERROR_BUSY Failed due to another operation is on going.
|
||||
* @retval OT_ERROR_NOT_CAPABLE Requested reset type is not supported by the co-processor
|
||||
*
|
||||
*/
|
||||
otError SendReset(uint8_t aResetType);
|
||||
@@ -1065,10 +1066,11 @@ private:
|
||||
otExtAddress mIeeeEui64;
|
||||
|
||||
State mState;
|
||||
bool mIsPromiscuous : 1; ///< Promiscuous mode.
|
||||
bool mIsReady : 1; ///< NCP ready.
|
||||
bool mSupportsLogStream : 1; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format.
|
||||
bool mIsTimeSynced : 1; ///< Host has calculated the time difference between host and RCP.
|
||||
bool mIsPromiscuous : 1; ///< Promiscuous mode.
|
||||
bool mIsReady : 1; ///< NCP ready.
|
||||
bool mSupportsLogStream : 1; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format.
|
||||
bool mSupportsResetToBootloader : 1; ///< RCP supports resetting into bootloader mode.
|
||||
bool mIsTimeSynced : 1; ///< Host has calculated the time difference between host and RCP.
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
|
||||
|
||||
|
||||
@@ -1606,6 +1606,8 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability)
|
||||
{SPINEL_CAP_NET_THREAD_1_1, "NET_THREAD_1_1"},
|
||||
{SPINEL_CAP_NET_THREAD_1_2, "NET_THREAD_1_2"},
|
||||
{SPINEL_CAP_RCP_API_VERSION, "RCP_API_VERSION"},
|
||||
{SPINEL_CAP_RCP_MIN_HOST_API_VERSION, "RCP_MIN_HOST_API_VERSION"},
|
||||
{SPINEL_CAP_RCP_RESET_TO_BOOTLOADER, "RCP_RESET_TO_BOOTLOADER"},
|
||||
{SPINEL_CAP_MAC_ALLOWLIST, "MAC_ALLOWLIST"},
|
||||
{SPINEL_CAP_MAC_RAW, "MAC_RAW"},
|
||||
{SPINEL_CAP_OOB_STEERING_DATA, "OOB_STEERING_DATA"},
|
||||
|
||||
@@ -897,8 +897,9 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
SPINEL_RESET_PLATFORM = 1,
|
||||
SPINEL_RESET_STACK = 2,
|
||||
SPINEL_RESET_PLATFORM = 1,
|
||||
SPINEL_RESET_STACK = 2,
|
||||
SPINEL_RESET_BOOTLOADER = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -928,8 +929,10 @@ enum
|
||||
* `PROP_LAST_STATUS` has been set to `STATUS_RESET_SOFTWARE`.
|
||||
*
|
||||
* The optional command payload specifies the reset type, can be
|
||||
* `SPINEL_RESET_PLATFORM` or `SPINEL_RESET_STACK`. Defaults to stack
|
||||
* reset if unspecified.
|
||||
* `SPINEL_RESET_PLATFORM`, `SPINEL_RESET_STACK`, or
|
||||
* `SPINEL_RESET_BOOTLOADER`.
|
||||
*
|
||||
* Defaults to stack reset if unspecified.
|
||||
*
|
||||
* If an error occurs, the value of `PROP_LAST_STATUS` will be emitted
|
||||
* instead with the value set to the generated status code for the error.
|
||||
@@ -1284,6 +1287,7 @@ enum
|
||||
SPINEL_CAP_RCP__BEGIN = 64,
|
||||
SPINEL_CAP_RCP_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 0),
|
||||
SPINEL_CAP_RCP_MIN_HOST_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 1),
|
||||
SPINEL_CAP_RCP_RESET_TO_BOOTLOADER = (SPINEL_CAP_RCP__BEGIN + 2),
|
||||
SPINEL_CAP_RCP__END = 80,
|
||||
|
||||
SPINEL_CAP_OPENTHREAD__BEGIN = 512,
|
||||
|
||||
@@ -1211,6 +1211,14 @@ otError NcpBase::CommandHandler_RESET(uint8_t aHeader)
|
||||
SuccessOrAssert(
|
||||
error = WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_RESET_POWER_ON));
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
else if (reset_type == SPINEL_RESET_BOOTLOADER)
|
||||
{
|
||||
// Signal a platform reset to bootloader mode.
|
||||
// If implemented, this function shouldn't return.
|
||||
error = otInstanceResetToBootloader(mInstance);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@@ -1843,6 +1851,10 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
|
||||
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_MIN_HOST_API_VERSION));
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_RESET_TO_BOOTLOADER));
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_PLATFORM_POSIX
|
||||
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_POSIX));
|
||||
#endif
|
||||
|
||||
@@ -978,6 +978,15 @@ otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t a
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
|
||||
otError otPlatResetToBootloader(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return GetRadioSpinel().SendReset(SPINEL_RESET_BOOTLOADER);
|
||||
}
|
||||
#endif
|
||||
|
||||
const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void) { return GetRadioSpinel().GetRadioSpinelMetrics(); }
|
||||
|
||||
const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void)
|
||||
|
||||
@@ -71,4 +71,7 @@ send "panid\n"
|
||||
expect "0xffff"
|
||||
expect_line "Done"
|
||||
|
||||
send "reset bootloader\n"
|
||||
expect_line "Error 27: NotCapable"
|
||||
|
||||
dispose_all
|
||||
|
||||
@@ -223,6 +223,8 @@ OT_TOOL_WEAK void otPlatUartReceived(const uint8_t *, uint16_t) {}
|
||||
|
||||
OT_TOOL_WEAK void otPlatReset(otInstance *) {}
|
||||
|
||||
OT_TOOL_WEAK otError otPlatResetToBootloader(otInstance *) { return OT_ERROR_NOT_CAPABLE; }
|
||||
|
||||
OT_TOOL_WEAK otPlatResetReason otPlatGetResetReason(otInstance *) { return OT_PLAT_RESET_REASON_POWER_ON; }
|
||||
|
||||
OT_TOOL_WEAK void otPlatLog(otLogLevel, otLogRegion, const char *, ...) {}
|
||||
|
||||
Reference in New Issue
Block a user