Skip to content
 
 

Repository files navigation

Meshtastic OTAFIX Bootloader

Build License: MIT

Adafruit nRF52 bootloader with enhanced OTA DFU, forked for Meshtastic from oltaco's OTAFIX bootloader. This is the bootloader several nRF52-based Meshtastic devices ship with, and the one the Meshtastic Android app can upgrade in-app.

Current release: OTAFIX 2.5 — see changelog.md for version history.

Contents


How this fits together

This repo builds only the bootloader — the small program that runs before anything else on the device. It does not contain the Meshtastic application (the LoRa mesh, BLE, and display code); that's built entirely separately in meshtastic/firmware. This bootloader's job is just to start that application, or, when asked, replace it (or itself) with a new version.

On every power-up or reset, a tiny fixed piece of code at the very start of flash — Nordic's MBR — hands off to this bootloader. From there, the bootloader either:

  • boots straight into the installed Meshtastic application, or
  • if no valid application is installed, or the user has asked for it, waits for a new one.

A new application image — or occasionally the bootloader itself — can be installed three different ways:

Method Transport Typical use
UF2 drag-and-drop USB, appears as a drive Manual flashing — see Installation
Serial DFU USB, appears as a serial port Recovery, and flashing a full bootloader+SoftDevice package with adafruit-nrfutil — see Installation
BLE OTA DFU Bluetooth, no cable needed The Meshtastic Android app's firmware/bootloader update, and any Nordic DFU app — see below and recommended settings

There is also one thing the UF2 drive accepts that is not an image: the factory-erase file, which wipes the application's saved data in place and leaves everything else alone.

BLE OTA DFU is the only wireless path, which is what the "OTA" in "OTAFIX" refers to — and it's also the bootloader's default fallback: since OTAFIX 2.0, if no valid application is present, the device waits in BLE OTA mode automatically rather than risk getting stuck (see Troubleshooting).

The application also relies on Nordic's SoftDevice — a closed-source, precompiled Bluetooth stack (vendored here as a hex blob under lib/softdevice/) that sits in flash alongside it. The bootloader and the application both call into it for BLE, so bootloader and SoftDevice versions are usually flashed together as a matched pair (that's why the Installation instructions below mention flashing "a full bootloader and SoftDevice zip package").


Boards supported

  • Elecrow ThinkNode M1
  • Elecrow ThinkNode M3
  • Elecrow ThinkNode M6
  • Heltec T096
  • Heltec T1
  • Heltec T114 / HT-nRF5262
  • LilyGO T-Echo
  • Minewsemi MX25LE01
  • MuziWorks Base Uno / Base Duo / Superbase
  • Nologo ProMicro NRF52840 (aka SuperMini NRF52840)
  • RAK 3401
  • RAK 4631 (See note)
  • RAK WisMesh Tag
  • Seeed Studio SenseCAP Card Tracker T1000-E
  • Seeed Studio SenseCAP MeshTracker X1 (See note)
  • Seeed SenseCAP Solar Node P1
  • Seeed Studio Wio Tracker L1
  • Seeed Studio XIAO nRF52840 BLE (See note)
  • Seeed Studio XIAO nRF52840 BLE SENSE

If there is another nRF52840-based Meshtastic board you would like to see supported, please raise a GitHub issue — or see Adding a new board in CONTRIBUTING.md if you want to submit it yourself.

BLE advertising names

When in OTA DFU mode, devices advertise using a board-specific name rather than the generic AdaDFU.

Board OTA DFU advertising name
Elecrow ThinkNode M1 TNM1_DFU
Elecrow ThinkNode M3 TNM3_DFU
Elecrow ThinkNode M6 TNM6_DFU
Heltec T096 T096_DFU
Heltec T1 T1_DFU
Heltec T114 T114_DFU
LILYGO T-Echo LGTE_DFU
Minewsemi MX25LE01 MX25_DFU
MuziWorks Base / Superbase MUZI_DFU
ProMicro NRF52840 PROM_DFU
RAK 4631 4631_DFU
RAK 3401 3401_DFU
RAK WisMesh Tag RTAG_DFU
Seeed MeshTracker X1 MTX1_DFU
Seeed SenseCAP Solar Node P1 SCAP_DFU
Seeed T1000e T1KE_DFU
Seeed WioTracker L1 WTL1_DFU
XIAO NRF52 BLE / SENSE XIAO_DFU

Installation

The recommended way to install the bootloader is using the UF2 file.
Download the UF2 file for your board (they can be found in the releases with filenames beginning with update-), enter UF2 mode (usually by double pressing the reset button within 0.5s) and copy the UF2 file across.

If an incorrect bootloader has been flashed to the device, a full bootloader and SoftDevice zip package will need to be flashed using adafruit-nrfutil.

Factory erase

To wipe the device's saved data — config, node DB, keys, BLE bonds — without a serial terminal or a special erase firmware: enter UF2 mode and copy meshtastic_factory_erase.uf2 (also attached to every release) onto the drive. The bootloader erases the application's data region, then reboots straight back into UF2 mode so you can copy the firmware across next. The application itself is left in place, so if you unplug instead, it boots factory-fresh. Copy this file on its own: the drive detaches about half a second after the copy finishes (or as soon as you eject it) and comes back a second or two later.

The file is the same for every board. It is a single UF2 block with family ID 0x4D455348 and no payload; a bootloader that predates this feature ignores it silently — check INFO_UF2.TXT on the drive for a Factory-Erase: line to know whether yours supports it. Regenerate it with tools/make_factory_erase_uf2.py (or make factory-erase-uf2).


Bootloader upgrade from the Meshtastic Android app

The Meshtastic Android app can flash this bootloader directly — no manual UF2 drag-and-drop needed.

With the radio connected over USB/serial (not Bluetooth), open the connected radio's configuration, go to Advanced → Firmware Update, and where an upgraded bootloader is published for your board you'll see an Upgrade bootloader option alongside Erase and reinstall. The app reads INFO_UF2.TXT from the device's update drive first to confirm the board and Bluetooth stack before writing anything, and will ask you to select the update drive twice — once for the bootloader image, once for the firmware. See the app's Firmware Updates guide for the full flow.


Troubleshooting

Device does not appear as a USB drive or serial port

If the device does not show up on your computer after flashing the bootloader or performing an OTA update, it may be waiting in OTA DFU mode.

In OTAFIX 2.0 and above, OTA DFU is the default state when no valid application is present.
In this mode:

  • No UF2 drive is exposed
  • No serial port is available
  • The device is waiting for an OTA firmware update over BLE

What to do:

  • Perform an OTA update using a supported DFU app, or
  • Explicitly request UF2/serial mode using double-reset.

This behaviour is intentional and prevents devices from getting stuck in UF2 mode after failed OTA updates.


OTA update fails with Error: Operation Failed

If an OTA update consistently fails early with Error: Operation Failed, this is often caused by BLE stack incompatibilities when Request High MTU is enabled.

What to try:

  • Experiment with different PRN settings — try 12, 8, 1, or off altogether.
  • Disable Request High MTU in the DFU app.

While high MTU significantly improves performance on supported devices, it is not required for a successful OTA update.


Recommended OTA DFU settings

To perform the OTA update, use nRF Device Firmware Update
(Android / iOS)
or nRF Connect
(Android / iOS).

nRF Device Firmware Update is the recommended app of the two.

For OTAFIX 2.0 and later, the following settings are recommended (these may change — feel free to experiment and report findings via a GitHub issue):

Packet Receipt Notification (PRN): ON
Number of packets: 30
Reboot time: 0ms
Scan timeout: 2000ms
Request high MTU: ON for Android (see notes below) / not available on iOS
Disable resume: ON
Prepare object delay: 0ms
Force scanning: ON
Keep bond: OFF
External MCU DFU: OFF

Notes:

  • Some Android devices and BLE stacks do not behave well with Request high MTU enabled.
    If the transfer fails early with ERROR: Operation Failed, retry with Request high MTU turned OFF.
  • For maximum speed, Packet Receipt Notification can be disabled, and the number of packets increased.
    Android is generally more tolerant of higher values; on iOS and other small-packet hosts, values above ~60 are not recommended.

Recommended settings for versions prior to 2.0 can be found here.

IMPORTANT:
On older versions of the bootloader, performing an OTA update while the device was connected to a computer USB host would complete successfully but would not automatically boot into the new application firmware, requiring a manual reset.
This issue is fixed in OTAFIX 2.0.


Notes on Xiao NRF52840 BLE

Many of these boards are shipped with the Sense version of the bootloader installed. If your board has the Sense version installed you must use the Sense version when updating via UF2.

You can look at the INFO_UF2.TXT file on the UF2 drive to check what version is currently installed.

To check:

  1. Enter UF2 DFU mode (double-press reset)
  2. Open the INFO_UF2.TXT file on the mounted drive

If the file shows: "Board-ID: nRF52840-SeeedXiaoSense-v1" then the SENSE variant must be used if updating via UF2 file.

Notes on RAK4631 bootloader

This version of the RAK4631 bootloader is based on a much newer version (0.9.2) of the Adafruit nRF52 bootloader than what RAK Wireless uses on their official bootloader (0.6.2-11). It has been tested with no problems found; whether RAK's own patches to the Adafruit bootloader introduce any behavioral difference has not been investigated. A variant of the official RAK bootloader with these patches included instead is available here.

Notes on MeshTracker X1 DFU mode

The X1 has a single user button, and its RESET line is not exposed as a second button, so double-press reset does not work on this board. Instead, hold the primary button down while the device boots: keep holding for about 3 seconds and the bootloader enters UF2 DFU mode and mounts the mass-storage drive. Releasing the button before then boots the application as normal.

Because a momentary press belongs to the application, a short press will not enter DFU — it has to be an uninterrupted hold through boot.

To leave DFU mode, eject the mounted drive: the bootloader exits DFU and boots the application. There is no RESET button to fall back on, so this is the way out if you entered DFU and no longer want to copy firmware across. (Copying a .uf2 across also reboots the board, as on any other board.) It has to be a real eject — eject, udisksctl power-off, or Finder/Explorer "Safely Remove" — since the bootloader only sees an eject as a SCSI START STOP UNIT.

Unplugging is not a way out. The board stays in the bootloader on battery, with no LED to show it, and boots the application when you next plug it in.


Contributing

Want to build from source, add a board, or submit a fix? See CONTRIBUTING.md for the development setup and PR process, and AGENTS.md for how the codebase is put together.

Getting help

License

MIT, originally Copyright (c) 2016 Adafruit Industries.

About

Meshtastic's fork of oltaco's Adafruit nRF52 bootloader with OTA DFU enhancements (OTAFIX) — used by several nRF52-based Meshtastic devices and flashable in-app from the Meshtastic Android app

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages