| boot_manager.py | ||
| main.py | ||
| README.md | ||
| st7789py.py | ||
ESP32-C6 Multi Boot Manager
A graphical boot manager for the Lafvin / Waveshare ESP32-C6 1.47" LCD board, written in MicroPython. Load multiple firmware files and choose which one to run at startup - no cable required after the initial setup.
No equivalent project exists for this specific board combination.
Features
- Graphical menu - scrollable firmware list with selection cursor on the 172×320 ST7789 display
- Auto-boot - remembers the last selected firmware and launches it on next power-on
- 5-second countdown - press BTN_A during countdown to abort and return to menu
- Force menu - hold BTN_A at boot to skip auto-launch and go straight to menu
- SD card support - automatically uses
/sd/boot/if an SD card is present, falls back to/boot/on internal flash - Large file support - firmware > 40 KB is launched via
reset()+ flag file for maximum available RAM - RGB LED feedback - NeoPixel WS2812 color-codes every action
- Auto-refresh - menu re-scans the firmware folder every 15 seconds (useful when adding files over Wi-Fi)
Hardware
| Board | Display | Tested |
|---|---|---|
| Lafvin ESP32-C6 1.47" LCD | ST7789 172×320 | ✅ |
| Waveshare ESP32-C6 1.47" LCD | ST7789 172×320 | ✅ (same pinout) |
Pin mapping
SCL = 7 SDA = 6 RST = 21 DC = 15
CS = 14 BLK = 22 LED = 8 (WS2812 RGB)
BTN_A = 9 BTN_B = 10
SD: SCK=4 MOSI=3 MISO=2 CS=5
Requirements
- MicroPython v1.23+ for ESP32-C6
st7789py.pydisplay driver (pure Python, included)sdcard.pyMicroPython driver (only if using SD card)
Installation
1. Flash MicroPython
Download the latest ESP32-C6 firmware from micropython.org/download/ESP32_GENERIC_C6
Flash via espboards.dev (browser-based, no install needed):
- Connect the board while holding BOOT
- Click Connect → select the COM port
- Click Erase Flash
- Upload the
.binfile → address0x0→ Flash
2. Upload files
Using Thonny (recommended) or mpremote:
pip install mpremote
mpremote cp st7789py.py :st7789py.py # upload driver first
mpremote cp boot_manager.py :main.py # boot manager as main
3. Create the folder structure
From the MicroPython REPL (Thonny shell):
import uos
uos.mkdir("/lib")
uos.mkdir("/boot")
4. Upload shared libraries to /lib/
Copy any modules used by your firmware into /lib/:
mpremote cp st7789py.py :/lib/st7789py.py
mpremote cp pager_core.py :/lib/pager_core.py
# ... any other shared modules
5. Upload your firmware files to /boot/
mpremote cp my_app.py :/boot/my_app.py
mpremote cp another_app.py :/boot/another_app.py
Important: rename each firmware's entry point to a descriptive name -
e.g. pager.py, scanner.py, dashboard.py.
Final structure
/ ← internal flash root
├── main.py ← boot manager (this file)
├── /lib/ ← shared libraries
│ ├── st7789py.py
│ ├── pager_core.py
│ └── ...
└── /boot/ ← firmware files
├── pager.py
├── scanner.py
├── .selected ← written automatically
└── .launch ← written automatically for large files
If an SD card is present it is mounted at /sd and /sd/boot/ is used instead.
Usage
Controls
| Button | Action |
|---|---|
| BTN_A short | Next firmware in list |
| BTN_A long (> 600 ms) | Set selected firmware as default (green dot) |
| BTN_B | Launch the default firmware (or selected if no default) |
| BTN_A held at boot | Force menu - skips auto-launch |
Workflow
- Power on → splash screen with RGB LED rainbow test
- If a default firmware is set → 5-second countdown
- Do nothing → firmware launches automatically
- Press BTN_A → return to menu
- In the menu:
- BTN_A to scroll through the list
- BTN_A long to set the highlighted firmware as default (● dot turns green)
- BTN_B to launch
Adding a new firmware
- Copy your
.pyfile to/boot/(or/sd/boot/) - The menu refreshes automatically within 15 seconds
- Select it and press BTN_A long to make it the new default
Shared libraries
Any module imported by your firmware must be available on the device.
Place shared modules in /lib/ - MicroPython searches there automatically.
# in your firmware file - these imports work if the module is in /lib/
import st7789py
from pager_core import BLEPager
import cookie_monster
If a firmware has a conflicting version of a shared library (e.g. a different
st7789py), rename it to something unique (st7789_myapp.py) and update the
import inside your firmware file accordingly.
RGB LED color codes
| Color | Event |
|---|---|
| Red → Green → Blue → Cyan → Purple | Boot rainbow test |
| Blue (2 flashes) | Firmware set as default |
| Green (1 flash) | Scroll / navigation |
| Green (solid) | Firmware launched successfully |
| Red (2 flashes) | Launch error |
Firmware compatibility
Any MicroPython .py file that runs standalone can be used as a firmware.
The boot manager launches it via exec() (small files) or reset() + flag
file (files > 40 KB) to maximise available RAM.
Tested firmware:
| Firmware | Description |
|---|---|
| Cookie Monster Scanner | WiFi + BLE wardriver |
| WiFi Hunter | Open WiFi scanner |
| BLE Pager | Encrypted peer-to-peer BLE messenger |
| rCompanion | Reticulum Network Stack companion display for esp32c6 |
Troubleshooting
| Problem | Solution |
|---|---|
| Menu shows "no firmware found" | Check that .py files are in /boot/ not in / |
| Firmware crashes on launch | Check that all imported modules are in /lib/ |
MemoryError on launch |
File is large - boot manager automatically uses reset() method |
| SD card not detected | Verify SD pin mapping matches your board; check sdcard.py is in /lib/ |
| Display offset / wrong colors | Adjust x_start / y_start in the ST7789() constructor |
| Can't return to menu | Hold BTN_A while pressing RST to force menu at next boot |
License
MIT - free to use, modify and redistribute.
Author
fr33n0w - github.com/fr33n0w/esp32c6-multiboot