[api] add API to reset to bootloader mode (#9523)

This commit is contained in:
Mason Tran
2023-10-27 15:54:15 -07:00
committed by GitHub
parent 1528c8831d
commit 0b0db37a13
18 changed files with 167 additions and 14 deletions
+1
View File
@@ -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")
+9
View File
@@ -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);
+15 -1
View File
@@ -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.
*
+14
View File
@@ -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
View File
@@ -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")
+11
View File
@@ -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
View File
@@ -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)
+4
View File
@@ -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(); }
+4
View File
@@ -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)
{
+12
View File
@@ -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.
+11
View File
@@ -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);
+7 -5
View File
@@ -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
+2
View File
@@ -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"},
+8 -4
View File
@@ -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,
+12
View File
@@ -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
+9
View File
@@ -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)
+3
View File
@@ -71,4 +71,7 @@ send "panid\n"
expect "0xffff"
expect_line "Done"
send "reset bootloader\n"
expect_line "Error 27: NotCapable"
dispose_all
+2
View File
@@ -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 *, ...) {}