Skip to content

feat(nrf54lm20dk): add the Nordic nRF54LM20-DK with native USB - #12130

Draft
cvaldess wants to merge 5 commits into
meshtastic:developfrom
cvaldess:feat/nrf54lm20dk-variant
Draft

cvaldess wants to merge 5 commits into
meshtastic:developfrom
cvaldess:feat/nrf54lm20dk-variant

Conversation

@cvaldess

@cvaldess cvaldess commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Adds the Nordic nRF54LM20-DK as a DIY board (PRIVATE_HW, board_level = extra, like the nRF54L15-DK), with the nRF54LM20's native USB: console, serial API and clients over USB, and firmware updates over USB (serial DFU and a UF2 drive) or BLE.

Draft: it builds against packages that are not released yet (see Dependencies). It is here so the variant can be reviewed alongside them; it will be marked ready once they land.

What it adds

  • variants/nrf54l15/nrf54lm20dk and boards/nrf54lm20dk.json: nRF54LM20-DK (nRF54LM20B, built as the A) with an EBYTE E22-900M30S on P3 (SPIM22), I²C on TWIM30 (P0.03/P0.04), Serial2 on UARTE21. The pin choices and the board's constraints (clock pins, port-bound serial instances, VDD) are documented in variant.h.
  • USB: Serial is a CDC port on the nRF USB connector (J3), through the core's TinyUSB port for the USBHS block (USE_TINYUSB). extra_scripts/nrf54_tinyusb.py (pre) adds the TinyUSB Arduino include path, as nRF52's platform builder does itself; a -I${platformio.packages_dir}/... build flag does not work on Windows, where the path expands with backslashes that the flag parser takes as escapes.
  • Updates over USB: upload_protocol = nrfutil touches the application's port at 1200 bps and uploads to the bootloader's port. The build also writes firmware-*.uf2 (extra_scripts/nrf54lm20_uf2.py, from userfirmware.hex) for the bootloader's UF2 drive. hwids keep the port finder off the on-board J-Link's VCOM ports.
  • The bootloader carries the USB stack and takes 64 KB, so the application links at 0x10000 (nrf54lm20a_s145_v10_bl64k.ld).
  • enterDfuMode() on nRF54: with USE_TINYUSB it calls enterUf2Dfu(), so "enter DFU" (meshtastic --enter-dfu) brings up the UF2 drive, as on nRF52. Boards without USB keep serial DFU.

Dependencies

Once those are released, platform_packages goes and platform points at the release.

Tested

On an nRF54LM20-DK with this variant (plus bench sensors not included here):

  • radio (E22, EU_868), BLE with the iOS app, Telemetry over I²C;
  • USB: the CDC port enumerates once at 0.7 s with the whole boot log; Meshtastic CLI and web client over USB, BLE at the same time;
  • pio run -t upload over USB (1200 bps touch → bootloader → adafruit-nrfutil), the UF2 drive (copy, CURRENT.UF2, --enter-dfu) and BLE OTA. After the USB and UF2 updates the RRAM read back over SWD matched the image; after every update --info reported the new version, with the node's settings kept.

This branch, as is, builds from a clean PlatformIO core with the packages fetched from git (Windows), and that build was uploaded to the DK with pio run -t upload over USB: it boots (USB up after the SoftDevice, as intended), and --info over USB reports it. Not tested: Linux and macOS hosts, long soak.

The nRF54LM20-DK (nRF54LM20B, built as the A) with an EBYTE E22-900M30S
on P3 (SPIM22), as a DIY board under PRIVATE_HW like the nRF54L15-DK.

- USB: Serial is a CDC port on the nRF's native USB (J3) through the
  core's TinyUSB port for the USBHS block, so the console, the serial API
  and the clients work over USB.
- Updates over USB: the board's bootloader does serial DFU over USB CDC
  and shows a UF2 drive. upload_protocol = nrfutil touches the
  application's port at 1200 bps and uploads to the bootloader's port;
  the build also writes firmware-*.uf2 (extra_scripts/nrf54lm20_uf2.py,
  from userfirmware.hex, family 0x9EEA6BF9).
- The bootloader carries the USB stack and takes 64 KB, so the
  application links at 0x10000 (nrf54lm20a_s145_v10_bl64k.ld).
- hwids for the application (239A:CAFE) and the bootloader (239A:4AFD
  with the UF2 drive, 239A:4AFE CDC only), so the port finder does not
  pick the J-Link's VCOM ports.

nRF54LM20A support is only on andyshinn/platform-nordicnrf54 so far, and
the USB changes to the core and the bootloader are under review there
(andyshinn/nRF54_Arduino#1, meshtastic#2, andyshinn/nRF54_Bootloader#2); the
environment pins them until they are released.
enterDfuMode() (admin "enter DFU") always asked for serial DFU, as no
nRF54L board had USB. With USE_TINYUSB (nRF54LM20) it now calls
enterUf2Dfu(), GPREGRET 0x57, and the bootloader shows its UF2 drive, as
on nRF52.
@github-actions

Copy link
Copy Markdown
Contributor

⚡ Try this PR in the Web Flasher

Note

Building this pull request… the flash button, badges and supported-board
list will appear here automatically once CI finishes.

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…e comment

The comment said the flag sets TX_GAIN_LORA 10; configuration.h maps the
module to 7. Name the settings instead of restating their values.
infer_architecture() knew nrf54l15 but not nrf54lm20a, so the mtjson target was
skipped for the nRF54LM20-DK and no manifest came out of its builds. The env
now declares the same spelling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant