mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 14:50:09 +00:00
1040 lines
34 KiB
Plaintext
1040 lines
34 KiB
Plaintext
/*
|
|
* ============================================================================
|
|
* ZephCore — board.overlay template
|
|
* ============================================================================
|
|
*
|
|
* A board.overlay adds ZephCore's nodes on top of a board definition:
|
|
* - a board that already exists in Zephyr (rak4631, xiao_nrf54l15, xiao_mg24,
|
|
* xiao_esp32c3, heltec_wifi_lora32_v3): this file carries everything
|
|
* - a custom board with its own .dts in this directory: the same nodes can
|
|
* live in the .dts instead, and board.overlay may be absent (ikoka_nano_30dbm,
|
|
* gat562_30s) or hold only the peripherals (lilygo_t3s3)
|
|
*
|
|
* HOW TO USE THIS FILE
|
|
* Every example is inside an #if 0 ... #endif pair, so the examples can
|
|
* carry real comments and real indentation. Keep the examples for your
|
|
* platform, delete the #if 0 and #endif lines around them, delete the rest,
|
|
* and CHANGE EVERY PIN. Each example names the board it was taken from: when
|
|
* in doubt, that board's files are the reference, not this one.
|
|
*
|
|
* WHAT A BOARD HAS TO PROVIDE
|
|
* 1. the lora0 alias and a radio node (sections 1, 2)
|
|
* 2. a flash layout with an lfs_partition, mounted at /lfs (section 3)
|
|
* 3. a console (section 4)
|
|
* everything else is optional (sections 5, 6)
|
|
*
|
|
* PLATFORM CHEAT SHEET
|
|
*
|
|
* nRF52840 nRF54L15 MG24 ESP32-C3/C6 ESP32-S3
|
|
* SPI bus &spi2/&spi3 &spi00 &eusart0 &spi2 &spi2
|
|
* GPIO &gpio0/1 &gpio0/1/2 &gpioa-d &gpio0 &gpio0, &gpio1 = GPIO32+
|
|
* Flash node &flash0 &cpuapp_rram &flash0 &flash0 &flash0
|
|
* Erase block 4 KB 4 KB 8 KB 4 KB 4 KB
|
|
* BLE bonds NVS partition file in /lfs file in /lfs NVS partition NVS partition
|
|
* Console USB CDC ACM UART (bridge) USART0 USB-Serial/JTAG USB-Serial/JTAG
|
|
* Flash map common .dtsi here here partitions.overlay
|
|
*
|
|
* nRF52840: SPIM0 and SPIM1 share their instance with TWIM0 / TWIM1. Put the
|
|
* radio on &spi2 or &spi3 if the board uses I2C at all.
|
|
* nRF54L15: port P2 has no GPIOTE, so no GPIO interrupt works there. A radio
|
|
* IRQ line cannot be on P2, and a button on P2 needs gpio-keys polling-mode.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
/* dt-bindings headers; keep the ones your nodes use.
|
|
* lora/sx126x.h SX126X_DIO3_TCXO_*
|
|
* input/input-event-codes.h INPUT_KEY_* (buttons)
|
|
* adc/nrf-saadc.h NRF_SAADC_AIN* (nRF battery ADC)
|
|
* gpio/espressif-esp32-gpio.h ESP32_GPIO_SLEEP_HOLD_EN (ESP32 light sleep) */
|
|
#if 0
|
|
#include <zephyr/dt-bindings/lora/sx126x.h>
|
|
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
|
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
|
|
#include <zephyr/dt-bindings/gpio/espressif-esp32-gpio.h>
|
|
#endif
|
|
|
|
|
|
/* ==================================================================
|
|
* SECTION 1: ALIASES AND CHOSEN
|
|
*
|
|
* What the firmware looks up. Only lora0 is required.
|
|
*
|
|
* aliases
|
|
* lora0 the radio node REQUIRED
|
|
* led0 heartbeat LED
|
|
* led1 second LED (unread messages on a companion)
|
|
* lora-tx-led blinks while transmitting
|
|
* sw0 user button; also the wake source from nRF System OFF
|
|
* and from ESP32 light sleep
|
|
* buzzer PWM buzzer (the node must also be LABELLED buzzer)
|
|
* gps-* GPS control pins, see section 6
|
|
*
|
|
* chosen
|
|
* zephyr,display the panel; turns the display UI on
|
|
* zephyr,settings-partition NVS partition for BLE bonds. nRF52 gets it
|
|
* from the partition .dtsi, ESP32 sets it in
|
|
* partitions.overlay. nRF54L and MG24 keep bonds
|
|
* in a file on /lfs and do NOT set it
|
|
* zephyr,code-partition nRF52: &code_partition (section 3)
|
|
* zephyr,console / zephyr,shell-uart section 4
|
|
* zephcore,gps-power regulator that powers the GPS (section 6)
|
|
* zephcore,companion-uart companion protocol on a plain UART, for
|
|
* boards without Bluetooth (lora_e5_mini)
|
|
* ================================================================== */
|
|
/ {
|
|
aliases {
|
|
lora0 = &lora;
|
|
};
|
|
};
|
|
|
|
|
|
/* ==================================================================
|
|
* SECTION 2: LORA RADIO (REQUIRED)
|
|
*
|
|
* Without it there is no mesh. Label the node `lora`.
|
|
*
|
|
* SX1261 / SX1262 / SX1268 / LLCC68 (Zephyr's driver, patched in-tree):
|
|
* reset-gpios ACTIVE_LOW
|
|
* busy-gpios ACTIVE_HIGH
|
|
* dio1-gpios interrupt, ACTIVE_HIGH with PULL_DOWN
|
|
* dio3-tcxo-voltage only if DIO3 powers a TCXO (SX126X_DIO3_TCXO_1V8...);
|
|
* a module with a plain crystal must NOT set it
|
|
* tcxo-power-startup-delay-ms
|
|
* rx-boosted boosted RX gain (better sensitivity, a little current)
|
|
* regulator-ldo only if the module is wired for LDO; DC-DC is the default
|
|
*
|
|
* RF switch and front end. Read the schematic: what a vendor calls RXEN or
|
|
* TXEN is sometimes a module power enable or a FEM control pin.
|
|
* dio2-tx-enable DIO2 drives the TX side of the switch (most modules)
|
|
* rx-enable-gpios separate RXEN line (Wio-SX1262 needs it AND DIO2)
|
|
* tx-enable-gpios separate TXEN line
|
|
* antenna-enable-gpios switch or FEM supply that must be on for RX and TX
|
|
* lna-bypass-gpios FEM receive-path select (KCT8103L CTX). It enables
|
|
* nothing: binding it as a TX enable costs ~69 dB of
|
|
* RX. Reference: boards/esp32/heltec_wifi_lora32_v43/
|
|
* A pin that is really a module POWER enable is not a radio property at all:
|
|
* delete it from the node and hog it high (boards/nrf52840/rak4631/).
|
|
*
|
|
* External PA: also cap the chip's output in board.conf
|
|
* (CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM / _MAX_TX_POWER_DBM).
|
|
*
|
|
* ESP32 repeaters that light-sleep: NSS, RESET and every MCU-driven RF switch
|
|
* or FEM line need ESP32_GPIO_SLEEP_HOLD_EN, or they float during each sleep
|
|
* while the radio keeps receiving (boards/common/pm_esp32.conf). The flag is
|
|
* inert without PM, so set it from the start.
|
|
* ================================================================== */
|
|
|
|
#if 0 /* ---- 2A: nRF52840, SX1262, custom board (wio_tracker_l1) ----
|
|
* Pins of a custom board come from <board>-pinctrl.dtsi. */
|
|
&spi2 {
|
|
compatible = "nordic,nrf-spim";
|
|
status = "okay";
|
|
cs-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
|
|
pinctrl-0 = <&spi2_default>;
|
|
pinctrl-1 = <&spi2_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,sx1262";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
|
|
busy-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
|
|
dio1-gpios = <&gpio0 7 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
|
rx-enable-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
|
|
dio2-tx-enable;
|
|
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
|
tcxo-power-startup-delay-ms = <5>;
|
|
rx-boosted;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 2B: nRF54L15, Wio-SX1262 on the XIAO header (xiao_nrf54l15) ---- */
|
|
/* The XIAO's default I2C pins are the kit's NSS / RXEN. */
|
|
&i2c22 {
|
|
status = "disabled";
|
|
};
|
|
|
|
/* SCK / MISO / MOSI are already in the board's pinctrl. */
|
|
&spi00 {
|
|
cs-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,sx1262";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
|
|
busy-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
|
|
dio1-gpios = <&gpio1 5 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
|
rx-enable-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
|
|
dio2-tx-enable;
|
|
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
|
tcxo-power-startup-delay-ms = <10>;
|
|
rx-boosted;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 2C: MG24, Wio-SX1262 on the XIAO header (xiao_mg24) ---- */
|
|
/* Secure element: hardware crypto and the TRNG that feeds mbedTLS / BLE. */
|
|
&se {
|
|
status = "okay";
|
|
};
|
|
|
|
/* The XIAO's default I2C pins (PC4 / PC5) are the kit's NSS / RXEN. */
|
|
&i2c0 {
|
|
status = "disabled";
|
|
};
|
|
|
|
&eusart0 {
|
|
status = "okay";
|
|
cs-gpios = <&gpioc 4 GPIO_ACTIVE_LOW>; /* overrides the default PC7 */
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,sx1262";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpioc 2 GPIO_ACTIVE_LOW>;
|
|
busy-gpios = <&gpioc 3 GPIO_ACTIVE_HIGH>;
|
|
dio1-gpios = <&gpioc 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
|
rx-enable-gpios = <&gpioc 5 GPIO_ACTIVE_HIGH>;
|
|
dio2-tx-enable;
|
|
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
|
tcxo-power-startup-delay-ms = <10>;
|
|
rx-boosted;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 2D: ESP32-C3 / C6, SX1262 (xiao_esp32c3) ---- */
|
|
&spi2 {
|
|
cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,sx1262";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
|
|
busy-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
|
|
dio1-gpios = <&gpio0 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
|
rx-enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
|
|
dio2-tx-enable;
|
|
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
|
tcxo-power-startup-delay-ms = <10>;
|
|
rx-boosted;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 2E: ESP32-S3, SX1262, sleep-hold on the driven lines (xiao_esp32s3) ----
|
|
* GPIO32 and up are on &gpio1: GPIO41 is <&gpio1 9>. */
|
|
&spi2 {
|
|
cs-gpios = <&gpio1 9 (GPIO_ACTIVE_LOW | ESP32_GPIO_SLEEP_HOLD_EN)>; /* GPIO41 */
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,sx1262";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpio1 10 (GPIO_ACTIVE_LOW | ESP32_GPIO_SLEEP_HOLD_EN)>; /* GPIO42 */
|
|
busy-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; /* GPIO40 */
|
|
dio1-gpios = <&gpio1 7 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* GPIO39 */
|
|
rx-enable-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | ESP32_GPIO_SLEEP_HOLD_EN)>; /* GPIO38 */
|
|
dio2-tx-enable;
|
|
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
|
tcxo-power-startup-delay-ms = <10>;
|
|
rx-boosted;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 2F: LR1110 / LR1120 / LR1121 (t1000_e) ----
|
|
* ZephCore's own driver. board.conf: CONFIG_ZEPHCORE_RADIO_LR1110=y
|
|
* The interrupt is irq-gpios, the TCXO is tcxo-voltage in mV, and the RF
|
|
* switch is a set of DIO bitmasks (bit0 = DIO5 ... bit3 = DIO8) taken
|
|
* from the module's reference design. */
|
|
&spi1 {
|
|
compatible = "nordic,nrf-spim";
|
|
status = "okay";
|
|
cs-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
|
|
pinctrl-0 = <&spi1_default>;
|
|
pinctrl-1 = <&spi1_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,lr1110";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
|
busy-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
|
|
irq-gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
|
tcxo-voltage = <1600>;
|
|
tcxo-power-startup-delay-ms = <5>;
|
|
rx-boosted;
|
|
rfsw-enable = <0x0F>;
|
|
rfsw-standby = <0x00>;
|
|
rfsw-rx = <0x09>;
|
|
rfsw-tx = <0x0B>;
|
|
rfsw-tx-hp = <0x0A>;
|
|
rfsw-gnss = <0x04>;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 2G: LR2021 (promicro_lr2021) ----
|
|
* ZephCore's own driver. board.conf: CONFIG_ZEPHCORE_RADIO_LR2021=y
|
|
* irq-dio names the chip DIO that is wired to irq-gpios. Leave
|
|
* tcxo-voltage out on a module without a TCXO: setting it there wedges
|
|
* the chip at start-up (BUSY stuck high). Absolute maximum VBAT is about
|
|
* 3.7 V; a 5 V feed destroys the module. */
|
|
&spi2 {
|
|
compatible = "nordic,nrf-spim";
|
|
status = "okay";
|
|
cs-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
|
|
pinctrl-0 = <&spi2_default>;
|
|
pinctrl-1 = <&spi2_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
/* 0x00 is the LR2021's NOP; Nordic's 0xff default reads as a bogus opcode. */
|
|
overrun-character = <0x00>;
|
|
|
|
lora: lora@0 {
|
|
compatible = "semtech,lr2021";
|
|
reg = <0>;
|
|
spi-max-frequency = <8000000>;
|
|
reset-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
|
|
busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
|
|
irq-gpios = <&gpio0 10 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
|
irq-dio = <9>;
|
|
rx-boosted;
|
|
rfsw-enable = <0x03>;
|
|
rfsw-standby = <0x00>;
|
|
rfsw-rx = <0x03>;
|
|
rfsw-tx = <0x02>;
|
|
rfsw-tx-hp = <0x03>;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
|
|
/* ==================================================================
|
|
* SECTION 3: FLASH LAYOUT AND /lfs (REQUIRED)
|
|
*
|
|
* ZephCore keeps identity, prefs, contacts and channels in a LittleFS volume
|
|
* on lfs_partition, mounted at /lfs by boards/common/filesystem.dtsi.
|
|
*
|
|
* Platform Layout
|
|
* ────────────── ─────────────────────────────────────────────────────────
|
|
* nRF52840 SD v6 SoftDevice 152K | app 680K | NVS 16K | lfs 128K | UF2 48K
|
|
* nRF52840 SD v7 SoftDevice 156K | app 676K | NVS 16K | lfs 128K | UF2 48K
|
|
* nRF54L15 MCUboot 64K (reserved) | app 1272K | lfs 92K
|
|
* MG24 MCUboot 48K (reserved) | app 1344K | lfs 144K
|
|
* ESP32-S3 MCUboot 64K | slot0 | slot1 | NVS 16K | lfs 384K
|
|
* ESP32-C3/C6 MCUboot 64K | slot0 | slot1 | lpcore | lfs 192K | NVS 16K
|
|
* Classic ESP32 stock app slots | lfs 192K | NVS 16K
|
|
* STM32WL app at flash origin | lfs (boards/stm32wl/lora_e5_mini/)
|
|
*
|
|
* Every partition node written by hand needs
|
|
* compatible = "zephyr,mapped-partition";
|
|
* (Zephyr main). Without it the code that opens the partition does not
|
|
* compile: "..._PARTITION_ID undeclared". The nRF52 .dtsi files below already
|
|
* carry what they need.
|
|
*
|
|
* Once a board has shipped, lfs and NVS must keep their offset and size: a
|
|
* firmware that moves them erases every user's identity, contacts and bonds.
|
|
* ================================================================== */
|
|
|
|
#if 0 /* ---- 3A: nRF52840 (rak4631, wio_tracker_l1) ----
|
|
*
|
|
* Do not write this map by hand. Include the shared layout that matches
|
|
* the SoftDevice the board's Adafruit bootloader carries; the same
|
|
* choice sets CONFIG_ZEPHCORE_SD_FWID in board.conf:
|
|
*
|
|
* nrf52_partitions_sdv6.dtsi s140 v6, app at 0x26000, FWID 0x00B6
|
|
* nrf52_partitions_sdv7.dtsi s140 v7, app at 0x27000, FWID 0x0123
|
|
*
|
|
* The Arduino MeshCore variant's platformio.ini names the linker script
|
|
* (nrf52840_s140_v6*.ld or _v7*.ld). The wrong one places the app at the
|
|
* wrong address: the board bootloops with no USB, BLE or logs.
|
|
*
|
|
* The include defines code_partition, storage_partition (NVS),
|
|
* lfs_partition and the reserved regions, sets zephyr,sram and
|
|
* zephyr,settings-partition, and mounts /lfs. Put it at the END of the
|
|
* file. The delete lines apply when the base DTS includes
|
|
* <nordic/nrf52840_partition.dtsi>, as upstream boards do. */
|
|
/delete-node/ &boot_partition;
|
|
/delete-node/ &slot0_partition;
|
|
/delete-node/ &slot1_partition;
|
|
/delete-node/ &storage_partition;
|
|
|
|
/ {
|
|
chosen {
|
|
zephyr,code-partition = &code_partition;
|
|
};
|
|
};
|
|
|
|
#include "../../common/nrf52_partitions_sdv7.dtsi"
|
|
#endif
|
|
|
|
#if 0 /* ---- 3B: nRF54L15, 1428 KB RRAM (xiao_nrf54l15) ----
|
|
* The 64 KB MCUboot region stays reserved although builds are
|
|
* --no-sysbuild; slot0 grows into slot1. No NVS partition: bonds are a
|
|
* settings file on /lfs. */
|
|
/delete-node/ &slot0_partition;
|
|
/delete-node/ &slot1_partition;
|
|
/delete-node/ &storage_partition;
|
|
|
|
&cpuapp_rram {
|
|
partitions {
|
|
slot0_partition: partition@10000 {
|
|
compatible = "zephyr,mapped-partition";
|
|
label = "image-0";
|
|
reg = <0x10000 0x13E000>; /* 1272 KB */
|
|
};
|
|
|
|
lfs_partition: partition@14e000 {
|
|
compatible = "zephyr,mapped-partition";
|
|
label = "lfs";
|
|
reg = <0x14E000 0x17000>; /* 92 KB */
|
|
};
|
|
};
|
|
};
|
|
|
|
#include "../../common/filesystem.dtsi"
|
|
#endif
|
|
|
|
#if 0 /* ---- 3C: MG24, 1536 KB flash, 8 KB erase blocks (xiao_mg24) ----
|
|
* Partition sizes must be multiples of 8 KB. No NVS partition: bonds
|
|
* are a settings file on /lfs. */
|
|
/delete-node/ &slot0_partition;
|
|
/delete-node/ &slot1_partition;
|
|
/delete-node/ &storage_partition;
|
|
|
|
&flash0 {
|
|
partitions {
|
|
slot0_partition: partition@c000 {
|
|
compatible = "zephyr,mapped-partition";
|
|
label = "image-0";
|
|
reg = <0x0C000 0x150000>; /* 1344 KB */
|
|
};
|
|
|
|
lfs_partition: partition@15c000 {
|
|
compatible = "zephyr,mapped-partition";
|
|
label = "lfs";
|
|
reg = <0x15C000 0x24000>; /* 144 KB */
|
|
};
|
|
};
|
|
};
|
|
|
|
#include "../../common/filesystem.dtsi"
|
|
#endif
|
|
|
|
#if 0 /* ---- 3D: ESP32-S3 / C3 / C6 (xiao_esp32s3, xiao_esp32c3) ----
|
|
* The map is NOT here. It is in partitions.overlay beside this file,
|
|
* which is also fed to MCUboot (see the template). This file only
|
|
* mounts the volume. */
|
|
#include "../../common/filesystem.dtsi"
|
|
#endif
|
|
|
|
#if 0 /* ---- 3E: classic ESP32, 4 MB (ttgo_tbeam) ----
|
|
* Simple boot only, no MCUboot and no partitions.overlay: the stock app
|
|
* slots stay, and the stock 192 KB storage_partition becomes lfs with a
|
|
* new 16 KB NVS above it. */
|
|
/delete-node/ &storage_partition;
|
|
|
|
/ {
|
|
chosen {
|
|
zephyr,settings-partition = &storage_partition;
|
|
};
|
|
};
|
|
|
|
&flash0 {
|
|
partitions {
|
|
lfs_partition: partition@3b0000 {
|
|
compatible = "zephyr,mapped-partition";
|
|
label = "lfs";
|
|
reg = <0x3B0000 0x30000>;
|
|
};
|
|
|
|
storage_partition: partition@3e0000 {
|
|
compatible = "zephyr,mapped-partition";
|
|
label = "storage";
|
|
reg = <0x3E0000 0x4000>;
|
|
};
|
|
};
|
|
};
|
|
|
|
#include "../../common/filesystem.dtsi"
|
|
#endif
|
|
|
|
|
|
/* ==================================================================
|
|
* SECTION 4: CONSOLE AND USB
|
|
*
|
|
* Check build/zephyr/zephyr.dts first: many board definitions already choose
|
|
* the right console.
|
|
*
|
|
* nRF52840 USB CDC ACM. Upstream boards that include Zephyr's
|
|
* cdc_acm_serial.dtsi (rak4631) already have it. A custom board
|
|
* declares it itself (4A).
|
|
* nRF54L15 no USB peripheral at all. Console is the UART the board DTS
|
|
* chooses (a debug-probe or CH340 bridge).
|
|
* MG24 USART0, set by the board DTS.
|
|
* ESP32-C3 / C6 USB-Serial/JTAG (4B).
|
|
* ESP32-S3 USB-Serial/JTAG for the console, and the same port becomes a
|
|
* native USB CDC companion transport in companion builds (4C).
|
|
* Classic ESP32, Heltec V3 uart0 through the on-board USB-UART bridge.
|
|
* STM32WL USART1; also carries the companion protocol (no Bluetooth).
|
|
* ================================================================== */
|
|
|
|
#if 0 /* ---- 4A: nRF52840 custom board, USB CDC ACM (thinknode_m1) ---- */
|
|
/ {
|
|
chosen {
|
|
zephyr,console = &cdc_acm_uart;
|
|
zephyr,shell-uart = &cdc_acm_uart;
|
|
};
|
|
};
|
|
|
|
zephyr_udc0: &usbd {
|
|
compatible = "nordic,nrf-usbd";
|
|
status = "okay";
|
|
|
|
cdc_acm_uart: cdc_acm_uart {
|
|
compatible = "zephyr,cdc-acm-uart";
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 4B: ESP32-C3 / C6 (xiao_esp32c3) ---- */
|
|
/ {
|
|
chosen {
|
|
zephyr,console = &usb_serial;
|
|
zephyr,shell-uart = &usb_serial;
|
|
};
|
|
};
|
|
|
|
/* WiFi carries the repeater's OTA update. */
|
|
&wifi {
|
|
status = "okay";
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 4C: ESP32-S3 with native USB (xiao_esp32s3) ----
|
|
*
|
|
* Including esp32s3_usb_otg.dtsi is the switch: CMake looks for that
|
|
* include in board.overlay and, for companion builds, adds
|
|
* boards/common/esp32s3_usb.conf, which hands the port to USB OTG for
|
|
* the companion protocol and moves the console to uart0. Repeater,
|
|
* room-server and debug builds keep the console on USB-Serial/JTAG.
|
|
* Consequence: esptool cannot auto-reset an S3 companion into download
|
|
* mode. Use `start dfu` or a 1200-baud touch (docs/adr/0002).
|
|
*
|
|
* Do NOT include esp32s3_console_uart0.dtsi here unless the board's
|
|
* USB-C really is a UART bridge on GPIO43/44 (Heltec V3, ThinkNode M9):
|
|
* it would strand the console of every non-USB build on those pins. */
|
|
/ {
|
|
chosen {
|
|
zephyr,console = &usb_serial;
|
|
zephyr,shell-uart = &usb_serial;
|
|
};
|
|
};
|
|
|
|
#include "../../common/esp32s3_usb_otg.dtsi"
|
|
#endif
|
|
|
|
|
|
/* ==================================================================
|
|
* SECTION 5: CLOCKS (Nordic)
|
|
*
|
|
* The 32.768 kHz source is a devicetree property since the Zephyr main pin.
|
|
* The old CONFIG_CLOCK_CONTROL_NRF_K32SRC_* choices are dropped with nothing
|
|
* but a Kconfig warning, which leaves a crystal-less board waiting on a
|
|
* crystal that is not there (docs/adr/0005).
|
|
* ================================================================== */
|
|
|
|
#if 0 /* ---- 5A: board WITHOUT a 32.768 kHz crystal (promicro_sx1262) ---- */
|
|
&lfclk {
|
|
k32src = "rc";
|
|
k32src-accuracy-ppm = <250>;
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- 5B: nRF54L, clock nodes the upstream board DTS leaves off (xiao_nrf54l15) ----
|
|
* The split clock driver builds only the clocks that are enabled; the
|
|
* BLE controller does not compile without lfclk. With no LF crystal add
|
|
* the two k32src lines of 5A as well (me25ls02). */
|
|
&xo {
|
|
status = "okay";
|
|
};
|
|
|
|
&lfclk {
|
|
status = "okay";
|
|
};
|
|
#endif
|
|
|
|
|
|
/* ==================================================================
|
|
* SECTION 6: OPTIONAL PERIPHERALS
|
|
*
|
|
* None of these is needed for a working mesh node. Each one switches its
|
|
* feature on by being present; board.conf stays untouched unless noted.
|
|
* ================================================================== */
|
|
|
|
#if 0 /* ---- LEDs ---- */
|
|
/ {
|
|
aliases {
|
|
led0 = &led_green; /* heartbeat */
|
|
led1 = &led_blue; /* unread (companion) */
|
|
lora-tx-led = &led_blue; /* TX blink */
|
|
};
|
|
|
|
leds {
|
|
compatible = "gpio-leds";
|
|
|
|
led_green: led_0 {
|
|
gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
|
|
label = "Green LED";
|
|
};
|
|
|
|
led_blue: led_1 {
|
|
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
|
label = "Blue LED";
|
|
};
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- Battery voltage (rak4631) ----
|
|
*
|
|
* mV = raw * vbat-mv-multiplier / 4096, so the multiplier is the ADC's
|
|
* full-scale voltage in mV times the divider ratio. An individual unit
|
|
* is trimmed at runtime with `set adc.multiplier`.
|
|
*
|
|
* If the divider is switched, label its regulator-fixed node
|
|
* vbat_enable: the firmware turns it on around each read only
|
|
* (t1000_e, heltec_wifi_lora32_v3).
|
|
*
|
|
* Other platforms use the same zephyr,user node with their own ADC
|
|
* channel: xiao_nrf54l15 (gain 1/4), heltec_wifi_lora32_v3 (ESP32; mind
|
|
* that the node labelled adc0 is ADC unit 1). */
|
|
/ {
|
|
zephyr,user {
|
|
io-channels = <&adc 3>;
|
|
vbat-mv-multiplier = <6161>;
|
|
};
|
|
};
|
|
|
|
&adc {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
|
|
channel@3 {
|
|
reg = <3>;
|
|
zephyr,gain = "ADC_GAIN_1_6";
|
|
zephyr,reference = "ADC_REF_INTERNAL";
|
|
zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)>;
|
|
zephyr,input-positive = <NRF_SAADC_AIN3>;
|
|
zephyr,resolution = <12>;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- One button, board WITHOUT a display (t1000_e) ----
|
|
*
|
|
* gpio-keys emits KEY_0. The longpress filter turns it into KEY_A
|
|
* (short) or KEY_F / KEY_POWER (held 1 s: power off). The multi-tap
|
|
* filter counts KEY_A presses:
|
|
* 1 tap → KEY_1 next page (no-op without a display)
|
|
* 2 taps → KEY_B LED heartbeat on/off
|
|
* 3 taps → KEY_D buzzer / notification mode
|
|
* 4 taps → KEY_C GPS on/off
|
|
* 5 taps → KEY_E flood advert (last entry, fires immediately)
|
|
*
|
|
* The sw0 alias makes the button the wake source from System OFF. */
|
|
/ {
|
|
aliases {
|
|
sw0 = &user_button;
|
|
};
|
|
|
|
buttons: buttons {
|
|
compatible = "gpio-keys";
|
|
|
|
user_button: button_0 {
|
|
gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
|
zephyr,code = <INPUT_KEY_0>;
|
|
label = "User Button";
|
|
};
|
|
};
|
|
|
|
user_btn_longpress {
|
|
compatible = "zephyr,input-longpress";
|
|
input = <&buttons>;
|
|
input-codes = <INPUT_KEY_0>;
|
|
short-codes = <INPUT_KEY_A>;
|
|
long-codes = <INPUT_KEY_POWER>;
|
|
long-delay-ms = <1000>;
|
|
};
|
|
|
|
/* No `input` phandle: KEY_A comes from the longpress pseudo-device, not
|
|
* from &buttons, so this filter must listen to every device. */
|
|
user_btn_multitap {
|
|
compatible = "zephcore,input-multi-tap";
|
|
input-codes = <INPUT_KEY_A>;
|
|
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C INPUT_KEY_E>;
|
|
tap-delay-ms = <400>;
|
|
};
|
|
};
|
|
|
|
/* nRF52 only, at the END of the file, and only if a node labelled `buttons`
|
|
* exists (a missing label is a build error). */
|
|
#include "../../common/nrf52_wakeup.dtsi"
|
|
#endif
|
|
|
|
#if 0 /* ---- One button, board WITH a display (rak4631) ----
|
|
*
|
|
* 1 tap → KEY_1 next page
|
|
* 2 taps → KEY_LEFT previous page
|
|
* long press → KEY_ENTER activate the item on the page
|
|
*
|
|
* board.conf: CONFIG_ZEPHCORE_UI_CONFIRM_WINDOW_MS=3000, because two
|
|
* long presses do not fit in the default 500 ms confirm window.
|
|
* Two-button boards map one button straight to KEY_ENTER (thinknode_m1). */
|
|
/ {
|
|
aliases {
|
|
sw0 = &user_button;
|
|
};
|
|
|
|
buttons: buttons {
|
|
compatible = "gpio-keys";
|
|
|
|
user_button: button_0 {
|
|
gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
|
zephyr,code = <INPUT_KEY_0>;
|
|
label = "User Button";
|
|
};
|
|
};
|
|
|
|
user_btn_longpress {
|
|
compatible = "zephyr,input-longpress";
|
|
input = <&buttons>;
|
|
input-codes = <INPUT_KEY_0>;
|
|
short-codes = <INPUT_KEY_A>;
|
|
long-codes = <INPUT_KEY_ENTER>;
|
|
long-delay-ms = <1000>;
|
|
};
|
|
|
|
page_btn_multitap {
|
|
compatible = "zephcore,input-multi-tap";
|
|
input-codes = <INPUT_KEY_A>;
|
|
tap-codes = <INPUT_KEY_1 INPUT_KEY_LEFT>;
|
|
tap-delay-ms = <400>;
|
|
};
|
|
};
|
|
|
|
#include "../../common/nrf52_wakeup.dtsi"
|
|
#endif
|
|
|
|
/* ---- GPS -----------------------------------------------------------
|
|
*
|
|
* Label the GNSS node `gnss`. Drivers in use: "gnss-nmea-generic" (a passive
|
|
* NMEA listener; works with anything) and "luatos,air530z" (CASIC / PCAS
|
|
* receivers: Air530Z, L76K).
|
|
*
|
|
* Power control is separate from the driver. The GPS manager uses whichever
|
|
* of these the board declares; the pins are children of a "gpio-leds" node,
|
|
* named through aliases:
|
|
*
|
|
* gps-enable supply switch; or the module's standby pin when that
|
|
* is the only control the board has (wio_tracker_l1)
|
|
* gps-wakeup module standby pin on a board that ALSO has a supply
|
|
* switch: standby keeps the supply (hot start), a full
|
|
* off cuts it (sensecap_solar)
|
|
* gps-reset hardware reset line
|
|
* gps-resetb active-low reset that must idle as an input with
|
|
* pull-up; left floating it holds an AG3335 in reset
|
|
* gps-vrtc-enable backup (VRTC) supply, kept on for warm starts
|
|
* gps-sleep-int, gps-rtc-int AG3335 sleep / RTC interrupt pins (t1000_e)
|
|
*
|
|
* Nothing else is needed for `set gps standby`: on every board a standby
|
|
* longer than that limit (default one hour) is a full power-off, a shorter
|
|
* one keeps the module's state if the pins above give a way to (gps-wakeup,
|
|
* or gps-vrtc-enable). With gps-enable alone the two are the same.
|
|
*
|
|
* chosen zephcore,gps-power a regulator instead of a pin: a
|
|
* regulator-fixed node, or a PMU rail (heltec_t096,
|
|
* ttgo_tbeam)
|
|
*
|
|
* Do not hand a rail to the GPS manager unless it feeds the GPS alone. A
|
|
* shared rail (sensors, display, a PA boost converter) is hogged on instead
|
|
* (rak4631, rak3401_1watt).
|
|
* ------------------------------------------------------------------- */
|
|
|
|
#if 0 /* ---- GPS A: NMEA module with no power control (rak4631, xiao_nrf54l15) ---- */
|
|
&uart1 {
|
|
status = "okay";
|
|
current-speed = <9600>;
|
|
|
|
gnss: gnss-nmea-generic {
|
|
compatible = "gnss-nmea-generic";
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- GPS B: CASIC receiver, standby pin driven by the driver (wio_tracker_l1) ----
|
|
* The same pin is also exposed as gps-enable so the GPS manager can
|
|
* switch it without going through the driver. */
|
|
/ {
|
|
aliases {
|
|
gps-enable = &gps_enable_pin;
|
|
};
|
|
|
|
gps_en: gps-enable {
|
|
compatible = "gpio-leds";
|
|
|
|
gps_enable_pin: gps_enable {
|
|
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
|
|
label = "GPS Enable";
|
|
};
|
|
};
|
|
};
|
|
|
|
&uart0 {
|
|
current-speed = <9600>;
|
|
|
|
gnss: gnss {
|
|
compatible = "luatos,air530z";
|
|
on-off-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- GPS C: module that needs a power-up sequence first (t1000_e) ----
|
|
* zephyr,deferred-init keeps the driver from starting at boot; the GPS
|
|
* manager sequences the pins, then initialises the device. The T1000-E
|
|
* declares gps-vrtc-enable, gps-rtc-int and gps-resetb the same way. */
|
|
/ {
|
|
aliases {
|
|
gps-enable = &gps_enable_pin;
|
|
gps-reset = &gps_reset_pin;
|
|
};
|
|
|
|
gps_en: gps-enable {
|
|
compatible = "gpio-leds";
|
|
|
|
gps_enable_pin: gps_enable {
|
|
gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
|
|
label = "GPS Enable";
|
|
};
|
|
};
|
|
|
|
gps_rst: gps-reset {
|
|
compatible = "gpio-leds";
|
|
|
|
gps_reset_pin: gps_reset {
|
|
gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
|
|
label = "GPS Reset";
|
|
};
|
|
};
|
|
};
|
|
|
|
&uart0 {
|
|
compatible = "nordic,nrf-uarte";
|
|
status = "okay";
|
|
current-speed = <115200>;
|
|
pinctrl-0 = <&uart0_default>;
|
|
pinctrl-1 = <&uart0_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
|
|
gnss: gnss {
|
|
compatible = "gnss-nmea-generic";
|
|
zephyr,deferred-init;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- GPS D: dedicated GPS rail behind a regulator (heltec_t096) ---- */
|
|
/ {
|
|
chosen {
|
|
zephcore,gps-power = &gps_power;
|
|
};
|
|
|
|
gps_power: gps-power {
|
|
compatible = "regulator-fixed";
|
|
regulator-name = "gps-power";
|
|
enable-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
|
regulator-boot-on;
|
|
startup-delay-us = <10000>;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- OLED on I2C (rak4631; the buffer line is from wio_tracker_l1) ----
|
|
* Compatibles in use: "solomon,ssd1306", "sinowealth,sh1106".
|
|
* A bus that is "nordic,nrf-twim" needs zephyr,concat-buf-size: a page
|
|
* write is 1 command byte + 128 data bytes, and without the buffer the
|
|
* panel ACKs its init and then never shows anything. Harmless on the
|
|
* legacy "nordic,nrf-twi" bus the rak4631 uses. */
|
|
/ {
|
|
chosen {
|
|
zephyr,display = &ssd1306;
|
|
};
|
|
};
|
|
|
|
&i2c0 {
|
|
status = "okay";
|
|
zephyr,concat-buf-size = <256>;
|
|
|
|
ssd1306: ssd1306@3c {
|
|
compatible = "solomon,ssd1306";
|
|
reg = <0x3c>;
|
|
width = <128>;
|
|
height = <64>;
|
|
segment-offset = <0>;
|
|
page-offset = <0>;
|
|
display-offset = <0>;
|
|
multiplex-ratio = <63>;
|
|
segment-remap;
|
|
com-invdir;
|
|
prechargep = <0x22>;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- E-paper on SPI (thinknode_m1) ----
|
|
* board.conf: CONFIG_HEAP_MEM_POOL_SIZE=6144 on nRF. The framebuffer is
|
|
* allocated at boot and a 200x200 panel does not fit the default heap;
|
|
* the only symptom is a blank panel.
|
|
* A panel with its own supply or boost enable gets a regulator-fixed
|
|
* node with regulator-boot-on. TFT panels: heltec_t114, heltec_t096. */
|
|
/ {
|
|
chosen {
|
|
zephyr,display = &epd;
|
|
};
|
|
|
|
mipi_dbi {
|
|
compatible = "zephyr,mipi-dbi-spi";
|
|
spi-dev = <&spi3>;
|
|
dc-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
|
|
reset-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
|
|
epd: ssd16xxfb@0 {
|
|
compatible = "solomon,ssd1681";
|
|
mipi-max-frequency = <4000000>;
|
|
reg = <0>;
|
|
width = <200>;
|
|
height = <200>;
|
|
busy-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
|
|
};
|
|
};
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- I2C sensors and hardware RTC ----
|
|
* sensors-i2c.dtsi declares every supported environment and power
|
|
* sensor; parts that are not fitted fail their probe and are skipped.
|
|
* A board with a BME680 swaps the default BME280 node (rak4631).
|
|
* rtc-i2c.dtsi is opt-in: include it ONLY when a battery-backed RTC is
|
|
* fitted, because its addresses collide with common parts (an IMU at
|
|
* 0x68). A sealed board with no sensor header includes neither. */
|
|
&i2c0 {
|
|
status = "okay";
|
|
|
|
#include "../../common/sensors-i2c.dtsi"
|
|
#include "../../common/rtc-i2c.dtsi"
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- PWM buzzer (thinknode_m1) ----
|
|
* The LABEL buzzer is what enables the buzzer code; the alias is how the
|
|
* code finds the PWM channel. Both are needed. */
|
|
/ {
|
|
aliases {
|
|
buzzer = &buzzer;
|
|
};
|
|
|
|
pwmbuzzer {
|
|
compatible = "pwm-leds";
|
|
|
|
buzzer: buzzer {
|
|
pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
|
|
};
|
|
};
|
|
};
|
|
|
|
&pwm0 {
|
|
status = "okay";
|
|
pinctrl-0 = <&pwm0_default>;
|
|
pinctrl-1 = <&pwm0_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
};
|
|
#endif
|
|
|
|
#if 0 /* ---- QSPI flash, /ext volume (nRF52840: wio_tracker_l1, thinknode_m1) ----
|
|
*
|
|
* With /ext mounted, contacts, channels and blobs move to the external
|
|
* flash; identity and prefs stay on /lfs.
|
|
*
|
|
* Declare it ONLY if the chip is fitted. An upstream board DTS that
|
|
* enables &qspi for a chip your variant lacks must be overridden with
|
|
* status = "disabled", or the driver hangs the boot (rak4631).
|
|
*
|
|
* jedec-id, sfdp-bfp and size (in BITS) are per chip; the values below
|
|
* are a P25Q16H, 2 MB, in single-bit mode. qspi-ext.dtsi adds the /ext
|
|
* mount and defers the flash probe until first use, because a probe at
|
|
* boot can beat a cold supply rail. It must come after the node. */
|
|
&qspi {
|
|
status = "okay";
|
|
|
|
qspi_flash: qspi_flash@0 {
|
|
compatible = "nordic,qspi-nor";
|
|
reg = <0>;
|
|
writeoc = "pp";
|
|
readoc = "fastread";
|
|
sck-frequency = <16000000>;
|
|
jedec-id = [85 60 15];
|
|
sfdp-bfp = [
|
|
e5 20 f1 ff ff ff ff 01 44 eb 08 6b 08 3b 04 bb
|
|
ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52
|
|
10 d8 00 ff
|
|
];
|
|
size = <16777216>;
|
|
has-dpd;
|
|
t-enter-dpd = <3000>;
|
|
|
|
partitions {
|
|
compatible = "fixed-partitions";
|
|
#address-cells = <1>;
|
|
#size-cells = <1>;
|
|
|
|
qspi_storage_partition: partition@0 {
|
|
label = "qspi_storage";
|
|
reg = <0x00000000 0x00200000>;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
#include "../../common/qspi-ext.dtsi"
|
|
#endif
|
|
|
|
#if 0 /* ---- Latched supply rail: true power-off (muziworks_r1neo) ----
|
|
*
|
|
* Only for a board with no mechanical power switch that keeps its own
|
|
* supply alive through a "hold" GPIO. There, sys_poweroff() alone is not
|
|
* a power-off: GPIO output latches persist in System OFF, so the rail
|
|
* stays up and drains the battery. The pins listed here are released as
|
|
* the very last step of shutdown, in order: loads first, rail latch
|
|
* LAST. They are usually the pins a gpio-hog asserts at boot, which is
|
|
* intended. */
|
|
/ {
|
|
poweroff_gpios: poweroff-gpios {
|
|
compatible = "zephcore,poweroff-gpios";
|
|
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>, /* radio module power */
|
|
<&gpio0 29 GPIO_ACTIVE_HIGH>, /* I/O controller "MCU on" */
|
|
<&gpio0 13 GPIO_ACTIVE_HIGH>; /* rail latch: cuts power */
|
|
};
|
|
};
|
|
#endif
|