---
name: emb-c-rtos
description: Use for C firmware — Zephyr, FreeRTOS, ESP-IDF, ISRs, linker scripts, stack budgets.
---
# C firmware and RTOS

Safety gates and baseline rules: `embedded-firmware`. Language rules: `cpp-engineering`; CMake: `cmake-ninja-builds`.

## Versions
- Zephyr 4.4.2 — Verified 2026-10-02 https://github.com/zephyrproject-rtos/zephyr/releases/latest
- ESP-IDF 6.1 — Verified 2026-10-02 https://github.com/espressif/esp-idf/releases/latest
- FreeRTOS-Kernel V11.3.1 — Verified 2026-10-02 https://github.com/FreeRTOS/FreeRTOS-Kernel/releases/latest
- Zephyr board names, Kconfig symbols and devicetree bindings change between minors: read the release's migration guide before bumping `west.yml`.

## Zephyr
- Workspace: `west init -m <manifest-url> --mr <tag> ws && cd ws && west update`; app outside the tree with its own `west.yml` (T2 topology) for real projects.
- Build: `west build -b <board>[/<soc>] app -p auto`; configuration in `prj.conf` (Kconfig) plus `boards/<board>.overlay` (devicetree); `west build -t menuconfig` / `guiconfig` to explore; never edit generated files under `build/`.
- Host-first: the `native_sim` board runs the app as a Linux process (POSIX arch; not on macOS — use a Linux container) and `qemu_cortex_m3`/`qemu_x86` boards run in QEMU (`west build -t run`).
- Tests: ztest suites under `tests/`, run with `west twister -T tests -p native_sim` (and `-p qemu_cortex_m3`).
- Size: `west build -t rom_report` / `ram_report`; thread stacks sized from `CONFIG_THREAD_ANALYZER` output, not guessed.
- Drivers use the device model (`DEVICE_DT_GET`, `device_is_ready`) and devicetree macros; never hard-code register addresses the devicetree already describes.

## FreeRTOS
- `FreeRTOSConfig.h`: `configASSERT` defined, `configCHECK_FOR_STACK_OVERFLOW 2`, `configUSE_MALLOC_FAILED_HOOK 1` in dev; static allocation (`configSUPPORT_STATIC_ALLOCATION`) where the heap must be predictable.
- Only `...FromISR` APIs inside ISRs, finishing with `portYIELD_FROM_ISR(xHigherPriorityTaskWoken)`.
- Cortex-M: ISRs that call FreeRTOS APIs must have a priority numerically ≥ `configMAX_SYSCALL_INTERRUPT_PRIORITY` (lower urgency); `NVIC_SetPriorityGrouping(0)` on STM32 HAL projects. A wrong priority gives assert failures or random corruption.
- Mutexes (priority inheritance) for shared resources, binary semaphores or task notifications for signalling, queues for data; never a mutex from an ISR.
- Check stacks with `uxTaskGetStackHighWaterMark` under worst-case load; heap with `xPortGetMinimumEverFreeHeapSize`.

## ESP-IDF
- `idf.py set-target <chip>`, `idf.py menuconfig`, `idf.py build`, `idf.py size` / `size-components`; components with `idf_component.yml` from the component registry, versions pinned (`dependencies.lock` committed).
- Partition table (`partitions.csv`) sized for OTA (two app slots + otadata) before the first field release; changing it later needs a serial reflash.
- Secure boot V2 and flash encryption burn eFuses: irreversible. Development mode first on a sacrificial board, release mode only with the user's explicit consent per device. `espefuse summary` is read-only and fine; every eFuse burn command is a consent gate.
- QEMU: `idf.py qemu` runs supported targets on Espressif's QEMU fork (target list is limited — check the IDF docs for the version in use).

## Bare-metal and vendor SDK rules
- Startup and linker script: vector table placement, `.data` copy and `.bss` zero before `main`, stack and heap symbols, sections for DMA buffers and no-init RAM; read the map file (`-Wl,-Map=fw.map`) after every linker change.
- `volatile` for MMIO and ISR-shared flags only; it is not a synchronization primitive — use critical sections (`__disable_irq`/PRIMASK save-restore) or C11 atomics where the core supports them.
- Compiler flags: `-ffunction-sections -fdata-sections -Wl,--gc-sections`, `-Wall -Wextra -Werror` on project code, `-fstack-usage` + `-Wstack-usage=<n>` to bound stacks; LTO only after the build is stable.
- Vendor HAL code generated by CubeMX/MCUXpresso/etc. stays in its regions (`USER CODE BEGIN/END`) so regeneration keeps edits.
- Coding standard: MISRA C:2012/2023 or CERT C when the project names one; check with cppcheck (MISRA addon) or the vendor's checker and record deviations with reasons.

## Pitfalls
ISR priority vs RTOS syscall priority; printf from ISRs; stack overflow silently corrupting neighbors; missing `volatile` on a polled flag (loop optimized away); cache coherency with DMA on Cortex-M7 (clean/invalidate by address, 32-byte aligned buffers); unaligned access faults on M0; watchdog not fed during long flash erases.

## Verify
Host or `native_sim` tests pass · Twister/QEMU run green · warnings-as-errors build · stack high-water marks and heap minimum logged under load · size within budget · map file checked after linker changes.
