From 8423693ca6294a666574eb7eedbdc48d5933f8e0 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Sat, 22 Aug 2026 19:09:13 +0200 Subject: [PATCH] add MinewSemi ME25LS02 board (nRF54L15 + SX1262) --- PROVIDER_CATALOG.md | 4 + build.sh | 24 ++ gen_provider_catalog.py | 20 +- releasenotes/RELEASE_NOTES_1.17.2-zephcore.md | 28 ++ zephcore/CMakeLists.txt | 2 +- zephcore/boards/example_board/README.md | 5 + .../boards/nrf54l/me25ls02/Kconfig.defconfig | 9 + .../boards/nrf54l/me25ls02/Kconfig.me25ls02 | 6 + zephcore/boards/nrf54l/me25ls02/board.cmake | 14 + zephcore/boards/nrf54l/me25ls02/board.conf | 20 ++ zephcore/boards/nrf54l/me25ls02/board.yml | 9 + .../nrf54l/me25ls02/me25ls02-pinctrl.dtsi | 54 ++++ .../me25ls02/me25ls02_nrf54l15_cpuapp.dts | 246 ++++++++++++++++++ .../me25ls02_nrf54l15_cpuapp_defconfig | 26 ++ .../boards/nrf54l/me25ls02/pre_dt_board.cmake | 3 + zephcore/boards/supported_boards.md | 6 + 16 files changed, 474 insertions(+), 2 deletions(-) create mode 100644 zephcore/boards/nrf54l/me25ls02/Kconfig.defconfig create mode 100644 zephcore/boards/nrf54l/me25ls02/Kconfig.me25ls02 create mode 100644 zephcore/boards/nrf54l/me25ls02/board.cmake create mode 100644 zephcore/boards/nrf54l/me25ls02/board.conf create mode 100644 zephcore/boards/nrf54l/me25ls02/board.yml create mode 100644 zephcore/boards/nrf54l/me25ls02/me25ls02-pinctrl.dtsi create mode 100644 zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp.dts create mode 100644 zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp_defconfig create mode 100644 zephcore/boards/nrf54l/me25ls02/pre_dt_board.cmake diff --git a/PROVIDER_CATALOG.md b/PROVIDER_CATALOG.md index e10edfc..6732eab 100644 --- a/PROVIDER_CATALOG.md +++ b/PROVIDER_CATALOG.md @@ -59,6 +59,10 @@ Notes on the mapping: custom `companionTcp` role. - **Heltec T114** lists screen and "No screen" variants (subTitle) under one tile. - **Native-Linux** boards (femtofox, rak6421) are `noflash` download-only tiles. +- **nRF54L15** boards (ME25LS02) are `noflash` too, for a different reason: the SoC has no USB + peripheral, so no bootloader exists and nothing the configurator can drive is possible. They + publish a `.hex` as a plain download, flashed over SWD, and the companion is listed under + `companionBle` only — there is no USB transport to offer. - **Thumbnails:** folded devices inherit MeshCore's image automatically (device-level fields come from the official entry on merge), so only the new tiles set a `tooltip`. Those reuse the configurator's own image set via jsDelivr (`IMG_BASE` in the script); diff --git a/build.sh b/build.sh index a2b739d..82a7513 100644 --- a/build.sh +++ b/build.sh @@ -35,6 +35,16 @@ Linux_boards=( rak6421_pi5 ) +# nRF54L15 boards. No bootloader exists for this SoC (it has no USB +# peripheral at all), so these build with --no-sysbuild and the app links at +# RRAM base 0x0 -- zephyr.hex IS the whole image. Flashing is SWD only, which +# is why they publish a .hex and no .uf2/.zip, and why they are download-only +# in the Mesh America catalog. +nRF54L_boards=( + me25ls02/nrf54l15/cpuapp + xiao_nrf54l15/nrf54l15/cpuapp +) + ESP32_boards=( xiao_esp32c3 xiao_esp32c6/esp32c6/hpcore @@ -115,6 +125,20 @@ if [[ $1 == "nrf" ]]; then fi fi +if [[ $1 == "nrf54l" ]]; then + for board in "${nRF54L_boards[@]}"; do + board_clean_for_path=$(echo "$board" | sed -e 's/\//-/g') + + echo "Now building $board companion" + west build -b "$board" zephcore --pristine --no-sysbuild + mv build/zephyr/zephyr.hex firmware/"$board_clean_for_path"-companion-"$COMMIT_HASH".hex + + echo "Now building $board repeater" + west build -b "$board" zephcore --pristine --no-sysbuild -- -DEXTRA_CONF_FILE="boards/common/repeater.conf" + mv build/zephyr/zephyr.hex firmware/"$board_clean_for_path"-repeater-"$COMMIT_HASH".hex + done +fi + if [[ $1 == "linux" ]]; then for board in "${Linux_boards[@]}"; do # Pick the native_sim variant + cross toolchain for the target SBC arch. diff --git a/gen_provider_catalog.py b/gen_provider_catalog.py index de22777..6c64ff4 100644 --- a/gen_provider_catalog.py +++ b/gen_provider_catalog.py @@ -54,6 +54,7 @@ MAKERS = { "Ikoka": "Ikoka", "femtofox": "Femtofox", "muziworks": "muzi works", + "minewsemi": "MinewSemi", } # Manufacturer per device name. @@ -93,6 +94,7 @@ MAKER_BY_DEVICE = { "RAK6421 WisMesh (Raspberry Pi)": "rak", "RAK6421 WisMesh (Raspberry Pi 5)": "rak", "muzi works R1 Neo": "muziworks", + "MinewSemi ME25LS02": "minewsemi", } DESCRIPTION = ( @@ -202,13 +204,22 @@ BOARDS = [ dict(stem="lilygo_tlora_c6-esp32c6-hpcore", kind="esp32", device="LilyGo T-Lora C6", new=True, img="lilygo_tlora_c6.svg"), dict(stem="heltec_wifi_lora32_v43-esp32s3-procpu", kind="esp32", device="Heltec v4.3", new=True, img="heltec_v4.svg"), + # --- nRF54L15 (SWD only, download-only tile): new tile ---------------- + # The nRF54L15 has no USB peripheral, so there is no bootloader and no + # WebUSB/DFU path the configurator could drive -- the Type-C port on the + # MX25LE02 carrier is a CH340x UART bridge. The tile therefore publishes + # the .hex as a plain download and the user flashes it over SWD. + dict(stem="me25ls02-nrf54l15-cpuapp", kind="nrf54l", device="MinewSemi ME25LS02", + new=True, img="lora.svg"), + # --- Native Linux (noflash, download only): new tiles ---------------- dict(stem="zephcore_linux_femtofox", kind="linux", device="Femtofox (Luckfox Pico Mini)", new=True, img="lora.svg"), dict(stem="zephcore_linux_rak6421", kind="linux", device="RAK6421 WisMesh (Raspberry Pi)", new=True, img="rpi.svg"), dict(stem="zephcore_linux_rak6421_pi5", kind="linux", device="RAK6421 WisMesh (Raspberry Pi 5)", new=True, img="rpi.svg"), ] -DEVICE_TYPE = {"nrf": "nrf52", "esp32": "esp32", "linux": "noflash"} +DEVICE_TYPE = {"nrf": "nrf52", "esp32": "esp32", "linux": "noflash", + "nrf54l": "noflash"} # nRF52 erase package (spec §4a). ZephCore's LittleFS layout differs from MeshCore's, # so the official erase would wipe the wrong region — we point `erase` at ZephCore's @@ -231,6 +242,8 @@ COMPANION_ROLES = { "nrf": ["companionBle", "companionUsb"], "esp32": ["companionBle", "companionUsb"], "linux": ["companionTcp"], + # nRF54L15 has no USB peripheral -- the companion is BLE-only there. + "nrf54l": ["companionBle"], } HASH_RE = r"[0-9a-f]{7,40}" @@ -270,6 +283,11 @@ def files_for(assets, board, token): update = find_file(assets, stem, token, variant, r"-update\.bin") if update: out.append(("flash-update", update, "Update (app only; keeps settings)")) + elif kind == "nrf54l": + hexf = find_file(assets, stem, token, variant, r"\.hex") + if hexf: + out.append(("download", hexf, + "Firmware image -- flash over SWD (no USB bootloader on this SoC)")) elif kind == "linux": elf = find_file(assets, stem, token, variant, r"") if elf: diff --git a/releasenotes/RELEASE_NOTES_1.17.2-zephcore.md b/releasenotes/RELEASE_NOTES_1.17.2-zephcore.md index c196662..aebda9c 100644 --- a/releasenotes/RELEASE_NOTES_1.17.2-zephcore.md +++ b/releasenotes/RELEASE_NOTES_1.17.2-zephcore.md @@ -49,6 +49,29 @@ The **LilyGo T3S3** is now supported — ESP32-S3 with an OLED screen, a button > LR1121) under one name. Flashed onto any of the others it boots and looks fine but never transmits or > receives. Check which radio your board has first. +## New board: MinewSemi ME25LS02 + +The **ME25LS02** is now supported — a MinewSemi module pairing an nRF54L15 with an SX1262, aimed at +people building low-cost repeaters. Both companion and repeater builds are provided, and the module's +LLCC68 variant uses the same firmware. Requested by **xpiREC** +([@xpiREC](https://github.com/xpiREC)), who also published the development board's documentation — +[#68](https://github.com/liquidraver/ZephCore/issues/68). + +> [!IMPORTANT] +> **This board can only be flashed with an SWD probe** — a J-Link or similar. The nRF54L15 has no USB +> hardware at all, so there is no drag-and-drop UF2 file and no update over a cable. The USB-C socket on +> the development board is a serial adapter for the console, not a programming port. The firmware is +> published as a `.hex` file, and the Mesh America configurator lists the board as a download rather than +> offering to flash it. + +The development board's RGB indicator and its user button both work, and the console appears on the +USB-C serial port at 115200 baud. + +> [!NOTE] +> **The node keeps time less precisely than most boards.** The module has no 32.768 kHz crystal of its +> own, so ZephCore runs the chip's internal oscillator instead — accurate to about ±250 ppm rather than +> the ±50 ppm a crystal gives. Everything works normally; the clock simply drifts a little faster. + ## Commands to your own node get their tick straight away When you send a command to your node's own chat contact (the one named `v` plus your node name), the app @@ -244,6 +267,11 @@ Housekeeping, listed for completeness — nothing here changes how a node behave but no real node has been broken and recovered. Normal healthy nodes are unaffected. - **Why that one node's identity broke is still unknown.** This release makes sure the same thing can no longer go unnoticed, but the original cause has not been found. +- **The ME25LS02 has not been run on hardware.** Nobody involved has one yet. Both builds compile, and + the pin mapping was taken from the module's own schematic and cross-checked against MinewSemi's working + sample firmware — but no packet has been sent or received on a real module. Note also that the module's + datasheet contradicts its own schematic about three of the radio's control pins, and lists one pin + twice; the schematic is what ZephCore follows. - **The antenna amplifier receive setting is compile-checked on every affected board, but has not been measured on hardware in this form.** The 23 dB figure above comes from the original proposal, which reached the same pin by a different route. Leaving the setting alone keeps every node behaving exactly diff --git a/zephcore/CMakeLists.txt b/zephcore/CMakeLists.txt index 2357bf9..a9a1dba 100644 --- a/zephcore/CMakeLists.txt +++ b/zephcore/CMakeLists.txt @@ -273,7 +273,7 @@ elseif(BOARD MATCHES ".*esp32.*" OR BOARD MATCHES "station_g2" OR BOARD MATCHES set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/esp32_common.conf") elseif(DEFINED BOARD_QUALIFIERS AND BOARD_QUALIFIERS MATCHES ".*esp32.*") set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/esp32_common.conf") -elseif(BOARD MATCHES ".*nrf54l.*") +elseif(BOARD MATCHES ".*nrf54l.*" OR BOARD MATCHES "me25ls02") set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf54l_common.conf") elseif(DEFINED BOARD_QUALIFIERS AND BOARD_QUALIFIERS MATCHES ".*nrf54l.*") set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf54l_common.conf") diff --git a/zephcore/boards/example_board/README.md b/zephcore/boards/example_board/README.md index 46620fe..5da8f1e 100644 --- a/zephcore/boards/example_board/README.md +++ b/zephcore/boards/example_board/README.md @@ -132,10 +132,15 @@ revision. | Board | Build string | Flash | |----------------------|------------------------------------------------------------------------|-----------------| | XIAO nRF54L15 | `west build -b xiao_nrf54l15/nrf54l15/cpuapp zephcore --no-sysbuild` | `west flash` | +| MinewSemi ME25LS02 | `west build -b me25ls02/nrf54l15/cpuapp zephcore --no-sysbuild` | SWD (`west flash`) | Requires J-Link or CMSIS-DAP (built into XIAO board via SAMD11 bridge). The `--no-sysbuild` flag is required (no MCUboot support yet). +The SoC has no USB peripheral at all, so neither board has a UF2 or DFU path — `zephyr.hex` +links at RRAM base 0x0 and is the complete image, written over SWD. On the ME25LS02's MX25LE02 +carrier the USB-C port is a CH340x UART bridge (console only), so it needs an external probe. + ### MG24 (Silicon Labs) | Board | Build string | Flash | diff --git a/zephcore/boards/nrf54l/me25ls02/Kconfig.defconfig b/zephcore/boards/nrf54l/me25ls02/Kconfig.defconfig new file mode 100644 index 0000000..5ee1807 --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2026 ZephCore +# SPDX-License-Identifier: MIT + +if BOARD_ME25LS02_NRF54L15_CPUAPP + +config HAS_BT_CTLR + default BT + +endif # BOARD_ME25LS02_NRF54L15_CPUAPP diff --git a/zephcore/boards/nrf54l/me25ls02/Kconfig.me25ls02 b/zephcore/boards/nrf54l/me25ls02/Kconfig.me25ls02 new file mode 100644 index 0000000..0967ccf --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/Kconfig.me25ls02 @@ -0,0 +1,6 @@ +# MinewSemi ME25LS02 board configuration +# Copyright (c) 2026 ZephCore +# SPDX-License-Identifier: MIT + +config BOARD_ME25LS02 + select SOC_NRF54L15_CPUAPP if BOARD_ME25LS02_NRF54L15_CPUAPP diff --git a/zephcore/boards/nrf54l/me25ls02/board.cmake b/zephcore/boards/nrf54l/me25ls02/board.cmake new file mode 100644 index 0000000..71bdaa9 --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/board.cmake @@ -0,0 +1,14 @@ +# Copyright (c) 2026 ZephCore +# SPDX-License-Identifier: MIT +# +# The nRF54L15 has no USB peripheral and this board has no bootloader — the +# Type-C port is a CH340x UART bridge only. Flashing is SWD, via a J-Link or +# any probe openocd/nrfutil can drive. `west flash` picks nrfutil first. + +board_runner_args(jlink "--device=nRF54L15_M33" "--speed=4000") +board_runner_args(openocd "--cmd-load=nrf54l-load" -c "targets nrf54l.cpu") + +include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/zephcore/boards/nrf54l/me25ls02/board.conf b/zephcore/boards/nrf54l/me25ls02/board.conf new file mode 100644 index 0000000..4c79947 --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/board.conf @@ -0,0 +1,20 @@ +# MinewSemi ME25LS02 (nRF54L15 + SX1262) on the MX25LE02 dev board +# Board-specific configuration + +# Board identification +CONFIG_ZEPHCORE_BOARD_NAME="ME25LS02" + +# Device Information Service model name +CONFIG_BT_DIS_MODEL_NUMBER_STR="ME25LS02" + +# 32.768 kHz source: calibrated RC, not a crystal. +# The module carries no LFXO of its own (XL1/XL2 are brought out on P1.00/P1.01 +# and the carrier's Y1 sits behind solder bridges), so selecting the crystal +# would hang at boot on any board that lacks one. See the LFXO comment block in +# me25ls02.dts before changing this. +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y +CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y + +# Same SoC and RAM budget as the XIAO nRF54L15 — 450 contacts is the ceiling +# that still fits. +CONFIG_ZEPHCORE_MAX_CONTACTS=450 diff --git a/zephcore/boards/nrf54l/me25ls02/board.yml b/zephcore/boards/nrf54l/me25ls02/board.yml new file mode 100644 index 0000000..055713f --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/board.yml @@ -0,0 +1,9 @@ +# Copyright (c) 2026 ZephCore +# SPDX-License-Identifier: MIT + +board: + name: me25ls02 + full_name: MinewSemi ME25LS02 on MX25LE02 dev board (nRF54L15 + SX1262) + vendor: minewsemi + socs: + - name: nrf54l15 diff --git a/zephcore/boards/nrf54l/me25ls02/me25ls02-pinctrl.dtsi b/zephcore/boards/nrf54l/me25ls02/me25ls02-pinctrl.dtsi new file mode 100644 index 0000000..403d6a6 --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/me25ls02-pinctrl.dtsi @@ -0,0 +1,54 @@ +/* + * MinewSemi ME25LS02 pin control + * Copyright (c) 2026 ZephCore + * SPDX-License-Identifier: MIT + * + * Pin assignments are fixed by the module: the SX1262 is wired inside the + * ME25LS02 can and those pins are not available for anything else. + * Source: ME25LS02 datasheet rev K §6 electrical schematic (the net list + * beside U2), cross-checked against MinewSemi's own working nRF Connect + * sample. Note that the DS §5.3.2 *table* disagrees with its own schematic + * and lists P0.01 twice — the schematic is the one that matches the sample + * and is what we follow. See datasheets/README.md. + */ + +&pinctrl { + /* SX1262 on spi00 (the high-speed SPI instance) */ + spi00_default: spi00_default { + group1 { + psels = , + , + ; + }; + }; + + spi00_sleep: spi00_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + /* Console UART -> CH340x -> USB-C. Jumpers JP1/JP2 on the dev board + * connect these to the bridge; they are fitted by default. */ + uart20_default: uart20_default { + group1 { + psels = ; + }; + + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart20_sleep: uart20_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; diff --git a/zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp.dts b/zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp.dts new file mode 100644 index 0000000..9e23c3a --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp.dts @@ -0,0 +1,246 @@ +/* + * MinewSemi ME25LS02 (nRF54L15 + SX1262/LLCC68) on the MX25LE02 dev board + * Copyright (c) 2026 ZephCore + * SPDX-License-Identifier: MIT + * + * Module (fixed, inside the can — schematic rev K §6): + * SPI00: SCK P2.01, MOSI P2.02, MISO P2.04, NSS P2.05 + * DIO1 P0.00 BUSY P0.01 NRESET P2.00 + * DIO2 -> ANT_SW1 via R3: the SX1262 drives the antenna switch itself. + * There is no RXEN line (ANT_SW2 is strapped to VDD_RADIO by R4). + * Radio clock: 32 MHz crystal Y3 across XTA/XTB. NOT a TCXO — DIO3 is + * unconnected, so no dio3-tcxo-voltage here. + * SX1262 DC-DC is fitted (L7 on DCC_SW). + * nRF54L15 DC-DC is fitted (ML1 on DCC), so vregmain runs in DCDC mode. + * HFXO uses external load capacitors (MC12/MC13 at XC1/XC2). + * + * Dev board (MX25LE02 datasheet §5): + * USB-C is a CH340x UART bridge — the nRF54L15 has no USB peripheral. + * Console on uart20: TX P1.05, RX P1.04. + * RGB LED D1, common anode to 3V3 (active low): R P0.02, B P0.03, G P0.04. + * K2 user button -> P1.08 (to GND). K1 is nRESET, wired to the SoC pin. + * 32.768 kHz crystal Y1 is on the carrier behind solder bridges SB1/SB3 — + * see the LFXO note at the bottom of this file before enabling it. + */ + +/dts-v1/; +#include +#include "me25ls02-pinctrl.dtsi" +#include +#include + +/ { + model = "MinewSemi ME25LS02"; + compatible = "minewsemi,me25ls02"; + + chosen { + zephyr,sram = &cpuapp_sram; + zephyr,flash = &cpuapp_rram; + zephyr,flash-controller = &rram_controller; + zephyr,console = &uart20; + zephyr,shell-uart = &uart20; + /* + * Deliberately no zephyr,code-partition: there is no bootloader + * on this part, so the image links at RRAM base 0x0 and the ROM + * starts it directly. CONFIG_USE_DT_CODE_PARTITION stays off. + */ + }; + + aliases { + lora0 = &lora; + led0 = &green_led; + led1 = &blue_led; + led2 = &red_led; + sw0 = &user_button; + }; + + leds { + compatible = "gpio-leds"; + + /* D1 is a common-anode RGB tied to 3V3 — all three are active low. */ + red_led: led_0 { + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + + green_led: led_1 { + gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + + blue_led: led_2 { + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons: buttons { + compatible = "gpio-keys"; + + /* K2 shorts P1.08 to GND; C13 does the hardware debounce. */ + user_button: button_0 { + gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "User Button"; + }; + }; +}; + +&cpuapp_sram { + status = "okay"; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&clock { + status = "okay"; +}; + +&uart20 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart20_default>; + pinctrl-1 = <&uart20_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi00 { + status = "okay"; + cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi00_default>; + pinctrl-1 = <&spi00_sleep>; + pinctrl-names = "default", "sleep"; + + /* + * The nRF54L SPIM applies an RX sample delay that the SX126x does not + * tolerate at these clock rates — MinewSemi drop it in their own sample + * and so do we. Symptom if left in: garbage on MISO, driver never sees + * the chip. + */ + /delete-property/ rx-delay-supported; + /delete-property/ rx-delay; + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + spi-max-frequency = <8000000>; + + reset-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; + busy-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; + dio1-gpios = <&gpio0 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + + /* DIO2 drives ANT_SW1; there is no separate RXEN line. */ + dio2-tx-enable; + + /* Crystal, not TCXO — do not add dio3-tcxo-voltage. */ + + rx-boosted; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +/* DIO1 and BUSY are on P0.x, which is served by GPIOTE30. */ +&gpiote30 { + status = "okay"; +}; + +®ulators { + status = "okay"; +}; + +&vregmain { + status = "okay"; + regulator-initial-mode = ; +}; + +/* + * HFXO: the module fits its own external load capacitors at XC1/XC2, so the + * internal ones must stay off or the 32 MHz oscillator is pulled off frequency. + */ +&hfxo { + load-capacitors = "external"; + status = "okay"; +}; + +/* + * LFXO is deliberately NOT enabled. + * + * The ME25LS02 module does not contain a 32.768 kHz crystal — it brings XL1/XL2 + * out on P1.00/P1.01 and the datasheet shows the crystal only as a reference + * design. The MX25LE02 carrier does fit one (Y1), but behind solder bridges + * SB1/SB3, and a module soldered onto anyone else's board very likely has + * nothing there at all. Configuring LFXO with no crystal present means LFCLK + * never becomes ready and the node hangs at boot instead of failing visibly. + * + * So the board runs the calibrated LFRC instead (K32SRC_RC in board.conf), + * which is what MinewSemi's own shipped firmware does. Cost is clock accuracy: + * ±250 ppm calibrated versus ±50 ppm for a crystal (nRF54L15 DS v1.0 §11.2.2). + * That is fine for BLE and for mesh timing, but it is the reason a node here + * drifts faster than a crystal-equipped board — relevant if MeshTimeSync is + * ever tuned against this hardware. + * + * To use the crystal on a carrier that definitely has one, delete + * CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC / add K32SRC_XTAL in board.conf and + * enable &lfxo here with the right load capacitance. + */ + +&radio { + status = "okay"; +}; + +&temp { + status = "okay"; +}; + +/* Default Nordic RRAM map, then re-carved below for ZephCore. */ +#include + +/* + * RRAM layout (1524 KB total, 0x17D000). + * + * No bootloader: the application starts at 0x0 and the linker is given the + * whole RRAM, so slot0/slot1 are meaningless here and are deleted to keep + * anyone from assuming a DFU layout that does not exist. The only partition + * that matters is the filesystem at the top of RRAM. + * + * 0x000000 - 0x14E000 (1336 KB) application (links from 0x0) + * 0x14E000 - 0x165000 (92 KB) LittleFS: identity, prefs, contacts, + * channels, BLE bonds + * 0x165000 - 0x17D000 (96 KB) unused tail + */ +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; +/delete-node/ &storage_partition; + +&cpuapp_rram { + partitions { + lfs_partition: partition@14e000 { + compatible = "zephyr,mapped-partition"; + label = "lfs"; + reg = <0x14E000 0x17000>; + }; + }; +}; + +/* LittleFS auto-mount — standard /lfs mount point */ +#include "../../common/filesystem.dtsi" diff --git a/zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp_defconfig b/zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp_defconfig new file mode 100644 index 0000000..bb6806a --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/me25ls02_nrf54l15_cpuapp_defconfig @@ -0,0 +1,26 @@ +# MinewSemi ME25LS02 default configuration +# SPDX-License-Identifier: MIT + +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y + +CONFIG_CACHE_MANAGEMENT=y +CONFIG_EXTERNAL_CACHE=y + +# Console on uart20 -> CH340x -> USB-C (no USB peripheral on this SoC) +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +CONFIG_GPIO=y +CONFIG_PINCTRL=y +CONFIG_SPI=y + +# RRAM + LittleFS +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y + +CONFIG_NRF_GRTC_START_SYSCOUNTER=y + +CONFIG_REGULATOR=y diff --git a/zephcore/boards/nrf54l/me25ls02/pre_dt_board.cmake b/zephcore/boards/nrf54l/me25ls02/pre_dt_board.cmake new file mode 100644 index 0000000..3789630 --- /dev/null +++ b/zephcore/boards/nrf54l/me25ls02/pre_dt_board.cmake @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT +# Suppress "unique_unit_address_if_enabled" to handle some overlaps +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/zephcore/boards/supported_boards.md b/zephcore/boards/supported_boards.md index 48966f6..0c7f746 100644 --- a/zephcore/boards/supported_boards.md +++ b/zephcore/boards/supported_boards.md @@ -102,9 +102,15 @@ xiao_mg24 ``` xiao_nrf54l15/nrf54l15/cpuapp +me25ls02/nrf54l15/cpuapp ``` > Requires `--no-sysbuild` flag: `west build -b xiao_nrf54l15/nrf54l15/cpuapp zephcore --no-sysbuild` +> +> The nRF54L15 has no USB peripheral, so there is no UF2 or DFU path on either board — flash +> `zephyr.hex` over SWD. `me25ls02` is the MinewSemi ME25LS02 module on its MX25LE02 carrier; +> its USB-C port is a CH340x UART bridge carrying the console, not a programming port. +> Untested on hardware. ## Native Linux