From 9d902ffea51af5e9fd6f399eb18c068e655158b8 Mon Sep 17 00:00:00 2001 From: Artur Hadasz Date: Thu, 7 Nov 2024 14:13:02 +0100 Subject: [PATCH] suit: Add "enter recovery button" This commit adds code allowing to enter SUIT foreground update (in most cases the same as recovery) mode via keeping a button pressed during system bootup. Signed-off-by: Artur Hadasz --- .../smp_transfer/sysbuild/recovery.overlay | 6 ++ subsys/suit/CMakeLists.txt | 1 + subsys/suit/Kconfig | 2 + subsys/suit/recovery_button/CMakeLists.txt | 11 ++++ subsys/suit/recovery_button/Kconfig | 16 +++++ .../src/suit_recovery_button.c | 59 +++++++++++++++++++ 6 files changed, 95 insertions(+) create mode 100644 subsys/suit/recovery_button/CMakeLists.txt create mode 100644 subsys/suit/recovery_button/Kconfig create mode 100644 subsys/suit/recovery_button/src/suit_recovery_button.c diff --git a/samples/suit/smp_transfer/sysbuild/recovery.overlay b/samples/suit/smp_transfer/sysbuild/recovery.overlay index e155e0e90112..17eeb76ec718 100644 --- a/samples/suit/smp_transfer/sysbuild/recovery.overlay +++ b/samples/suit/smp_transfer/sysbuild/recovery.overlay @@ -5,3 +5,9 @@ */ #include "../boards/nrf54h20dk_nrf54h20_cpuapp_common.dtsi" + +/ { + chosen { + recovery-button = &button0; + }; +}; diff --git a/subsys/suit/CMakeLists.txt b/subsys/suit/CMakeLists.txt index 686d42a301d9..7155c8081b0f 100644 --- a/subsys/suit/CMakeLists.txt +++ b/subsys/suit/CMakeLists.txt @@ -20,3 +20,4 @@ add_subdirectory_ifdef(CONFIG_SUIT_DFU orchestrator_app) add_subdirectory_ifdef(CONFIG_SUIT_ENVELOPE_INFO envelope_info) add_subdirectory_ifdef(CONFIG_SUIT_EXECUTION_MODE execution_mode) add_subdirectory_ifdef(CONFIG_SUIT_VALIDATOR validator) +add_subdirectory_ifdef(CONFIG_SUIT_RECOVERY_BUTTON recovery_button) diff --git a/subsys/suit/Kconfig b/subsys/suit/Kconfig index 2d4d75a3c015..daf3bd9be54e 100644 --- a/subsys/suit/Kconfig +++ b/subsys/suit/Kconfig @@ -196,10 +196,12 @@ rsource "envelope_info/Kconfig" rsource "execution_mode/Kconfig" rsource "memory_layout/Kconfig" rsource "validator/Kconfig" +rsource "recovery_button/Kconfig" # Configure SUIT_LOG_LEVEL module = SUIT module-str = Software Updates for Internet of Things source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" + endif # SUIT diff --git a/subsys/suit/recovery_button/CMakeLists.txt b/subsys/suit/recovery_button/CMakeLists.txt new file mode 100644 index 000000000000..0d10b4fa5c9c --- /dev/null +++ b/subsys/suit/recovery_button/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +zephyr_library() +zephyr_library_sources(src/suit_recovery_button.c) + +zephyr_library_link_libraries(suit_platform_err) +zephyr_library_link_libraries(suit_utils) diff --git a/subsys/suit/recovery_button/Kconfig b/subsys/suit/recovery_button/Kconfig new file mode 100644 index 000000000000..6bb8b950270e --- /dev/null +++ b/subsys/suit/recovery_button/Kconfig @@ -0,0 +1,16 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menuconfig SUIT_RECOVERY_BUTTON + bool "Enable SUIT enter recovery button checking on startup" + depends on $(dt_chosen_enabled,recovery-button) + help + This will make the firmware check if the recovery button specified in the + device tree is pressed on startup. If it is, the firmware will enter + the "foreground update mode", in which the same SUIT manifests are booted + as in case of the recovery mode. + + select SSF_SUIT_SERVICE_ENABLED diff --git a/subsys/suit/recovery_button/src/suit_recovery_button.c b/subsys/suit/recovery_button/src/suit_recovery_button.c new file mode 100644 index 000000000000..859ec6821ee7 --- /dev/null +++ b/subsys/suit/recovery_button/src/suit_recovery_button.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include + +#define RECOVERY_BUTTON_NODE DT_CHOSEN(recovery_button) +#define RECOVERY_BUTTON_PIN DT_GPIO_PIN(RECOVERY_BUTTON_NODE, gpios) +#define RECOVERY_BUTTON_PORT_NUM DT_PROP(DT_GPIO_CTLR(RECOVERY_BUTTON_NODE, gpios), port) +#define RECOVERY_BUTTON_FLAGS DT_GPIO_FLAGS(RECOVERY_BUTTON_NODE, gpios) + +#define RECOVERY_BUTTON_ABS_PIN NRF_GPIO_PIN_MAP(RECOVERY_BUTTON_PORT_NUM, RECOVERY_BUTTON_PIN) +#define RECOVERY_BUTTON_PULL (RECOVERY_BUTTON_FLAGS & GPIO_PULL_UP ? NRF_GPIO_PIN_PULLUP : \ + RECOVERY_BUTTON_FLAGS & GPIO_PULL_DOWN ? NRF_GPIO_PIN_PULLDOWN : \ + NRF_GPIO_PIN_NOPULL) + +#define RECOVERY_BUTTON_PRESSED(pin_value) (RECOVERY_BUTTON_FLAGS & GPIO_ACTIVE_LOW ? (!pin_value) \ + : pin_value) + +BUILD_ASSERT(DT_NODE_EXISTS(DT_CHOSEN(recovery_button)), "No recovery button chosen in dts"); + +static int recovery_button_check(void) +{ + suit_boot_mode_t mode = SUIT_BOOT_MODE_INVOKE_RECOVERY; + suit_ssf_err_t err = SUIT_PLAT_SUCCESS; + + err = suit_boot_mode_read(&mode); + + if (err != SUIT_PLAT_SUCCESS) { + suit_invoke_confirm(-EPIPE); + return -EPIPE; + } + + if (mode == SUIT_BOOT_MODE_INVOKE) { + nrf_gpio_pin_dir_t dir = NRF_GPIO_PIN_DIR_INPUT; + nrf_gpio_pin_input_t input = NRF_GPIO_PIN_INPUT_CONNECT; + nrf_gpio_pin_pull_t pull = RECOVERY_BUTTON_PULL; + + nrf_gpio_reconfigure(RECOVERY_BUTTON_ABS_PIN, &dir, &input, &pull, NULL, NULL); + + uint32_t pin_value = nrf_gpio_pin_read(RECOVERY_BUTTON_ABS_PIN); + if (RECOVERY_BUTTON_PRESSED(pin_value)) { + suit_foreground_dfu_required(); + } + else + { + suit_invoke_confirm(0); + } + } + + return 0; +} + +SYS_INIT(recovery_button_check, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);