Merge pull request #69 from tommaier123/dev

Added LilyGo T3S3 support
This commit is contained in:
liquidraver
2026-08-22 10:51:13 +02:00
committed by GitHub
11 changed files with 398 additions and 0 deletions
@@ -0,0 +1,5 @@
# Extra heap for the SSD1306 128x64 CFB (UI pages) + ZephCore UI/BLE
# allocations on top of the esp32_common.conf platform heap.
config HEAP_MEM_POOL_ADD_SIZE_BOARD
int
default 4096
@@ -0,0 +1,3 @@
config BOARD_LILYGO_T3S3
select SOC_ESP32S3_WROOM_N4R2
select SOC_ESP32S3_PROCPU if BOARD_LILYGO_T3S3_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,18 @@
# LilyGo T3S3 — ESP32-S3-WROOM-1-N4R2, SX1262, SSD1306 OLED
#
# Hardware:
# SX1262 on SPI2 (DIO2 RF switch, 1.8V TCXO via DIO3)
# SSD1306 128x64 OLED on I2C0
# User button on GPIO0, TX LED on GPIO37
# VBAT ADC on GPIO1
# Native USB Serial/JTAG console
#
# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → board.conf
# Board identification
CONFIG_ZEPHCORE_BOARD_NAME="LilyGo T3S3"
CONFIG_BT_DIS_MODEL_NUMBER_STR="LilyGo T3S3"
# SX1262 — 22 dBm TX power (MeshCore variant default)
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=22
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=22
@@ -0,0 +1,170 @@
/*
* SPDX-License-Identifier: MIT
* LilyGo T3S3 — ZephCore overlay
*
* The board DTS defines the minimal SoC/bus layer (SPI2, I2C0, GPIO, USB
* serial, BLE, WiFi, flash partitions). This overlay adds the ZephCore
* peripheral wiring on top.
*
* Pin mapping (from Arduino MeshCore variants/lilygo_t3s3):
* LoRa SPI2: SCLK=GPIO5, MOSI=GPIO6, MISO=GPIO3, NSS=GPIO7
* LoRa ctrl: RESET=GPIO8, BUSY=GPIO34, DIO1=GPIO33
* DIO2 = antenna RF switch, DIO3 = 1.8V TCXO
* Display I2C0: SDA=GPIO18, SCL=GPIO17, RST=GPIO21 (SSD1306 @0x3C)
* Button: GPIO0
* TX LED: GPIO37
* VBAT ADC: GPIO1 = ADC unit 1 ch 0 (&adc0)
*
* GPIO bank note (ESP32-S3): GPIO0-31 are on &gpio0, GPIO32-47 on &gpio1.
* GPIO33 = &gpio1 pin 1, GPIO34 = &gpio1 pin 2, GPIO37 = &gpio1 pin 5.
*/
#include <zephyr/dt-bindings/lora/sx126x.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <zephyr/dt-bindings/adc/adc.h>
/ {
aliases {
lora0 = &lora;
sw0 = &user_button;
lora-tx-led = &tx_led;
};
chosen {
zephyr,display = &ssd1306;
};
/* User button chain — same mapping as RAK4631 / WisMesh Pocket. */
buttons: buttons {
compatible = "gpio-keys";
user_button: button_0 {
gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "User Button";
zephyr,code = <INPUT_KEY_0>;
};
};
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>;
};
/* TX activity LED — GPIO37, active-HIGH. Blinks on LoRa TX. */
leds {
compatible = "gpio-leds";
tx_led: led_0 {
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; /* GPIO37 = gpio1 pin 5 */
label = "TX LED";
};
};
/* Battery ADC — ZephCore reads via zephyr,user { io-channels }.
* GPIO1 = ADC unit 1 ch 0 = &adc0 (label 0-indexed, unit 1-indexed).
* Multiplier: 1100 mV ref × 4 gain × 2:1 divider = 8800, matching
* MeshCore's 2 × analogReadMilliVolts. */
zephyr,user {
io-channels = <&adc0 0>;
vbat-mv-multiplier = <8800>;
};
};
/* SX1262 on SPI2 (pinctrl already set in board DTS). */
&spi2 {
cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; /* NSS = GPIO7 */
lora: lora@0 {
compatible = "semtech,sx1262";
reg = <0>;
spi-max-frequency = <8000000>;
reset-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; /* RESET = GPIO8 */
busy-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; /* BUSY = GPIO34 = gpio1 pin 2 */
dio1-gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* DIO1 = GPIO33 = gpio1 pin 1 */
/* DIO2 drives the antenna TX/RX switch (no rx/tx-enable GPIOs). */
dio2-tx-enable;
/* TCXO 1.8V via DIO3 — 5 ms matches Arduino (RadioLib ctrl timeout) */
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
tcxo-power-startup-delay-ms = <5>;
rx-boosted;
};
};
/* SSD1306 128x64 OLED on I2C0 */
&i2c0 {
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;
inversion-on;
prechargep = <0x22>;
reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; /* RST_OLED = GPIO21 */
};
#include "../../common/sensors-i2c.dtsi"
};
/* Battery ADC channel configuration on adc0 (ADC unit 1 -> GPIO1 = ch0).
* Without the channel node adc_channel_setup_dt() fails and
* getBattMilliVolts() returns 0. */
&adc0 {
status = "okay";
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
/* ADC_GAIN_1_4 = 12 dB ≈ Arduino's default 3.3V scale;
* 1/6 not supported by the esp32 driver → channel setup fails. */
zephyr,gain = "ADC_GAIN_1_4";
zephyr,reference = "ADC_REF_INTERNAL";
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
zephyr,resolution = <12>;
};
};
/* ADC unit 2 (label adc1) is unused on this board; keep it disabled. */
&adc1 {
status = "disabled";
};
/*
* 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. The node is inert unless the build enables the
* USB device stack via boards/common/esp32s3_usb.conf.
*
* This board consoles over USB Serial/JTAG (board DTS), which shares D+/D-
* with USB OTG — so the console reroute to uart0 lives in the auto-paired
* boards/common/esp32s3_usb.overlay and applies only when that conf is passed.
* Do NOT include esp32s3_console_uart0.dtsi here: it would move the console
* onto GPIO43/44 in every build of this board. */
#include "../../common/esp32s3_usb_otg.dtsi"
@@ -0,0 +1,6 @@
board:
name: lilygo_t3s3
full_name: LilyGo T3S3
vendor: lilygo
socs:
- name: esp32s3
@@ -0,0 +1,42 @@
/*
* SPDX-License-Identifier: MIT
* LilyGo T3S3 — Pin Control Definitions
*
* Pin mapping (from Arduino MeshCore variants/lilygo_t3s3):
* SPI2 LoRa: SCLK=GPIO5, MOSI=GPIO6, MISO=GPIO3, NSS=GPIO7 (GPIO CS)
* LoRa ctrl: RESET=GPIO8, BUSY=GPIO34, DIO1=GPIO33 (DIO2 = RF switch)
* I2C0: SDA=GPIO18, SCL=GPIO17 (SSD1306 OLED @0x3C, RST=GPIO21)
* Button: GPIO0
* TX LED: GPIO37
* VBAT ADC: GPIO1
* Console: USB Serial/JTAG (native)
*/
#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 {
/* SPI2 — SX1262 LoRa (CS via cs-gpios, not pinctrl) */
spim2_default: spim2_default {
group1 {
pinmux = <SPIM2_MISO_GPIO3>,
<SPIM2_SCLK_GPIO5>;
};
group2 {
pinmux = <SPIM2_MOSI_GPIO6>;
output-low;
};
};
/* I2C0 — SSD1306 OLED + optional sensors */
i2c0_default: i2c0_default {
group1 {
pinmux = <I2C0_SDA_GPIO18>,
<I2C0_SCL_GPIO17>;
bias-pull-up;
drive-open-drain;
output-high;
};
};
};
@@ -0,0 +1,81 @@
/*
* SPDX-License-Identifier: MIT
* LilyGo T3S3 — ESP32-S3 (WROOM-1 N4R2), 4MB flash, 2MB QSPI PSRAM
*
* Hardware:
* MCU: ESP32-S3 (Xtensa LX7, dual-core)
* Module: ESP32-S3-WROOM-1-N4R2 (4MB flash, 2MB QSPI PSRAM)
* Radio: SX1262 on SPI2 (defined in board.overlay)
* Display: SSD1306 128x64 OLED on I2C0 (defined in board.overlay)
* Button: GPIO0
* TX LED: GPIO37
* VBAT: GPIO1 ADC
* Console: Native USB Serial/JTAG
*
* Peripheral wiring (radio, display, button, LED, battery) is intentionally
* kept in board.overlay — this DTS is the minimal SoC/bus layer.
*/
/dts-v1/;
#include <espressif/esp32s3/esp32s3_wroom_n4r2.dtsi>
#include "lilygo_t3s3-pinctrl.dtsi"
#include <espressif/partitions_0x0_amp_4M.dtsi>
/ {
model = "LilyGo T3S3";
compatible = "lilygo,t3s3";
chosen {
zephyr,sram = &sram1;
zephyr,console = &usb_serial;
zephyr,shell-uart = &usb_serial;
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,bt-hci = &esp32_bt_hci;
};
aliases {
uart-0 = &uart0;
i2c-0 = &i2c0;
watchdog0 = &wdt0;
};
};
&usb_serial {
status = "okay";
};
&i2c0 {
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;
pinctrl-0 = <&i2c0_default>;
pinctrl-names = "default";
};
&spi2 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
pinctrl-0 = <&spim2_default>;
pinctrl-names = "default";
};
&gpio0 { status = "okay"; };
&gpio1 { status = "okay"; };
&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 @@
# LilyGo T3S3 — 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.
*
* 4MB 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 0x1C6000>;
};
slot1_partition: partition@1D6000 {
label = "image-1";
reg = <0x1D6000 0x1C6000>;
};
/* BLE bond NVS — offset unchanged so bonds survive the reflash. */
storage_partition: partition@39C000 {
label = "storage";
reg = <0x39C000 0x4000>;
};
/* LittleFS (identity/prefs/contacts) — offset unchanged. */
lfs_partition: partition@3A0000 {
label = "lfs";
reg = <0x3A0000 0x60000>;
};
};
};
+1
View File
@@ -40,6 +40,7 @@ xiao_esp32c3
xiao_esp32c6/esp32c6/hpcore
xiao_esp32s3/esp32s3/procpu
lilygo_tlora_c6/esp32c6/hpcore
lilygo_t3s3/esp32s3/procpu
station_g2/esp32s3/procpu
heltec_wifi_lora32_v3/esp32s3/procpu
heltec_wifi_lora32_v4/esp32s3/procpu