Skip to content

feat: portenta ota#424

Draft
gibix wants to merge 47 commits intoarduino:mainfrom
gibix:feat/ota
Draft

feat: portenta ota#424
gibix wants to merge 47 commits intoarduino:mainfrom
gibix:feat/ota

Conversation

@gibix
Copy link
Copy Markdown
Member

@gibix gibix commented Apr 14, 2026

This is a first porting of portenta_ota

The main "change" is that now the ota payload contains <llext loader + padding + user sketch>

Features

  • example with ethernet
  • example with progress download
  • user callback for ota compleated
  • http
  • https
  • zephyr sockets
  • ota
  • lzss compression

Boards

  • portentah7 (compile and tested)
  • opta
  • giga
  • c33

Step to reproduce

  • build extra/ota-pack
  • rebuild the core for you board
  • compile an example (blink) and save the .ota file from the output dir
  • run a simple http server python -m http.server 8000 in the directory that contains the sketch
  • flash the bootloader
  • flash the ota example sketch

pennam and others added 30 commits March 4, 2026 17:10
This patch changes the build to perform two-pass linking to separate rodata
with relocations (copied to RAM) from rodata with no relocations (pure data)
that can be kept in flash by llext.

For dynamic linking mode:
- First pass: Link with build-dynamic.ld to create temp ELF (unchanged).
- Analyze the elf and extract, sort and write out the sections:
    - .rodata: sections WITH relocations → copied to RAM (LLEXT_MEM_RODATA)
    - .rodata_noreloc: sections WITHOUT relocations → kept in flash (LLEXT_MEM_RODATA_NO_RELOC)
- Second pass: Link with generated rodata_split.ld + build-dynamic.ld.

For static linking mode:
- Generates empty rodata_split.ld (no section separation needed)

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Older toolchains will not use the multi-step linking. Make sure the
rodata sections are merged into one to avoid wasting memory on small
one-item sections at LLEXT link time.
PR arduino#309 addressed the C++ issues that were
causing the Ethernet examples to fail to link. With those fixes in
place, these examples can be removed from the known issues list.

Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
-Os is already used in cpp flags but was missing from cflags.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
Co-authored-by: Per Tillisch <accounts@perglass.com>
Co-authored-by: Luca Burelli <pil@iol.it>
Explicitly state the license in all source files to comply with SPDX
best practices. In addition, update the copyright notice to the new
format.
- ea_malloc: MIT (derived from https://github.com/embeddedartistry/c-linked-list)
- Arduino_LED_Matrix: Apache-2.0 (new code)
- Camera: LGPL-3.0+ (derived)
- all others: LGPL-2.1+ (derived)
We cannot depend on Zephyr's action since it actively flags any
non-Apache2 contribution. Instead, use the official scancode-action and
process the resulting JSON file to point out missing or new licenses.
Fix minor typo in comment.

Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
strcpy, memcmp and memset were missing from export, they are however
exported by zephyr llext/llext_export.c.

Signed-off-by: Andrea Gilardoni <a.gilardoni@arduino.cc>
added time and sys_clock_settime export

Signed-off-by: Andrea Gilardoni <a.gilardoni@arduino.cc>
Make sure the verification passed before deleting temporary files. These
may be used in a re-run of verify-core if failed jobs are retried by the
user via the Github interface.
This change fixes the errors that are raised when the workflow is
triggered by a push event, which does not have a PR number associated
with it. Also, no need to error if the PR number is invalid or if the
workflow file is changed in the PR - just issue a warning.

Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
They appear as regular files but can't be copied without '-r', causing
an error and preventing the scan from running properly.

Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
Action crashes if no files are found in the scancode-inputs folder.
Otherwise USB_NEXT complains with

<wrn> usbd_class: Class instance already registered

and callbacks don't get registered (the only real effect is that 1200bps touch doesn't work)
facchinm and others added 17 commits March 4, 2026 17:13
PortentaC33 and PortentaH7 still have bugs
Provide long-call trampolines for the LLEXT extension.
Precompiled toolchain libraries emit R_ARM_THM_JUMP24 / R_ARM_THM_CALL
relocations for the export libc functions. These have a +/-16 MB range
limit which is exceeded when the LLEXT is loaded in a different memory
region than the kernel.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
CONFIG_POSIX is now frozen and cause import error on new picolib libc
because doesn't implement all posix compliance timers. Replace all
CONFIG_POSIX with equivalent, more limited apis as reported in the
mainline POSIX#Legacy documentation.

Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
The LLEXT modules share the loader's thread pool but can't access Thread
Local Storage variables (like errno) directly because the compiler bakes
in wrong memory offsets at link time.

When Zephyr 4.3 broke CONFIG_POSIX_API=y, fixing the POSIX headers
required touching ZephyrClient::read(), which exposed a latent TLS issue
with the errno check. Since both branches of that check returned 0
anyway (dead code), the simplest correct fix is if (received <= 0)
return 0 — no errno access needed.

Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
With local-exec TLS, the generated code is essentially:

BLX  __aeabi_read_tp       ; get thread pointer → r0
LDR  r1, [r0, #errno_off]  ; add a CONSTANT offset baked in at link time

The errno_off constant is computed by the linker at LLEXT link time
using an R_ARM_TLS_LE32 relocation. To compute it correctly, the linker
needs to know the full TLS block layout of the loader binary — every TLS
variable from every module (picolibc, Zephyr kernel, etc.) in their
final positions.

The LLEXT linker does not have that information. It only sees the
llext-edk headers and syms-dynamic.ld stubs. So the offset it bakes in
is very likely wrong — the LLEXT would call the right __aeabi_read_tp,
get the right thread pointer, then read from the wrong offset and get
garbage instead of errno.

The new exported function arduino_errno_ptr() runs inside the loader,
where local-exec is valid and correct. It computes thread_ptr +
errno_off (the loader's errno), and returns a plain int *.

An alternative fix is to ignore errno and just return 0 as done before.

Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
Signed-off-by: Gilberto Conti <g.conti@arduino.cc>
@gibix gibix changed the title Feat/ota feat: ota Apr 14, 2026
@gibix gibix changed the title feat: ota feat: portenta ota Apr 14, 2026
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 14, 2026

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.