Skip to content

teensy30/LC: Teensy orchestrator compiles unreferenced framework libraries (FNET, Snooze, RadioHead, mbedtls) — causes .bss / .dmabuffers RAM overflow #204

@zackees

Description

@zackees

Summary

fbuild's Teensy orchestrator compiles and links every bundled framework library found under the Teensyduino package's libraries/ directory, regardless of whether project sources reference them. For RAM-constrained Teensy targets (teensyLC: 8 KB, teensy30: 16 KB) this blows the RAM budget at link time because unreachable libraries leave static-initialized allocations in .bss / .dmabuffers that --gc-sections can't prune (init_array references pin them).

This is the root cause of FastLED/FastLED#2406.

Evidence

For fbuild 2.2.3 building the Blink sketch (FastLED examples/Blink/Blink.ino) on teensylc:

  • Total translation units compiled: 451 (vs. 242 for PlatformIO's LDF chain mode on the same sketch/board)
  • Breakdown of fbuild's TUs by origin:
Library fbuild TUs Referenced by FastLED? Notes
cores/teensy3 67 yes (core) expected
libraries/Audio 91 yes (audio_input_teensy.h) expected
libraries/SdFat 47 yes (fs_sdcard_arduino.hpp) expected
libraries/FNET 153 NO ❌ TCP/IP stack, never referenced
libraries/Snooze 44 NO ❌ low-power lib, never referenced
libraries/RadioHead 35 NO ❌ radio stack, never referenced
libraries/mbedtls 68 NO ❌ crypto, pulled in transitively by FNET
misc (Wire, SPI, Adafruit_NeoPixel, OctoWS2811, DmxSimple, SoftwareSerial, SerialFlash) 13 partial mixed
FastLED + sketch 23 yes expected

300 of the 451 TUs (~66%) are unreferenced.

RAM impact (teensyLC, 8192 B RAM)

Observed in CI (https://github.com/FastLED/FastLED/actions/runs/24901454197 — link failure logs):

ld: firmware.elf section `.bss' will not fit in region `RAM'
ld: region `RAM' overflowed by 2172 bytes    (Blink)
ld: region `RAM' overflowed by 2424 bytes    (Apa102HD)
ld: region `RAM' overflowed by 1708 bytes    (AudioInput)
...

For comparison, the same Blink sketch built via PlatformIO pio run on the same host:

.text                 37852
.data                   312
.bss                   2636
.dmabuffers             192
.usbbuffers             864
.usbdescriptortable     160
-------------------------------
RAM total              4164  (50.8 % of 8192)

→ fbuild's RAM footprint for Blink is ~10364 B (150 % over budget), PlatformIO's is ~4164 B. Delta ≈ 6.2 KB, almost entirely explained by .bss statics from the four unreferenced libraries.

Suspected cause

#163 / #164 fixed the opposite problem — not discovering framework libraries at all — by switching to framework-arduinoteensy and "selecting and compiling only bundled framework libraries referenced by project sources, following transitive framework includes while skipping examples/extras/tests."

The observed behavior on teensyLC suggests the selection step either:

  1. Does not actually run for teensyLC/teensy30 (maybe gated on teensy4 only), or
  2. Runs but the transitive-include walk grows to the entire libraries/* set because one of the reachable headers (e.g., Audio.h) transitively #includes something that fans out into FNET/RadioHead/Snooze/mbedtls, or
  3. Runs but conservatively falls back to "include everything" when selection fails.

Walking .fbuild/build/teensylc/release/compile_commands.json confirms every libraries/FNET/**/*.c(pp), libraries/Snooze/**/*.c(pp), libraries/RadioHead/**/*.c(pp), libraries/mbedtls/**/*.c(pp) is compiled.

Reproduction

In FastLED master:

./compile --no-interactive --no-parallel --max-failures 1 teensylc Blink
./compile --no-interactive --no-parallel --max-failures 1 teensy30 AnalogOutput

CI reproduces this on every teensy30/teensyLC job.

Expected behavior

For Blink on teensylc, fbuild should compile only the libraries transitively referenced by the sketch + FastLED + the teensy3 core. Minimum set observed in PlatformIO: teensy3 core, Audio, SdFat (+ its deps), SPI, Wire, Adafruit_NeoPixel. Not: FNET, Snooze, RadioHead, mbedtls.

Match PlatformIO's LDF chain mode for the framework = arduino / platform = teensy pair.

Suggested direction

Two tiers:

Short-term stopgap (unblock CI for teensy30/LC):

  • Allowlist the libraries that FastLED actually needs, or equivalently deny-list the unreferenced set (FNET, Snooze, RadioHead, mbedtls, FlightSim, HID, OSC, TimerOne, TimerThree) when a per-target RAM budget <= 16 KB.
  • Per-target RAM budget guard: refuse to link .bss-heavy libs when the target's RAM budget is below a threshold.

Long-term fix: implement true LDF-style transitive reachability. Filed as a separate feature issue (see cross-ref when created).

Impact

Blocks teensy30 and teensyLC CI coverage in FastLED/FastLED. Workaround is to route these boards through pio run instead of fbuild (see FastLED/FastLED#2406 for the consumer-side tracking issue and the --backend=platformio escape hatch added there).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions