Files
ZephCore/README.md
T
2026-03-04 22:51:44 +01:00

7.3 KiB

ZephCore — MeshCore for Zephyr RTOS

A port of MeshCore LoRa mesh firmware from Arduino to Zephyr RTOS. Aiming for full protocol compatibility with the original Arduino firmware and the MeshCore mobile apps.

Why Zephyr?

The Arduino version uses a loop(). This port replaces that with Zephyr's event-driven primitives (k_event_wait, k_poll, k_msgq), so the CPU sleeps in WFI (Wait For Interrupt) between events.

Other benefits:

  • Proper driver model -- LoRa, GNSS, display, sensors, and BLE all use Zephyr subsystem drivers rather than Arduino libraries
  • Hierarchical build configuration -- board-specific settings compose cleanly via Kconfig and devicetree overlays
  • DFU support -- generates Arduino compatible zip packages for OTA updates and UF2 binaries for drag-and-drop flashing
  • Back and forth compatible -- Adapted to softdevice and adafruit's bootloader, so no bootloader re-flashing required.

Supported Boards

nRF52840

Board Radio Extras
Wio Tracker L1 SX1262 GPS (L76KB), OLED (SH1106), joystick, buzzer, QSPI flash
Seeed T1000-E LR1110 GPS (AG3335), LEDs, button
RAK4631 SX1262 GPS (u-blox MAX-7Q), I2C sensors (SHTC3, LPS22HB, BME680)
RAK WisMesh Tag SX1262 GPS (AT6558R), accelerometer, RGB LEDs, buzzer
ThinkNode M1 SX1262 GPS, e-paper display (SSD1681), QSPI flash, buzzer, RGB LEDs
Ikoka Nano 30dBm SX1262 (E22-900M30S, 30dBm PA) RGB LEDs

ESP32

Board MCU Radio Extras
XIAO ESP32-C3 ESP32-C3 SX1262 BLE 5.0
XIAO ESP32-C6 ESP32-C6 SX1262 BLE 5.0, Wi-Fi 6
Station G2 ESP32-S3 SX1262 (+PA) OLED (SH1106), GPS, 16MB flash, 8MB PSRAM
LilyGo TLoRa C6 ESP32-C6 SX1262 BLE 5.0, Wi-Fi 6

Other

Board MCU Radio Extras
XIAO nRF54L15 nRF54L15 SX1262 FLPR multicore, RRAM storage
XIAO MG24 EFR32MG24 SX1262 BLE (SiLabs blob)

Device Roles

  • Companion (default) -- connects to MeshCore mobile apps via BLE
  • Repeater -- forwards packets, configured via USB serial CLI

Building

Prerequisites: Zephyr SDK and west installed.

# Initialize workspace (first time only)
cd %cloned folder%
west init -l zephcore
west update

# Companion (with logging)
west build -b wio_tracker_l1 zephcore --pristine

# Companion (production, no logging)
west build -b wio_tracker_l1 zephcore --pristine -- \
 -DEXTRA_CONF_FILE="boards/common/prod.conf"

# Repeater (with logging)
west build -b rak4631/nrf52840 zephcore --pristine -- \
  -DEXTRA_CONF_FILE="boards/common/repeater.conf"

# Repeater (production)
west build -b rak4631/nrf52840 zephcore --pristine -- \
  -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/prod.conf"

# Repeater with packet logging (clean RAW/RX/TX lines only, no debug spam)
west build -b rak4631/nrf52840 zephcore --pristine -- \
  -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/common/packet_logging.conf"

# Formatter (with serial logging)
west build -b wio_tracker_l1 zephcore/tools/formatter --pristine

# Companion (BLE debug logging)
west build -b rak4631/nrf52840 zephcore --pristine -- -DCONFIG_ZEPHCORE_BLE_LOG_LEVEL_DBG=y

Output binaries are in build/zephyr/ -- .hex, .uf2, and DFU .zip as applicable.

Architecture Overview

Mobile App  <--BLE (NUS)--> [ Companion ]  <--LoRa-->  Mesh Network
                                  |
                            k_event_wait()
                           /      |       \
                    LORA_RX   LORA_TX_DONE  BLE_RX

All code paths are event-driven. The CPU sleeps in WFI between events.

  • LoRa RX: Zephyr driver callback enqueues to a ring buffer and signals the mesh event loop
  • LoRa TX: A dedicated thread blocks on k_poll(), restarts RX on completion, then notifies the mesh loop
  • BLE: NUS write handler enqueues to k_msgq and signals the mesh loop; TX uses bt_gatt_notify_cb() chaining
  • USB: CDC-ACM with V3 binary framing protocol, frame timeout recovery
  • Main loop: k_event_wait() blocks until work arrives; housekeeping runs every 5s

Key Differences from Arduino

Arduino Zephyr
Main loop 50ms polling k_event_wait() (blocks until event)
LoRa TX Blocking transmit() Async thread with k_poll()
BLE queues Ring buffer + mutex k_msgq (lock-free, ISR-safe)
Drivers Arduino libraries Zephyr subsystem drivers
Configuration #define constants Kconfig + devicetree
Threading Single-threaded loop() Multi-threaded with explicit sync
Power Always-on loop WFI sleep between events

Power Saving

  • LoRa RX duty cycle: CAD-based receive windowing reduces LoRa RX current from ~10-15mA to ~3-5mA (configurable via CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE)
  • USB disabled in production: Saves ~2-5mA and 62KB flash when logging is off
  • GPIO-gated GPS: Powered on only during fix acquisition

Configuration

Key Kconfig options (set in board configs or via -D flags):

Option Default Description
CONFIG_ZEPHCORE_ROLE_COMPANION y BLE companion mode
CONFIG_ZEPHCORE_ROLE_REPEATER n USB CLI repeater mode
CONFIG_ZEPHCORE_RADIO_NATIVE y SX126x, SX127x, LLCC68, STM32WL
CONFIG_ZEPHCORE_RADIO_LR1110 n LR1110/LR1120/LR1121 (custom driver)
CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE n CAD-based RX power saving (enabled on WisMesh Tag, ThinkNode M1)
CONFIG_ZEPHCORE_MAX_CONTACTS 350 Contact storage slots (companion)
CONFIG_ZEPHCORE_MAX_CHANNELS 40 Channel slots (companion)
CONFIG_ZEPHCORE_BLE_PASSKEY 123456 BLE pairing PIN
CONFIG_ZEPHCORE_GPS_POLL_INTERVAL_SEC 300 GPS fix interval (seconds)
CONFIG_ZEPHCORE_WIFI_OTA n WiFi AP + HTTP OTA updates (ESP32 repeaters)
CONFIG_ZEPHCORE_PACKET_LOGGING n Arduino-compatible mesh packet logging
CONFIG_ZEPHCORE_HOUSEKEEPING_INTERVAL_MS 5000 Periodic maintenance interval

Project Structure

zephcore/
  src/              Main entry points and core mesh protocol
  app/              Companion and repeater role implementations
  adapters/
    ble/            BLE NUS transport
    board/          GPIO, LED, power management
    clock/          Millisecond and RTC clocks
    datastore/      LittleFS filesystem wrapper
    gps/            GPS/GNSS drivers
    ota/            WiFi OTA firmware updates
    radio/          LoRa radio drivers (SX126x, LR1110)
    rng/            Random number generator
    sensors/        I2C sensor auto-detection
    usb/            USB serial transport (CDC-ACM, V3 framing)
  helpers/
    ui/             Display, buzzer, button input
  boards/
    nrf52840/       nRF52840 board overlays and configs
    esp32/          ESP32-C3/C6/S3 board overlays and configs
    nrf54l/         nRF54L15 board overlay and config
    mg24/           EFR32MG24 board overlay and config
    common/         Shared Kconfig fragments and devicetree includes
  lib/              ED25519 crypto library
  patches/          Auto-applied patches to the Zephyr tree

License

Same license as the upstream MeshCore project.