BERGSONNE

Implementation status

The same core_* API and behavior DSL target every Core — this page is the honest map of how far each one is along, and where the platform is headed across architectures. One contract, many implementations.

Core.ST.H5: sleep awaits a re-bench
The H5 clock, interrupt-table and SPI issues found in the September 2026 audit are fixed and bench-verified. What stays partial is sleep: power.stop (the H5 moved to the shared, watchdog-safe sleep code on 13 October and hasn’t been re-benched) and power.rtc_wake. See Power.

Overview

A peripheral feature is “done” on a Core when the layers beneath the core_* API are implemented for that MCU and the result is checked on hardware. Because the contract is shared, this is the only thing that varies between Cores — so a single matrix captures the whole platform.

Today the shipping Cores are STMicroelectronics Arm Cortex-M parts. WCH (RISC-V) and Nordic (nRF54) Cores are in development; when they arrive they populate the same matrix without changing a line of your firmware.

Status, not marketing
Statuses come straight from the SDK’s own status files, re-synced whenever they change in the SDK. This snapshot: 17 October 2026, from tiles@e539b7b. Verified means checked on real hardware; compiles means the code builds but hasn’t been hardware-verified yet. Hover a dot for its note: most name the bench test and date.

Cores by architecture

Cores are named by vendor and series — Core.ST.L4, Core.ST.W5, Core.ST.H5. The vendor segment is the architecture seam: everything above the core_* line is shared, everything below is re-implemented per family.

STMicroelectronics

· Arm Cortex-MShipping

The Cores shipping today, from an ultra-low-power M0+ up to an M33 rated for 250 MHz. The full feature matrix below is measured against these.

Core.ST.L0
STM32L011
M0+ · rated 32 MHz
Core.ST.L4
STM32L422
M4 · rated 80 MHz
Core.ST.W5
STM32WBA55
M33 · rated 100 MHz
Core.ST.H5
STM32H523
M33 · rated 250 MHz

WCH

· RISC-VIn development

RISC-V Cores bringing a lower-cost architecture to the same tile platform. The core_* API and behavior DSL are unchanged — only the layers beneath are re-implemented.

In development — same core_* contract, drivers via the PAL.

Nordic

· Arm Cortex-M33In development

nRF54 Cores adding modern wireless (BLE / 802.15.4) alongside the Arm M33 line. Same contract, same drivers via the PAL.

In development — same core_* contract, drivers via the PAL.

Feature support matrix

Features by group, against the shipping Cores. Each entry carries the SDK layer it reaches (LL → HAL → TAL → Core); a layer implies everything beneath it.

FeatureLayerL0M0+L4M4W5M33H5M33
System
core initializationCore●●●●
LEDStudio●●●●
delay (ms / µs)Studio●●●●
SysTickLL●●●●
fault handlers●●●●
unique device IDCore●●●●
brick recoveryCore·●·●
software resetStudio●●●●
reset reasonStudio●●●●
SWO / ITM debug outputHAL·●●●
WAMR (Wasm) runtimeStudio··●●
Clocks
HSI (internal RC)LL●●●●
HSE (external crystal)LL··●·
MSI / MSIS (low-power)LL●●··
CSI (low-power internal)LL···●
PLL (high-speed)LL●●●●
GPIO
digital I/O (read / write)Studio●●●●
EXTI (external interrupts)Studio●●●●
alternate function configLL●●●●
open-drain / pull configCore●●●●
UART
TX / RX (polling)Core●●●●
interrupt-drivenCore●●●●
DMACore○○○○
hardware flow control○○○○
LPUART (low-power)Core●●·●
I2C
standard mode (100 kHz)Core●●●●
fast mode (400 kHz)Core●●●●
fast-mode plus (1 MHz)·●·●
interrupt-drivenCore○○○○
target / device modeCore●●●●
DMA○○○○
10-bit addressingCore○○○○
SMBus mode○○○○
SPI
master TX / RX (polling)Core·●●●
interrupt-drivenCore·○○○
DMACore·●●●
slave mode·○○○
OctoSPI / QSPI···○
I3C
SDR controllerCore···●
dynamic addressingCore···●
CCCsCore···●
private read / writeCore···●
in-band interrupts (IBI)Core···●
tile drivers over I3CCore···●
target mode···○
HDR modes (DDR)····
Timers
basic timebase / tickStudio●●●●
PWM outputStudio●●●●
STEP/DIR stepper pulsesCore●●●●
input captureCore●●●●
one-shot pulse○○○○
encoder mode○○○○
LPTIM (low-power timer)○○○○
IWDG (watchdog)Studio●●●●
ADC
single-shot raw readStudio●●●●
millivolt read (VREFINT)Studio◐●●●
temperature sensorStudio●●●●
resolution (8 / 10 / 12-bit)Core●●◐●
oversampling / burstCore●●●●
DMACore●●◐●
DMA results in millivoltsCore◐●●●
continuous / scan modeCore●●●●
external trigger (TIMx TRGO / EXTI)Core●◐◐◐
analog watchdog○○○○
Audio
PDM microphone captureCore··●·
NVM
true EEPROMCore●···
flash emulationCore·●●●
OTP identity slotsCore·○◐○
Project Generation (Coregen)
GPIO pad auto-initCore●●●●
I2C auto-initCore●●●●
analog pad initCore●●●●
I3C auto-initCore···●
SPI auto-initCore·●●●
UART auto-initCore●●●●
timer / PWM auto-initCore●●●●
Power Management
sleep modeCore●●●●
STOP modeCore●●●◐
standby / shutdownCore●●●●
RTC wakeupStudio●●●◐
EXTI wakeupCore●●●●
wakeup pin (Standby)Core○●○○
RTC Alarm AStudio●●●●
backup registersStudio●●●●
Security
hardware RNG·●●●
AES (hardware)·○◐·
PKA / ECC··○○
HASH (SHA-256)··○○
Connectivity
USB CDC serialStudio·●·●
Scope over USBCore·●·●
Scope over BluetoothCore··●·
USB HID·●·●
USB-reachable sleepCore·◐·○
USB MSC·○·○
ROM DFU bootloader·●·●
serial update (USB CDC)HAL·●·●
firmware update over BLECore··●·
remote reset over USB serialHAL·●·●
remote reset over BLECore··●·
SWD flash from StudioStudio○○●○
BLE radio··●·
BLE advertising··●·
BLE GATT server··●·
FDCAN···○
Advanced
COMP (analog comparator)○○○·
DACStudio···●
Bluetooth LE
advertisingCore··●·
GATT services + characteristicsCore··●·
notify / on-write callbacksCore··●·
pairing + bondingCore··◐·
central / scanner roleCore··○·
Thread
network (fixed dataset)Core··●·
UDP send / broadcast / receiveCore··●·
role + link diagnosticsCore··●·
settings in flashCore··◐·
BLE + Thread in one imageCore··●·
provisioning (BLE + C API)Core··●·
commissioning (joiner / commissioner)Core··○·

Legend

Status of each feature on each Core:

  • ●Verified on hardware
  • ●Compiles (not yet hardware-verified)
  • ◐Partial
  • ○Planned
  • ·Not applicable to this MCU

The Layer column uses the SDK’s stack vocabulary — see SDK layers & API tiers. A higher layer implies the ones beneath it are present too.

Known gaps

The matrix says how far each feature has got; these say what’s missing. Each SDK header lists its own gaps (@studio unsupported), and they are published here as written. High / medium / low is how much closing the gap is worth; C API / DSL / wire is where it sits (the C API, the Studio DSL, or the Scope wire format). The subsystem guides show their own.

ADC
lowDSLTwin VDD / die-temp are constants

read_pad / read_mv_pad use the per-pad slider on the chip view, but temp_decidegc and vdd_mv return fixed values (25.0 °C / 3300 mV). No UI affordance to vary them yet — DSL programs that branch on under-/over-temp or low-VDD logic always see nominal in the IDE.

mediumDSLNo DSL access to sampling speed / resolution

Tier 2 calls the default instance at its compile-time resolution (12-bit) and per-pad sampling speed set during init. SAMP_FAST / MED / SLOW / VERY_SLOW and ADC_6/8/10/12BIT aliases are reachable only via the explicit-handle Tier 1 API.

mediumDSLNo multi-instance ADC dispatch

Tier 2 wrappers always hit core_adc1. Cores with multiple ADCs (Core.ST.H5 has ADC1 + ADC2) need per-pad peripheral tagging in tile JSON before coregen can emit the dispatch. Until then DSL programs are limited to whichever pads coregen routed to ADC1.

lowDSLNo core_adc / DSL oversampling wrapper

Hardware oversampling (2x to 256x; 1024x on Core.ST.H5) works through the HAL on the same handle: hal_adc_set_oversample(&core_adc1, ratio) averages, hal_adc_set_oversample_ex() also widens the result. There is no core_adc_* wrapper or DSL surface for it.

lowC APINo injected channels

Regular-group external triggers ARE supported: core_adc_set_trigger() paces DMA conversions from a TIMx TRGO or EXTI line. Injected groups (a second, higher-priority conversion sequence that preempts the regular one) are not surfaced. Bring-your-own register writes if you need a preempting sample inside a control loop.

Backup
lowDSLTwin backup state wipes on Reset

read/write round-trip within a single run, but the per-slot store is cleared on every project reload — DSL programs that rely on backup state surviving a soft reset (e.g., boot counters across the user clicking Reset in the IDE) can't be exercised end-to-end.

lowC APINo tamper / anti-tamper integration

The TAMP block on WBA/H5 hosts the backup registers but also drives tamper detection (active edge, anti-tamper erase, time-stamping on tamper). None of that is wrapped — backup is read/write only.

BLE
mediumDSLNo Twin coverage for BLE

DSL coverage landed: a project declares a contract, gets palette blocks to publish and receive, and can bind a characteristic to a variable so coregen generates the publisher. What is still missing is the simulator side, so a DSL program that uses BLE cannot be exercised without flashing a board.

mediumDSLConnect / disconnect are not DSL events

core_ble_on_connect() and core_ble_on_disconnect() take a callback pointer rather than overriding a weak symbol, so coregen has no seam to emit a dispatcher against. Every other event in the DSL arrives through that weak-symbol pipeline. Until this is wired the only way to notice a connection from the DSL is to poll.

lowDSLByte-array characteristics have no DSL form

A `bytes` characteristic can be declared and published from C, but the DSL has no type that carries a buffer and a length, so it gets neither a publish block nor a write handler, and it cannot be bound to a variable. Scalars and strings both work.

mediumC APICentral / scanner mode

Peripheral-only today. No scanning, no central-role connections, no GATT-client reads/writes. Tracked as its own initiative — most Bergsonne use-cases are peripheral-role (sensor advertising to a phone). Apps that need central-role drop into the WBA BLE stack.

lowC APIPairing refinements (LE Secure Connections, directed reconnect)

core_ble_enable_pairing() does Just Works *legacy* pairing with bonding: characteristics require an encrypted link and the keys persist in flash NVM, so a bonded host reconnects without re-prompting. Not yet exposed: LE Secure Connections (numeric-comparison / passkey MITM protection) and directed advertising for fast reconnect to a known bonded central.

lowC APIArbitrary 128-bit UUIDs

Narrower than it used to be. A contract pins its own 16-bit ids, custom (placed in the Bergsonne base UUID) or SIG-adopted, and core_ble_add_service_id() / _sig() take them verbatim, so ids never shift and deployed clients keep working. What is still missing is a fully arbitrary 128-bit UUID, which is what interop with an existing app that expects some other vendor's base requires.

lowC APIAdvanced features (LE Audio, extended adv, multi-link)

The WBA radio supports LE Audio (LC3), extended advertising / 2M PHY / coded PHY, and multi-link (multiple simultaneous connections). None of that is exposed.

DAC
mediumC APINo waveform / DMA generation

Single-sample writes only. STM32H5's DAC supports DMA-fed sample buffers + the internal noise / triangle wave generators — none of which are wrapped. Audio + arbitrary-waveform tiles need this.

lowC APINo dual-channel synchronization

The DAC peripheral has two channels that can be triggered together for stereo / I-Q output. Only single-channel writes are exposed.

Debug
lowDSLNo DSL surface

Debug output is intentionally Tier 1 — the DSL doesn't have a notion of "debug print to a hardware probe." DSL programs use Core.USB.print for visible output; SWO is reserved for users who are already in C and have a probe attached.

lowC APINo ITM channel selection / timestamps

All output goes to ITM stimulus port 0 with no timestamp packets. Multi-channel routing (e.g., separate streams for log vs. data) and ETM/CYCCNT correlation aren't wrapped.

Fault
mediumC APINo structured fault report capture

The default handler dumps to USB CDC at runtime on the L4 only (the W5, H5 and L0 lose the cause), and there's no crash log that survives reset for post-mortem analysis. A small ring buffer in backup or NVM (with the captured PC / LR / xPSR / fault status registers) would make field debugging tractable.

I2C
mediumDSLTier 2 is byte-level only — no bulk / scan

The current Tier 2 surface is write_byte_bus / read_byte_bus / probe_bus. DSL programs that need to push a multi-byte payload (display init sequences, IMU FIFO drains) or discover what's on a bus (`scan -> int[]`) drop back to Tier 1 with a hal_i2c_t handle. Adds need the array-IN / array-OUT host-call ABI prototyped on the tile-driver side — track with the DSL Capability Coverage close.

highC APIInterrupt-driven / non-blocking I/O

All current operations are polled. A non-blocking variant (with completion callback or status poll) would let DSL programs interleave bus traffic without stalling the main loop. Tracked on the SDK roadmap as 'I2C interrupt-driven'.

highC APIDMA transfers

No DMA path for bulk reads/writes. Long FIFO drains (e.g., IMU water-level batch reads) currently block on polled byte loops.

mediumDSLTarget mode is C-only

Target (device) mode landed at Tier 1: core_i2c_target_init() lets a Core answer as an I2C device on a host bus, using a register-file model with an optional ISR callback. There is no Tier 2 / DSL surface, because a register buffer and a callback have no representation in the DSL host-call ABI. A Studio-level version would need a declarative "expose these variables as registers" binding, close to what the BLE characteristic binding does.

lowC APITarget mode on H5 I2C2 / I2C3

Target mode runs on I2C1 only on Core.ST.H5 (driver-deferred). startup_stm32h523xx.s now has the I2C2 and I2C3 event and error vectors (51-54, 80-81, RM0481 Table 147), but hal_i2c.c registers a target on I2C1 alone there. I2C1 + I2C3 both work on Core.ST.L4 and Core.ST.W5; Core.ST.L0 has only I2C1.

mediumC API10-bit addressing

API takes uint8_t addr — 7-bit only. No path for 10-bit-addressed peripherals (rare in practice but in spec).

lowC APISMBus / PMBus extensions

No PEC, no Alert Response, no block read/write protocol framing. Not requested by any current tile.

I3C
mediumC APINo HDR modes

The H5 I3C peripheral is SDR-only (RM0481 §49.2): no HDR-DDR, HDR-TSL/TSP or HDR-BT, although targets such as the ICM-42686-P offer DDR.

mediumC APINo legacy I2C targets on an I3C bus

The peripheral can send legacy I2C messages (MTYPE 0100), but this SDK does not expose them: coregen keeps a bus on I2C unless every tile on it speaks I3C, so a mixed bus never happens.

lowC APINo DMA, hot-join or secondary controller

FIFOs are serviced by polling (the controller stalls SCL for up to ~100 µs while it waits, §49.16.21); hot-join requests are NACKed (HJACK 0) and controller-role requests are not acknowledged.

mediumDSLNot in the DSL / Studio yet

Nothing here carries `@studio expose`, and Studio cannot request I3C for a bus yet; a hand-written config.json can ("i3c": true).

LED
lowDSLNo DSL access to SOS

core_led_sos is `__attribute__((noreturn))` so it can't be exposed safely — DSL programs that "call SOS" would deadlock the worker. Reserved for fault-handler escape-to-C use.

lowC APINo PWM brightness / color

The onboard LED is hard-wired as a digital push-pull output. No PWM dimming wrapper, no RGB/RGBW support (tiles with addressable LEDs use Disp.RGBW or similar, not core_led).

NVM
mediumDSLNo bulk read / write Tier 2 yet

Tier 2 covers the byte-level pair (read_byte, write_byte) — enough for boot counters, single flags, small struct fields. Multi-byte read_buf / write_buf still need the array-IN / array-OUT host-call ABI prototyped on the tile-driver side. Tracked with the DSL Capability Coverage close.

lowDSLTwin NVM state wipes on Reset

read_byte / write_byte round-trip within a single run, but the per-slot store is cleared on every project reload — DSL programs that rely on NVM state surviving a soft reset (boot counters, crash flags) can't be exercised end-to-end in the IDE. Same issue the Backup register gap calls out; closing both needs persistent per-slot state across worker resets.

lowC APINo wear-tracking API

core_nvm_erase_all clears the region, but nothing reports the page erase count or the remaining write budget. Long-running data loggers budget their write rate from the figures in core_nvm.h.

OTP
highC APIOTP only on Core.ST.W5

CORE_OTP_* is backed only on Core.ST.W5 (STM32WBA55, 512 B @ 0x0BF90000). L0 / L4 / H5 report size 0 and every read/program returns an error until their OTP geometry is added. WBA55 is the only Core that currently ships a product using OTP identity.

mediumDSLprogram_slot is escape-to-C (destructive)

Reads (size, slot_count, slot_is_blank, read) are safe to surface, but the burn (core_otp_program_slot) is irreversible and write-once, so it is intentionally NOT exposed to the DSL — a stray palette call could permanently consume a slot. Provisioning burns happen from C / the production programmer, not from a Studio program.

GPIO
mediumDSLNo DSL access to slew-rate / pull / drive-strength

Tier 2 exposes write/read/toggle only. core_pad_speed, core_pad_output_od pull-config, and the analog-mode setter are reachable only by escaping to C. A Tier 2 wrapper (or @studio expose annotation) for slew-rate would let DSL programs tune SPI/UART rise times without leaving the IDE.

lowDSLBulk / fast pad write is C-only

The single-pad DSL ops do a pad→port/pin lookup each call. A C fast path now exists — core_pad_resolve() + core_pad_fast_* (resolved {port,mask} handle, direct BSRR/IDR) and core_pad_bulk_write() (one atomic BSRR for many pins) — used by bitbang inner loops like the CMSIS-DAP probe. Still no DSL surface (pointer/struct ABI), so synchronized-bus / LED-matrix updates from the IDE remain a gap.

Power
mediumDSLStandby family stays Tier 1 (noreturn)

core_standby_for / core_standby reset on wake — they never return on success and can't be safely exposed to the DSL, since the simulator would deadlock on a call that never returns. Recoverable variants (sleep, stop_for) are Tier 2; reaching Standby from a DSL program needs an "escape-to-C" fallthrough or a separate "would have entered Standby" event the simulator can model.

mediumDSLNo wake-on-pad Tier 2

core_stop_until_on_change blocks until a configured pad edge wakes the chip. The DSL surface is straightforward in spirit but needs the EXTI handler bridge to express "block until" cleanly across the host-call boundary. Tracked alongside the broader DSL event- model story.

highC APIStandby not bench-verified on Core.ST.L0 or Core.ST.W5; Core.ST.H5 sleep compile-only

The register maps behind stop_for / standby_for / RTC / backup were corrected against RM0377 and RM0493 on 2026-09-25. Stop with the watchdog running passed tests/hw-sleep-cycle on Core.ST.L4 and Core.ST.W5 (2026-09-25) and Core.ST.L0 (2026-09-26). Standby on the L0 and the W5 is compile-only. Core.ST.H5 moved to the same fed, chunked Stop code on 2026-10-13 and has not run it on a board yet; its core_standby_for() still has no watchdog check.

mediumC APIStandby can't outlast the watchdog

The IWDG keeps counting in Standby (always on the L0, by option byte on the L4/WBA) and nothing feeds it until main() runs again, so with the watchdog on (the Studio default, 5 s) core_standby_for refuses anything longer than half the timeout and returns HAL_ERROR, and core_standby_until_on_change returns without sleeping. Long sleeps use core_stop_for, which wakes to feed. Changing the IWDG_STDBY option byte would lift this on the L4/WBA; the SDK doesn't touch option bytes.

mediumC APIWKUP-pin Standby is L4-only

core_standby_until_on_change is implemented for STM32L422 only — Core.ST.L4.2's PA0/PA2 WKUP pins. Other Cores hit the (void) fallback and return without entering Standby.

mediumC APINo LPTIM (low-power timer) wakeup

The SDK roadmap flags LPTIM as Tier 1 high-impact: it runs in Stop without the RTC and gives finer wakeup granularity than seconds. Not wrapped here yet.

lowC APINo autonomous-mode peripherals (Core.ST.W5)

The WBA's Stop2 autonomous mode (ADC / SPI / I2C / UART operating while the CPU sleeps) is on the roadmap as Tier 3 — none of it is surfaced through core_power yet.

PWM
mediumDSLNo DSL access to PWM frequency

Tier 2 only exposes duty. Frequency is fixed at coregen time from config.json's timer.freq_hz. DSL programs that want to sweep frequency (e.g., a buzzer playing notes) need set_freq exposed per-pad — the underlying tal_pwm has the path, but the wrapper + default-instance dispatch don't.

mediumDSLNo DSL access to periodic 'every' callbacks

core_every_us is Tier 1 only — it takes a C function pointer for the ISR callback. The DSL surface is `Core.Timer.tick` (in core_timer.h) which fires at config.json's timer.tick_ms; finer custom periods aren't reachable.

mediumC APINo complementary PWM / dead-time (TIM1 advanced)

SDK roadmap Tier 2 item: TIM1's complementary outputs + dead-time insertion + break input are needed for half-bridge / motor / power-converter tiles. The PWM wrapper is single-channel only.

lowC APINo phase / center-aligned modes

Edge-aligned PWM only. STM32 timers can do center-aligned (Mode 1 / 2 / 3) and per-channel phase offsets — useful for low-EMI switching. Not surfaced.

Reset: software reset and reset reason
lowC APIBrownout reads as power-on

The four Cores set one flag for a power-on and a brownout (BORRSTF on the L4, W5 and H5, PORRSTF on the L0), so core_reset_reason() can't tell them apart and reports both as power-on. Hardware limit, not a driver gap.

mediumDSLStudio's simulator doesn't model reset

Core.Power.reset() and Core.Power.reset_reason() run on the board; the simulator needs its own handlers (restart the program, report power-on) in web apps/studio/src/lib/simulator/runtime.ts.

lowC APIRemote and app resets not bench-verified

core_reset(), the USB reset frame and the BLE R frame compile on every Core and pass the host tests (make -C sdk/serial_update test); none has run on a board yet (2026-10-16). tests/hw-reset is the L4 bench test.

RNG
lowC APINo bias correction / health tests

The hardware exposes a CED (clock error) and SEIS (seed error) bit which core_rng_error checks, but there's no NIST SP 800-90B continuous-health-test wrapper. Crypto-grade users should consume the raw words through a vetted DRBG (mbedTLS, etc.).

RTC
mediumDSLNo DSL get_time / get_date

The C surface has core_rtc_get_time / get_date taking out-pointers; they're not exposed because the host-call ABI doesn't map cleanly to multi-out values. The newer multi-scalar-out ABI (see DSL Capability Coverage close, 2026-05-03) could land them.

mediumC APILSE / external crystal not exposed

core_rtc_init always selects LSI (~32 kHz RC, ±5% typical drift on the L4/WBA). The L0's LSI is 26-56 kHz part to part; it is measured once against SYSCLK (ll_lsi_hz(), sdk/hal/hal_lsi.c) and the RTC prescaler is set from that, so the second is as good as SYSCLK at that moment (HSI16 at high / max, MSI at low / medium) and drifts with temperature. Cores with an LSE crystal need ll_rtc_init(1) — no Tier 2 wrapper that takes a clock-source argument.

lowC APINo subsecond / millisecond accuracy

The wrapper exposes whole-second resolution. STM32 RTCs have a subsecond register (1/PREDIV_S) that's reachable from ll_rtc but not from this header — wall-clock timestamps round to the second.

Scope
mediumDSLNo host-to-device control channel

The stream is one-way. A host cannot start, stop or re-rate it, or pick channels; core_scope_enable() is firmware-side only. USB has an RX path and BLE would need a write characteristic beside Studio Scope.

mediumDSLNo units or scaling in the stream

The SDK is integer-only by convention (milli-units), so a channel in mdeg plots in mdeg. A per-channel unit + scale frame is planned (docs/scope-protocol.md, reserved frame types).

lowwireBLE packet size is assumed, not negotiated

core_ble does not report the ATT MTU, so the BLE link sends 180-byte notifications. The Core requests a 251-byte MTU itself after connecting (core_ble_set_auto_mtu), but a central that answers below 183, or a project that turns the request off, would see nothing but CRC failures. Driver-deferred: needs core_ble_mtu().

lowwireNo 64-bit or double channels

The wire has no 8-byte type. Watching one is a compile error by design.

Serial
mediumDSLNo Tier 2 read surface

Tier 2 wraps the write side (print_bus, putc_bus) only. getc_bus, read_bus, available_bus need a Twin input affordance to be meaningful — without one the read functions would just return -1/0 always, defeating the point. Adding a "serial input" pane (analog of the GPIO toggle / ADC slider) closes both ends.

lowDSLCoregen sets up USART pads only, not LPUART

A USART<n>.TX / .RX pad in config.json makes coregen emit the handle (core_usart<n>) and its init in core_init(), with `baud` and `rx_interrupt` from interfaces.USART<n>. LPUART1 pads get no handle or init: call core_serial_init() on it by hand.

mediumC APINo DMA or interrupt-driven TX

TX is polled: core_serial_write() and print return once the last byte is in the data register. RX is interrupt-driven into a ring buffer only when `rx_interrupt` is set (or hal_uart_config_t.rx_interrupt); otherwise reads poll the data register. hal_uart_tx_dma() is a stub that returns HAL_ERROR.

mediumC API8N1 only: no flow control, parity or 9-bit modes

ll_uart_init() sets 8 data bits, no parity, 1 stop bit. hal_uart_config_t carries only `baud` and `rx_interrupt`, so RTS/CTS, parity, other stop bits, 9-bit data and inversion need register writes after init.

mediumC APINo LPUART (low-power UART)

SDK roadmap Tier 2: LPUART works in Stop mode for wake-on-serial. Compile-only on every Core today; not surfaced through this header.

SPI
mediumDSLTier 2 is single-byte xfer only — no bulk / persistent CS

The Tier 2 surface is core_spi_xfer_byte_bus: one byte, CS auto- managed around the call. DSL programs that need to push a multi-byte payload with CS held (display init streams, SD-card sectors, audio frame transfers) drop back to Tier 1 (core_spi_xfer, core_spi_write_read, core_spi_exchange_dma). Bulk variants need the array-IN / array-OUT host-call ABI prototyped on the tile- driver side — track with the DSL Capability Coverage close.

lowC API8-bit Motorola frames only

Frames are 8 bits. No 16-bit frames, hardware CRC, TI frame format or hardware NSS at the core level; the LL layer has the Core.ST.W5 half-duplex (1-line) mode.

mediumC APISlave mode missing

Master-only. No path for a Core to act as a SPI peripheral on another host's bus.

lowC APIQuad / Octo SPI / OctoSPI

SDK roadmap Tier 2: QUADSPI / OctoSPI (memory-mapped external flash for NOR / PSRAM tiles) is wired only on Core.ST.L4 + Core.ST.H5 silicon and isn't wrapped here.

Stepper
mediumDSLNo default-instance / DSL surface

Everything takes a core_stepper_t*. Coregen does not yet read a `stepper` block from config.json, so there is no `core_stepper_move(pad, steps)`-style wrapper and nothing in the Studio palette. The natural Tier 2 shape is one axis per config.json entry with STEP/DIR pads, initialised in core_init().

lowC APISTEP must be a timer output pad

The pulse is made by a compare channel, so STEP is restricted to pads carrying a TIMx.y function. There is no GPIO-bitbang fallback for arbitrary pads; DIR and ENABLE can be any pad.

lowC APILinear ramps only

The profile is trapezoidal (constant acceleration). No S-curve, no per-move acceleration override, no synchronised multi-axis moves.

lowC APINo stall, fault or limit-switch inputs

Drivers' nFAULT / ALM outputs and end-stop switches are left to the application (core_pad_on_change + core_stepper_halt).

Thread
highC APIBLE provisioning is open (development only)

With "ble_provisioning" any phone that connects can move the node to another Thread network: there is no pairing or authorization yet. The network key cannot be read back. core_thread_prov_allow_write() is the hook for a gate; pairing-protected writes are planned.

mediumDSLNo DSL blocks for Thread

Thread is C-only (Tier 1) for now, like BLE: no palette blocks, no twin. The role and UDP callbacks need the host-call ABI to grow first.

highC APINo commissioning (fixed development network)

Every node built from the same config.json joins the same network with the same network key, unless it is moved at run time (core_thread_set_dataset(), or the open BLE provisioning service); there is no joiner / commissioner yet. Development only.

lowC APIBLE + Thread builds use a trimmed OpenThread

With BLE in the same image, OpenThread is rebuilt without the commissioner, joiner, CoAP secure (DTLS), SRP and DNS clients, TCP, ping, mesh and link-metrics diagnostics, with 64 message buffers instead of 128, so both stacks fit in RAM with room for an application. A full router (FTD) all the same; Thread-only builds keep ST's complete library.

mediumC APIFTD only: no sleepy end devices (MTD / SED)

The device is always a full Thread device with its receiver on; battery end devices that sleep between polls are deferred.

lowC APINo ECC (PKA): ECJPAKE, ECDSA, DTLS unavailable

The prebuilt mbedTLS calls the ST HAL for the PKA; the SDK answers those calls with an error, so commissioning, SRP client keys and CoAP secure fail. AES (MAC and MLE security) runs on the AES peripheral.

lowC APINo CoAP / SRP / DNS / border routing wrappers

Present in the OpenThread library and callable through core_thread_instance() and the OpenThread headers, but not wrapped.

Tiles
mediumC APIHard cap of 4 cached PALs per bus type

Each bus type keeps its own table of 4 PALs. A fifth distinct bus of the same type gets the first bus's PAL back, so its tile driver silently talks to the first bus. No current Core has more than 4 buses of one type.

lowC APINo bus / address discovery

Tile drivers receive a bare tiles_pal_t* and a tile JSON; there's no wrapper here that walks coregen's tile_handles.h to enumerate "what tiles are on what bus." Each test builds the wiring by hand.

Timer
mediumDSLTick event period is set in config.json, not from DSL

The DSL's `Core.Timer.tick` event fires at the period baked into coregen from config.json's timer.tick_ms. There's no `Core.Timer.set_tick_ms()` host call to retune at runtime — the period is fixed for the life of the program.

mediumDSLNo DSL access to per-channel capture / PWM

core_timer_capture_init / capture_read / pwm_set are Tier 1 — they take a core_timer_t* the DSL can't construct. PWM has its own default-instance helper (Core.PWM.duty); capture / measurement has no DSL surface.

mediumC APINo encoder / quadrature mode

The hardware supports incremental encoder mode (CH1+CH2 quadrature counting). The wrapper exposes neither encoder init nor read. Motion / rotary-encoder tiles can't use it without dropping into ll_tim.

lowC APINo one-pulse mode (OPM)

STM32 timers can fire a single pulse of programmable width and then auto-disable — useful for camera trigger / strobe / ultrasound ranging. Not wrapped.

Timing
lowC APINo monotonic 64-bit clock

millis wraps at ~49.7 days. Long-running systems (industrial / datalogger) need either a 64-bit upcounter or a wrap-aware helper for diff-since-start.

USB
mediumDSLNo DSL surface for receive (byte read / available)

The Core.USB.receive event handles inbound bytes one at a time, and Core.USB.line delivers newline-terminated text commands, but DSL programs can't poll core_usb_available() / core_usb_read(). That makes binary message-framed protocols (read N bytes after a header) awkward — the workaround is to accumulate bytes in a DSL array inside the receive handler.

lowDSLNo DSL printf-with-formatting

print_int / float / bool emit one value per call, each on its own line. For multi-field log lines DSL programs concatenate with string ops (or call print multiple times). A `print_fmt(template, ...args)` host call would be the next step.

mediumC APIUSB MSC (mass storage)

SDK roadmap Tier 3: drag-and-drop firmware / datalog volume needs SCSI + FAT. A feature gap, not a workflow blocker — projects that need persistent storage today reach for NVM or SD via SPI.

mediumC APIUSB Host mode

Core.ST.H5 has DRD silicon but the wrapper is device-only. Most projects don't need host mode; the few that do (USB-keyboard / thumb-drive readers) drop into the lower-layer USB stack.

mediumC APINo CDC line-coding callback

Host-side baud changes (1200-touch bootloader trigger included) land in the lower stack. The header doesn't expose a hook for programs that want to react to baud / DTR changes.

USB HID
mediumDSLNo DSL surface for HID

Sending a HID report needs a buffer pointer + length. The DSL's array-host ABI (used for tile reads) could carry it, but no default-instance wrapper is wired up.

lowC APIVendor descriptor only

The HID descriptor is hard-coded as a 64-byte vendor report with usage page 0xFF00. No way to register custom reports (keyboard, mouse, gamepad) — that needs the full HID descriptor tooling.

Watchdog
lowDSLNo DSL access to caused_reset / clear_flags

Both stay C-only. The DSL reads the same answer from Core.Power.reset_reason() (2 = watchdog), which core_init() keeps for the whole run, so there is no "before studio_start" phase to model.

lowC APINo window watchdog (WWDG)

STM32 also has a windowed watchdog (must feed within a window, not just before the deadline). Useful for catching feed-too-fast bugs. Not wrapped here.

From the @studio unsupported notes in core_adc.h, core_backup.h, core_ble.h, core_dac.h, core_debug.h, core_fault.h, core_i2c.h, core_i3c.h, core_led.h, core_nvm.h, core_otp.h, core_pad.h, core_power.h, core_pwm.h, core_reset.h, core_rng.h, core_rtc.h, core_scope.h, core_serial.h, core_spi.h, core_stepper.h, core_thread.h, core_tiles.h, core_timer.h, core_timing.h, core_usb.h, core_usb_hid.h, core_watchdog.h — tiles@217a38f.