This commit is contained in:
Rastislav Vysoky
2026-04-07 19:05:32 +02:00
parent 2af08b251b
commit da22b127c3
16 changed files with 572 additions and 1 deletions
@@ -0,0 +1,37 @@
# TTGO LoRa32 — ESP32 + SX1276
#
# Hardware:
# ESP32 (4MB flash)
# SX1276 on SPI3
# SSD1306 128x64 OLED on I2C0
#
# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → board.conf
# Board identification
CONFIG_ZEPHCORE_BOARD_NAME="TTGO LoRa32"
CONFIG_BT_DIS_MODEL_NUMBER_STR="TTGO LoRa32"
# Radio: SX1276 via Zephyr loramac-node driver (not the native SX126x driver)
# zephcore_common.conf sets CONFIG_LORA_MODULE_BACKEND_NATIVE=y for SX126x boards.
# Override here: SX127x uses the loramac-node backend (classic LoRaMac-node library).
CONFIG_LORA_MODULE_BACKEND_NATIVE=n
CONFIG_LORA_MODULE_BACKEND_LORAMAC_NODE=y
CONFIG_ZEPHCORE_RADIO_SX127X=y
# SX1276 PA_BOOST output: 17 dBm is the safe maximum without an external PA
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=17
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=17
# RX duty cycle is not supported by the loramac-node SX127x driver
# (lora_recv_duty_cycle returns -ENOSYS and gracefully falls back to
# lora_recv_async, but disable it to avoid the spurious attempt)
CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE=n
# Flash mode: ESP32-PICO-D4 (rev 1.0) — use DIO, not QIO.
# esp32_common.conf enables QIO for the ESP32-S3/C3/C6 boards in this repo.
# Classic ESP32 PICO-D4 rev 1.0 has an issue where bootloader_enable_qio_mode()
# polls the SPI flash WIP bit indefinitely; this hangs with no output after the
# chip-revision "Proceeding" message, the RTCWDT fires, and the board bootloops.
# DIO avoids the QIO-enable SPI sequence entirely and works reliably on PICO-D4.
CONFIG_ESPTOOLPY_FLASHMODE_QIO=n
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
@@ -0,0 +1,55 @@
/*
* SPDX-License-Identifier: Apache-2.0
* TTGO LoRa32 — ZephCore overlay
*
* The upstream Zephyr DTS (ttgo_lora32_esp32_procpu.dts) already defines:
* SX1276 on SPI3 (NSS=GPIO18, SCK/MOSI/MISO via pinctrl)
* SSD1306 OLED on I2C0 (SDA=GPIO21, SCL=GPIO22)
* UART0 console (TX=GPIO1, RX=GPIO3)
* LED0 on GPIO25, WiFi
*
* LoRa SPI3 pins: NSS=18, DIO0=26, DIO1=35, DIO2=34
* LoRa control: RESET=23
* Display I2C0: SDA=21, SCL=22 (SSD1306 @ 0x3C)
*
* Flash layout (partitions_0x1000_amp_4M.dtsi):
* storage_partition @ 0x3B0000 (192KB) — repurposed as LittleFS
*/
/ {
chosen {
/* UART0 console is correct for classic ESP32 (no native USB) */
zephyr,console = &uart0;
zephyr,shell-uart = &uart0;
};
};
/*
* Flash partitions — repurpose storage_partition as LittleFS.
* The 4MB layout has appcpu slots we don't use (procpu-only build),
* but we leave them to avoid changing the partition map.
*/
/delete-node/ &storage_partition;
&flash0 {
partitions {
/* LittleFS 192KB for DataStore (identity, prefs, creds) */
lfs_partition: partition@3b0000 {
label = "lfs";
reg = <0x3B0000 0x30000>;
};
};
};
/* LittleFS auto-mount — standard /lfs mount point */
#include "../../common/filesystem.dtsi"
/* WiFi — required for observer MQTT connectivity */
&wifi {
status = "okay";
};
/* I2C sensors — auto-detected at runtime */
&i2c0 {
#include "../../common/sensors-i2c.dtsi"
};
@@ -0,0 +1,6 @@
# ProMicro SX1262 (Ebyte E22-900M30S) board configuration
# Copyright (c) 2025 ZephCore
# SPDX-License-Identifier: Apache-2.0
config BOARD_PROMICRO_SX1262
select SOC_NRF52840_QIAA
@@ -0,0 +1,15 @@
# ProMicro SX1262 — nRF52840 SuperMini + Ebyte E22-900M30S
# SoftDevice v6 (S140 v6) — NiceNano/SuperMini bootloader uses S140 6.1.1
# 0x00B6 = S140 v6 firmware ID; app partition starts at 0x26000
CONFIG_ZEPHCORE_BOARD_NAME="ProMicro SX1262"
CONFIG_BT_DIS_MODEL_NUMBER_STR="ProMicro SX1262 nRF52840-SX1262"
CONFIG_ZEPHCORE_SD_FWID=0x00B6
# Native Zephyr SX1262 driver (Ebyte E22-900M30S)
CONFIG_ZEPHCORE_RADIO_NATIVE=y
# E22-900M30S has 30dB external PA — cap SX1262 output to 10 dBm
# to avoid PA damage on TX
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=10
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=10
@@ -0,0 +1,8 @@
# Copyright (c) 2025 ZephCore
# SPDX-License-Identifier: Apache-2.0
board:
name: promicro_sx1262
full_name: ProMicro sx1262 (nRF52840 SuperMini + sx1262)
vendor: zephcore
socs:
- name: nrf52840
@@ -0,0 +1,58 @@
/*
* ProMicro SX1262 pin control definitions
* Copyright (c) 2025 ZephCore
* SPDX-License-Identifier: Apache-2.0
*
* SPI2 (SX1262): SCK=P1.11, MOSI=P1.15, MISO=P0.02
* I2C0 (sensors): SDA=P1.04, SCL=P0.11
* UART0 (GPS): TX=P0.20→GPS RX, RX=P0.22←GPS TX
*/
&pinctrl {
spi2_default: spi2_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
<NRF_PSEL(SPIM_MOSI, 1, 15)>,
<NRF_PSEL(SPIM_MISO, 0, 2)>;
};
};
spi2_sleep: spi2_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 1, 11)>,
<NRF_PSEL(SPIM_MOSI, 1, 15)>,
<NRF_PSEL(SPIM_MISO, 0, 2)>;
low-power-enable;
};
};
i2c0_default: i2c0_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 1, 4)>,
<NRF_PSEL(TWIM_SCL, 0, 11)>;
};
};
i2c0_sleep: i2c0_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 1, 4)>,
<NRF_PSEL(TWIM_SCL, 0, 11)>;
low-power-enable;
};
};
uart0_default: uart0_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 20)>;
};
group2 {
psels = <NRF_PSEL(UART_RX, 0, 22)>;
bias-pull-up;
};
};
uart0_sleep: uart0_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 20)>,
<NRF_PSEL(UART_RX, 0, 22)>;
low-power-enable;
};
};
};
@@ -0,0 +1,196 @@
/*
* ProMicro SX1262 — nRF52840 SuperMini + Ebyte E22-900M30S
* Copyright (c) 2025 ZephCore
*
* SPDX-License-Identifier: Apache-2.0
*
* Hardware:
* - nRF52840 (SuperMini/ProMicro form factor) with BLE 5
* - Ebyte E22-900M30S (SX1262 + 30dB PA), TCXO, DIO2=TXEN, RXEN on P0.17
* - GPS module on UART0 (9600 baud, P0.22 RX, P0.20 TX)
* - Battery ADC on AIN7 (P0.31), 150K+150K divider (2:1)
* - User button on P1.00, LED on P0.15
* - 3V3 enable on P0.13 (must be HIGH for SX1262 to function)
*/
/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
#include "promicro_sx1262-pinctrl.dtsi"
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <zephyr/dt-bindings/lora/sx126x.h>
/ {
model = "ProMicro SX1262";
compatible = "zephcore,promicro-sx1262";
chosen {
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,code-partition = &code_partition;
zephyr,console = &cdc_acm_uart;
zephyr,shell-uart = &cdc_acm_uart;
};
aliases {
lora0 = &lora;
led0 = &led0;
sw0 = &user_button;
watchdog0 = &wdt0;
gps-enable = &gps_enable_pin;
};
leds {
compatible = "gpio-leds";
led0: led_0 {
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
label = "LED";
};
};
buttons: buttons {
compatible = "gpio-keys";
user_button: button_0 {
gpios = <&gpio1 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
zephyr,code = <INPUT_KEY_ENTER>;
label = "User Button";
};
};
/* 3V3 enable — must be HIGH to power E22-900M30S module */
vcc3v3_enable: vcc3v3-enable {
compatible = "regulator-fixed";
regulator-name = "vcc3v3-enable";
enable-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
regulator-boot-on;
startup-delay-us = <5000>;
};
/* GPS power control */
gps_en: gps-enable {
compatible = "gpio-leds";
gps_enable_pin: gps_enable {
gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
label = "GPS Enable";
};
};
/* Battery ADC: P0.31 (AIN7), 1M+1.5M voltage divider (5:3) */
zephyr,user {
io-channels = <&adc 7>;
vbat-mv-multiplier = <6000>;
};
};
&reg0 {
status = "okay";
};
&reg1 {
regulator-initial-mode = <NRF5X_REG_MODE_DCDC>;
};
&uicr {
nfct-pins-as-gpios;
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&adc {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
/* Battery voltage on P0.31 (AIN7) */
channel@7 {
reg = <7>;
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_AIN7>;
zephyr,resolution = <12>;
};
};
/* ---- SPI2 for SX1262 (Ebyte E22-900M30S) ---- */
&spi2 {
compatible = "nordic,nrf-spim";
status = "okay";
pinctrl-0 = <&spi2_default>;
pinctrl-1 = <&spi2_sleep>;
pinctrl-names = "default", "sleep";
cs-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; /* P1.13 SX1262_CS */
lora: lora@0 {
compatible = "semtech,sx1262";
reg = <0>;
spi-max-frequency = <8000000>;
reset-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
dio1-gpios = <&gpio0 10 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
/* RF switch: DIO2 drives TXEN, RXEN on P0.17 */
dio2-tx-enable;
rx-enable-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
/* E22-900M30S TCXO, 1.8V supply via DIO3 */
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
tcxo-power-startup-delay-ms = <10>;
/* RX boosted mode for better sensitivity */
rx-boosted;
};
};
/* ---- I2C0 for optional sensors ---- */
&i2c0 {
compatible = "nordic,nrf-twim";
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;
pinctrl-0 = <&i2c0_default>;
pinctrl-1 = <&i2c0_sleep>;
pinctrl-names = "default", "sleep";
/* All supported environment & power sensors — auto-detected at runtime */
#include "../../common/sensors-i2c.dtsi"
};
/* ---- GPS on UART0 (9600 baud) ---- */
&uart0 {
compatible = "nordic,nrf-uarte";
status = "okay";
current-speed = <9600>;
pinctrl-0 = <&uart0_default>;
pinctrl-1 = <&uart0_sleep>;
pinctrl-names = "default", "sleep";
gnss: gnss {
compatible = "luatos,air530z";
on-off-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
};
};
/* ---- USB CDC for console/CLI ---- */
zephyr_udc0: &usbd {
compatible = "nordic,nrf-usbd";
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
/* ---- Flash partitions (SoftDevice v6, app@0x26000) ---- */
#include "../../common/nrf52_partitions_sdv6.dtsi"
#include "../../common/nrf52_wakeup.dtsi"
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: Apache-2.0
CONFIG_ARM_MPU=y
CONFIG_HW_STACK_PROTECTION=y
CONFIG_GPIO=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_UART_LINE_CTRL=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_PINCTRL=y
CONFIG_SPI=y
CONFIG_ADC=y