Skip to content

P7(c-2) S2: cross-compile libsrt for bare-metal arm-none-eabi + boot smoke#2

Merged
aklofas merged 5 commits into
mainfrom
s2-libsrt-cross-compile
Jun 1, 2026
Merged

P7(c-2) S2: cross-compile libsrt for bare-metal arm-none-eabi + boot smoke#2
aklofas merged 5 commits into
mainfrom
s2-libsrt-cross-compile

Conversation

@aklofas

@aklofas aklofas commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

Sub-arc S2 of the libsrt-on-FreeRTOS arc (P7(c-2)). Cross-compiles libsrt for bare-metal arm-none-eabi and proves its runtime initializes on the S1 FreeRTOS + lwIP substrate under QEMU mps2-an386:

PASS: s2_libsrt (startup+socket+cleanup)

srt_startupsrt_create_socketsrt_getsockstate == SRTS_INITsrt_closesrt_cleanup. RED-proven (flip the expected sockstate → FAIL/exit 1).

Not a cargo crate → zero crates/ change; cargo public-api unchanged (8 crates), #[non_exhaustive] = 258.

What's here (embedded/s2-libsrt/)

  • CMake toolchain (arm-none-eabi.cmake): CMAKE_SYSTEM_NAME=Generic + -DGNU=ON to clear libsrt's GNU/GNU_OS detection bug → portable ::select() path (no epoll), pthread sync backend (ENABLE_STDCXX_SYNC=OFF), logging/encryption off.
  • ~13 posix-shims/: route libsrt's system includes (syslog, sys/uio, endian, netdb, netinet/in, sys/ioctl, …) and bridge newlib↔FreeRTOS-Plus-POSIX type collisions (pthread_*, timer_t, sigval/sigevent) — these are independent of _GNU_SOURCE (verified); fixed with sentinel guards + a __POSIX_VISIBLE-masking sys/signal.h.
  • pthread_key_shim.c: FreeRTOS-Plus-POSIX has no pthread_key_* (TSD); implemented over FreeRTOS TLS slot 0, with a pre-scheduler bootstrap fallback (libsrt touches its TLS key from a static-init global ctor before vTaskStartScheduler, where there is no current task — this was the boot-smoke hang).
  • atomic64_stub.c (__atomic_*_8 via PRIMASK critical sections — no libatomic for cortex-m4f) + syscalls_stub.c (_getentropy, encryption off).
  • patches/0001-srt-baremetal-portability.patch: three minimal vendor/srt portability fixes (int32_t==long: std::min<int>, EventVariant(int32_t(0)); pthread_cancel guarded by SRT_NO_PTHREAD_CANCEL), applied to the pinned submodule at build time so the vendor/srt pointer stays pristine. Filed upstream as Fix int32_t-vs-int portability; align CThread assignment with std::thread Haivision/srt#3329.

Footprint (R5)

text 758 KB / data 4.6 KB / bss 238 KB (S1 was ≈66 KB text; libsrt + libstdc++ add ~690 KB) — fits an STM32H7-class part.

CI

scripts/check-s2-libsrt.sh wired continue-on-error into the no-std-baremetal job after S1 (skips cleanly if the ARM toolchain / QEMU / cmake are absent). No new apt packages — cmake is already on the runner. Promote to hard-gate after a few green apt runs.

Scope boundaries

Runtime init/teardown only — the SRT data plane (handshake/ARQ) and encryption are S3. lwIP IPv6 is enabled so libsrt's sockaddr_in6/ip6_addr_t types resolve, but traffic stays IPv4.

aklofas added 4 commits June 1, 2026 13:27
CMake toolchain (CMAKE_SYSTEM_NAME=Generic + -DGNU=ON to clear libsrt's
GNU/GNU_OS detection bug) compiles libsrt's portable ::select() path (no
epoll) against the FreeRTOS-Plus-POSIX pthread backend (ENABLE_STDCXX_SYNC=OFF)
and lwIP sockets (LWIP_COMPAT_SOCKETS=2 -> real bare-name fns, not macros).

posix-shims/ route libsrt's system includes and bridge newlib<->FreeRTOS-Plus-
POSIX namespace collisions (independent of _GNU_SOURCE): syslog/uio/endian/netdb
forwarders, _pthreadtypes + sys/signal (__POSIX_VISIBLE mask) + s2_prefix
(timer_t) suppress newlib's POSIX types so FreeRTOS-Plus-POSIX owns them;
netinet/in supplies sockaddr_in6 gap-fills. lwIP IPv6 enabled (libsrt needs the
types; runtime stays IPv4). pthread_key_shim.c implements the TSD API
FreeRTOS-Plus-POSIX lacks over FreeRTOS TLS slot 0.

Three minimal vendor/srt portability fixes (int32_t==long on this newlib:
std::min<int>, EventVariant(int32_t(0)); pthread_cancel guarded by
SRT_NO_PTHREAD_CANCEL) carried as patches/0001 and applied to the pinned
submodule at build time, keeping vendor/srt's git pointer pristine.

libsrt.a (737 KB) cross-builds; substrate still boots under QEMU.
…r QEMU

Link libsrt.a into the firmware and run a boot smoke that initializes libsrt's
runtime on the FreeRTOS+lwIP substrate: srt_startup (spawns the SRT:GC pthread)
-> srt_create_socket -> srt_getsockstate==SRTS_INIT -> srt_close -> srt_cleanup.

New firmware glue surfaced by linking libsrt:
- atomic64_stub.c: __atomic_{load,store,exchange,fetch_add,fetch_sub,
  compare_exchange}_8 via PRIMASK critical sections — Cortex-M4 has no native
  64-bit atomics and the bare-metal multilib ships no libatomic.
- syscalls_stub.c: _getentropy (libsrt seeds seqnos via std::random_device ->
  newlib getentropy, no bare-metal backend); deterministic, encryption is OFF.
- pthread_key_shim.c: pre-scheduler bootstrap fallback. libsrt touches its TLS
  key from a global constructor before vTaskStartScheduler, where there is no
  current task; vTaskSetThreadLocalStoragePointer(NULL,...) would assert
  (pxCurrentTCB==NULL). Route to a global slot until the scheduler runs.

main.cpp includes srt.h at C++ linkage (it pulls C++ stdlib). RED-proven: a
fresh socket reports SRTS_INIT; flipping the expected state -> FAIL/exit 1.

R5 footprint: text 758 KB, data 4.6 KB, bss 238 KB (S1 was ~66 KB text;
libsrt + libstdc++ add ~690 KB). Resolves R4 (libsrt<->lwIP socket/select link)
and R5/R6; the SRT data plane + encryption remain S3.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an S2 embedded harness that cross-compiles Haivision libsrt for bare-metal arm-none-eabi, links it against the existing FreeRTOS + lwIP substrate, and runs a QEMU mps2-an386 boot-smoke proving srt_startup → srt_create_socket → sockstate == SRTS_INIT → srt_close → srt_cleanup.

Changes:

  • Introduces embedded/s2-libsrt/ firmware, build script, toolchain file, linker script, and POSIX/newlib compatibility shims needed to compile/link libsrt on Cortex-M4F.
  • Adds a CI step and a local script to build + run the S2 smoke test under QEMU (soft-gated with continue-on-error + SKIP behavior when tools are missing).
  • Applies a small portability patchset to the pinned vendor/srt submodule at build time (without moving the git pointer).

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
scripts/check-s2-libsrt.sh Builds and runs the S2 libsrt QEMU boot-smoke gate, with tool-presence SKIPs.
embedded/s2-libsrt/syscalls_stub.c Adds bare-metal syscall stubs (notably _getentropy) to satisfy newlib/libsrt link needs.
embedded/s2-libsrt/sys_arch.c Provides lwIP sys_arch FreeRTOS port used by the sockets/select path.
embedded/s2-libsrt/startup.c Cortex-M4F startup + vector table wiring for FreeRTOS handlers + semihosting _exit.
embedded/s2-libsrt/pthread_key_shim.c Implements minimal pthread_key_* TSD support on FreeRTOS TLS slot 0 (incl. pre-scheduler fallback).
embedded/s2-libsrt/posix-shims/syslog.h Adds syslog LOG_* constants expected by libsrt headers.
embedded/s2-libsrt/posix-shims/sys/uio.h Provides struct iovec inclusion via lwIP sockets.
embedded/s2-libsrt/posix-shims/sys/signal.h Avoids newlib vs FreeRTOS-Plus-POSIX sigval/sigevent redefinition collisions.
embedded/s2-libsrt/posix-shims/sys/ioctl.h Routes ioctl macros/decls to lwIP sockets compatibility.
embedded/s2-libsrt/posix-shims/sys/_pthreadtypes.h Suppresses newlib pthread typedefs to avoid conflicts with FreeRTOS-Plus-POSIX types.
embedded/s2-libsrt/posix-shims/semaphore.h Routes semaphore API to FreeRTOS-Plus-POSIX.
embedded/s2-libsrt/posix-shims/sched.h Routes sched API to FreeRTOS-Plus-POSIX.
embedded/s2-libsrt/posix-shims/s2_prefix.h Force-included macro sentinel overrides to prevent newlib typedef collisions.
embedded/s2-libsrt/posix-shims/pthread.h Routes pthread API to FreeRTOS-Plus-POSIX and declares pthread_key_* used by libsrt.
embedded/s2-libsrt/posix-shims/netinet/in.h Supplies netinet/in.h (and IPv6 bits as needed) via lwIP/compat.
embedded/s2-libsrt/posix-shims/netdb.h Routes netdb to lwIP and stubs missing getnameinfo + NI_* flags.
embedded/s2-libsrt/posix-shims/endian.h Provides <endian.h> macros required by libsrt’s GNU endian branch.
embedded/s2-libsrt/patches/0001-srt-baremetal-portability.patch Minimal upstream-targeted portability fixes applied at build time.
embedded/s2-libsrt/mps2_an386.ld Linker script for QEMU mps2-an386, including init/fini ordering + unwind tables.
embedded/s2-libsrt/main.cpp Implements the S2 libsrt startup/socket/cleanup smoke test and semihosting exit.
embedded/s2-libsrt/lwipopts.h lwIP configuration tuned for loopback sockets/select + libsrt compile/link needs.
embedded/s2-libsrt/FreeRTOSConfig.h FreeRTOS configuration for Cortex-M4F with C++/POSIX needs enabled.
embedded/s2-libsrt/FreeRTOS_POSIX_portable.h Suppresses type collisions between newlib and FreeRTOS-Plus-POSIX for this port.
embedded/s2-libsrt/FreeRTOS_POSIX_config.h Placeholder for FreeRTOS-Plus-POSIX overrides (currently none).
embedded/s2-libsrt/clock_shim.c Wraps clock_gettime to provide higher-resolution monotonic time.
embedded/s2-libsrt/build.sh Cross-builds libsrt via CMake, builds firmware, links, and prints sizes.
embedded/s2-libsrt/atomic64_stub.c Implements missing __atomic_*_8 libcalls for Cortex-M4F without libatomic.
embedded/s2-libsrt/arm-none-eabi.cmake CMake toolchain file for bare-metal libsrt cross-compilation.
embedded/s2-libsrt/arch/sys_arch.h lwIP arch header defining sys_arch types for FreeRTOS primitives.
embedded/s2-libsrt/arch/cc.h lwIP arch header for diagnostics/assert/timeval inclusion.
.gitignore Ignores S2 build artifacts (elf/o/srt-build/srt-install).
.github/workflows/ci.yml Adds an S2 boot-smoke step to the no-std-baremetal job (continue-on-error).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread embedded/s2-libsrt/sys_arch.c Outdated
Comment thread embedded/s2-libsrt/pthread_key_shim.c
Comment thread embedded/s2-libsrt/posix-shims/netdb.h
Comment thread embedded/s2-libsrt/lwipopts.h Outdated
Comment thread embedded/s2-libsrt/posix-shims/netinet/in.h Outdated
Comment thread embedded/s2-libsrt/syscalls_stub.c
Six code-quality fixes (none change behavior on libsrt's actual usage paths):
- sys_arch.c: round byte->word stack depth up in sys_thread_new (avoid
  under-allocation on non-word-aligned sizes).
- pthread_key_shim.c: pthread_key_create returns EINVAL on a NULL key instead
  of claiming the slot.
- posix-shims/netdb.h: getnameinfo stub returns EAI_FAIL (POSIX contract) and
  clears host/serv instead of returning -1 and leaving them unset.
- syscalls_stub.c: _getentropy fails cleanly (errno=EFAULT) on a NULL buffer.
- lwipopts.h / posix-shims/netinet/in.h: correct stale comments that claimed
  IPv6 is off (it is enabled for libsrt's sockaddr_in6/ip6 types).
@aklofas
aklofas merged commit bb41e33 into main Jun 1, 2026
13 checks passed
@aklofas
aklofas deleted the s2-libsrt-cross-compile branch June 1, 2026 23:21
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.

2 participants