Skip to content

Board Support Packages

The Board Support Packages super-module groups everything under boards/ — the per-board adaptations that let a single firmware codebase run on 18 different hardware targets, from headless WiFi-to-serial bridges and 1.47” status displays to full-featured touchscreen pendants.

Each board directory follows a common three-layer structure:

  • components/bsp/ — the hardware abstraction consumed by the main firmware: board_init.c / board_config.h implement a common C interface (display panel configuration, LVGL setup, touch/button/encoder input registration, backlight and activity management) so the application layer never touches hardware directly.
  • Factory/ — a standalone recovery application flashed to a dedicated factory partition. It can boot OTA partitions, flash esp3dfw.bin firmware and ui_resources.bin from an SD card, and restore otadata so a failed update always rolls back safely. It is deliberately minimal (self-contained C drivers, no LVGL, no esp3d framework).
  • build_scripts/ — Python tooling (build_one.py, variants.py, common.py) that assembles the per-board firmware variants (flash size, transport options) and produces flashable packages.

Related super-modules:


recovery button held at boot

flash esp3dfw.bin / ui_resources.bin from SD

assemble & package

Main firmware

(ESP3DX::begin)

components/bsp

board_init() - common C interface

Hardware Peripheral Drivers

(display / touch / input / bus)

Factory recovery app

(factory partition)

Custom bootloader

(otadata backup → recovery entry)

build_scripts

Python variant builder

Full pendants (display + touch + physical controls)

BoardDisplayBusTouchExtra inputs
pibot_pendant_v1_0 (ESP32)ILI9341 320×240SPIFT6336U3 buttons, rotary encoder, 4-pos switch, potentiometer, buzzer

Display + touch boards (touch-only input)

BoardDisplayBusTouch
dlc32_max_lcd (ESP32)ST7796 3.5″ 480×320SPIcapacitive
esp32_2432s028r “CYD” (ESP32)ILI9341 2.8″SPIXPT2046 resistive
esp32_3248s035c (ESP32)3.5″ IPSSPIGT911 capacitive
esp32_3248s035r (ESP32)3.5″SPIXPT2046 resistive
esp32s3_4827s043cILI9485 4.3″ 480×272RGB parallelGT911
esp32s3_8048s043cST7262 4.3″ 800×480RGB parallelGT911
esp32s3_8048s050cST7262 5″ 800×480RGB parallelGT911
esp32s3_8048s070cEK9716 7″ 800×480RGB parallelGT911
esp32s3_8048_touch_lcd_7ST7262 7″ 800×480RGB parallelcapacitive (SD CS via CH422G expander)
esp32s3_bzm_tft35_gt911ST7796 3.5″ 480×320SPIGT911
esp32s3_hmi43v3RM68120 4.3″ 800×480I80FT5x06 (+ TCA9554 IO expander)
esp32s3_zx3d50ce02s_usrc_4832ST7796 3.5″ 480×320I80FT5x06

Small status displays (Small UI tier, ESP32-S3, 16 MB flash + PSRAM)

BoardDisplayTouchUI
ESP32_S3_TOUCH_LCD_1_47 (Waveshare ESP32-S3-Touch-LCD-1.47)JD9853 1.47” 172×320, SPIAXS5106LBasic read-only dashboard (UI_TIER=SMALL, see UI_Framework_&_Screens)
ESP32_S3_LCD_1_47B (Waveshare ESP32-S3-LCD-1.47B)ST7789 1.47” 172×320, SPInone (BOOT key = page button)Same basic dashboard

Both boards: SD card over SDIO 4-bit, native USB with optional USB CDC device client (sdkconfig.usb_cdc_device), one build variant (16mb_wifi_fluidnc), no factory app. A BOARD_DISPLAY_TEST option runs a hardware bring-up test of the LCD (and touch) from board_init() instead of the UI. No codewiki page per board yet (added after the generation).

Headless bridges (no display, no LVGL)

BoardRole
esp32_c3_bare (ESP32-C3)Minimal WiFi-to-serial bridge between a CNC controller (UART) and a remote Web UI
esp32_s3_wroom_cam (ESP32-S3, 16 MB flash / 8 MB PSRAM)WiFi CNC bridge with optional camera streaming, USB OTG
fysetc_wifi_proWiFi bridge module; BSP is a minimal stub satisfying the common interface

All display boards ship a recovery stack with two variants of increasing sophistication:

  1. Simple factory app (most boards): a self-contained menu driven by touch (or buttons) that flashes firmware and UI resources from SD card and manages OTA partition selection — see for example esp32s3_8048s050c_factory.
  2. Custom bootloader + factory app (pibot_pendant_v1_0_bootloader + pibot_pendant_v1_0_factory_app): holding a button at boot makes the bootloader back up otadata to a raw flash sector, erase it, and jump to the factory partition; the factory app restores otadata on exit, so a power cut mid-recovery can never brick the device.

RGB-parallel boards additionally need bsp_accessFs / bsp_releaseFs guards to arbitrate SD-card vs. display access on the shared bus; SPI-display boards (e.g. pibot) do not.

The two 1.47” boards have no factory app (FACTORY_VARIANTS = {} in their variants.py).

PiBot 8 MB layout since a14: two 3 MB OTA slots (app0 0x20000, app1 0x320000), ui_resources 256 KB at 0x620000, flashfs 0x660000; the factory image is flashed at 0x780000 (see pibot_pendant_v1_0_factory_app).


Every board carries a build_scripts/ package (build_one.py, common.py, variants.py) that drives idf.py through the board’s variant matrix — flash size (4/8/16 MB), transport (serial, BT serial, BLE), and target firmware (FluidNC / grblHAL / grbl) — then assembles flashable packages. The shared logic (clean build dirs, size reports, flash maps, installer directories) lives in each board’s common.py, mirroring the repository-wide tooling documented in tools_build_scripts.


  • LVGL 9.6: its Kconfig defaults LV_CONF_SKIP to y, which would ignore each board’s tuned components/bsp/lv_conf.h (LV_MEM_SIZE, feature set sized to the board DRAM budget) and fall back to LVGL’s much larger defaults. Every display board’s main sdkconfig.* sets CONFIG_LV_CONF_SKIP=n (headless boards have no LVGL).
  • System event task stack raised from 2048 to 3072 bytes in the WiFi sdkconfig files (PiBot, dlc32_max_lcd).
  • Factory postbuild.cmake: app now depends on the bootloader sub-build, because the post-build step copies bootloader.bin and a clean build could run the copy first and fail.