Files
meshtastic_firmware/variants/nrf52840/diy/moonshine_NRF52_mini/readme.md
T
2026-07-19 17:46:04 +08:00

5.4 KiB

Moonshine NRF52 Mini

Minimal DIY Meshtastic node variant: nRF52840 + RA-01S-P (SX1262) LoRa module with a single status LED on P0.15. No display, GPS, button, or battery ADC - LoRa-only minimal system.

Tested on a nice!nano board (nRF52840, S140 SoftDevice v6.1.1, Adafruit UF2 bootloader 0.9.2). Also compatible with any nRF52840 board that has the Adafruit UF2 bootloader with S140 v6.x SoftDevice (e.g. Adafruit Feather nRF52840 Express factory bootloader).

Hardware

  • MCU: nRF52840 (512 KB flash / 128 KB RAM)
  • LF clock: external 32.768 kHz crystal (USE_LFXO)
  • LoRa: Ai-Thinker RA-01S-P (SX1262, no TCXO, internal RF switch, 22 dBm max)
    • SX126X_MAX_POWER=22
    • TCXO_OPTIONAL (no TCXO on module - firmware tries XTAL first)
    • DIO2 drives TXEN internally; RXEN is controlled by P0.17
  • LED: status LED on P0.15 (active high, LED_STATE_ON = 1)

Pin map

Function Pin Notes
SPI_MISO P0.02 LORA_MISO
LORA_RESET P0.09 SX126X_RESET
LORA_DIO1 P0.10 SX126X_DIO1 (IRQ)
LED P0.15 Status LED (active high)
LORA_RXEN P0.17 SX126X_RXEN
LORA_BUSY P0.29 SX126X_BUSY
SPI_SCK P1.11 LORA_SCK
LORA_CS P1.13 SX126X_CS
SPI_MOSI P1.15 LORA_MOSI

Only the status LED on P0.15 is wired (no button, battery ADC, GPS, or display). The board has no user button, so DFU entry is via double-tap reset or the 1200 bps touch.

Build & Flash

Build

pio run -e moonshine_NRF52_node_mini

Uses PRIVATE_HW (HardwareModel 255) - no protobuf or architecture.h changes required.

The build inherits the default v6 ldscript from [nrf52840_base] (src/platform/nrf52/nrf52840_s140_v6.ld), so the application is linked to start at 0x26000 and requires the S140 SoftDevice v6.x to be present on the chip at 0x0-0x25FFF. The Adafruit nRF52 UF2 bootloader bundles its own SoftDevice (v6.1.1 on the nice!nano), so if UF2 mode works the SoftDevice is already present. The build output (firmware-*.hex / .uf2) contains only the application, not the SoftDevice.

Prerequisite: the board has the Adafruit UF2 bootloader installed (factory default on nice!nano and Adafruit Feather nRF52840 Express). Confirm by entering UF2 mode and reading INFO_UF2.TXT on the bootloader USB volume - it should show SoftDevice: S140 6.1.1 (or similar v6.x).

First-time install (clean flash):

  1. Double-tap the Reset button to enter UF2 bootloader mode. A USB mass storage volume appears (e.g. NICENANO or FTHR840BOOT).
  2. Drag-and-drop bin/Meshtastic_nRF52_factory_erase_v3_S140_6.1.0.uf2 onto the volume. This erases any stale LittleFS/NodeDB/config from a prior firmware. The board reboots when the copy completes.
  3. Double-tap Reset again to re-enter UF2 mode.
  4. Drag-and-drop .pio/build/moonshine_NRF52_node_mini/firmware-moonshine_NRF52_node_mini-*.uf2 onto the volume. The board reboots into Meshtastic.

App-only update (SoftDevice already present, config already clean):

Skip steps 2-3 above - just double-tap Reset and drag-and-drop the application .uf2.

Flash via SWD (for a bare nRF52840 without bootloader)

A factory-fresh nRF52840 has no SoftDevice and no bootloader. The SoftDevice must be flashed once via SWD before the application; otherwise Bluefruit.begin() fails, sd_flash_* calls (LittleFS, NodeDB, config persistence) return errors, and the node appears dead.

For a v6 SoftDevice layout, use the combined bootloader+SoftDevice hex at bin/generic/Meshtastic_6.1.0_bootloader-0.9.2_s140_6.1.1.hex (this installs both the UF2 bootloader and the SoftDevice in one SWD pass, enabling UF2 updates thereafter). Flash via SWD with OpenOCD (CMSIS-DAP / J-Link / ST-Link). The nrf52_recover command does a chip-wide ERASEALL through the nRF52 CTRL-AP and clears APPROTECT, so it is the recommended first step on a fresh module (ebyte/Raytac modules ship with APPROTECT engaged).

# Full flow: recover (erase all + unlock) -> bootloader+SoftDevice -> app -> reset
C:/openocd/bin/openocd.exe -s C:/openocd/share/openocd/scripts \
  -f interface/cmsis-dap.cfg -f target/nrf52.cfg \
  -c "init; nrf52_recover; \
      program bin/generic/Meshtastic_6.1.0_bootloader-0.9.2_s140_6.1.1.hex verify; \
      program .pio/build/moonshine_NRF52_node_mini/firmware-moonshine_NRF52_node_mini-*.hex verify; \
      reset run; exit"

Notes

  • The firmware hex/uf2 filename contains a commit hash (e.g. 2.8.0.fbbfcf0); use the actual file produced by pio run or a shell glob.
  • The combined bootloader+SoftDevice hex occupies 0x0-0x26000 and does not write UICR, so nrf52_recover is safe (UICR resets to defaults).
  • Swap interface/cmsis-dap.cfg for interface/jlink.cfg or interface/stlink.cfg if using a different SWD probe.
  • To switch to the S140 v7 SoftDevice (app start at 0x27000, slightly larger app region), add board_build.ldscript = src/platform/nrf52/nrf52840_s140_v7.ld to platformio.ini and flash bin/generic/Meshtastic_7.3.0_bootloader-0.9.2_s140_7.3.0.hex via SWD. The v6 SoftDevice cannot be upgraded via UF2 - SWD is required.