Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion boards.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ giga.debug.server.openocd.scripts.2=target/stm32h7x_dual_bank.cfg
giga.debug.cortex-debug.custom.request=attach
giga.debug.svd_file={runtime.platform.path}/svd/STM32H747_CM7.svd

giga.build.ota.magic=0x23410266
giga.build.ota.sketch_offset=0xA0000

##########################################################################################

nano33ble.name=Arduino Nano 33 BLE
Expand Down Expand Up @@ -256,6 +259,9 @@ portentah7.bootloader.interface=0
portentah7.bootloader.file=zephyr-{build.variant}.bin
portentah7.bootloader.address=0x08040000

portentah7.build.ota.magic=0x2341025B
portentah7.build.ota.sketch_offset=0xA0000

portentah7.debug.tool=gdb
portentah7.debug.server.openocd.scripts.0=interface/{programmer.protocol}.cfg
portentah7.debug.server.openocd.scripts.1={programmer.transport_script}
Expand Down Expand Up @@ -308,6 +314,9 @@ nicla_vision.bootloader.interface=0
nicla_vision.bootloader.file=zephyr-{build.variant}.bin
nicla_vision.bootloader.address=0x08040000

nicla_vision.build.ota.magic=0x2341025F
nicla_vision.build.ota.sketch_offset=0xA0000

nicla_vision.debug.tool=gdb
nicla_vision.debug.server.openocd.scripts.0=interface/{programmer.protocol}.cfg
nicla_vision.debug.server.openocd.scripts.1={programmer.transport_script}
Expand Down Expand Up @@ -445,9 +454,12 @@ portentac33.upload.wait_for_upload_port=false
portentac33.upload.native_usb=true
portentac33.upload.dfuse=

portentac33.sfu.file=loader/blobs/c33_sfu.bin
portentac33.sfu.size=0x20000

portentac33.bootloader.tool=dfu-util
portentac33.bootloader.tool.default=dfu-util
portentac33.bootloader.file=zephyr-{build.variant}.bin
portentac33.bootloader.file=zephyr-{build.variant}-sfu.bin
portentac33.bootloader.interface=0
portentac33.bootloader.address=0x10000
portentac33.bootloader.pid=0x0368
Expand All @@ -458,6 +470,9 @@ portentac33.leave.dfuse={empty} -Q
portentac33.loader.args.with_sketch={empty} -w
portentac33.sketch.args.without_loader={empty} -w

portentac33.build.ota.magic=0x23410068
portentac33.build.ota.sketch_offset=0xF0000

##########################################################################################

opta.name=Arduino Opta
Expand Down Expand Up @@ -510,6 +525,9 @@ opta.debug.server.openocd.scripts.2=target/stm32h7x_dual_bank.cfg
opta.debug.cortex-debug.custom.request=attach
opta.debug.svd_file={runtime.platform.path}/svd/STM32H747_CM7.svd

opta.build.ota.magic=0x23410064
opta.build.ota.sketch_offset=0xA0000

##########################################################################################

nano_matter.name=Arduino Nano Matter
Expand Down
2 changes: 2 additions & 0 deletions cores/arduino/llext_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ W2(char *, strstr, const char *, const char *)
W2(int, strcmp, const char *, const char *)
W3(int, strncmp, const char *, const char *, size_t)
W2(int, strcasecmp, const char *, const char *)
W3(int, strncasecmp, const char *, const char *, size_t)
W3(char *, strncpy, char *, const char *, size_t)
W2(char *, strcat, char *, const char *)
W2(char *, strcpy, char *, const char *)
Expand Down Expand Up @@ -216,6 +217,7 @@ VN(__aeabi_fcmpun)
VN(__aeabi_d2iz)
VN(__aeabi_d2uiz)
VN(__aeabi_d2lz)
VN(__aeabi_d2ulz)
VN(__aeabi_i2d)
VN(__aeabi_ui2d)
VN(__aeabi_l2d)
Expand Down
11 changes: 11 additions & 0 deletions cores/arduino/ota_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifdef CONFIG_OTA

#include "../../loader/ota/ota_api.h"

#endif // CONFIG_OTA
15 changes: 15 additions & 0 deletions extra/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ if ! [ -z "$chosen_board" ]; then
if [ x$2 == x"--debug" ]; then
args+=(-- -DEXTRA_CONF_FILE=../extra/debug.conf)
fi

# check if the board requires to prepend a second stage bootloader to the loader
sfu_file=$(jq -cr '.sfu_file' <<< "$chosen_board")
sfu_size=$(jq -cr '.sfu_size' <<< "$chosen_board")
else
# expect Zephyr-compatible target and args
target=$1
Expand Down Expand Up @@ -125,6 +129,17 @@ done
cp ${BUILD_DIR}/zephyr/zephyr.dts firmwares/zephyr-$variant.dts
cp ${BUILD_DIR}/zephyr/.config firmwares/zephyr-$variant.config

# Some boards, like the C33, need a second stage bootloader to enable OTA upgrades,
# if the file is specified in boards.txt under .sfu.file, prepend it to the loader binary into a
# firmwares/zephyr-$variant-sfu.bin file.
# this file needs to be specified in bootloader.file=zephyr-{build.variant}-sfu.bin
if [ "$sfu_file" ] ; then
dd if=${sfu_file} of=firmwares/zephyr-$variant-sfu.bin conv=notrunc status=none

offset=$(printf "%d" "${sfu_size}")
dd if=firmwares/zephyr-$variant.bin of=firmwares/zephyr-$variant-sfu.bin bs=1 seek=${offset} conv=notrunc status=none
fi

# 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
Expand Down
6 changes: 5 additions & 1 deletion extra/get_board_details.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ for BOARD in $(get_boards); do
ARTIFACT=$(get_board_field $BOARD "build\\.artifact")
ARTIFACT=${ARTIFACT:-zephyr_contrib}
UPLOAD_OFFSET=$(get_board_field $BOARD "upload\\.offset")
SFU_FILE=$(get_board_field $BOARD "sfu\\.file")
SFU_SIZE=$(get_board_field $BOARD "sfu\\.size")

ARTIFACT_JSON=extra/artifacts/$ARTIFACT.json
if ! [ -f "$ARTIFACT_JSON" ] ; then
Expand Down Expand Up @@ -51,7 +53,9 @@ for BOARD in $(get_boards); do
"hals": "$HALS",
"artifact": "$ARTIFACT",
"subarch": "$SUBARCH",
"upload_offset": "$UPLOAD_OFFSET"
"upload_offset": "$UPLOAD_OFFSET",
"sfu_file": "$SFU_FILE",
"sfu_size": "$SFU_SIZE"
}
EOF
done | jq -crs .
2 changes: 2 additions & 0 deletions loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(app LANGUAGES C CXX)

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/blobs)
add_subdirectory_ifdef(CONFIG_OTA ${CMAKE_CURRENT_SOURCE_DIR}/ota)

# Memory region relocation based on Kconfig
# Relocate LLEXT heap if region specified
Expand All @@ -44,3 +45,4 @@ target_compile_definitions(app PUBLIC _XOPEN_SOURCE=700)
target_compile_definitions(app PUBLIC _GNU_SOURCE)

target_link_libraries(app PUBLIC blobs)
target_link_libraries_ifdef(CONFIG_OTA app PUBLIC ota)
2 changes: 2 additions & 0 deletions loader/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ config MAIN_STACK_REGION
depends on CODE_DATA_RELOCATION
help
Specify the memory region for main stack.

rsource "ota/Kconfig"
Binary file added loader/blobs/c33_sfu.bin
Binary file not shown.
4 changes: 4 additions & 0 deletions loader/llext_exports.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <strings.h>
#include <zephyr/llext/symbol.h>
#include <zephyr/usb/usb_device.h>
#include <zephyr/sys/reboot.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -53,6 +54,7 @@ EXPORT_LIBC_SYM(strstr);
EXPORT_LIBC_SYM(strncmp);
EXPORT_LIBC_SYM(strncpy);
EXPORT_LIBC_SYM(strcasecmp);
EXPORT_LIBC_SYM(strncasecmp);
EXPORT_LIBC_SYM(strcmp);
EXPORT_LIBC_SYM(strlen);
EXPORT_LIBC_SYM(strnlen);
Expand Down Expand Up @@ -349,6 +351,7 @@ EXPORT_LIBC_SYM(gettimeofday);
#endif

EXPORT_SYMBOL(sys_clock_settime);

EXPORT_SYMBOL(mktime);
EXPORT_SYMBOL(gmtime);

Expand Down Expand Up @@ -409,6 +412,7 @@ EXPORT_AEABI_SYM(__aeabi_fcmpun);
EXPORT_AEABI_SYM(__aeabi_d2iz);
EXPORT_AEABI_SYM(__aeabi_d2uiz);
EXPORT_AEABI_SYM(__aeabi_d2lz);
EXPORT_AEABI_SYM(__aeabi_d2ulz);
EXPORT_AEABI_SYM(__aeabi_i2d);
EXPORT_AEABI_SYM(__aeabi_ui2d);
EXPORT_AEABI_SYM(__aeabi_l2d);
Expand Down
5 changes: 5 additions & 0 deletions loader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ LOG_MODULE_REGISTER(sketch);

#include <zephyr/devicetree/fixed-partitions.h>
#include "../cores/arduino/zephyr_sketch_header.h"
#include "ota/ota_sketch_check.h"

#define SKETCH_RAM_BUFFER_LEN 131072

Expand Down Expand Up @@ -136,6 +137,10 @@ static int loader(const struct shell *sh) {
return rc;
}

#if defined(CONFIG_OTA)
try_ota_update(fa);
#endif

uintptr_t base_addr = DT_PARTITION_ADDR(DT_NODELABEL(user_sketch));

char header[SKETCH_HEADER_LEN];
Expand Down
15 changes: 15 additions & 0 deletions loader/ota/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_interface_library_named(ota)

target_sources(app PRIVATE ${CMAKE_CURRENT_LIST_DIR}/ota_sketch_check.c)
target_sources(app PRIVATE ${CMAKE_CURRENT_LIST_DIR}/ota_llext_exports.c)
zephyr_include_directories(${CMAKE_CURRENT_LIST_DIR})

target_sources_ifdef(CONFIG_BOARD_ARDUINO_PORTENTA_C33 app PRIVATE
${CMAKE_CURRENT_LIST_DIR}/ota_portentac33.c)

target_sources_ifdef(CONFIG_SOC_SERIES_STM32H7X app PRIVATE
${CMAKE_CURRENT_LIST_DIR}/ota_arduino_stm32h7.c)

target_sources(app PRIVATE ${CMAKE_CURRENT_LIST_DIR}/ota_sketch.c)
58 changes: 58 additions & 0 deletions loader/ota/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#
# Copyright (c) Arduino s.r.l. and/or its affiliated companies
#
# SPDX-License-Identifier: Apache-2.0
#

menuconfig OTA
bool "Enable lookup for sketch update at boot"
depends on FILE_SYSTEM
select REBOOT
select RTC if SOC_SERIES_STM32H7X
default n
help
Enable checking for an update inside of the filesystem. If a file inside of
OTA_SKETCH_UPDATE_PATH is found during the boot, the OTA procedure is started and the
current sketch binary is replaced

if OTA

config OTA_SKETCH_UPDATE_PATH
string "The path it is looked for ota"
default "/ota:/UPDATE_SKETCH.BIN"
help
the path that is checked for a sketch new binary

config OTA_SKETCH_TEMP_PATH_POSTFIX
string "temporary file name postfix for sketch ota not ready"
default ".TEMP"
help
String that is appended to sketch ota filename when it is still not ready to be loaded,
a rename operation is required to make the ota file enabled for next reboot

config OTA_LOADER_UPDATE_PATH
string "The path it is looked for ota"
default "/ota:/UPDATE.BIN"
help
the path that is checked for the loader new binary

config OTA_LOADER_TEMP_PATH_POSTFIX
string "temporary file name postfix for loader ota not ready"
default "" if SOC_SERIES_STM32H7X
default ".TEMP"
help
String that is appended to loader ota filename when it is still not ready to be loaded,
a rename operation is required to make the ota file enabled for next reboot

config OTA_TRANSCRIPTION_CHUNK_SIZE
int "The size of the stack allocated chunk in bytes for transcription"
default 1024
help
The size of the stack allocated chunk in bytes for ota file transcription

module = OTA
module-str = OTA
module-help = Sets log level for OTA
source "subsys/logging/Kconfig.template.log_config"

endif
24 changes: 24 additions & 0 deletions loader/ota/ota_api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/device.h>

#ifdef __cplusplus
extern "C" {
#endif

#define OTA_SKETCH_FILENAME CONFIG_OTA_SKETCH_UPDATE_PATH CONFIG_OTA_SKETCH_TEMP_PATH_POSTFIX
#define OTA_LOADER_FILENAME CONFIG_OTA_LOADER_UPDATE_PATH CONFIG_OTA_LOADER_TEMP_PATH_POSTFIX

int ota_sketch_ready();
int ota_sketch_start();

int ota_loader_ready();
int ota_loader_start();

#ifdef __cplusplus
}
#endif
55 changes: 55 additions & 0 deletions loader/ota/ota_arduino_stm32h7.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "ota_api.h"
#include <zephyr/fs/fs.h>
#include <zephyr/sys/reboot.h>
#include <stm32h7xx_ll_rtc.h>
#include <stm32_backup_domain.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(ota_loader, CONFIG_OTA_LOG_LEVEL);

#define OTA_MAGIC_BOOT 0x07AA
// #define OTA_STORAGE_TYPE 0xA4 // QSPI_FLASH | FATFS | MBR
#define OTA_STORAGE_TYPE ((1 << 2) | (1 << 5) | (1 << 7))
#define OTA_MBR_PART 2

int ota_loader_ready() {
struct fs_dirent entry;
int ret;

if (fs_stat(OTA_LOADER_FILENAME, &entry) < 0) {
LOG_WRN("tried to perform an ota without binary present");
return -1;
}

if (sizeof(CONFIG_OTA_LOADER_TEMP_PATH_POSTFIX) > 1) {
ret = fs_rename(OTA_LOADER_FILENAME, CONFIG_OTA_LOADER_UPDATE_PATH);
if (ret < 0) {
LOG_ERR("unable to rename ota file: %d", ret);
return ret;
}
}

stm32_backup_domain_enable_access();
LL_RTC_BAK_SetRegister(RTC, RTC_BKP_DR0, OTA_MAGIC_BOOT);
LL_RTC_BAK_SetRegister(RTC, RTC_BKP_DR1, OTA_STORAGE_TYPE);
LL_RTC_BAK_SetRegister(RTC, RTC_BKP_DR2, OTA_MBR_PART);
LL_RTC_BAK_SetRegister(RTC, RTC_BKP_DR3, entry.size);
stm32_backup_domain_disable_access();

LOG_INF("OTA marked as ready");

return 0;
}

int ota_loader_start() {
LOG_INF("OTA started, reboot in progress");

sys_reboot(SYS_REBOOT_COLD);
return 0; // unreachable
}
14 changes: 14 additions & 0 deletions loader/ota/ota_llext_exports.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Arduino s.r.l. and/or its affiliated companies
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "ota_api.h"
#include <zephyr/llext/symbol.h>

EXPORT_SYMBOL(ota_sketch_ready);
EXPORT_SYMBOL(ota_sketch_start);

EXPORT_SYMBOL(ota_loader_ready);
EXPORT_SYMBOL(ota_loader_start);
Loading
Loading