mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-09 17:25:39 +00:00
add meshnology w12
This commit is contained in:
@@ -70,6 +70,7 @@ ESP32_boards=(
|
||||
heltec_wifi_lora32_v43/esp32s3/procpu
|
||||
heltec_wireless_tracker/esp32s3/procpu
|
||||
heltec_wireless_tracker_v2/esp32s3/procpu
|
||||
meshnology_w12/esp32s3/procpu
|
||||
ttgo_tbeam/esp32/procpu
|
||||
)
|
||||
|
||||
|
||||
+7
-13
@@ -231,18 +231,12 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/patches/modules/hal-espressif)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Copy new files into Zephyr tree
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/patches/zephyr-new)
|
||||
file(GLOB_RECURSE ZEPHCORE_NEW_FILES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/patches/zephyr-new
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patches/zephyr-new/*)
|
||||
foreach(REL_PATH ${ZEPHCORE_NEW_FILES})
|
||||
set(SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/patches/zephyr-new/${REL_PATH})
|
||||
set(DST_FILE ${ZEPHYR_DIR}/${REL_PATH})
|
||||
configure_file(${SRC_FILE} ${DST_FILE} COPYONLY)
|
||||
message(STATUS " [zephyr-new] ${REL_PATH}")
|
||||
endforeach()
|
||||
endif()
|
||||
# Copy new files into Zephyr tree.
|
||||
# Shared with sysbuild/CMakeLists.txt, which must do the same thing before
|
||||
# MCUboot's devicetree pass — see the module for why.
|
||||
set(ZEPHCORE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(ZEPHCORE_ZEPHYR_DIR ${ZEPHYR_DIR})
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/zephyr_new_files.cmake)
|
||||
|
||||
# Custom board root: boards/<mcu>/<board>/ discovered via BOARD_ROOT
|
||||
list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -329,7 +323,7 @@ if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wi
|
||||
set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf")
|
||||
elseif(DEFINED BOARD_QUALIFIERS AND BOARD_QUALIFIERS MATCHES ".*nrf52.*")
|
||||
set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf")
|
||||
elseif(BOARD MATCHES ".*esp32.*" OR BOARD MATCHES "station_g2" OR BOARD MATCHES "thinknode_m9" OR BOARD MATCHES "lilygo_tlora_c6" OR BOARD MATCHES "heltec_wifi_lora32_v3" OR BOARD MATCHES "heltec_wifi_lora32_v4")
|
||||
elseif(BOARD MATCHES ".*esp32.*" OR BOARD MATCHES "station_g2" OR BOARD MATCHES "thinknode_m9" OR BOARD MATCHES "lilygo_tlora_c6" OR BOARD MATCHES "heltec_wifi_lora32_v3" OR BOARD MATCHES "heltec_wifi_lora32_v4" OR BOARD MATCHES "meshnology_w12")
|
||||
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")
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
config HEAP_MEM_POOL_ADD_SIZE_BOARD
|
||||
int
|
||||
default 4096
|
||||
@@ -0,0 +1,3 @@
|
||||
config BOARD_MESHNOLOGY_W12
|
||||
select SOC_ESP32S3_WROOM_N16R8
|
||||
select SOC_ESP32S3_PROCPU if BOARD_MESHNOLOGY_W12_ESP32S3_PROCPU
|
||||
@@ -0,0 +1,7 @@
|
||||
if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*")
|
||||
set(OPENOCD OPENOCD-NOTFOUND)
|
||||
endif()
|
||||
find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH)
|
||||
|
||||
include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Meshnology W12 "WiFi LoRa 32 V5" — ESP32-S3R8 + LR2021 + GC1109 FEM
|
||||
#
|
||||
# Hardware (schematic W12-MB-V0.2, archived in devdocs/w12/vendor/):
|
||||
# - ESP32-S3R8 (WROOM-1 N16R8): 16 MB QIO flash, 8 MB OPI PSRAM
|
||||
# - LR2021 on SPI2 (GPIO8 NSS, 9 SCK, 10 MOSI, 11 MISO, 12 RST, 13 BUSY),
|
||||
# IRQ on GPIO14 = chip DIO8, plain crystal (no TCXO)
|
||||
# - GC1109 sub-GHz PA/LNA on chip DIO9/10/11, rail enable GPIO4 (active HIGH)
|
||||
# - RFX2402E 2.4 GHz PA on chip DIO5/6, rail enable GPIO3 (held LOW, unused)
|
||||
# - SSD1315 128x64 bicolour OLED @ 0x3C on I2C0 (SDA 17, SCL 18, RST 47)
|
||||
# - Battery ADC GPIO1 = ADC1_CH0, divider enable GPIO2 (active HIGH), ratio 4.90
|
||||
# - Vext GPIO45 active LOW; user button GPIO0; RGB LED GPIO46 (unused, see below)
|
||||
# - GNSS header on UART1 (unpopulated from the factory)
|
||||
#
|
||||
# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → board.conf
|
||||
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="Meshnology W12"
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="Meshnology W12 LR2021"
|
||||
|
||||
CONFIG_ZEPHCORE_RADIO_LR2021=y
|
||||
|
||||
# Flash — 16 MB (override the 4 MB esp32_common.conf default)
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
|
||||
# 8 MB OPI PSRAM. Enable is auto-detected from DTS by Kconfig.psram; only the
|
||||
# mode is set here, same as station_g2 / thinknode_m9 / xiao_esp32s3.
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
|
||||
# ========== TX power: the number here is CHIP output, not antenna output ==========
|
||||
#
|
||||
# The GC1109 sits between the LR2021 and the antenna and adds roughly 26 dB.
|
||||
# The vendor rates the finished board at 30 +/- 1 dBm conducted, and MeshCore's
|
||||
# variant notes the part's absolute maximum TX-port input is +5 dBm with full
|
||||
# saturation already reached around 3-4 dBm. So 4 dBm at the chip is both the
|
||||
# most that is useful and the most that is safe: beyond it the extra drive turns
|
||||
# into distortion and heat, not range.
|
||||
#
|
||||
# Cap and default are deliberately the same value. Unlike Station G2 (default 15,
|
||||
# cap 19) there is no useful headroom above saturation to leave a user, and the
|
||||
# knob still spans -9..4 downward — roughly 17..30 dBm at the antenna — which is
|
||||
# the range that matters for staying inside a regional ERP limit. Anyone setting
|
||||
# this for EU 868 should note that even -9 dBm at the chip is well above 14 dBm
|
||||
# ERP once the FEM has had its way.
|
||||
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=4
|
||||
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=4
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Meshnology W12 — ZephCore overlay
|
||||
*
|
||||
* The board's own DTS (meshnology_w12_procpu.dts) already declares the LR2021,
|
||||
* the SSD1315, the FEM rails, the battery ADC, the GNSS UART and the button.
|
||||
* This overlay only adds the ZephCore integration on top: the runtime sensor
|
||||
* bus, the LittleFS mount, the button gesture chain and the USB companion node.
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
/* Button chain — same mapping as RAK4631 / Heltec V3.
|
||||
* GPIO0 is the only button the firmware sees; the second hole in the
|
||||
* case is the ESP32 EN/reset key, which never reaches software. */
|
||||
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>;
|
||||
};
|
||||
|
||||
chosen {
|
||||
/* Plain-UART companion backend (CONFIG_ZEPHCORE_COMPANION_SERIAL).
|
||||
* uart0 is GPIO43/44 on the expansion header — there is no bridge
|
||||
* chip, so this is a wired-header option rather than the USB-C port.
|
||||
* Inert unless that conf is built. */
|
||||
zephcore,companion-uart = &uart0;
|
||||
};
|
||||
};
|
||||
|
||||
/* Runtime-probed I2C sensors share the OLED bus, which is broken out on the
|
||||
* display connector and the expansion header. */
|
||||
&i2c0 {
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash partitions live in partitions.overlay (this dir) so the identical map
|
||||
* is fed to both the app and the MCUboot image — see that file and
|
||||
* sysbuild/CMakeLists.txt.
|
||||
*/
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
|
||||
/* USB OTG companion transport. Including this dtsi is also the signal that
|
||||
* CMakeLists.txt greps for to auto-enable boards/common/esp32s3_usb.conf on
|
||||
* companion builds, so the companion speaks its protocol over the USB-C port.
|
||||
*
|
||||
* That matters more here than on most boards: the W12 has no USB-UART bridge,
|
||||
* so the USB-C port is the ONLY wired route in. The cost is the documented one
|
||||
* — once the port is USB OTG CDC-ACM rather than USB Serial/JTAG, esptool can
|
||||
* no longer auto-reset the chip into download mode. Use `start dfu`, an
|
||||
* Arduino-style 1200-baud touch (the vendor's own PlatformIO board JSON sets
|
||||
* use_1200bps_touch for the same reason), or hold BOOT while plugging in.
|
||||
*
|
||||
* The console reroute to uart0 lives in the auto-paired esp32s3_usb.overlay and
|
||||
* applies only on those companion builds. Do NOT include
|
||||
* esp32s3_console_uart0.dtsi here — repeater and debug builds keep their USB
|
||||
* Serial/JTAG console, which is the only console they have. */
|
||||
#include "../../common/esp32s3_usb_otg.dtsi"
|
||||
@@ -0,0 +1,6 @@
|
||||
board:
|
||||
name: meshnology_w12
|
||||
full_name: Meshnology W12 LR2021
|
||||
vendor: meshnology
|
||||
socs:
|
||||
- name: esp32s3
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Meshnology W12 — Pin Control Definitions
|
||||
*
|
||||
* Verified against vendor schematic W12-MB-V0.2 (devdocs/w12/vendor/).
|
||||
*
|
||||
* UART0: TX=GPIO43, RX=GPIO44
|
||||
* I2C0: SDA=GPIO17, SCL=GPIO18 (SSD1315 OLED + expansion header)
|
||||
* SPI2: SCLK=GPIO9, MOSI=GPIO10, MISO=GPIO11 (LR2021 LoRa)
|
||||
* UART1: TX=GPIO38, RX=GPIO39 (GNSS header, unpopulated from factory)
|
||||
*
|
||||
* The FEM control pins (GPIO3/GPIO4) and the LoRa NSS/RST/BUSY/IRQ lines are
|
||||
* plain GPIO — no pinctrl entries needed.
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/esp32s3-pinctrl.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h>
|
||||
|
||||
&pinctrl {
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
pinmux = <UART0_TX_GPIO43>;
|
||||
output-high;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <UART0_RX_GPIO44>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
/* GNSS header. The vendor pin table names these from the GNSS module's
|
||||
* point of view — "GNSS_RX" (GPIO38) is the module's RX, i.e. the SoC's
|
||||
* TX, and "GNSS_TX" (GPIO39) is the SoC's RX. Module-perspective naming is
|
||||
* the usual trap here (same one as lilygo_timpulse_plus and the RAK3401);
|
||||
* the schematic net names settle it and this is the wiring that follows
|
||||
* from them. */
|
||||
uart1_default: uart1_default {
|
||||
group1 {
|
||||
pinmux = <UART1_TX_GPIO38>;
|
||||
output-high;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <UART1_RX_GPIO39>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
pinmux = <I2C0_SDA_GPIO17>,
|
||||
<I2C0_SCL_GPIO18>;
|
||||
drive-open-drain;
|
||||
};
|
||||
};
|
||||
|
||||
spim2_default: spim2_default {
|
||||
group1 {
|
||||
pinmux = <SPIM2_MISO_GPIO11>,
|
||||
<SPIM2_SCLK_GPIO9>;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <SPIM2_MOSI_GPIO10>;
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* Meshnology W12 "WiFi LoRa 32 V5" — ZephCore procpu DTS
|
||||
*
|
||||
* Every pin and polarity below is taken from the vendor schematic
|
||||
* W12-MB-V0.2 and the vendor pin-assignment sheet, both archived in
|
||||
* devdocs/w12/vendor/. Several of them contradict what the Arduino-side
|
||||
* variants for this board claim; the schematic decides every time — see
|
||||
* devdocs/w12/HANDOVER_MESHNOLOGY_W12.md for the list.
|
||||
*
|
||||
* Hardware:
|
||||
* MCU: ESP32-S3R8 (WROOM-1 N16R8) — 16 MB QIO flash, 8 MB OPI PSRAM
|
||||
* Radio: Semtech LR2021 on SPI2, plain 32 MHz crystal (no TCXO)
|
||||
* FEM: GC1109 sub-GHz PA/LNA (~30 dBm out) + RFX2402E 2.4 GHz PA
|
||||
* OLED: SSD1315 128x64 (SSD1306-compatible) on I2C0, bicolour glass
|
||||
* Button: GPIO0 (BOOT doubles as the user key)
|
||||
* BatADC: GPIO1 = ADC1_CH0, divider enable GPIO2 active-HIGH
|
||||
* Vext: GPIO45 active-LOW (AO3401 P-FET gating an LDO enable)
|
||||
* GNSS: header on UART1, unpopulated from the factory
|
||||
* Console: native USB Serial/JTAG (there is no USB-UART bridge)
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa ctrl: RESET=12, BUSY=13, IRQ=14 (chip DIO8)
|
||||
* FEM rails: sub-GHz enable GPIO4, 2.4 GHz enable GPIO3 (both active-HIGH)
|
||||
* FEM switch: chip DIO9=CTX, DIO10=CPS, DIO11=CSD, DIO5/6 = 2.4 GHz TX/RX EN
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <espressif/esp32s3/esp32s3_wroom_n16r8.dtsi>
|
||||
#include "meshnology_w12-pinctrl.dtsi"
|
||||
#include <espressif/partitions_0x0_default_16M.dtsi>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/dt-bindings/adc/adc.h>
|
||||
|
||||
/ {
|
||||
model = "Meshnology W12 PROCPU";
|
||||
compatible = "meshnology,w12";
|
||||
|
||||
aliases {
|
||||
uart-0 = &uart0;
|
||||
i2c-0 = &i2c0;
|
||||
lora0 = &lora0;
|
||||
sw0 = &button0;
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
button0: button_0 {
|
||||
gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "USER Key";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Vext rail — GPIO45, ACTIVE LOW.
|
||||
*
|
||||
* Schematic sheet 1: GPIO45 drives the gate of Q1 (AO3401, P-channel)
|
||||
* through R3 1k. Q1's source sits on VDD_3V3 with R2 100k gate-to-source
|
||||
* holding it off, and its drain feeds the EN pin of U4 (TLV75733 LDO),
|
||||
* which R5 100k pulls to ground. So GPIO45 LOW turns the P-FET on, pulls
|
||||
* EN high and brings VEXT_3V3 up; GPIO45 high or floating leaves the rail
|
||||
* dead. That makes this active-LOW, and it makes the rail OFF by default.
|
||||
*
|
||||
* MeshCore's variant declares PIN_VEXT_EN_ACTIVE=HIGH, which is wrong for
|
||||
* this circuit. Do not "fix" this to active-HIGH to match it without
|
||||
* re-reading sheet 1 — the whole peripheral rail, OLED included, hangs
|
||||
* off this pin.
|
||||
*
|
||||
* GPIO45 is also an ESP32-S3 strapping pin (VDD_SPI voltage select) with
|
||||
* an internal pull-down at reset. That default reads as 0, which is the
|
||||
* same level we drive to enable the rail, so there is no boot conflict —
|
||||
* but never add a pull-up here, it would flip the strap. */
|
||||
vext_enable: vext-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vext";
|
||||
enable-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; /* GPIO45 */
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/* Sub-GHz front end rail — GPIO4 (PA_EN_M), ACTIVE HIGH.
|
||||
*
|
||||
* Drives the EN pin of the adjustable regulator that supplies the GC1109
|
||||
* (net VR_PA). Its pull-up R56 is marked NC on the schematic, so the rail
|
||||
* is off until firmware asserts this — the radio is deaf and mute without
|
||||
* it, in both directions, because the GC1109 carries the RX LNA too.
|
||||
*
|
||||
* startup-delay-us matches the 100 ms MeshCore waits after enabling the
|
||||
* FEM before touching the radio. Expressed as a regulator startup delay it
|
||||
* is paid once at regulator init, which runs at priority 75 — ahead of the
|
||||
* LoRa driver — instead of being a sleep on the radio init path. */
|
||||
fem_lf_power: fem-lf-power {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "fem-lf";
|
||||
enable-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; /* GPIO4 = PA_EN_M */
|
||||
startup-delay-us = <100000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
/* 2.4 GHz front end rail — GPIO3 (PA_EN_G), ACTIVE HIGH, deliberately
|
||||
* left DISABLED. ZephCore is sub-GHz only, so the RFX2402E never needs
|
||||
* power, and leaving its rail up would burn current for nothing.
|
||||
*
|
||||
* This is a regulator rather than a comment because an undriven GPIO3
|
||||
* floats: R38 (the EN pull-up) is marked NC, so nothing else defines the
|
||||
* level. regulator_fixed_init() configures the enable pin
|
||||
* GPIO_OUTPUT_INACTIVE when the node has neither regulator-boot-on nor
|
||||
* regulator-always-on, which actively drives GPIO3 LOW at boot. That is
|
||||
* the entire purpose of this node — do not add boot-on/always-on. */
|
||||
fem_hf_power: fem-hf-power {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "fem-hf";
|
||||
enable-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; /* GPIO3 = PA_EN_G */
|
||||
};
|
||||
|
||||
/* Battery divider enable — GPIO2, ACTIVE HIGH.
|
||||
* GPIO2 -> R52 1k -> base of Q7 (S8050 NPN); Q7's collector pulls the gate
|
||||
* of Q6 (AO3401A P-FET) down through R48 1k, switching BAT onto the
|
||||
* R50 390K / R51 100K divider. Driving GPIO2 high therefore enables the
|
||||
* divider; undriven, the divider is open and GPIO1 reads a hard 0 mV.
|
||||
* ZephyrBoard toggles this per reading, so the divider draws nothing
|
||||
* between samples. */
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; /* GPIO2 = ADC_CTRL */
|
||||
};
|
||||
|
||||
/* GNSS module power — GPIO48 (GNSS_CTRL), ACTIVE LOW.
|
||||
* The header is unpopulated on shipping units; the node is unconditional
|
||||
* so a user-fitted module just works, exactly like the RAK4631's optional
|
||||
* RAK1910. With nothing fitted the driver simply never sees a fix. */
|
||||
gps_en: gps-enable {
|
||||
compatible = "gpio-leds";
|
||||
gps_enable_pin: gps_enable {
|
||||
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; /* GPIO48 */
|
||||
label = "GNSS Enable";
|
||||
};
|
||||
};
|
||||
|
||||
/* Battery ADC — ZephCore reads this via zephyr,user { io-channels }.
|
||||
* Multiplier = internal reference (1100 mV) x divider ratio 4.90
|
||||
* ((390K + 100K) / 100K, schematic R50/R51) = 5390. */
|
||||
zephyr,user {
|
||||
io-channels = <&adc0 0>;
|
||||
vbat-mv-multiplier = <5390>;
|
||||
};
|
||||
|
||||
aliases {
|
||||
gps-enable = &gps_enable_pin;
|
||||
};
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram1;
|
||||
/* There is no USB-UART bridge on this board — GPIO43/44 only reach
|
||||
* the expansion header — so the stock console is USB Serial/JTAG.
|
||||
* A companion build pulls in boards/common/esp32s3_usb.conf, which
|
||||
* hands D+/D- to USB OTG CDC-ACM and reroutes this console to
|
||||
* uart0 on the header. */
|
||||
zephyr,console = &usb_serial;
|
||||
zephyr,shell-uart = &usb_serial;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
zephyr,bt-hci = &esp32_bt_hci;
|
||||
zephyr,display = &ssd1306_128x64;
|
||||
};
|
||||
};
|
||||
|
||||
/* Battery ADC on adc0 (ADC unit 1 -> GPIO1 = ADC1_CH0). The node *labelled*
|
||||
* adc0 is unit 1; the node labelled adc1 is unit 2 (GPIO11 = LR2021 MISO).
|
||||
* The channel@0 node is required — without it adc_channel_setup_dt() fails and
|
||||
* getBattMilliVolts() returns 0 before ever performing a conversion.
|
||||
* ADC_GAIN_1 (0 dB) with ADC_REF_INTERNAL (~1100 mV): a 3.0-4.2 V cell lands at
|
||||
* 612-857 mV after the 4.90 divider, comfortably inside range. */
|
||||
&adc0 {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
zephyr,gain = "ADC_GAIN_1";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
||||
|
||||
/* ADC unit 2 (label adc1) is unused; keep it disabled so nothing can claim
|
||||
* GPIO11 (LR2021 MISO) as an ADC pad. */
|
||||
&adc1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&usb_serial {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
current-speed = <115200>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
current-speed = <9600>;
|
||||
pinctrl-0 = <&uart1_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
gnss: gnss-nmea-generic {
|
||||
compatible = "gnss-nmea-generic";
|
||||
};
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
/* SSD1315 — register-compatible with the SSD1306 the Zephyr driver binds
|
||||
* to; the difference is the panel glass (bicolour: top 16 rows yellow),
|
||||
* which is invisible to the driver. Same part as lilygo_timpulse_plus.
|
||||
*
|
||||
* Reset is GPIO47, not GPIO21. The vendor pin sheet lists IO47 = OLED/LCD
|
||||
* RST and IO21 = OLED/LCD CS (CS belongs to the SPI-LCD option this
|
||||
* connector also supports and the shipping I2C panel does not use).
|
||||
* MeshCore's pins_arduino.h has RST_OLED = 21, which is the CS pin. */
|
||||
ssd1306_128x64: display-controller@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;
|
||||
inversion-on;
|
||||
prechargep = <0x22>;
|
||||
reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; /* GPIO47 */
|
||||
vin-supply = <&vext_enable>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi2 {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-0 = <&spim2_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
/* The LR2021 driver takes NSS from here but strips CS out of its own
|
||||
* spi_dt_spec and toggles the pin itself, because the chip needs NSS held
|
||||
* across a two-window read. The ESP32 SPI controller therefore never
|
||||
* drives CS and the two cannot fight.
|
||||
*
|
||||
* No overrun-character property, and none is needed: the LR2021 HAL clocks
|
||||
* NULL TX buffers on its read windows and the chip parses those bytes, so
|
||||
* MOSI must idle at 0x00 (its NOP) rather than 0xff. On Nordic that takes
|
||||
* an explicit overrun-character; spi_esp32_spim allocates a zero-filled TX
|
||||
* buffer for any RX-only transfer, so ESP32 already sends 0x00. */
|
||||
cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; /* NSS = GPIO8 */
|
||||
|
||||
lora0: lora@0 {
|
||||
compatible = "semtech,lr2021";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <8000000>;
|
||||
|
||||
reset-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; /* GPIO12 */
|
||||
busy-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; /* GPIO13 */
|
||||
dio1-gpios = <&gpio0 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;/* GPIO14 */
|
||||
|
||||
/* Chip DIO8 -> GPIO14 (schematic net IO14_LORA_INT2). DIO7 goes to
|
||||
* GPIO7 as a second IRQ line (IO7_LORA_INT1) that ZephCore does not
|
||||
* use. DIO5 is NOT free for interrupts here — it drives the 2.4 GHz
|
||||
* PA's TX enable — so leaving irq-dio at its default of 9 would also
|
||||
* be wrong. */
|
||||
irq-dio = <8>;
|
||||
|
||||
/* No tcxo-voltage-mv: schematic sheet 3 shows a plain crystal on
|
||||
* XTA/XTB (pins 4/5) and pin 6 wired to the VNTC net, not a TCXO
|
||||
* supply. Setting a TCXO voltage on a board without one wedges the
|
||||
* chip at HF-XOSC startup — that is what happened on the
|
||||
* promicro_lr2021 module. */
|
||||
|
||||
rx-boosted;
|
||||
|
||||
/* RF switch — the LR2021 drives the whole front end itself.
|
||||
*
|
||||
* DIO5 (bit 0) = RFX2402E 2.4 GHz TX_EN
|
||||
* DIO6 (bit 1) = RFX2402E 2.4 GHz RX_EN
|
||||
* DIO9 (bit 4) = GC1109 CTX (transmit path select)
|
||||
* DIO10 (bit 5) = GC1109 CPS (PA vs bypass path)
|
||||
* DIO11 (bit 6) = GC1109 CSD (shutdown, HIGH = awake)
|
||||
*
|
||||
* CSD and CPS carry 10k pull-downs (R26/R27), so the GC1109 boots
|
||||
* into shutdown and stays there until these are configured. That is
|
||||
* why the driver's DIO5..DIO8-only loop had to be widened to
|
||||
* DIO5..DIO11 for this board: with DIO9/10/11 unconfigured the node
|
||||
* looks healthy on every register read and hears nothing.
|
||||
*
|
||||
* RX is split per band because the two front ends are mutually
|
||||
* exclusive: sub-GHz RX wakes the GC1109 (CSD high, CTX low = LNA
|
||||
* path), while 2.4 GHz RX must leave it in shutdown and enable the
|
||||
* RFX2402E instead. ZephCore only ever uses the sub-GHz side; the HF
|
||||
* masks are here so the table is a faithful description of the
|
||||
* hardware rather than a half-truth. */
|
||||
rfswitch-enable = <0x73>; /* DIO5,6,9,10,11 */
|
||||
rfswitch-standby = <0x00>; /* everything off */
|
||||
rfswitch-rx-lf = <0x40>; /* DIO11: GC1109 out of shutdown, LNA */
|
||||
rfswitch-rx-hf = <0x02>; /* DIO6: 2.4 GHz LNA, GC1109 shut down */
|
||||
rfswitch-tx = <0x70>; /* DIO9|10|11: GC1109 full PA */
|
||||
rfswitch-tx-hp = <0x01>; /* DIO5: 2.4 GHz PA */
|
||||
};
|
||||
};
|
||||
|
||||
&timer0 { status = "okay"; };
|
||||
&timer1 { status = "okay"; };
|
||||
&timer2 { status = "okay"; };
|
||||
&timer3 { status = "okay"; };
|
||||
|
||||
&wdt0 { status = "okay"; };
|
||||
&trng0 { status = "okay"; };
|
||||
|
||||
&esp32_bt_hci { status = "okay"; };
|
||||
&wifi { status = "okay"; };
|
||||
@@ -0,0 +1,12 @@
|
||||
# Meshnology W12 — minimal Zephyr defconfig (procpu)
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_CLOCK_CONTROL=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Flash partition layout — SHARED by the app image and MCUboot.
|
||||
*
|
||||
* Fed to BOTH images (app via EXTRA_DTC_OVERLAY_FILE, MCUboot via
|
||||
* mcuboot_EXTRA_DTC_OVERLAY_FILE in sysbuild/CMakeLists.txt) so their flash maps
|
||||
* are identical — otherwise MCUboot stages/looks for the OTA image at a different
|
||||
* address than the app writes it to and OTA silently reverts on reboot.
|
||||
*
|
||||
* slot0 starts at 0x10000 (right after the 64KB MCUboot region), matching the
|
||||
* Arduino/ESP-IDF app offset (Mesh America "flash-update" compatible). sys_partition
|
||||
* is reclaimed. Slots are equal size and slot1 ends exactly on the unchanged
|
||||
* storage/lfs offsets, so a -merged reflash keeps identity/prefs/contacts/BLE-bonds.
|
||||
*
|
||||
* 16MB layout.
|
||||
*/
|
||||
/delete-node/ &sys_partition;
|
||||
/delete-node/ &slot0_lpcore_partition;
|
||||
/delete-node/ &slot1_lpcore_partition;
|
||||
/delete-node/ &storage_partition;
|
||||
/delete-node/ &scratch_partition;
|
||||
/delete-node/ &coredump_partition;
|
||||
/delete-node/ &slot0_partition;
|
||||
/delete-node/ &slot1_partition;
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,settings-partition = &storage_partition;
|
||||
};
|
||||
};
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
/* App slots — equal size (swap-mode compatible), slot0 at 0x10000. */
|
||||
slot0_partition: partition@10000 {
|
||||
label = "image-0";
|
||||
reg = <0x10000 0x7C6000>;
|
||||
};
|
||||
slot1_partition: partition@7D6000 {
|
||||
label = "image-1";
|
||||
reg = <0x7D6000 0x7C6000>;
|
||||
};
|
||||
/* BLE bond NVS — offset unchanged so bonds survive the reflash. */
|
||||
storage_partition: partition@F9C000 {
|
||||
label = "storage";
|
||||
reg = <0xF9C000 0x4000>;
|
||||
};
|
||||
/* LittleFS (identity/prefs/contacts) — offset unchanged. */
|
||||
lfs_partition: partition@FA0000 {
|
||||
label = "lfs";
|
||||
reg = <0xFA0000 0x60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -51,9 +51,17 @@ SWD flash: `west flash` (requires J-Link, pyocd, or nrfjprog connected).
|
||||
| Heltec Wireless Tracker V2 | `west build -b heltec_wireless_tracker_v2/esp32s3/procpu zephcore` | `west flash` |
|
||||
| LilyGo T-Beam v1.2 | `west build -b ttgo_tbeam/esp32/procpu zephcore` | `west flash` |
|
||||
| ThinkNode M9 | `west build -b thinknode_m9/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Meshnology W12 (LR2021) | `west build -b meshnology_w12/esp32s3/procpu zephcore` | `west flash` |
|
||||
|
||||
**Heltec V3 console:** ZephCore routes console/shell to `uart0` on V3. Use the UART serial port for boot logs and CLI.
|
||||
|
||||
**Meshnology W12:** the only board here with an LR2021 *and* an external PA, and
|
||||
the only ESP32 board whose TX power is capped well below the chip maximum —
|
||||
4 dBm at the chip is ~30 dBm at the antenna through the GC1109 front end. It has
|
||||
no USB-UART bridge, so esptool cannot auto-reset a companion build into download
|
||||
mode; use `start dfu`, a 1200-baud touch, or hold BOOT. Full port notes and the
|
||||
vendor schematic live in `devdocs/w12/`.
|
||||
|
||||
**Heltec V4.2 vs V4.3:** The hardware revision is printed on the PCB silkscreen. If
|
||||
unclear, check GPIO2's default pull: the V4.2 GC1109 PA has an internal pull-down
|
||||
(GPIO2 reads LOW at boot), while the V4.3 KCT8103L PA has an internal pull-up
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Copy patches/zephyr-new/* into the Zephyr tree.
|
||||
#
|
||||
# These are whole files ZephCore adds to Zephyr that have no upstream to patch
|
||||
# against — today the LR11xx and LR20xx LoRa drivers and their devicetree
|
||||
# bindings. They are copied rather than patched because there is nothing to
|
||||
# apply a diff to.
|
||||
#
|
||||
# This lives in its own module because it has to run from TWO places, and the
|
||||
# order matters:
|
||||
#
|
||||
# - zephcore/CMakeLists.txt, for the application image.
|
||||
# - zephcore/sysbuild/CMakeLists.txt, BEFORE find_package(Sysbuild).
|
||||
#
|
||||
# Under --sysbuild, sysbuild configures the MCUboot image first, and MCUboot
|
||||
# runs a full devicetree pass over the same board DTS the app uses. If the
|
||||
# copy only happened in the app's CMakeLists, MCUboot's DTS pass would see
|
||||
# whatever version of these bindings a previous build happened to leave behind
|
||||
# — or, on a clean workspace, none at all. Editing a vendored binding then
|
||||
# fails the MCUboot image with "not declared in 'properties:'" while the app
|
||||
# image would have been perfectly happy, and the error points at the copy in
|
||||
# the Zephyr tree rather than at the real source in patches/zephyr-new.
|
||||
#
|
||||
# configure_file(... COPYONLY) is a no-op when the contents already match, so
|
||||
# running this twice per configure costs nothing and never churns timestamps.
|
||||
#
|
||||
# Expects ZEPHCORE_SOURCE_DIR and ZEPHCORE_ZEPHYR_DIR to be set by the caller.
|
||||
|
||||
if(EXISTS ${ZEPHCORE_SOURCE_DIR}/patches/zephyr-new)
|
||||
file(GLOB_RECURSE ZEPHCORE_NEW_FILES
|
||||
RELATIVE ${ZEPHCORE_SOURCE_DIR}/patches/zephyr-new
|
||||
${ZEPHCORE_SOURCE_DIR}/patches/zephyr-new/*)
|
||||
foreach(REL_PATH ${ZEPHCORE_NEW_FILES})
|
||||
configure_file(${ZEPHCORE_SOURCE_DIR}/patches/zephyr-new/${REL_PATH}
|
||||
${ZEPHCORE_ZEPHYR_DIR}/${REL_PATH} COPYONLY)
|
||||
message(STATUS " [zephyr-new] ${REL_PATH}")
|
||||
endforeach()
|
||||
endif()
|
||||
@@ -61,7 +61,12 @@ struct lr20xx_config {
|
||||
/* RF switch DIO bitmasks (bit 0 = DIO5, bit 1 = DIO6, ...) */
|
||||
uint8_t rfswitch_enable;
|
||||
uint8_t rfswitch_standby;
|
||||
uint8_t rfswitch_rx;
|
||||
/* RX masks are split per band: a front end that shuts its sub-GHz PA
|
||||
* down during 2.4 GHz RX (Meshnology W12 / GC1109 CSD) needs the two
|
||||
* to differ. Boards that set only the combined `rfswitch-rx` get the
|
||||
* same mask in both, which is the pre-split behaviour. */
|
||||
uint8_t rfswitch_rx_lf;
|
||||
uint8_t rfswitch_rx_hf;
|
||||
uint8_t rfswitch_tx;
|
||||
uint8_t rfswitch_tx_hp;
|
||||
};
|
||||
@@ -350,19 +355,45 @@ lr20xx_irq_dio_pull(const struct lr20xx_config *cfg)
|
||||
|
||||
/* ── Configure RF switch DIOs ───────────────────────────────────────── */
|
||||
|
||||
/* DIO5..DIO11 inclusive — the full RF-switch-capable range on this chip.
|
||||
* Bit i of every rfswitch-* mask is DIO(5 + i), so the masks stay uint8_t. */
|
||||
#define LR20XX_RFSWITCH_DIO_COUNT \
|
||||
(LR20XX_SYSTEM_DIO_11 - LR20XX_SYSTEM_DIO_5 + 1)
|
||||
|
||||
static void lr20xx_configure_rfswitch(void *ctx, const struct lr20xx_config *cfg)
|
||||
{
|
||||
/* LR20xx RF switch uses per-DIO configuration.
|
||||
* DIO5..DIO8 map to enable bitmask bits 0..3.
|
||||
* DIO5..DIO11 map to enable bitmask bits 0..6 (the chip has no RF
|
||||
* switch DIOs outside 5..11 — see lr20xx_system_dio_t).
|
||||
* For each enabled DIO, compute which operational modes
|
||||
* should drive it HIGH by looking at the per-mode bitmasks. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
* should drive it HIGH by looking at the per-mode bitmasks.
|
||||
*
|
||||
* This used to stop at bit 3 (DIO5..DIO8), which silently dropped the
|
||||
* top three DIOs from any board that used them: the enable bit was set
|
||||
* in devicetree, the loop never reached it, so the DIO kept its default
|
||||
* function and the front end it drives never switched. The Meshnology
|
||||
* W12 puts its entire sub-GHz front end there (DIO9 = GC1109 CTX,
|
||||
* DIO10 = CPS, DIO11 = CSD), and with those three left unconfigured the
|
||||
* FEM stays in the shutdown its 10k pull-downs assert at reset — the
|
||||
* node is both deaf and mute while every register readback looks fine. */
|
||||
for (int i = 0; i < LR20XX_RFSWITCH_DIO_COUNT; i++) {
|
||||
if (!(cfg->rfswitch_enable & BIT(i))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lr20xx_system_dio_t dio = (lr20xx_system_dio_t)(LR20XX_SYSTEM_DIO_5 + i);
|
||||
|
||||
/* Never repurpose the interrupt line. A board that sets the IRQ
|
||||
* DIO's bit in rfswitch-enable by mistake would otherwise have its
|
||||
* only IRQ pin switched to RF-switch duty here, and the driver
|
||||
* would then wait forever on TX_DONE/RX_DONE with no way to tell
|
||||
* why. Skipping it turns a silent hang into a warning. */
|
||||
if (dio == lr20xx_irq_dio(cfg)) {
|
||||
LOG_WRN("rfswitch: DIO%d is the IRQ line, not configuring "
|
||||
"it as an RF switch", (int)dio);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set this DIO function to RF switch control */
|
||||
lr20xx_system_set_dio_function(ctx, dio,
|
||||
LR20XX_SYSTEM_DIO_FUNC_RF_SWITCH,
|
||||
@@ -375,9 +406,11 @@ static void lr20xx_configure_rfswitch(void *ctx, const struct lr20xx_config *cfg
|
||||
if (cfg->rfswitch_standby & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_STANDBY;
|
||||
}
|
||||
if (cfg->rfswitch_rx & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_LF |
|
||||
LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_HF;
|
||||
if (cfg->rfswitch_rx_lf & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_LF;
|
||||
}
|
||||
if (cfg->rfswitch_rx_hf & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_RX_HF;
|
||||
}
|
||||
if (cfg->rfswitch_tx & BIT(i)) {
|
||||
sw_cfg |= LR20XX_SYSTEM_DIO_RF_SWITCH_WHEN_TX_LF;
|
||||
@@ -3238,8 +3271,10 @@ static int lr20xx_hw_init(struct lr20xx_data *data,
|
||||
lr20xx_status_t st;
|
||||
|
||||
lr20xx_configure_rfswitch(ctx, cfg);
|
||||
LOG_DBG("RF switch: en=0x%02x stby=0x%02x rx=0x%02x tx=0x%02x txhp=0x%02x",
|
||||
cfg->rfswitch_enable, cfg->rfswitch_standby, cfg->rfswitch_rx,
|
||||
LOG_DBG("RF switch: en=0x%02x stby=0x%02x rxlf=0x%02x rxhf=0x%02x "
|
||||
"tx=0x%02x txhp=0x%02x",
|
||||
cfg->rfswitch_enable, cfg->rfswitch_standby,
|
||||
cfg->rfswitch_rx_lf, cfg->rfswitch_rx_hf,
|
||||
cfg->rfswitch_tx, cfg->rfswitch_tx_hp);
|
||||
|
||||
st = lr20xx_system_set_dio_function(ctx, lr20xx_irq_dio(cfg),
|
||||
@@ -3408,7 +3443,14 @@ static DEVICE_API(lora, lr20xx_lora_api) = {
|
||||
.irq_dio = DT_INST_PROP_OR(n, irq_dio, 9), \
|
||||
.rfswitch_enable = DT_INST_PROP_OR(n, rfswitch_enable, 0), \
|
||||
.rfswitch_standby = DT_INST_PROP_OR(n, rfswitch_standby, 0),\
|
||||
.rfswitch_rx = DT_INST_PROP_OR(n, rfswitch_rx, 0), \
|
||||
/* rfswitch-rx-lf / -hf are optional and carry no binding \
|
||||
* default, so an absent one falls back to the combined \
|
||||
* rfswitch-rx — which keeps every pre-split board (e.g. \
|
||||
* promicro_lr2021) byte-identical. */ \
|
||||
.rfswitch_rx_lf = DT_INST_PROP_OR(n, rfswitch_rx_lf, \
|
||||
DT_INST_PROP_OR(n, rfswitch_rx, 0)), \
|
||||
.rfswitch_rx_hf = DT_INST_PROP_OR(n, rfswitch_rx_hf, \
|
||||
DT_INST_PROP_OR(n, rfswitch_rx, 0)), \
|
||||
.rfswitch_tx = DT_INST_PROP_OR(n, rfswitch_tx, 0), \
|
||||
.rfswitch_tx_hp = DT_INST_PROP_OR(n, rfswitch_tx_hp, 0), \
|
||||
}; \
|
||||
|
||||
@@ -60,8 +60,10 @@ properties:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
RF switch DIO enable bitmask (bit 0 = DIO5, bit 1 = DIO6, ...).
|
||||
Set a bit to include that DIO in RF switch control.
|
||||
RF switch DIO enable bitmask (bit 0 = DIO5, bit 1 = DIO6, ... bit 6 =
|
||||
DIO11). DIO5..DIO11 is the chip's entire RF-switch-capable range, so
|
||||
bit 7 is unused. Set a bit to include that DIO in RF switch control.
|
||||
The DIO named by irq-dio is skipped even if its bit is set here.
|
||||
|
||||
rfswitch-standby:
|
||||
type: int
|
||||
@@ -74,8 +76,30 @@ properties:
|
||||
type: int
|
||||
default: 0
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in RX mode (both LF and HF).
|
||||
Bit mapping matches rfswitch-enable.
|
||||
Bitmask of RF switch DIOs that are HIGH in RX mode, in BOTH bands.
|
||||
Bit mapping matches rfswitch-enable. This is the convenient form for
|
||||
the common single-band board; set rfswitch-rx-lf / rfswitch-rx-hf
|
||||
instead when the two bands need different masks.
|
||||
|
||||
rfswitch-rx-lf:
|
||||
type: int
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in sub-GHz RX only.
|
||||
Defaults to rfswitch-rx when omitted. Bit mapping matches
|
||||
rfswitch-enable.
|
||||
|
||||
rfswitch-rx-hf:
|
||||
type: int
|
||||
description: |
|
||||
Bitmask of RF switch DIOs that are HIGH in 2.4 GHz RX only.
|
||||
Defaults to rfswitch-rx when omitted. Bit mapping matches
|
||||
rfswitch-enable.
|
||||
|
||||
Split from rfswitch-rx for front ends whose two bands are mutually
|
||||
exclusive: the Meshnology W12 must hold the GC1109 sub-GHz FEM in
|
||||
shutdown (DIO11 low) during 2.4 GHz RX, which a single shared mask
|
||||
cannot express. Do NOT give these two a `default:` here — the driver
|
||||
falls back to rfswitch-rx by testing for the property's absence.
|
||||
|
||||
rfswitch-tx:
|
||||
type: int
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
# so the BOARD_ROOT set there never fires. Set it here, before find_package(Sysbuild).
|
||||
set(BOARD_ROOT "${APP_DIR}" CACHE STRING "" FORCE)
|
||||
|
||||
# Same story for the files ZephCore adds to the Zephyr tree: the app copies them
|
||||
# in its own CMakeLists, but MCUboot is configured first and runs a devicetree
|
||||
# pass over the same board DTS. A board whose radio node uses a ZephCore-only
|
||||
# binding (the LR11xx / LR20xx LoRa drivers) needs that binding present before
|
||||
# MCUboot's DTS pass, not after. See cmake/zephyr_new_files.cmake.
|
||||
set(ZEPHCORE_SOURCE_DIR "${APP_DIR}")
|
||||
set(ZEPHCORE_ZEPHYR_DIR "$ENV{ZEPHYR_BASE}")
|
||||
include("${APP_DIR}/cmake/zephyr_new_files.cmake")
|
||||
|
||||
# Auto-propagate flash size from board.conf to MCUboot.
|
||||
#
|
||||
# MCUboot is built as a separate image and does NOT inherit the app's board.conf
|
||||
|
||||
Reference in New Issue
Block a user