From a8aa116b9df4f3e26ac862c58638942fe4806ba1 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Wed, 16 Sep 2026 10:16:24 +0300 Subject: [PATCH 01/11] loader: added MCUboot support over USB and serial. Signed-off-by: Sercan Erat --- .gitignore | 2 - .vscode/tasks.json | 3 +- extra/build.sh | 61 ++++++++++++++----- key/rak_key_ecdsa-p256.c | 21 +++++++ key/rak_key_ecdsa-p256.pem | 5 ++ loader/CMakeLists.txt | 5 +- loader/overlay_mcuboot.conf | 29 +++++++++ loader/sysbuild.conf | 10 +++ .../mcuboot/boards/rak4631_nrf52840.overlay | 32 ++++++++++ loader/sysbuild/mcuboot/prj.conf | 37 +++++++++++ .../rak4631_nrf52840/rak4631_nrf52840.overlay | 40 ++---------- .../rak4631_nrf52840_partitions.dtsi | 53 ++++++++++++++++ west.yml | 1 + 13 files changed, 245 insertions(+), 54 deletions(-) create mode 100644 key/rak_key_ecdsa-p256.c create mode 100644 key/rak_key_ecdsa-p256.pem create mode 100644 loader/overlay_mcuboot.conf create mode 100644 loader/sysbuild.conf create mode 100644 loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay create mode 100644 loader/sysbuild/mcuboot/prj.conf create mode 100644 variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi diff --git a/.gitignore b/.gitignore index 39e50c86b..8965cf832 100644 --- a/.gitignore +++ b/.gitignore @@ -17,5 +17,3 @@ includes.txt syms-dynamic.ld syms-static.ld tls-syms.S - -__pycache__/ diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 09919db82..07e37e0cb 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -32,7 +32,8 @@ "command": "extra/build.sh", "args": [ "${BOARD_ARD}", - "--debug" + "--debug", + "--mcuboot" ], "group": "build", "problemMatcher": ["$gcc"] diff --git a/extra/build.sh b/extra/build.sh index b22b5e113..0733e510e 100755 --- a/extra/build.sh +++ b/extra/build.sh @@ -21,7 +21,7 @@ fi if [ $# -eq 0 ] || [ x$1 == x"-h" ] || [ x$1 == x"--help" ]; then cat << EOF Usage: - $0 + $0 [--debug] [--mcuboot] $0 [] Build the loader for the given target. @@ -60,9 +60,25 @@ if ! [ -z "$chosen_board" ]; then fi upload_offset=$(jq -cr '.upload_offset' <<< "$chosen_board") - # Check for debug flag and append - if [ x$2 == x"--debug" ]; then - args+=(-- -DEXTRA_CONF_FILE=../extra/debug.conf) + # Check for debug and mcuboot flags and append + for opt in "${@:2}"; do + case "$opt" in + --debug) debug=1 ;; + --mcuboot) mcuboot=1 ;; + *) echo "Unknown option: $opt"; exit 1 ;; + esac + done + + conf="" + if [ -n "$mcuboot" ]; then + args+=(--sysbuild) + conf="overlay_mcuboot.conf" + fi + if [ -n "$debug" ]; then + conf="${conf:+$conf;}../extra/debug.conf" + fi + if [ -n "$conf" ]; then + args+=(-- "-DEXTRA_CONF_FILE=$conf") fi else # expect Zephyr-compatible target and args @@ -100,12 +116,17 @@ fi BUILD_DIR=build/${variant} VARIANT_DIR=variants/${variant} rm -rf ${BUILD_DIR} -west build -d ${BUILD_DIR} -b ${target} loader -t llext-edk "${args[@]}" +west build -d ${BUILD_DIR} -b ${target} loader "${args[@]}" + +# With sysbuild the loader is one image among several and has its own build +# directory as loader; the EDK target only exists there. +LOADER_DIR=${BUILD_DIR}${mcuboot:+/loader} +west build -d ${LOADER_DIR} -t llext-edk # Extract the generated EDK tarball and copy it to the variant directory mkdir -p ${VARIANT_DIR} firmwares -(set -e ; cd ${BUILD_DIR} && rm -rf llext-edk && tar xf zephyr/llext-edk.tar.Z) -rsync -a --delete ${BUILD_DIR}/llext-edk ${VARIANT_DIR}/ +(set -e ; cd ${LOADER_DIR} && rm -rf llext-edk && tar xf zephyr/llext-edk.tar.Z) +rsync -a --delete ${LOADER_DIR}/llext-edk ${VARIANT_DIR}/ # remove all inline comments in macro definitions # (especially from devicetree_generated.h and sys/util_internal.h) @@ -124,19 +145,27 @@ perl -0pi -e "s/__pinned_func\nstatic inline ($edk_funcs)/$edk_qual \$1/g" "$sys perl -0pi -e "s/__syscall ($edk_funcs);/$edk_qual \$1;/g" "$kernel_hdr" for ext in elf bin hex uf2; do - rm -f firmwares/zephyr-$variant.$ext - if [ -f ${BUILD_DIR}/zephyr/zephyr.$ext ]; then - cp ${BUILD_DIR}/zephyr/zephyr.$ext firmwares/zephyr-$variant.$ext - fi + rm -f firmwares/zephyr-$variant.$ext + # under MCUboot only the signed image boots, so prefer it when it exists + for src in $IMG.signed.$ext $IMG.$ext; do + if [ -f $src ]; then + cp $src firmwares/zephyr-$variant.$ext + break + fi + done done -cp ${BUILD_DIR}/zephyr/zephyr.dts firmwares/zephyr-$variant.dts -cp ${BUILD_DIR}/zephyr/.config firmwares/zephyr-$variant.config +rm -f firmwares/mcuboot-$variant.hex +if [ -n "$mcuboot" ]; then + cp ${BUILD_DIR}/mcuboot/zephyr/zephyr.hex firmwares/mcuboot-$variant.hex +fi +cp ${LOADER_DIR}/zephyr/zephyr.dts firmwares/zephyr-$variant.dts +cp ${LOADER_DIR}/zephyr/.config firmwares/zephyr-$variant.config # Generate the provides.ld file for linked builds echo "Generating exported symbol scripts" -extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -T > ${VARIANT_DIR}/tls-syms.S -extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -L > ${VARIANT_DIR}/syms-dynamic.ld -extra/gen_provides.py "${BUILD_DIR}/zephyr/zephyr.elf" -LF \ +extra/gen_provides.py "${LOADER_DIR}/zephyr/zephyr.elf" -T > ${VARIANT_DIR}/tls-syms.S +extra/gen_provides.py "${LOADER_DIR}/zephyr/zephyr.elf" -L > ${VARIANT_DIR}/syms-dynamic.ld +extra/gen_provides.py "${LOADER_DIR}/zephyr/zephyr.elf" -LF \ "+kheap_llext_heap" \ "+kheap__system_heap" \ "*sketch_base_addr=_sketch_start" \ diff --git a/key/rak_key_ecdsa-p256.c b/key/rak_key_ecdsa-p256.c new file mode 100644 index 000000000..e1a1411b4 --- /dev/null +++ b/key/rak_key_ecdsa-p256.c @@ -0,0 +1,21 @@ +/* + The key is only for test purpose!!! + Please use your own key at your production code!!! +*/ + +/* Autogenerated by imgtool.py, do not edit. */ +const unsigned char ecdsa_pub_key[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x42, 0x4e, 0x36, 0x58, 0x49, + 0xaf, 0xc7, 0x7a, 0x75, 0x5b, 0xf2, 0xe1, 0xc6, + 0xee, 0x3e, 0xbe, 0x9c, 0x7b, 0x2a, 0x4a, 0xa0, + 0xe8, 0xa0, 0xc4, 0xb9, 0x90, 0xdb, 0xc1, 0xe2, + 0xb7, 0x69, 0x6a, 0x1a, 0xe4, 0x78, 0xee, 0xba, + 0x50, 0x06, 0x96, 0xc7, 0x6c, 0x72, 0x46, 0xba, + 0xef, 0x13, 0x2e, 0x01, 0xcb, 0xaf, 0xb3, 0xe0, + 0x37, 0xd6, 0x58, 0x51, 0xde, 0xd8, 0x9f, 0x85, + 0x43, 0x36, 0x67, +}; +const unsigned int ecdsa_pub_key_len = 91; diff --git a/key/rak_key_ecdsa-p256.pem b/key/rak_key_ecdsa-p256.pem new file mode 100644 index 000000000..ecfc7e8ad --- /dev/null +++ b/key/rak_key_ecdsa-p256.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWIfFB5fjaNwpBXxa +19V/TCsa7QQRMPykwR52i1PLvS2hRANCAARCTjZYSa/HenVb8uHG7j6+nHsqSqDo +oMS5kNvB4rdpahrkeO66UAaWx2xyRrrvEy4By6+z4DfWWFHe2J+FQzZn +-----END PRIVATE KEY----- diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 5e6f2c9f2..3c7b1742d 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -5,7 +5,10 @@ cmake_minimum_required(VERSION 3.20.0) # get value of NORMALIZED_BOARD_TARGET early -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS yaml boards) +# 'basic_settings' must load before 'boards' so the board lookup works under +# sysbuild: it creates the sysbuild_cache target that the boards module reads. +# It is a no-op in a non-sysbuild build, so plain builds are unaffected. +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS basic_settings yaml boards) set(DTC_OVERLAY_FILE ${CMAKE_CURRENT_LIST_DIR}/../variants/${NORMALIZED_BOARD_TARGET}/${NORMALIZED_BOARD_TARGET}.overlay) set(EXTRA_CONF_FILE ${CMAKE_CURRENT_LIST_DIR}/../variants/${NORMALIZED_BOARD_TARGET}/${NORMALIZED_BOARD_TARGET}.conf) diff --git a/loader/overlay_mcuboot.conf b/loader/overlay_mcuboot.conf new file mode 100644 index 000000000..b23c24689 --- /dev/null +++ b/loader/overlay_mcuboot.conf @@ -0,0 +1,29 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MCUMGR=y +CONFIG_NET_BUF=y +CONFIG_ZCBOR=y +CONFIG_BASE64=y +CONFIG_CRC=y + +# Enable flash operations. +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_IMG_MANAGER=y +CONFIG_STREAM_FLASH=y + +# Enable most core commands. +CONFIG_MCUMGR_GRP_IMG=y +CONFIG_MCUMGR_GRP_OS=y + +# Enable the storage erase command. +CONFIG_MCUMGR_GRP_ZBASIC=y +CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y + +# Enable the serial MCUmgr transport. +CONFIG_UART_MCUMGR=y +CONFIG_MCUMGR_TRANSPORT_UART=y + +CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/loader/sysbuild.conf b/loader/sysbuild.conf new file mode 100644 index 000000000..28cde1006 --- /dev/null +++ b/loader/sysbuild.conf @@ -0,0 +1,10 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +# Enable MCUboot bootloader support +SB_CONFIG_BOOTLOADER_MCUBOOT=y + +# Do not forget to use your own key at your production code!!! +SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/../key/rak_key_ecdsa-p256.pem" +SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y diff --git a/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay new file mode 100644 index 000000000..58fed577a --- /dev/null +++ b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 RAKwireless Technology Limited + * Author: sercan.erat@rakwireless.com + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Same flash layout as the loader, so the two images always agree on it. */ +#include "../../../../variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi" + +/ { + aliases { + mcuboot-led0 = &green_led; + }; +}; + +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; + +/* + * The RAK4631 LEDs are active high: green on P1.03 (D7), + * blue on P1.04 (D8). The base board declares them active low. + */ +&green_led { + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; +}; + +&blue_led { + gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; +}; diff --git a/loader/sysbuild/mcuboot/prj.conf b/loader/sysbuild/mcuboot/prj.conf new file mode 100644 index 000000000..f8da974e0 --- /dev/null +++ b/loader/sysbuild/mcuboot/prj.conf @@ -0,0 +1,37 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=4096 + +# Enable Serial Recovery over UART +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_UART=y +CONFIG_BOOT_SERIAL_ENTRANCE_GPIO=n +CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y +CONFIG_BOOT_SERIAL_NO_APPLICATION=y + +# Force ECDSA-P256, since this is not necessarily the default +CONFIG_BOOT_SIGNATURE_TYPE_RSA=n +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +# The build won't fit on the partition allocated for it without size +# optimizations. +CONFIG_SIZE_OPTIMIZATIONS=y + +# Use minimal C library instead of the Picolib +CONFIG_MINIMAL_LIBC=y + +CONFIG_FLASH=y +CONFIG_MCUBOOT_INDICATION_LED=y +CONFIG_REBOOT=y +CONFIG_CBPRINTF_NANO=y + +CONFIG_LOG=n +CONFIG_LOG_PRINTK=n + +CONFIG_BOOT_BANNER=n +CONFIG_DEBUG_OPTIMIZATIONS=n +CONFIG_UART_CONSOLE=n +CONFIG_RTT_CONSOLE=n +CONFIG_STDOUT_CONSOLE=n diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay index d79912e01..0c626f870 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay @@ -4,12 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Flash layout, shared with the MCUboot image (loader/sysbuild/mcuboot). */ +#include "rak4631_nrf52840_partitions.dtsi" + /{ chosen { zephyr,console = &board_cdc_acm_logging; zephyr,log-uart = &log_uarts; zephyr,shell-uart = &board_cdc_acm_shell; zephyr,code-partition = &code_partition; + zephyr,uart-mcumgr = &board_cdc_acm_sketch; }; aliases { @@ -118,40 +122,6 @@ pinctrl-names = "default", "sleep"; }; -/delete-node/ &boot_partition; -/delete-node/ &slot0_partition; -/delete-node/ &slot1_partition; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - code_partition: partition@0 { - label = "code"; - reg = <0x00000000 0x00070000>; - read-only; - }; - - user_sketch: partition@70000 { - label = "user"; - reg = <0x070000 0x88000>; - }; - - /* - * The flash starting at 0x000f8000 and ending at - * 0x000fffff is reserved for use by the application. - * - * Storage partition will be used by FCB/LittleFS/NVS - * if enabled. - */ - storage_partition: partition@f8000 { - label = "storage"; - reg = <0x000f8000 0x00008000>; - }; - }; -}; /* Arduino API pin mappings */ / { @@ -226,6 +196,8 @@ <&adc 2>, /* A2 - WB_IO4 (AIN2) */ <&adc 4>; /* A3 - WB_IO7 (AIN4) */ + builtin-led-gpios = <&gpio1 3 0>; + i2cs = <&i2c0>; /* 'Wire': WisBlock sensor I2C (SDA P0.13, SCL P0.14) */ spis = <&spi2>; /* 'SPI': WisBlock header SPI */ diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi b/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi new file mode 100644 index 000000000..0a830a0cd --- /dev/null +++ b/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 RAKwireless Technology Limited + * Author: sercan.erat@rakwireless.com + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * RAK4631 flash layout, shared by the loader and the MCUboot image. + * + * MCUboot and the mcumgr image group address the slots through the + * slot0_partition / slot1_partition labels; the loader addresses the same + * partitions as code_partition / user_sketch. + */ + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00010000>; + read-only; + }; + + /* Loader; the MCUboot image header takes its first 0x200 bytes. */ + slot0_partition: code_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00070000>; + read-only; + }; + + /* Sketch. */ + slot1_partition: user_sketch: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x00078000>; + }; + + /* + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 0x00008000>; + }; + }; +}; diff --git a/west.yml b/west.yml index ab7246bf3..35fad7049 100644 --- a/west.yml +++ b/west.yml @@ -38,6 +38,7 @@ manifest: - lvgl - fatfs - loramac-node + - zcbor - hal_nordic # path-allowlist: # - modules/hal/* From 304fea3b61f807c15b1a0a767b65be1e4a3d7b03 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Fri, 18 Sep 2026 11:39:54 +0300 Subject: [PATCH 02/11] modules: added regout0 fix and double-tap driver Signed-off-by: Sercan Erat --- .editorconfig-checker.json | 4 +- CMakeLists.txt | 4 + Kconfig.rak | 2 + extra/rak/license_check.py | 2 +- key/rak_key_ecdsa-p256.c | 30 +++---- loader/CMakeLists.txt | 2 + modules/CMakeLists.txt | 6 ++ modules/Kconfig | 8 ++ modules/rak_double_tap/CMakeLists.txt | 6 ++ modules/rak_double_tap/Kconfig | 25 ++++++ modules/rak_double_tap/double_tap.c | 78 +++++++++++++++++++ modules/rak_regout0_fix/CMakeLists.txt | 6 ++ modules/rak_regout0_fix/Kconfig | 13 ++++ .../rak_regout0_fix/regout0_fix.c | 10 +-- 14 files changed, 173 insertions(+), 23 deletions(-) create mode 100644 modules/CMakeLists.txt create mode 100644 modules/Kconfig create mode 100644 modules/rak_double_tap/CMakeLists.txt create mode 100644 modules/rak_double_tap/Kconfig create mode 100644 modules/rak_double_tap/double_tap.c create mode 100644 modules/rak_regout0_fix/CMakeLists.txt create mode 100644 modules/rak_regout0_fix/Kconfig rename loader/rak4630_regout0.c => modules/rak_regout0_fix/regout0_fix.c (83%) diff --git a/.editorconfig-checker.json b/.editorconfig-checker.json index 2ed2559f0..378291c67 100644 --- a/.editorconfig-checker.json +++ b/.editorconfig-checker.json @@ -11,6 +11,8 @@ "firmwares/", "loader/blobs/", "llext-edk/", - "extra/build.sh" + "extra/build.sh", + "loader/CMakeLists.txt", + "^CMakeLists\\.txt$" ] } diff --git a/CMakeLists.txt b/CMakeLists.txt index 59aeebe90..c4a01af39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,9 @@ +# Copyright (c) Arduino s.r.l. and/or its affiliated companies +# Copyright (c) 2026 RAKwireless Technology Limited # SPDX-License-Identifier: Apache-2.0 +add_subdirectory(modules) + # Do nothing unless the Arduino API is enabled in the Zephyr project if(NOT CONFIG_ARDUINO_API) return() diff --git a/Kconfig.rak b/Kconfig.rak index eca81397d..d675fdeca 100644 --- a/Kconfig.rak +++ b/Kconfig.rak @@ -12,3 +12,5 @@ config RAK_RUI_API With this option disabled the core behaves like upstream ArduinoCore-zephyr and none of the RAK sources are compiled. + +rsource "modules/Kconfig" diff --git a/extra/rak/license_check.py b/extra/rak/license_check.py index df0f36f5d..628f3a66f 100644 --- a/extra/rak/license_check.py +++ b/extra/rak/license_check.py @@ -22,7 +22,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parent)) import rak_utils as utils -IGNORE_SUFFIXES = {".md", ".rst", ".txt", ".pde", ".json", ".svg"} +IGNORE_SUFFIXES = {".md", ".rst", ".txt", ".pde", ".json", ".svg", ".pem"} # Never checked, matched by exact file name (dotfiles have no suffix). IGNORE_NAMES = {".gitignore", "VERSION"} # Checked even though their suffix is ignored. diff --git a/key/rak_key_ecdsa-p256.c b/key/rak_key_ecdsa-p256.c index e1a1411b4..2a1ee5ffd 100644 --- a/key/rak_key_ecdsa-p256.c +++ b/key/rak_key_ecdsa-p256.c @@ -1,21 +1,21 @@ /* - The key is only for test purpose!!! - Please use your own key at your production code!!! -*/ + * Copyright (c) 2026 RAKwireless Technology Limited + * Author: sercan.erat@rakwireless.com + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * The key is only for test purpose!!! + * Please use your own key at your production code!!! + */ /* Autogenerated by imgtool.py, do not edit. */ const unsigned char ecdsa_pub_key[] = { - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, - 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, - 0x42, 0x00, 0x04, 0x42, 0x4e, 0x36, 0x58, 0x49, - 0xaf, 0xc7, 0x7a, 0x75, 0x5b, 0xf2, 0xe1, 0xc6, - 0xee, 0x3e, 0xbe, 0x9c, 0x7b, 0x2a, 0x4a, 0xa0, - 0xe8, 0xa0, 0xc4, 0xb9, 0x90, 0xdb, 0xc1, 0xe2, - 0xb7, 0x69, 0x6a, 0x1a, 0xe4, 0x78, 0xee, 0xba, - 0x50, 0x06, 0x96, 0xc7, 0x6c, 0x72, 0x46, 0xba, - 0xef, 0x13, 0x2e, 0x01, 0xcb, 0xaf, 0xb3, 0xe0, - 0x37, 0xd6, 0x58, 0x51, 0xde, 0xd8, 0x9f, 0x85, - 0x43, 0x36, 0x67, + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x42, 0x4e, 0x36, 0x58, 0x49, + 0xaf, 0xc7, 0x7a, 0x75, 0x5b, 0xf2, 0xe1, 0xc6, 0xee, 0x3e, 0xbe, 0x9c, 0x7b, 0x2a, 0x4a, 0xa0, + 0xe8, 0xa0, 0xc4, 0xb9, 0x90, 0xdb, 0xc1, 0xe2, 0xb7, 0x69, 0x6a, 0x1a, 0xe4, 0x78, 0xee, 0xba, + 0x50, 0x06, 0x96, 0xc7, 0x6c, 0x72, 0x46, 0xba, 0xef, 0x13, 0x2e, 0x01, 0xcb, 0xaf, 0xb3, 0xe0, + 0x37, 0xd6, 0x58, 0x51, 0xde, 0xd8, 0x9f, 0x85, 0x43, 0x36, 0x67, }; const unsigned int ecdsa_pub_key_len = 91; diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 3c7b1742d..851e974ce 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -1,3 +1,5 @@ +# Copyright (c) Arduino s.r.l. and/or its affiliated companies +# Copyright (c) 2026 RAKwireless Technology Limited # SPDX-License-Identifier: Apache-2.0 #set(DTC_OVERLAY_FILE ${BOARD}.overlay) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100644 index 000000000..4b463590a --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory_ifdef(CONFIG_RAK_DOUBLE_TAP rak_double_tap) +add_subdirectory_ifdef(CONFIG_RAK_REGOUT0_FIX rak_regout0_fix) diff --git a/modules/Kconfig b/modules/Kconfig new file mode 100644 index 000000000..33008cb1e --- /dev/null +++ b/modules/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +menu "RAKwireless Modules" +rsource "rak_double_tap/Kconfig" +rsource "rak_regout0_fix/Kconfig" +endmenu diff --git a/modules/rak_double_tap/CMakeLists.txt b/modules/rak_double_tap/CMakeLists.txt new file mode 100644 index 000000000..784030c55 --- /dev/null +++ b/modules/rak_double_tap/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(double_tap.c) diff --git a/modules/rak_double_tap/Kconfig b/modules/rak_double_tap/Kconfig new file mode 100644 index 000000000..88969db90 --- /dev/null +++ b/modules/rak_double_tap/Kconfig @@ -0,0 +1,25 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +menuconfig RAK_DOUBLE_TAP + bool "Enter the bootloader on a double tap reset" + depends on RETENTION_BOOT_MODE + select HWINFO + help + Pressing the reset button twice within RAK_DOUBLE_TAP_WINDOW_MS duration + to set the boot-mode to BOOT_MODE_TYPE_BOOTLOADER through the retention + area chosen as zephyr,boot-mode. + +if RAK_DOUBLE_TAP + +config RAK_DOUBLE_TAP_WINDOW_MS + int "Double-tap window in milliseconds" + default 500 + range 50 5000 + help + Time after a press of the reset button during which a second press + enters the bootloader. The bootloader busy-waits for this long after + every such press, so it adds directly to that boot's time. + +endif # RAK_DOUBLE_TAP diff --git a/modules/rak_double_tap/double_tap.c b/modules/rak_double_tap/double_tap.c new file mode 100644 index 000000000..202292ee0 --- /dev/null +++ b/modules/rak_double_tap/double_tap.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2026 RAKwireless Technology Limited + * Author: sercan.erat@rakwireless.com + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Double-tap reset: press the reset button twice within + * CONFIG_RAK_DOUBLE_TAP_WINDOW_MS duration to enter the bootloader's recovery mode. + */ + +#include +#include +#include +#include +#include + +#define RAK_BOOT_MODE_DOUBLE_TAP_ARMED 0xD7 + +#ifdef CONFIG_MCUBOOT_INDICATION_LED +static const struct gpio_dt_spec window_led = GPIO_DT_SPEC_GET(DT_ALIAS(mcuboot_led0), gpios); +#endif + +static void window_led_set(bool on) { +#ifdef CONFIG_MCUBOOT_INDICATION_LED + (void)gpio_pin_configure_dt(&window_led, on ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE); +#else + ARG_UNUSED(on); +#endif +} + +static bool reset_by_button(void) { + uint32_t cause = 0; + int rc; + + rc = hwinfo_get_reset_cause(&cause); + (void)hwinfo_clear_reset_cause(); + + if (rc != 0) { + return false; + } + + return (cause & RESET_PIN) != 0; +} + +static int double_tap_check(void) { + bool button = reset_by_button(); + + if (bootmode_check(BOOT_MODE_TYPE_BOOTLOADER) == 1) { + return 0; + } + + if (!button) { + (void)bootmode_clear(); + return 0; + } + + if (bootmode_check(RAK_BOOT_MODE_DOUBLE_TAP_ARMED) == 1) { + /* Second tap: keep the LED on; MCUboot takes it over in recovery. */ + window_led_set(true); + (void)bootmode_set(BOOT_MODE_TYPE_BOOTLOADER); + return 0; + } + + if (bootmode_set(RAK_BOOT_MODE_DOUBLE_TAP_ARMED) != 0) { + return 0; + } + + window_led_set(true); + k_busy_wait(CONFIG_RAK_DOUBLE_TAP_WINDOW_MS * USEC_PER_MSEC); + window_led_set(false); + + (void)bootmode_clear(); + + return 0; +} + +SYS_INIT(double_tap_check, APPLICATION, 0); diff --git a/modules/rak_regout0_fix/CMakeLists.txt b/modules/rak_regout0_fix/CMakeLists.txt new file mode 100644 index 000000000..69ffae478 --- /dev/null +++ b/modules/rak_regout0_fix/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(regout0_fix.c) diff --git a/modules/rak_regout0_fix/Kconfig b/modules/rak_regout0_fix/Kconfig new file mode 100644 index 000000000..4c1779bce --- /dev/null +++ b/modules/rak_regout0_fix/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +config RAK_REGOUT0_FIX + bool "Program UICR REGOUT0 to 3.3 V on a VDDH-powered RAK4630" + depends on BOARD_RAK4631_NRF52840 + help + Early-boot hook for the RAK4630 module, whose nRF52840 is supplied + through VDDH. A full chip erase leaves UICR REGOUT0 at its 1.8 V + default, which underpowers the LEDs and 3.3 V peripherals. The hook + programs REGOUT0 to 3.3 V once and resets the chip. It is a no-op + when the chip runs in normal-voltage mode or REGOUT0 is already set. diff --git a/loader/rak4630_regout0.c b/modules/rak_regout0_fix/regout0_fix.c similarity index 83% rename from loader/rak4630_regout0.c rename to modules/rak_regout0_fix/regout0_fix.c index 14dec3865..527a7dc89 100644 --- a/loader/rak4630_regout0.c +++ b/modules/rak_regout0_fix/regout0_fix.c @@ -17,13 +17,12 @@ * boards powered in normal-voltage mode. */ -#include - -#if defined(CONFIG_BOARD_NRF52840DK) || defined(CONFIG_BOARD_RAK4631_NRF52840) #include #include -static int rak4630_vddh_regout0_3v3(void) { +#include + +static int rak_vddh_regout0_3v3(void) { if ((nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) && ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos))) { @@ -46,5 +45,4 @@ static int rak4630_vddh_regout0_3v3(void) { return 0; } -SYS_INIT(rak4630_vddh_regout0_3v3, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); -#endif /* CONFIG_BOARD_NRF52840DK || CONFIG_BOARD_RAK4631_NRF52840 */ +SYS_INIT(rak_vddh_regout0_3v3, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); From 70d840694c409daa04c183f69ab2539ea772d7c6 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Tue, 22 Sep 2026 15:47:52 +0300 Subject: [PATCH 03/11] variants: rak4631: enable the REGOUT0 fix in the loader and the samples Signed-off-by: Sercan Erat --- modules/rak_double_tap/Kconfig | 1 + samples/blinky_arduino/boards/rak4631_nrf52840.conf | 2 ++ samples/hello_arduino/boards/rak4631_nrf52840.conf | 2 ++ variants/rak4631_nrf52840/rak4631_nrf52840.conf | 1 + 4 files changed, 6 insertions(+) diff --git a/modules/rak_double_tap/Kconfig b/modules/rak_double_tap/Kconfig index 88969db90..5bed3fa25 100644 --- a/modules/rak_double_tap/Kconfig +++ b/modules/rak_double_tap/Kconfig @@ -4,6 +4,7 @@ menuconfig RAK_DOUBLE_TAP bool "Enter the bootloader on a double tap reset" + depends on BOARD_RAK4631_NRF52840 depends on RETENTION_BOOT_MODE select HWINFO help diff --git a/samples/blinky_arduino/boards/rak4631_nrf52840.conf b/samples/blinky_arduino/boards/rak4631_nrf52840.conf index 62c41b919..0d16c0332 100644 --- a/samples/blinky_arduino/boards/rak4631_nrf52840.conf +++ b/samples/blinky_arduino/boards/rak4631_nrf52840.conf @@ -4,6 +4,8 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +CONFIG_RAK_REGOUT0_FIX=y + CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_USB_DEVICE_PRODUCT="RAKwireless RAK4631" CONFIG_USB_DEVICE_MANUFACTURER="RAKwireless" diff --git a/samples/hello_arduino/boards/rak4631_nrf52840.conf b/samples/hello_arduino/boards/rak4631_nrf52840.conf index 62c41b919..0d16c0332 100644 --- a/samples/hello_arduino/boards/rak4631_nrf52840.conf +++ b/samples/hello_arduino/boards/rak4631_nrf52840.conf @@ -4,6 +4,8 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 +CONFIG_RAK_REGOUT0_FIX=y + CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_USB_DEVICE_PRODUCT="RAKwireless RAK4631" CONFIG_USB_DEVICE_MANUFACTURER="RAKwireless" diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.conf b/variants/rak4631_nrf52840/rak4631_nrf52840.conf index f3f92a149..d547d366b 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.conf +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.conf @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_RAK_RUI_API=y +CONFIG_RAK_REGOUT0_FIX=y CONFIG_BT=y CONFIG_BT_HCI_RAW=y From d0abba77beeaf038ca5c4ae9343915396a09b68a Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Tue, 22 Sep 2026 15:50:32 +0300 Subject: [PATCH 04/11] loader: enter MCUboot serial recovery over USB on a double-tap reset Signed-off-by: Sercan Erat --- loader/mcuboot.md | 36 +++++++++++++ loader/overlay_mcuboot.conf | 6 +-- loader/sysbuild.conf | 4 ++ .../mcuboot/boards/rak4631_nrf52840.conf | 20 ++++++++ .../mcuboot/boards/rak4631_nrf52840.overlay | 14 +++++- loader/sysbuild/mcuboot/prj.conf | 24 +++++++-- .../rak4631_nrf52840/rak4631_nrf52840.overlay | 6 ++- .../rak4631_nrf52840_bootmode.dtsi | 50 +++++++++++++++++++ 8 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 loader/mcuboot.md create mode 100644 loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf create mode 100644 variants/rak4631_nrf52840/rak4631_nrf52840_bootmode.dtsi diff --git a/loader/mcuboot.md b/loader/mcuboot.md new file mode 100644 index 000000000..29ea37729 --- /dev/null +++ b/loader/mcuboot.md @@ -0,0 +1,36 @@ +### How to use MCUmgr: + +Install go tool: + +```shell +brew install go +``` + +# Updating MCU over UART/USB-CDC +Firstly, go must be installed. After that, mcumgr and scripting-tools +can be installed via following command: +```shell +go install github.com/apache/mynewt-mcumgr-cli/mcumgr@latest +go install github.com/arduino/scripting-tools@latest +``` + +mcumgr path can be find via following command: +```shell +go env GOPATH +``` + +To test, send a string to the remote target device and have it echo it back: +```shell +mcumgr version +mcumgr --conntype serial --connstring "/dev/cu.usbserial-xxx,baud=115200" echo hello +``` + +Other commands to update mcu: +```shell +mcumgr --conntype serial --connstring image upload -n 1 ../firmwares/zephyr-rak4631_nrf52840.bin +mcumgr --conntype serial --connstring image upload -n 2 ../sketch/arduino_blinky/build/rak.zephyr.rak4631/arduino_blinky.ino.bin-zsk.bin + +mcumgr --conntype serial --connstring image list +mcumgr --conntype serial --connstring image confirm +mcumgr --conntype serial --connstring reset +``` diff --git a/loader/overlay_mcuboot.conf b/loader/overlay_mcuboot.conf index b23c24689..41173ca74 100644 --- a/loader/overlay_mcuboot.conf +++ b/loader/overlay_mcuboot.conf @@ -22,8 +22,8 @@ CONFIG_MCUMGR_GRP_OS=y CONFIG_MCUMGR_GRP_ZBASIC=y CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y -# Enable the serial MCUmgr transport. -CONFIG_UART_MCUMGR=y -CONFIG_MCUMGR_TRANSPORT_UART=y +# Disabled the serial MCUmgr transport. +CONFIG_UART_MCUMGR=n +CONFIG_MCUMGR_TRANSPORT_UART=n CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/loader/sysbuild.conf b/loader/sysbuild.conf index 28cde1006..5f52ea42e 100644 --- a/loader/sysbuild.conf +++ b/loader/sysbuild.conf @@ -8,3 +8,7 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y # Do not forget to use your own key at your production code!!! SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/../key/rak_key_ecdsa-p256.pem" SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + +# Serial recovery writes the loader straight into slot0 +# and the sketch straight into slot1; no swap ever runs. +SB_CONFIG_MCUBOOT_MODE_OVERWRITE_ONLY=y diff --git a/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf new file mode 100644 index 000000000..fba59b2a8 --- /dev/null +++ b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf @@ -0,0 +1,20 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_RAK_REGOUT0_FIX=y + +CONFIG_BOOT_SERIAL_UART=n +CONFIG_BOOT_SERIAL_CDC_ACM=y + +CONFIG_WARN_DEPRECATED=n + +# USB identity of the bootloader; a different PID from the loader (0x5300). +CONFIG_USB_DEVICE_PRODUCT="RAKwireless RAK4631" +CONFIG_USB_DEVICE_MANUFACTURER="RAKwireless" +CONFIG_USB_DEVICE_VID=0x1915 +CONFIG_USB_DEVICE_PID=0x5301 +# MCUboot enables USB itself when it enters recovery. +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +# Hold a whole 4 KB SMP packet (BOOT_SERIAL_MAX_RECEIVE_SIZE in prj.conf). +CONFIG_USB_CDC_ACM_RINGBUF_SIZE=4096 diff --git a/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay index 58fed577a..bb5f7902c 100644 --- a/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay +++ b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.overlay @@ -4,18 +4,28 @@ * SPDX-License-Identifier: Apache-2.0 */ -/* Same flash layout as the loader, so the two images always agree on it. */ +/* Same flash layout as the loader. */ #include "../../../../variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi" +/* Same boot-mode retention area as the loader. */ +#include "../../../../variants/rak4631_nrf52840/rak4631_nrf52840_bootmode.dtsi" / { aliases { - mcuboot-led0 = &green_led; + mcuboot-led0 = &blue_led; }; }; / { chosen { zephyr,code-partition = &boot_partition; + zephyr,uart-mcumgr = &board_cdc_acm_mcuboot; + }; +}; + +&zephyr_udc0 { + board_cdc_acm_mcuboot: board_cdc_acm_mcuboot { + compatible = "zephyr,cdc-acm-uart"; + status = "okay"; }; }; diff --git a/loader/sysbuild/mcuboot/prj.conf b/loader/sysbuild/mcuboot/prj.conf index f8da974e0..6e682a729 100644 --- a/loader/sysbuild/mcuboot/prj.conf +++ b/loader/sysbuild/mcuboot/prj.conf @@ -2,15 +2,30 @@ # Author: sercan.erat@rakwireless.com # SPDX-License-Identifier: Apache-2.0 -CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_MAIN_STACK_SIZE=10240 -# Enable Serial Recovery over UART +# Enable Serial Recovery CONFIG_MCUBOOT_SERIAL=y -CONFIG_BOOT_SERIAL_UART=y CONFIG_BOOT_SERIAL_ENTRANCE_GPIO=n -CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=y +CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=n CONFIG_BOOT_SERIAL_NO_APPLICATION=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y + +# Larger SMP packets +CONFIG_BOOT_LINE_BUFS=32 +CONFIG_BOOT_SERIAL_MAX_RECEIVE_SIZE=4096 + +# Enter serial recovery when the boot-mode retention area asks for it +# (set by the application or by the double-tap module below). +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y +CONFIG_RETENTION_BOOT_MODE=y +CONFIG_BOOT_SERIAL_BOOT_MODE=y + +# Double-tap reset enters serial recovery mode. +CONFIG_RAK_DOUBLE_TAP=y + # Force ECDSA-P256, since this is not necessarily the default CONFIG_BOOT_SIGNATURE_TYPE_RSA=n CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y @@ -32,6 +47,5 @@ CONFIG_LOG_PRINTK=n CONFIG_BOOT_BANNER=n CONFIG_DEBUG_OPTIMIZATIONS=n -CONFIG_UART_CONSOLE=n CONFIG_RTT_CONSOLE=n CONFIG_STDOUT_CONSOLE=n diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay index 0c626f870..b99ea2955 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay @@ -4,8 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -/* Flash layout, shared with the MCUboot image (loader/sysbuild/mcuboot). */ +/* Flash layout, shared with the MCUboot image as well. */ #include "rak4631_nrf52840_partitions.dtsi" +/* Boot-mode retention area, shared with the MCUboot image as well. */ +#include "rak4631_nrf52840_bootmode.dtsi" /{ chosen { @@ -13,7 +15,7 @@ zephyr,log-uart = &log_uarts; zephyr,shell-uart = &board_cdc_acm_shell; zephyr,code-partition = &code_partition; - zephyr,uart-mcumgr = &board_cdc_acm_sketch; + /delete-property/ zephyr,uart-mcumgr; }; aliases { diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840_bootmode.dtsi b/variants/rak4631_nrf52840/rak4631_nrf52840_bootmode.dtsi new file mode 100644 index 000000000..e39f419d9 --- /dev/null +++ b/variants/rak4631_nrf52840/rak4631_nrf52840_bootmode.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2026 RAKwireless Technology Limited + * Author: sercan.erat@rakwireless.com + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Boot-mode retention area, shared by the loader and the MCUboot image. + * + * It lives in the last 1 KB of SRAM. RAM keeps its content across pin and + * software resets and loses it on a power cycle. + */ + +/ { + chosen { + zephyr,boot-mode = &boot_mode0; + }; + + sram@2003fc00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003fc00 0x400>; + ranges = <0x0 0x2003fc00 0x400>; + zephyr,memory-region = "BootMode"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + bootmode_retained_mem: bootmode_retained_mem { + compatible = "zephyr,retained-ram"; + status = "okay"; + ranges; + #address-cells = <1>; + #size-cells = <1>; + + /* 2-byte prefix + 1 boot-mode byte + CRC-8 */ + boot_mode0: retention@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x4>; + prefix = [52 4b]; + checksum = <1>; + }; + }; + }; +}; + +/* Hand the last 1 KB to the retained area above. */ +&sram0 { + reg = <0x20000000 DT_SIZE_K(255)>; +}; From bcfcc3e88752e41b1a716d66c115d75bbe067002 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Tue, 22 Sep 2026 15:51:40 +0300 Subject: [PATCH 05/11] platform: add an mcumgr tool and use it for RAK4631 uploads Signed-off-by: Sercan Erat --- boards.txt | 13 ++++++++++++- platform.txt | 29 +++++++++++++++++++++++++++-- programmers.txt | 8 ++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/boards.txt b/boards.txt index dc64e7ca6..c5f21e0af 100644 --- a/boards.txt +++ b/boards.txt @@ -791,7 +791,18 @@ rak4631.build.board=RAK4631 rak4631.vid.0=0x1915 rak4631.pid.0=0x5300 rak4631.upload_port.0.vid=0x1915 -rak4631.upload_port.0.pid=0x5300 +rak4631.upload_port.0.pid=0x5301 rak4631.upload.target=nrf52840 +rak4631.upload.tool=mcumgr +rak4631.upload.tool.default=mcumgr +rak4631.upload.protocol= +rak4631.upload.transport= +rak4631.upload.use_1200bps_touch=false +rak4631.upload.wait_for_upload_port=false + +rak4631.bootloader.tool=mcumgr +rak4631.bootloader.tool.default=mcumgr +rak4631.bootloader.file=zephyr-{build.variant}.bin + ########################################################################################## diff --git a/platform.txt b/platform.txt index 4eee89658..a58518a6c 100644 --- a/platform.txt +++ b/platform.txt @@ -62,7 +62,7 @@ compiler.zephyr.common_ldflags=-fno-exceptions -fno-rtti -fno-threadsafe-statics compiler.zephyr.extra_cxxflags= compiler.zephyr.extra_ldflags=-lstdc++ -lsupc++ -lm -lgcc -lc -# these can be overriden in boards.txt +# these can be overridden in boards.txt build.extra_flags= build.extra_ldflags= build.link_mode=dynamic @@ -106,7 +106,7 @@ compiler.objcopy.eep.extra_flags= compiler.elf2hex.extra_flags= # {build.library_discovery_phase} is set to 1 by the builder during library discovery. -# (this is available since arduino-builder>=1.5.5, keeping the default here for backward compatiblity) +# (this is available since arduino-builder>=1.5.5, keeping the default here for backward compatibility) build.library_discovery_phase=0 build.library_discovery_phase_flag=-DARDUINO_LIBRARY_DISCOVERY_PHASE={build.library_discovery_phase} @@ -368,6 +368,31 @@ tools.jlink.upload.params.quiet= tools.jlink.upload.pattern="{path}/{cmd}" -CommanderScript "{build.path}/flasher.jlink" +# +# MCUmgr WRAPPER +# + +tools.mcumgr.path={runtime.tools.mcumgr.path} +tools.mcumgr.cmd=mcumgr +tools.mcumgr.cmd.windows=mcumgr.exe +tools.mcumgr.conn=--conntype serial --connstring "dev={serial.port},baud=115200,mtu=4096" +tools.mcumgr.scripting.path={runtime.tools.scripting.path} +tools.mcumgr.scripting.cmd=scripting-tools +tools.mcumgr.scripting.cmd.windows=scripting-tools.exe + +tools.mcumgr.loader.cmd="{path}/{cmd}" {conn} image upload -n 1 "{upload.artifacts.loader}" +tools.mcumgr.sketch.cmd="{path}/{cmd}" {conn} image upload -n 2 "{upload.artifacts.sketch}" +tools.mcumgr.reset.cmd="{path}/{cmd}" {conn} reset + +tools.mcumgr.upload.params.verbose= +tools.mcumgr.upload.params.quiet= +tools.mcumgr.upload.pattern="{scripting.path}/{scripting.cmd}" run {sketch.cmd} :: run {reset.cmd} + +tools.mcumgr.bootloader.params.verbose= +tools.mcumgr.bootloader.params.quiet= +tools.mcumgr.bootloader.pattern="{scripting.path}/{scripting.cmd}" run {loader.cmd} :: run {reset.cmd} + + # # Debugger # diff --git a/programmers.txt b/programmers.txt index e84569ceb..133c83d10 100644 --- a/programmers.txt +++ b/programmers.txt @@ -21,3 +21,11 @@ openocd.protocol=SWD openocd.program.tool=openocd openocd.program.tool.default=openocd openocd.program.extra_params= + +mcumgr.name=MCUmgr +mcumgr.communication=serial +mcumgr.protocol= +mcumgr.program.protocol= +mcumgr.program.tool=mcumgr +mcumgr.program.tool.default=mcumgr +mcumgr.program.extra_params= From 5bfb0847046cf412e789cca6639ee2855247de12 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Tue, 22 Sep 2026 16:00:06 +0300 Subject: [PATCH 06/11] vscode: add mcumgr upload tasks Signed-off-by: Sercan Erat --- .vscode/flash_loader.jlink | 1 + .vscode/flash_sketch.jlink | 2 +- .vscode/tasks.json | 29 ++++++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.vscode/flash_loader.jlink b/.vscode/flash_loader.jlink index d9d91340e..57fccf76c 100644 --- a/.vscode/flash_loader.jlink +++ b/.vscode/flash_loader.jlink @@ -1,3 +1,4 @@ +loadfile firmwares/mcuboot-rak4631_nrf52840.hex loadfile firmwares/zephyr-rak4631_nrf52840.hex r g diff --git a/.vscode/flash_sketch.jlink b/.vscode/flash_sketch.jlink index 5171b8e99..149ed8d73 100644 --- a/.vscode/flash_sketch.jlink +++ b/.vscode/flash_sketch.jlink @@ -1,4 +1,4 @@ -loadbin sketch/wisblock_rak13800/build/rak.zephyr.rak4631/wisblock_rak13800.ino.elf-zsk.bin, 0x70000 +loadbin sketch/arduino_blinky/build/rak.zephyr.rak4631/arduino_blinky.ino.elf-zsk.bin, 0x80000 r g exit diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 07e37e0cb..46c0c97ec 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -9,9 +9,10 @@ "BOARD_WEST": "rak4631/nrf52840", "VARIANT": "rak4631_nrf52840", "DEVICE": "NRF52840_XXAA", - "SKETCH": "sketch/wisblock_rak13800", + "SKETCH": "sketch/arduino_blinky", "SKETCH_DEBUG": "false", "SAMPLE": "samples/blinky_arduino", + "SERIAL_PORT": "/dev/cu.usbmodem1101" }, "cwd": "${workspaceFolder}" }, @@ -51,6 +52,19 @@ ], "problemMatcher": [] }, + { + // Board in MCUboot serial recovery (double-tap reset); MCUboot itself needs J-Link. + "label": "Loader: Upload (mcumgr)", + "type": "shell", + "command": "arduino-cli", + "args": [ + "burn-bootloader", + "-b", "rak:zephyr:${BOARD_ARD}", + "-P", "mcumgr", + "-p", "${SERIAL_PORT}" + ], + "problemMatcher": [] + }, { "label": "Loader: Clean", "type": "shell", @@ -115,6 +129,19 @@ ], "problemMatcher": [] }, + { + "label": "Sketch: Upload (mcumgr)", + "type": "shell", + "command": "arduino-cli", + "args": [ + "upload", + "-b", "rak:zephyr:${BOARD_ARD}", + "-p", "${SERIAL_PORT}", + "--input-dir", "${SKETCH}/build/rak.zephyr.${BOARD_ARD}", + "${SKETCH}" + ], + "problemMatcher": [] + }, { "label": "Sketch: Clean", "type": "shell", From 788f8161eb2371d1da0412265754117836154b4d Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Tue, 22 Sep 2026 16:00:25 +0300 Subject: [PATCH 07/11] ci: build the loader with MCUboot Signed-off-by: Sercan Erat --- extra/rak/checkall.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extra/rak/checkall.py b/extra/rak/checkall.py index 2015e3790..ceb2f66b0 100644 --- a/extra/rak/checkall.py +++ b/extra/rak/checkall.py @@ -63,8 +63,11 @@ def _build_checks(board): log.die(f"Board '{board}' not found in boards.txt / boards.local.txt") return [ - (f"loader build ({board})", ["./extra/build.sh", board]), - ("cppcheck static analysis", ["west", "rak-lint", "-b", f"build/{variant}"]), + (f"loader build ({board})", ["./extra/build.sh", board, "--mcuboot"]), + ( + "cppcheck static analysis", + ["west", "rak-lint", "-b", f"build/{variant}/loader"], + ), (f"sketch compilation ({board})", ["west", "rak-sketch-check", "-b", board]), (f"sample build ({target})", ["west", "rak-sample-check", "-b", target]), ] From 68f43ecae28796f9476f250d91cca2f43ad269b8 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Thu, 24 Sep 2026 14:58:37 +0300 Subject: [PATCH 08/11] rak4631: enter MCUboot serial recovery with a 1200-bps method Signed-off-by: Sercan Erat --- boards.txt | 8 ++++--- loader/llext_exports.c | 4 ++++ .../mcuboot/boards/rak4631_nrf52840.conf | 2 +- loader/sysbuild/mcuboot/prj.conf | 21 ++++++++----------- modules/rak_double_tap/double_tap.c | 2 ++ .../rak4631_nrf52840/rak4631_nrf52840.conf | 6 ++++++ .../rak4631_nrf52840/rak4631_nrf52840.overlay | 12 +++++------ variants/rak4631_nrf52840/variant.cpp | 13 ++++++++++++ 8 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 variants/rak4631_nrf52840/variant.cpp diff --git a/boards.txt b/boards.txt index c5f21e0af..a205940cd 100644 --- a/boards.txt +++ b/boards.txt @@ -764,7 +764,7 @@ nrf52840dk.upload.target=nrf52840 rak4631.name=RAKwireless RAK4631 rak4631.build.core=arduino rak4631.build.crossprefix=arm-zephyr-eabi- -rak4631.build.compiler_path={runtime.tools.arm-zephyr-eabi-0.16.8.path}/bin/ +rak4631.build.compiler_path={runtime.tools.arm-zephyr-eabi-1.0.1.path}/bin/ rak4631.menu.debug.false=Standard rak4631.menu.debug.true=Debug @@ -783,6 +783,7 @@ rak4631.menu.baseboard.rak19007.build.extra_flags=-DWISBLOCK_BASE_19007 rak4631.build.zephyr_target=rak4631/nrf52840 rak4631.build.zephyr_args= rak4631.build.zephyr_hals=hal_nordic +rak4631.build.zephyr_toolchain=arm-zephyr-eabi rak4631.build.variant=rak4631_nrf52840 rak4631.build.extra_flags= @@ -798,8 +799,9 @@ rak4631.upload.tool=mcumgr rak4631.upload.tool.default=mcumgr rak4631.upload.protocol= rak4631.upload.transport= -rak4631.upload.use_1200bps_touch=false -rak4631.upload.wait_for_upload_port=false +rak4631.upload.use_1200bps_touch=true +rak4631.upload.wait_for_upload_port=true +rak4631.upload.native_usb=true rak4631.bootloader.tool=mcumgr rak4631.bootloader.tool.default=mcumgr diff --git a/loader/llext_exports.c b/loader/llext_exports.c index 5d89422a5..f2cf0d425 100644 --- a/loader/llext_exports.c +++ b/loader/llext_exports.c @@ -549,4 +549,8 @@ FORCE_EXPORT_SYM(lorawan_register_dr_changed_callback); FORCE_EXPORT_SYM(lorawan_register_link_check_ans_callback); #endif +#if defined(CONFIG_RETENTION_BOOT_MODE) +FORCE_EXPORT_SYM(bootmode_set); +#endif + EXPORT_SYMBOL(sketch_header_v1_verify); diff --git a/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf index fba59b2a8..87021a79e 100644 --- a/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf +++ b/loader/sysbuild/mcuboot/boards/rak4631_nrf52840.conf @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_RAK_REGOUT0_FIX=y +CONFIG_RAK_DOUBLE_TAP=y CONFIG_BOOT_SERIAL_UART=n CONFIG_BOOT_SERIAL_CDC_ACM=y @@ -16,5 +17,4 @@ CONFIG_USB_DEVICE_VID=0x1915 CONFIG_USB_DEVICE_PID=0x5301 # MCUboot enables USB itself when it enters recovery. CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n -# Hold a whole 4 KB SMP packet (BOOT_SERIAL_MAX_RECEIVE_SIZE in prj.conf). CONFIG_USB_CDC_ACM_RINGBUF_SIZE=4096 diff --git a/loader/sysbuild/mcuboot/prj.conf b/loader/sysbuild/mcuboot/prj.conf index 6e682a729..c8894216c 100644 --- a/loader/sysbuild/mcuboot/prj.conf +++ b/loader/sysbuild/mcuboot/prj.conf @@ -6,29 +6,27 @@ CONFIG_MAIN_STACK_SIZE=10240 # Enable Serial Recovery CONFIG_MCUBOOT_SERIAL=y +CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_MCUBOOT_INDICATION_LED=y + +# Enable Serial boot mode CONFIG_BOOT_SERIAL_ENTRANCE_GPIO=n CONFIG_BOOT_SERIAL_WAIT_FOR_DFU=n CONFIG_BOOT_SERIAL_NO_APPLICATION=y - -CONFIG_MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD=y +CONFIG_BOOT_SERIAL_BOOT_MODE=y # Larger SMP packets CONFIG_BOOT_LINE_BUFS=32 CONFIG_BOOT_SERIAL_MAX_RECEIVE_SIZE=4096 +# Force ECDSA-P256, since this is not necessarily the default +CONFIG_BOOT_SIGNATURE_TYPE_RSA=n +CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y + # Enter serial recovery when the boot-mode retention area asks for it -# (set by the application or by the double-tap module below). CONFIG_RETAINED_MEM=y CONFIG_RETENTION=y CONFIG_RETENTION_BOOT_MODE=y -CONFIG_BOOT_SERIAL_BOOT_MODE=y - -# Double-tap reset enters serial recovery mode. -CONFIG_RAK_DOUBLE_TAP=y - -# Force ECDSA-P256, since this is not necessarily the default -CONFIG_BOOT_SIGNATURE_TYPE_RSA=n -CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y # The build won't fit on the partition allocated for it without size # optimizations. @@ -38,7 +36,6 @@ CONFIG_SIZE_OPTIMIZATIONS=y CONFIG_MINIMAL_LIBC=y CONFIG_FLASH=y -CONFIG_MCUBOOT_INDICATION_LED=y CONFIG_REBOOT=y CONFIG_CBPRINTF_NANO=y diff --git a/modules/rak_double_tap/double_tap.c b/modules/rak_double_tap/double_tap.c index 202292ee0..d8c1da4c3 100644 --- a/modules/rak_double_tap/double_tap.c +++ b/modules/rak_double_tap/double_tap.c @@ -47,6 +47,8 @@ static int double_tap_check(void) { bool button = reset_by_button(); if (bootmode_check(BOOT_MODE_TYPE_BOOTLOADER) == 1) { + /* 1200 bps touch: same as a second tap. */ + window_led_set(true); return 0; } diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.conf b/variants/rak4631_nrf52840/rak4631_nrf52840.conf index d547d366b..186345b16 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.conf +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.conf @@ -35,6 +35,12 @@ CONFIG_USBD_CDC_ACM_LOG_LEVEL_ERR=y CONFIG_UDC_DRIVER_LOG_LEVEL_ERR=y CONFIG_USBD_LOG_LEVEL_ERR=y +# Boot mode (rak4631_nrf52840_bootmode.dtsi): the 1200 bps touch in +# variant.cpp asks MCUboot for serial recovery through it. +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y +CONFIG_RETENTION_BOOT_MODE=y + CONFIG_GPIO=y CONFIG_I2C=y CONFIG_SPI=y diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay index b99ea2955..4f7d3d1db 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay @@ -31,22 +31,22 @@ /* * USB CDC-ACM ports, in enumeration order: - * 1. logging: console (printk/stdout msg)+ log backend - * 2. sketch: the sketch's 'Serial' (SerialUSB) - * 3. shell: Zephyr shell (debug builds only, unused otherwise) + * 1. sketch: the sketch's 'Serial' (SerialUSB) + * 2. shell: Zephyr shell (debug builds only, unused otherwise) + * 3. logging: console (printk/stdout msg)+ log backend (debug builds only, unused otherwise) */ &zephyr_udc0 { - board_cdc_acm_logging: board_cdc_acm_logging { + board_cdc_acm_sketch: board_cdc_acm_sketch { compatible = "zephyr,cdc-acm-uart"; status = "okay"; }; - board_cdc_acm_sketch: board_cdc_acm_sketch { + board_cdc_acm_shell: board_cdc_acm_shell { compatible = "zephyr,cdc-acm-uart"; status = "okay"; }; - board_cdc_acm_shell: board_cdc_acm_shell { + board_cdc_acm_logging: board_cdc_acm_logging { compatible = "zephyr,cdc-acm-uart"; status = "okay"; }; diff --git a/variants/rak4631_nrf52840/variant.cpp b/variants/rak4631_nrf52840/variant.cpp new file mode 100644 index 000000000..0528feeea --- /dev/null +++ b/variants/rak4631_nrf52840/variant.cpp @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2026 RAKwireless Technology Limited + * Author: sercan.erat@rakwireless.com + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* MCUboot sees the boot mode after the reset and enters serial recovery. */ +void _on_1200_bps() { + (void)bootmode_set(BOOT_MODE_TYPE_BOOTLOADER); + NVIC_SystemReset(); +} From fe5cddc4a15cc1c947d0886c4e50bc6c6bea5588 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Thu, 24 Sep 2026 16:13:21 +0300 Subject: [PATCH 09/11] arduino: send the 1200-bps before burn-bootloader uploads Signed-off-by: Sercan Erat --- platform.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform.txt b/platform.txt index a58518a6c..9031e29e1 100644 --- a/platform.txt +++ b/platform.txt @@ -384,13 +384,21 @@ tools.mcumgr.loader.cmd="{path}/{cmd}" {conn} image upload -n 1 "{upload.artifac tools.mcumgr.sketch.cmd="{path}/{cmd}" {conn} image upload -n 2 "{upload.artifacts.sketch}" tools.mcumgr.reset.cmd="{path}/{cmd}" {conn} reset +# arduino-cli never sends the 1200-bps touch for burn-bootloader, so the +# bootloader pattern sends it itself and waits for MCUboot's port. +tools.mcumgr.touch.cmd=stty -F {serial.port} 1200 +tools.mcumgr.touch.cmd.macosx=stty -f {serial.port} 1200 +tools.mcumgr.touch.cmd.windows=mode {serial.port} BAUD=1200 +tools.mcumgr.wait.cmd=sleep 2 +tools.mcumgr.wait.cmd.windows=powershell -NoProfile -Command Start-Sleep -Seconds 2 + tools.mcumgr.upload.params.verbose= tools.mcumgr.upload.params.quiet= tools.mcumgr.upload.pattern="{scripting.path}/{scripting.cmd}" run {sketch.cmd} :: run {reset.cmd} tools.mcumgr.bootloader.params.verbose= tools.mcumgr.bootloader.params.quiet= -tools.mcumgr.bootloader.pattern="{scripting.path}/{scripting.cmd}" run {loader.cmd} :: run {reset.cmd} +tools.mcumgr.bootloader.pattern="{scripting.path}/{scripting.cmd}" run {touch.cmd} :: run {wait.cmd} :: run {loader.cmd} :: run {reset.cmd} # From c8e067252e0511f2f69f69078e0ab5aedd0dbe0f Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Thu, 24 Sep 2026 16:28:42 +0300 Subject: [PATCH 10/11] loader: use newly created arduino ecdsa-p256 key for mcuboot Signed-off-by: Sercan Erat --- key/arduino_key_ecdsa-p256.pem | 5 +++++ key/rak_key_ecdsa-p256.c | 21 --------------------- key/rak_key_ecdsa-p256.pem | 5 ----- loader/mcuboot.md | 7 +++++++ loader/sysbuild.conf | 2 +- 5 files changed, 13 insertions(+), 27 deletions(-) create mode 100644 key/arduino_key_ecdsa-p256.pem delete mode 100644 key/rak_key_ecdsa-p256.c delete mode 100644 key/rak_key_ecdsa-p256.pem diff --git a/key/arduino_key_ecdsa-p256.pem b/key/arduino_key_ecdsa-p256.pem new file mode 100644 index 000000000..10a8119ac --- /dev/null +++ b/key/arduino_key_ecdsa-p256.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgoDdEoVMhi3aY27HX +cxBaM5+nqp9tNbm0Q4PHywRo3HuhRANCAATEGlLJf8OiiVl0DJcddiM2JuNPlraW +AV6J6SbzclJna5YXFKSKPk8JwHhQ81d4nFFzRJKnoHQ8XcwTl3X0PAvC +-----END PRIVATE KEY----- diff --git a/key/rak_key_ecdsa-p256.c b/key/rak_key_ecdsa-p256.c deleted file mode 100644 index 2a1ee5ffd..000000000 --- a/key/rak_key_ecdsa-p256.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2026 RAKwireless Technology Limited - * Author: sercan.erat@rakwireless.com - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * The key is only for test purpose!!! - * Please use your own key at your production code!!! - */ - -/* Autogenerated by imgtool.py, do not edit. */ -const unsigned char ecdsa_pub_key[] = { - 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, - 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x42, 0x4e, 0x36, 0x58, 0x49, - 0xaf, 0xc7, 0x7a, 0x75, 0x5b, 0xf2, 0xe1, 0xc6, 0xee, 0x3e, 0xbe, 0x9c, 0x7b, 0x2a, 0x4a, 0xa0, - 0xe8, 0xa0, 0xc4, 0xb9, 0x90, 0xdb, 0xc1, 0xe2, 0xb7, 0x69, 0x6a, 0x1a, 0xe4, 0x78, 0xee, 0xba, - 0x50, 0x06, 0x96, 0xc7, 0x6c, 0x72, 0x46, 0xba, 0xef, 0x13, 0x2e, 0x01, 0xcb, 0xaf, 0xb3, 0xe0, - 0x37, 0xd6, 0x58, 0x51, 0xde, 0xd8, 0x9f, 0x85, 0x43, 0x36, 0x67, -}; -const unsigned int ecdsa_pub_key_len = 91; diff --git a/key/rak_key_ecdsa-p256.pem b/key/rak_key_ecdsa-p256.pem deleted file mode 100644 index ecfc7e8ad..000000000 --- a/key/rak_key_ecdsa-p256.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWIfFB5fjaNwpBXxa -19V/TCsa7QQRMPykwR52i1PLvS2hRANCAARCTjZYSa/HenVb8uHG7j6+nHsqSqDo -oMS5kNvB4rdpahrkeO66UAaWx2xyRrrvEy4By6+z4DfWWFHe2J+FQzZn ------END PRIVATE KEY----- diff --git a/loader/mcuboot.md b/loader/mcuboot.md index 29ea37729..a860ebf24 100644 --- a/loader/mcuboot.md +++ b/loader/mcuboot.md @@ -6,6 +6,13 @@ Install go tool: brew install go ``` +If a new key will be used, please run following commands: +```shell +cd +/bin/python3 -m pip install -r bootloader/mcuboot/scripts/requirements.txt +/bin/python3 bootloader/mcuboot/scripts/imgtool.py keygen -k ArduinoCore-zephyr/key/arduino_key_ecdsa-p256.pem -t ecdsa-p256 +``` + # Updating MCU over UART/USB-CDC Firstly, go must be installed. After that, mcumgr and scripting-tools can be installed via following command: diff --git a/loader/sysbuild.conf b/loader/sysbuild.conf index 5f52ea42e..31ba83690 100644 --- a/loader/sysbuild.conf +++ b/loader/sysbuild.conf @@ -6,7 +6,7 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y # Do not forget to use your own key at your production code!!! -SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/../key/rak_key_ecdsa-p256.pem" +SB_CONFIG_BOOT_SIGNATURE_KEY_FILE="${APP_DIR}/../key/arduino_key_ecdsa-p256.pem" SB_CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y # Serial recovery writes the loader straight into slot0 From ca3f2a306836c954bf837a0a2772b56a14328f97 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Mon, 28 Sep 2026 11:34:34 +0300 Subject: [PATCH 11/11] rak4631: address MCUboot PR review feedback Signed-off-by: Sercan Erat --- .github/workflows/rak-build.yml | 6 +- .vscode/tasks.json | 2 +- README.rak.md | 5 +- boards.txt | 7 +- extra/build.sh | 11 ++ extra/rak/license_check.py | 13 +- loader/llext_exports.c | 4 + loader/main.c | 23 ++- loader/mcuboot.md | 7 + loader/overlay_mcuboot.conf | 24 +--- modules/rak_double_tap/double_tap.c | 13 +- platform.txt | 7 +- tools/mcumgr/.gitignore | 1 + tools/mcumgr/README.md | 19 +++ tools/mcumgr/go.mod | 11 ++ tools/mcumgr/go.sum | 135 ++++++++++++++++++ tools/mcumgr/main.go | 105 ++++++++++++++ variants/rak4631_nrf52840/doc/index.txt | 23 ++- .../rak4631_nrf52840/known_example_issues.txt | 12 ++ .../rak4631_nrf52840/rak4631_nrf52840.conf | 5 +- .../rak4631_nrf52840/rak4631_nrf52840.overlay | 2 - .../rak4631_nrf52840_partitions.dtsi | 5 +- variants/rak4631_nrf52840/test_setup.sh | 21 +++ variants/rak4631_nrf52840/variant.cpp | 3 +- 24 files changed, 414 insertions(+), 50 deletions(-) create mode 100644 tools/mcumgr/.gitignore create mode 100644 tools/mcumgr/README.md create mode 100644 tools/mcumgr/go.mod create mode 100644 tools/mcumgr/go.sum create mode 100644 tools/mcumgr/main.go create mode 100644 variants/rak4631_nrf52840/known_example_issues.txt create mode 100644 variants/rak4631_nrf52840/test_setup.sh diff --git a/.github/workflows/rak-build.yml b/.github/workflows/rak-build.yml index 53d4ec391..b31cb4d1a 100644 --- a/.github/workflows/rak-build.yml +++ b/.github/workflows/rak-build.yml @@ -67,7 +67,7 @@ jobs: run: | mkdir -p venv/bin && touch venv/bin/activate ./extra/build.sh nrf52840dk - ./extra/build.sh rak4631 + ./extra/build.sh rak4631 --mcuboot - name: Build samples # Standalone Zephyr build of the samples. The sample list comes @@ -91,7 +91,7 @@ jobs: if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'upstream-sync') }} working-directory: ${{ env.MODULE_PATH }} - run: west rak-lint -v -b build/rak4631_nrf52840 + run: west rak-lint -v -b build/rak4631_nrf52840/loader - name: Install arduino-cli # Pinned (script and binary) for reproducible sketch builds. @@ -102,7 +102,7 @@ jobs: arduino-cli version - name: Install the Arduino Zephyr toolchain - run: arduino-cli core install arduino:zephyr_main@0.90.0 + run: arduino-cli core install arduino:zephyr_main@1.0.0 - name: Install the sketch libraries # Third-party libraries the sketches in sketch/ include, pinned diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 46c0c97ec..d264e2e70 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -33,7 +33,7 @@ "command": "extra/build.sh", "args": [ "${BOARD_ARD}", - "--debug", + // "--debug", "--mcuboot" ], "group": "build", diff --git a/README.rak.md b/README.rak.md index 11a52fb84..fc1ad817e 100644 --- a/README.rak.md +++ b/README.rak.md @@ -162,11 +162,11 @@ arduino-cli version # verify the installation ### Install the Arduino Zephyr toolchain (one time) ```shell -arduino-cli core install arduino:zephyr_main@0.90.0 +arduino-cli core install arduino:zephyr_main@1.0.0 ``` The official `arduino:zephyr_main` core supplies the cross compiler -referenced by `boards.txt` (`arm-zephyr-eabi` 0.16.8) and the +referenced by `boards.txt` (`arm-zephyr-eabi` 1.0.1) and the post-processing tools (`gen-rodata-ld`, `zephyr-sketch-tool`, `zephyr-check-size`) that the `{runtime.tools.*}` recipes in `platform.txt` resolve against. @@ -181,6 +181,7 @@ cd ~/rak-arduino-zephyr/ArduinoCore-zephyr (cd tools/zephyr-sketch-tool && go build) (cd tools/gen-rodata-ld && go build) (cd tools/zephyr-check-size && go build) +(cd tools/mcumgr && go build) ``` Each binary is produced inside its own tool directory diff --git a/boards.txt b/boards.txt index a205940cd..f732bdb4f 100644 --- a/boards.txt +++ b/boards.txt @@ -734,8 +734,7 @@ ventunoq.bootloader.target=stm32h5f5xx nrf52840dk.name=Nordic nRF52840 DK nrf52840dk.build.core=arduino nrf52840dk.build.crossprefix=arm-zephyr-eabi- -nrf52840dk.build.compiler_path={runtime.tools.arm-zephyr-eabi-0.16.8.path}/bin/ - +nrf52840dk.build.compiler_path={runtime.tools.arm-zephyr-eabi-1.0.1.path}/bin/ nrf52840dk.menu.debug.false=Standard nrf52840dk.menu.debug.true=Debug nrf52840dk.menu.debug.true.build.zsk_args.debug=-debug @@ -792,7 +791,9 @@ rak4631.build.board=RAK4631 rak4631.vid.0=0x1915 rak4631.pid.0=0x5300 rak4631.upload_port.0.vid=0x1915 -rak4631.upload_port.0.pid=0x5301 +rak4631.upload_port.0.pid=0x5300 +rak4631.upload_port.1.vid=0x1915 +rak4631.upload_port.1.pid=0x5301 rak4631.upload.target=nrf52840 rak4631.upload.tool=mcumgr diff --git a/extra/build.sh b/extra/build.sh index 0733e510e..68b3c560a 100755 --- a/extra/build.sh +++ b/extra/build.sh @@ -144,6 +144,17 @@ edk_funcs='int32_t k_sleep\(k_timeout_t timeout\)|void k_busy_wait\(uint32_t use perl -0pi -e "s/__pinned_func\nstatic inline ($edk_funcs)/$edk_qual \$1/g" "$syscalls_hdr" perl -0pi -e "s/__syscall ($edk_funcs);/$edk_qual \$1;/g" "$kernel_hdr" +IMG=${LOADER_DIR}/zephyr/zephyr +# a signed build that produced no signed bin/hex would brick the board, so bail +# out before touching firmwares/ +if [ -n "$mcuboot" ]; then + for ext in bin hex; do + if [ ! -f $IMG.signed.$ext ]; then + echo "error: --mcuboot build produced no $IMG.signed.$ext" >&2 + exit 1 + fi + done +fi for ext in elf bin hex uf2; do rm -f firmwares/zephyr-$variant.$ext # under MCUboot only the signed image boots, so prefer it when it exists diff --git a/extra/rak/license_check.py b/extra/rak/license_check.py index 628f3a66f..536d244f7 100644 --- a/extra/rak/license_check.py +++ b/extra/rak/license_check.py @@ -22,7 +22,18 @@ sys.path.insert(0, str(Path(__file__).resolve().parent)) import rak_utils as utils -IGNORE_SUFFIXES = {".md", ".rst", ".txt", ".pde", ".json", ".svg", ".pem"} +IGNORE_SUFFIXES = { + ".md", + ".rst", + ".txt", + ".pde", + ".json", + ".svg", + ".pem", + ".sum", + ".mod", +} + # Never checked, matched by exact file name (dotfiles have no suffix). IGNORE_NAMES = {".gitignore", "VERSION"} # Checked even though their suffix is ignored. diff --git a/loader/llext_exports.c b/loader/llext_exports.c index f2cf0d425..bab9c846c 100644 --- a/loader/llext_exports.c +++ b/loader/llext_exports.c @@ -553,4 +553,8 @@ FORCE_EXPORT_SYM(lorawan_register_link_check_ans_callback); FORCE_EXPORT_SYM(bootmode_set); #endif +#if defined(CONFIG_REBOOT) +FORCE_EXPORT_SYM(sys_reboot); +#endif + EXPORT_SYMBOL(sketch_header_v1_verify); diff --git a/loader/main.c b/loader/main.c index 5741cf9ab..fa90bceef 100644 --- a/loader/main.c +++ b/loader/main.c @@ -25,6 +25,11 @@ LOG_MODULE_REGISTER(sketch); #include #include "../cores/arduino/zephyr_sketch_header.h" +#if defined(CONFIG_RETENTION_BOOT_MODE) +#include +#include +#endif + #define SKETCH_RAM_BUFFER_LEN 131072 /* Need to replicate logic from zephyrSerial.h to avoid C++ here */ @@ -59,6 +64,21 @@ static void loader_usb_msg_cb(struct usbd_context *const ctx, const struct usbd_ usbd_enable(ctx); } } + +#if defined(CONFIG_RETENTION_BOOT_MODE) + /* 1200-bps touch while the loader owns USB for no sketch yet case. */ + if (msg->type == USBD_MSG_CDC_ACM_LINE_CODING && msg->dev == usb_dev) { + uint32_t baudrate = 0; + + uart_line_ctrl_get(usb_dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); + if (baudrate == 1200) { + k_sleep(K_MSEC(100)); + usbd_disable(ctx); + bootmode_set(BOOT_MODE_TYPE_BOOTLOADER); + sys_reboot(SYS_REBOOT_COLD); + } + } +#endif } int loader_usb_enable(void) { @@ -310,7 +330,8 @@ static int loader(const struct shell *sh) { size_t sketch_buf_len = sketch_hdr->len; - if (sketch_hdr->flags & SKETCH_FLAG_LINKED) { + // an erased sketch area reads flags 0xff, never jump into it + if (sketch_valid && (sketch_hdr->flags & SKETCH_FLAG_LINKED)) { #ifdef CONFIG_BOARD_ARDUINO_PORTENTA_C33 #if CONFIG_MPU barrier_dmem_fence_full(); diff --git a/loader/mcuboot.md b/loader/mcuboot.md index a860ebf24..8abbe4403 100644 --- a/loader/mcuboot.md +++ b/loader/mcuboot.md @@ -41,3 +41,10 @@ mcumgr --conntype serial --connstring image list mcumgr --conntype serial --connstring image confirm mcumgr --conntype serial --connstring reset ``` + +# Entering serial recovery +A 1200-bps touch on the board's USB port reboots into MCUboot serial +recovery. A sketch handles it after `Serial.begin()`; the loader handles +it when no sketch is on the board or when it is a `--debug` build. Without +a USB port (the sketch never opens `Serial`, or it has crashed), double-tap +the reset button instead. diff --git a/loader/overlay_mcuboot.conf b/loader/overlay_mcuboot.conf index 41173ca74..2d1b05e54 100644 --- a/loader/overlay_mcuboot.conf +++ b/loader/overlay_mcuboot.conf @@ -2,28 +2,10 @@ # Author: sercan.erat@rakwireless.com # SPDX-License-Identifier: Apache-2.0 -CONFIG_MCUMGR=y -CONFIG_NET_BUF=y -CONFIG_ZCBOR=y -CONFIG_BASE64=y -CONFIG_CRC=y - -# Enable flash operations. -CONFIG_FLASH=y -CONFIG_FLASH_MAP=y +# Sysbuild always passes CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE to the loader; +# the symbol only exists with the image manager (library only, no mcumgr). +# Enable flash operations for footer. CONFIG_IMG_MANAGER=y CONFIG_STREAM_FLASH=y -# Enable most core commands. -CONFIG_MCUMGR_GRP_IMG=y -CONFIG_MCUMGR_GRP_OS=y - -# Enable the storage erase command. -CONFIG_MCUMGR_GRP_ZBASIC=y -CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y - -# Disabled the serial MCUmgr transport. -CONFIG_UART_MCUMGR=n -CONFIG_MCUMGR_TRANSPORT_UART=n - CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/modules/rak_double_tap/double_tap.c b/modules/rak_double_tap/double_tap.c index d8c1da4c3..9a81351e4 100644 --- a/modules/rak_double_tap/double_tap.c +++ b/modules/rak_double_tap/double_tap.c @@ -31,15 +31,22 @@ static void window_led_set(bool on) { static bool reset_by_button(void) { uint32_t cause = 0; - int rc; - rc = hwinfo_get_reset_cause(&cause); + int ret = hwinfo_get_reset_cause(&cause); (void)hwinfo_clear_reset_cause(); - if (rc != 0) { + if (ret != 0) { return false; } + /* + * Consume only RESET_PIN: the loader and the sketch still need the + * remaining bits to tell a power-on from a watchdog or soft reset. + */ + if (cause & RESET_PIN) { + (void)hwinfo_clear_reset_cause(); + } + return (cause & RESET_PIN) != 0; } diff --git a/platform.txt b/platform.txt index 9031e29e1..246cda9a1 100644 --- a/platform.txt +++ b/platform.txt @@ -376,9 +376,6 @@ tools.mcumgr.path={runtime.tools.mcumgr.path} tools.mcumgr.cmd=mcumgr tools.mcumgr.cmd.windows=mcumgr.exe tools.mcumgr.conn=--conntype serial --connstring "dev={serial.port},baud=115200,mtu=4096" -tools.mcumgr.scripting.path={runtime.tools.scripting.path} -tools.mcumgr.scripting.cmd=scripting-tools -tools.mcumgr.scripting.cmd.windows=scripting-tools.exe tools.mcumgr.loader.cmd="{path}/{cmd}" {conn} image upload -n 1 "{upload.artifacts.loader}" tools.mcumgr.sketch.cmd="{path}/{cmd}" {conn} image upload -n 2 "{upload.artifacts.sketch}" @@ -394,11 +391,11 @@ tools.mcumgr.wait.cmd.windows=powershell -NoProfile -Command Start-Sleep -Second tools.mcumgr.upload.params.verbose= tools.mcumgr.upload.params.quiet= -tools.mcumgr.upload.pattern="{scripting.path}/{scripting.cmd}" run {sketch.cmd} :: run {reset.cmd} +tools.mcumgr.upload.pattern="{runtime.tools.scripting-tools.path}/scripting-tools" run {sketch.cmd} :: run {reset.cmd} tools.mcumgr.bootloader.params.verbose= tools.mcumgr.bootloader.params.quiet= -tools.mcumgr.bootloader.pattern="{scripting.path}/{scripting.cmd}" run {touch.cmd} :: run {wait.cmd} :: run {loader.cmd} :: run {reset.cmd} +tools.mcumgr.bootloader.pattern="{runtime.tools.scripting-tools.path}/scripting-tools" run {touch.cmd} :: run {wait.cmd} :: run {loader.cmd} :: run {reset.cmd} # diff --git a/tools/mcumgr/.gitignore b/tools/mcumgr/.gitignore new file mode 100644 index 000000000..46b25f285 --- /dev/null +++ b/tools/mcumgr/.gitignore @@ -0,0 +1 @@ +mcumgr diff --git a/tools/mcumgr/README.md b/tools/mcumgr/README.md new file mode 100644 index 000000000..5533f5ab6 --- /dev/null +++ b/tools/mcumgr/README.md @@ -0,0 +1,19 @@ +## mcumgr + +This directory packages the [mcumgr] command-line tool from the Apache Mynewt +project as an Arduino tool, so the core can upload images to boards running +MCUboot. + +**None of the code here is original work.** It is a copy of the upstream +mcumgr CLI, and all rights to it belong to mcumgr contributors. + +[mcumgr]: https://github.com/apache/mynewt-mcumgr-cli + +### Building manually + +To build the tool, you need to have the Go programming language installed; make +sure you have the `go` command available in your PATH. Then, use the `go build` +command to build the tool for your platform. + +To build the full set of binaries for all platforms, run +`extra/package_tool.sh tools/mcumgr` from the repository root. diff --git a/tools/mcumgr/go.mod b/tools/mcumgr/go.mod new file mode 100644 index 000000000..1b056f721 --- /dev/null +++ b/tools/mcumgr/go.mod @@ -0,0 +1,11 @@ +module github.com/arduino/mcumgr + +go 1.12 + +require ( + github.com/JuulLabs-OSS/ble v0.0.0-20200716215611-d4fcc9d598bb // indirect + github.com/go-ble/ble v0.0.0-20181002102605-e78417b510a3 // indirect + golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 // indirect + mynewt.apache.org/newt v0.0.0-20201028015609-b57111dbd19f + mynewt.apache.org/newtmgr v0.0.0-20201028150837-60b2da78788c +) diff --git a/tools/mcumgr/go.sum b/tools/mcumgr/go.sum new file mode 100644 index 000000000..5aaed4ea6 --- /dev/null +++ b/tools/mcumgr/go.sum @@ -0,0 +1,135 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/JuulLabs-OSS/ble v0.0.0-20200716215611-d4fcc9d598bb h1:kIZ7fr8RxucJXNHifPxm71yiWuzpw0SmjlafMzoOd0U= +github.com/JuulLabs-OSS/ble v0.0.0-20200716215611-d4fcc9d598bb/go.mod h1:6deIuswYSv6W1l3sM/nonw0OKWtIZCn7ZOWvIREoq2A= +github.com/JuulLabs-OSS/cbgo v0.0.1 h1:A5JdglvFot1J9qYR0POZ4qInttpsVPN9lqatjaPp2ro= +github.com/JuulLabs-OSS/cbgo v0.0.1/go.mod h1:L4YtGP+gnyD84w7+jN66ncspFRfOYB5aj9QSXaFHmBA= +github.com/NickBall/go-aes-key-wrap v0.0.0-20170929221519-1c3aa3e4dfc5/go.mod h1:w5D10RxC0NmPYxmQ438CC1S07zaC1zpvuNW7s5sUk2Q= +github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= +github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8= +github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= +github.com/apache/mynewt-artifact v0.0.16/go.mod h1:vFUd47t74KPQMzSBhQ2qp5Hc7D29OU/Tl3xHtFwN3k8= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/cheggaaa/pb v2.0.7+incompatible/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cosiner/argv v0.0.1/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= +github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-ble/ble v0.0.0-20181002102605-e78417b510a3/go.mod h1:UMPB54/KFpdTdfH7Yovhk3J6kzgzE88e3QZi8cbayis= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joaojeronimo/go-crc16 v0.0.0-20140729130949-59bd0194935e h1:LY29wmnTcSR92avOm1dW0LSjeE3d9Xnhm/mpGzMT/wc= +github.com/joaojeronimo/go-crc16 v0.0.0-20140729130949-59bd0194935e/go.mod h1:+X++CLDTje8Yr7J4bGuUYx5LVbNpXPeO5ZLpI42hKVk= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab h1:n8cgpHzJ5+EDyDri2s/GC7a9+qK3/YEGnBsd0uS/8PY= +github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab/go.mod h1:y1pL58r5z2VvAjeG1VLGc8zOQgSOzbKN7kMHPvFXJ+8= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/raff/goble v0.0.0-20190909174656-72afc67d6a99/go.mod h1:CxaUhijgLFX0AROtH5mluSY71VqpjQBw9JXE2UKZmc4= +github.com/raff/goble v0.0.0-20200327175727-d63360dcfd80 h1:IZkjNgPZXcE4USkGzmJQyHco3KFLmhcLyFdxCOiY6cQ= +github.com/raff/goble v0.0.0-20200327175727-d63360dcfd80/go.mod h1:CxaUhijgLFX0AROtH5mluSY71VqpjQBw9JXE2UKZmc4= +github.com/runtimeco/go-coap v0.0.0-20190911184520-8e5532820fc0 h1:WOVbcRe5kFuLbhZdyz8PKVR6L22C6I48fWIUS5ucpGY= +github.com/runtimeco/go-coap v0.0.0-20190911184520-8e5532820fc0/go.mod h1:x/rLuxedbWFDN497ZirUaDklkWz6JhZLjGdgurMysxM= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shirou/gopsutil v2.20.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= +github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.starlark.net v0.0.0-20190919145610-979af19b165c/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg= +golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 h1:MlY3mEfbnWGmUi4rtHOtNnnnN4UJRGSyLPx+DXA5Sq4= +golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68 h1:z8Hj/bl9cOV2grsOpEaQFUaly0JWN3i97mo3jXKJNp0= +golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/VividCortex/ewma.v1 v1.1.1/go.mod h1:TekXuFipeiHWiAlO1+wSS23vTcyFau5u3rxXUSXj710= +gopkg.in/abiosoft/ishell.v2 v2.0.0 h1:/J5yh3nWYSSGFjALcitTI9CLE0Tu27vBYHX0srotqOc= +gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v2 v2.0.7/go.mod h1:0CiZ1p8pvtxBlQpLXkHuUTpdJ1shm3OqCF1QugkjHL4= +gopkg.in/fatih/color.v1 v1.7.0/go.mod h1:P7yosIhqIl/sX8J8UypY5M+dDpD2KmyfP5IRs5v/fo0= +gopkg.in/mattn/go-colorable.v0 v0.1.0/go.mod h1:BVJlBXzARQxdi3nZo6f6bnl5yR20/tOL6p+V0KejgSY= +gopkg.in/mattn/go-isatty.v0 v0.0.4/go.mod h1:wt691ab7g0X4ilKZNmMII3egK0bTxl37fEn/Fwbd8gc= +gopkg.in/mattn/go-runewidth.v0 v0.0.4/go.mod h1:BmXejnxvhwdaATwiJbB1vZ2dtXkQKZGu9yLFCZb4msQ= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +mynewt.apache.org/newt v0.0.0-20200409145402-c5d1e422bfa3/go.mod h1:GTc1Q2t1eVSWNtTWGLyZW8UeRM81SQnq3urDorrJ6AA= +mynewt.apache.org/newt v0.0.0-20201028015609-b57111dbd19f h1:ZZM0GfqgTGAtTWiBk/Xo0ePsBnbEDb5F1iKDII3OWDw= +mynewt.apache.org/newt v0.0.0-20201028015609-b57111dbd19f/go.mod h1:0HULbbiMWkyIHsKyv3KozsdVzCZyK2lY9sjeexub4ac= +mynewt.apache.org/newtmgr v0.0.0-20201028150837-60b2da78788c h1:6361yI7aHLT2VPKYdNjZ2EqDm3PgQiupOUGwgGGqRrw= +mynewt.apache.org/newtmgr v0.0.0-20201028150837-60b2da78788c/go.mod h1:qUNQJ6Jz87jAtOZzPWlKMK7WX/o7baHr8ubtcSwvSTc= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/tools/mcumgr/main.go b/tools/mcumgr/main.go new file mode 100644 index 000000000..8187c4ed6 --- /dev/null +++ b/tools/mcumgr/main.go @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2026 RAKwireless Technology Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * This file mirrors mcumgr/mcumgr.go from github.com/apache/mynewt-mcumgr-cli + * (Apache-2.0) on top of the same newtmgr libraries. + */ + +package main + +import ( + "fmt" + "os" + "os/signal" + "syscall" + + "mynewt.apache.org/newt/util" + "mynewt.apache.org/newtmgr/newtmgr/cli" + "mynewt.apache.org/newtmgr/newtmgr/config" + "mynewt.apache.org/newtmgr/newtmgr/nmutil" + "mynewt.apache.org/newtmgr/nmxact/nmserial" +) + +func stopXport() { + x, err := cli.GetXportIfOpen() + if err == nil { + // Don't attempt to close a serial transport. Attempting to close + // the serial port while a read is in progress (in MacOS) just + // blocks until the read completes. Instead, let the OS close the + // port on termination. + if _, ok := x.(*nmserial.SerialXport); !ok { + x.Stop() + } + } +} + +func closeSesn() { + s, err := cli.GetSesnIfOpen() + if err == nil { + s.Close() + } +} + +func cleanup() { + closeSesn() + stopXport() +} + +func main() { + nmutil.ToolInfo = nmutil.ToolInfoType{ + ExeName: "mcumgr", + ShortName: "mcumgr", + LongName: "mcumgr", + VersionString: "0.0.0-dev", + CfgFilename: ".mcumgr.cp.json", + } + + if err := config.InitGlobalConnProfileMgr(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error()) + os.Exit(1) + } + + defer cleanup() + cli.SetOnExit(cleanup) + + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan) + + go func() { + for { + s := <-sigChan + switch s { + case os.Interrupt, syscall.SIGTERM: + cli.SilenceErrors() + cli.NmExit(1) + + case syscall.SIGQUIT: + util.PrintStacks() + } + } + }() + + cli.Commands().Execute() +} diff --git a/variants/rak4631_nrf52840/doc/index.txt b/variants/rak4631_nrf52840/doc/index.txt index d6e2873e8..852501b81 100644 --- a/variants/rak4631_nrf52840/doc/index.txt +++ b/variants/rak4631_nrf52840/doc/index.txt @@ -47,9 +47,8 @@ ecosystem. The pinout is as follows: | GND | GND | 39 | 40 | GND | GND | +-----------------------------+----------+-----+-----+----------+-----------------------------+ -Signal names follow the WisBlock connector specification (see the -[upstream WisBlock platform PR](https://github.com/zephyrproject-rtos/zephyr/pull/113140) -and the WisBlock Technical Specification v1.0 attached to it). +Signal names follow the WisBlock connector specification (see the WisBlock Technical +Specification v1.0). | Arduino pin | WisBlock signal | nRF52840 pin | Notes | |-------------|-----------------|--------------|------------------------------------------| @@ -78,10 +77,24 @@ Buses: On the RAK19007 base board: - Sensor slots A-D get their switched 3V3_S rail through WB_IO2 (D1): - IO2=1 on, IO2=0 off. The loader drives it low at boot - (`regulator-fixed` node in the overlay), so the rail is off until a + IO2=1 on, IO2=0 off. The loader drives it low at boot , so the rail is off until a sketch enables it. Modules that only use VDD, such as the RAK1901, are unaffected. - A0 is also wired to the battery voltage divider (1.5 MOhm / 2.5 MOhm), so `VBAT = analogRead(A0)` scaled by 5/3 (and by the ADC reference); IO-slot modules driving AIN0 conflict with it. + +How to use MCUboot bootloader with arduino-cli: + +Requirement: arduino-cli uploads through MCUboot's serial recovery (mcumgr over +USB), so MCUboot must already be on the board. Before the first arduino-cli +upload, flash the MCUboot hex (`firmwares/mcuboot-rak4631_nrf52840.hex`, built by +`extra/build.sh rak4631 --mcuboot`) over SWD with a J-Link or a RAKDAP1 probe. +arduino-cli cannot install MCUboot itself. + +Entering serial recovery: `arduino-cli upload` first sends a 1200-bps touch to +the board's USB port. A sketch that has called `Serial.begin()` handles it; with +no sketch on the board (or with a `--debug` loader) the loader handles it. When +the board shows no USB port (the sketch never opens `Serial`, or it has +crashed), the touch is lost: double-tap the reset button to enter serial +recovery, then upload. diff --git a/variants/rak4631_nrf52840/known_example_issues.txt b/variants/rak4631_nrf52840/known_example_issues.txt new file mode 100644 index 000000000..b9aee7130 --- /dev/null +++ b/variants/rak4631_nrf52840/known_example_issues.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +# This file contains a list of examples that are shipped with the core (or used +# by continuous integration tests), but are known to be currently failing for +# this specific variant. +# +# Each line in this file is treated as a regular expression and will be matched +# against the path of each sketch found in this repo. If a match is found, the +# sketch compilation result will be ignored. + diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.conf b/variants/rak4631_nrf52840/rak4631_nrf52840.conf index 186345b16..bb557390c 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.conf +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.conf @@ -36,10 +36,13 @@ CONFIG_UDC_DRIVER_LOG_LEVEL_ERR=y CONFIG_USBD_LOG_LEVEL_ERR=y # Boot mode (rak4631_nrf52840_bootmode.dtsi): the 1200 bps touch in -# variant.cpp asks MCUboot for serial recovery through it. +# variant.cpp (sketch) or loader/main.c (no sketch, debug shell) asks +# MCUboot for serial recovery through it. CONFIG_RETAINED_MEM=y CONFIG_RETENTION=y CONFIG_RETENTION_BOOT_MODE=y +# sys_reboot() after the loader's 1200 bps touch +CONFIG_REBOOT=y CONFIG_GPIO=y CONFIG_I2C=y diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay index 4f7d3d1db..861e1423b 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840.overlay +++ b/variants/rak4631_nrf52840/rak4631_nrf52840.overlay @@ -198,8 +198,6 @@ <&adc 2>, /* A2 - WB_IO4 (AIN2) */ <&adc 4>; /* A3 - WB_IO7 (AIN4) */ - builtin-led-gpios = <&gpio1 3 0>; - i2cs = <&i2c0>; /* 'Wire': WisBlock sensor I2C (SDA P0.13, SCL P0.14) */ spis = <&spi2>; /* 'SPI': WisBlock header SPI */ diff --git a/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi b/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi index 0a830a0cd..3c88ac5d7 100644 --- a/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi +++ b/variants/rak4631_nrf52840/rak4631_nrf52840_partitions.dtsi @@ -35,7 +35,10 @@ read-only; }; - /* Sketch. */ + /* + * Sketch: a zsk blob, not an MCUboot image. The slot1 label only + * makes it "image 2" for mcumgr direct uploads. + */ slot1_partition: user_sketch: partition@80000 { label = "image-1"; reg = <0x00080000 0x00078000>; diff --git a/variants/rak4631_nrf52840/test_setup.sh b/variants/rak4631_nrf52840/test_setup.sh new file mode 100644 index 000000000..0443a02d1 --- /dev/null +++ b/variants/rak4631_nrf52840/test_setup.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2026 RAKwireless Technology Limited +# Author: sercan.erat@rakwireless.com +# SPDX-License-Identifier: Apache-2.0 + +# This script is sourced by extra/ci_apply_tests.sh to customize the CI test +# list for this board variant. Three helper functions are available: +# get_branch_tip [ ...] +# get_latest_release [ ...] +# skip_for_this_board +# +# get_branch_tip / get_latest_release add external repos to the test list +# (the repos must have been downloaded by ci_fetch_tests.sh first). +# skip_for_this_board removes all tests under the given path prefix. + +skip_for_this_board libraries/Arduino_SecureElement +skip_for_this_board libraries/Camera +skip_for_this_board libraries/Ethernet +skip_for_this_board libraries/Storage +skip_for_this_board libraries/WiFi +skip_for_this_board libraries/Zephyr_SDRAM +skip_for_this_board libraries/CAN diff --git a/variants/rak4631_nrf52840/variant.cpp b/variants/rak4631_nrf52840/variant.cpp index 0528feeea..a2ca7998f 100644 --- a/variants/rak4631_nrf52840/variant.cpp +++ b/variants/rak4631_nrf52840/variant.cpp @@ -5,9 +5,10 @@ */ #include +#include /* MCUboot sees the boot mode after the reset and enters serial recovery. */ void _on_1200_bps() { (void)bootmode_set(BOOT_MODE_TYPE_BOOTLOADER); - NVIC_SystemReset(); + sys_reboot(SYS_REBOOT_COLD); }