A modern CMake + C++20 firmware SDK for the Theta Machines G2 Nano — an NXP i.MX RT1171 (1 GHz Cortex-M7) robotics dev board — with TinyUSB, FreeRTOS, and drivers for the on-board sensors.
Unofficial / third-party. This is an independent firmware SDK for the G2 Nano hardware. It is not affiliated with or endorsed by Theta Machines. The hardware design is theirs (CERN-OHL-P-2.0); this firmware is MIT-licensed. The complete pin map here was extracted from the published KiCad netlist.
The G2 Nano ships as an open-hardware KiCad project with no firmware. This SDK
gives it a clean, turnkey bring-up: one cmake --preset pulls the NXP SDK,
TinyUSB, FreeRTOS and CMSIS, and builds a working image — no MCUXpresso IDE, no
manual SDK download, no vendor lock-in.
- Turnkey build —
FetchContentpulls every dependency at configure time. PointMCUX_SDK_ROOTat a local SDK to go fully offline. - i.MX RT1171 board support — 996 MHz clock tree, IOMUXC pin mux, and the W25Q64JW FlexSPI XIP boot header, all derived from the actual schematic.
- Modern C++ HAL — type-safe, zero-overhead
Gpio(+ interrupts),Uart(+ buffered RX),SpiBus,I2c,Can(CAN-FD),Rtc,Watchdog. - Sensor drivers — LSM6DSV 6-axis IMU and LIS2MDL magnetometer over the shared LPSPI5 bus, with data-ready and FIFO support.
- TinyUSB — high-speed CDC-ACM on the native USB-C (USB_OTG1).
- FreeRTOS — Cortex-M7 port, multi-task-safe newlib,
configASSERT, and C++Thread/Mutex/Queue/Semaphorewrappers. - Crash diagnostics — fault handlers dump the decoded exception state to the console; optional D-cache with an MPU non-cacheable DMA region.
- Reproducible builds — CMake presets, a Docker build image, and CI.
- On-board debug — flash & console over the built-in MKL26 CMSIS-DAP probe; no external hardware required.
Prerequisites: cmake ≥ 3.23, ninja, an arm-none-eabi-gcc
(brew install --cask gcc-arm-embedded), and pyocd to flash.
cd firmware
cmake --preset debug # fetches NXP SDK + TinyUSB + FreeRTOS + CMSIS
cmake --build --preset debug
cmake --build --preset debug --target flash-g2nano_demo # flash via CMSIS-DAPTwo apps are built:
| App | What it does |
|---|---|
blinky |
minimal board bring-up + LED blink + button on the console |
g2nano_demo |
FreeRTOS + native USB-CDC streaming live IMU/mag data |
See docs/flashing.md and docs/hardware.md.
A multi-arch container (native on x86-64 and Apple-Silicon) with the official Arm toolchain pinned:
docker build -t g2nano-sdk firmware
docker run --rm -v "$PWD/firmware:/work" g2nano-sdk # -> build/debug/apps/.../*.elf,.hex,.binfirmware/
├── cmake/ toolchain + FetchContent modules (SDK, TinyUSB, FreeRTOS)
├── board/ BSP: clocks, pin mux, XIP boot header, fault handlers, init
│ └── xip/ vendored NXP IVT/boot-data (BSD-3)
├── hal/ C++ HAL: gpio(+irq), uart(+buffered), spi, i2c, can, rtc, watchdog
├── drivers/ LSM6DSV IMU + LIS2MDL magnetometer (data-ready, FIFO)
├── usb/ TinyUSB config, descriptors, CDC facade
├── rtos/ FreeRTOSConfig + thread/mutex/queue/semaphore wrappers
├── wireless/ MAYA-W166 Wi-Fi/BT bring-up (power seq + SDIO; stack TODO)
├── motion/ RTMC-G2 motion controller over LPSPI1 (protocol TODO)
├── apps/ blinky, demo
└── Dockerfile reproducible multi-arch build environment
Verified: both apps compile and link cleanly with the Arm GNU Toolchain
15.2 (gcc 15.2.1) into bootable XIP images. The boot header was checked at the
byte level — FCB (FCFB) at 0x30000400, IVT (0x412000D1, entry =
Reset_Handler) at 0x30001000, vector table (SP = 0x20040000) at
0x30002000 — so the ROM boot path is structurally correct.
Because this was developed without the physical board, the following are correct by construction (datasheet/netlist) but not yet silicon-validated — verify before relying on them:
- Clock tree — 996 MHz ARM PLL; confirm by reading
SystemCoreClockand scoping a GPIO toggle. A wrong value is re-flashable via SWD, not bricking. - FlexSPI boot — ships the conservative single-line Fast-Read config that boots reliably; Quad I/O is one config change away (see the source).
- Sensor register configs — follow the ST datasheets;
WHO_AM_Ichecks gate bring-up so a wiring/mode error is reported, not silent.
Fully derived from authoritative sources (no guessing): the pin map (KiCad netlist), the boot header/IVT (NXP), and the peripheral driver APIs.
Not yet implemented (scaffolded with correct pins/clocks, drivers TODO): Wi-Fi/BT networking stack (USDHC2 + LPUART2 wired, needs the NXP IW612 blob) and the RTMC-G2 motion controller (LPSPI1 wired).
MIT (this firmware). Bundled/fetched components keep their own licenses — see
LICENSE. G2 Nano hardware © Theta Machines LLC, CERN-OHL-P-2.0.