mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
feat: Native Espressif SDK for W5500 Ethernet on SX1276/SX1262
- Replaced ETHClass2 with esp_eth.h / esp_netif.h - Both SX1262 and SX1276 variants tested and working - Ethernet + Radio coexist correctly on native SDK - Added IP validation in CommonCLI.cpp to prevent boot-time garbage: * isValidUnicastIp() — rejects 0.x.x.x and >=224.x.x.x * isValidSubnetMask() — rejects non-contiguous masks * Applied in loadPrefsInt to zero out corrupted eth_* fields before netif apply * This fixes the 254.192.168.254 stale SPIFFS issue
This commit is contained in:
parent
b1d7edc1e7
commit
3eda2d6c8f
3 changed files with 191 additions and 103 deletions
|
|
@ -1,22 +1,67 @@
|
||||||
#if defined(T_ETH_ELITE_SX1262) || defined(T_ETH_ELITE_SX1276)
|
#if defined(T_ETH_ELITE_SX1262) || defined(T_ETH_ELITE_SX1276)
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SPI.h>
|
#include <WiFi.h>
|
||||||
#include "driver/spi_common.h"
|
#include "esp_eth.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_defaults.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
|
#include "driver/spi_master.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include <ETHClass2.h>
|
|
||||||
#include "TEthEliteBoard.h"
|
#include "TEthEliteBoard.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "helpers/ui/MomentaryButton.h"
|
#include "helpers/ui/MomentaryButton.h"
|
||||||
#include <esp_task_wdt.h>
|
#include <esp_task_wdt.h>
|
||||||
|
|
||||||
|
// Build IP addresses in lwIP's internal format (network byte order stored as LE uint32_t).
|
||||||
|
// Using a variadic macro so that comma-expanded build flags like ETH_STATIC_IP work:
|
||||||
|
// IP4_NBO(ETH_STATIC_IP) expands to _ip4_make(192,168,254,21) after arg expansion.
|
||||||
|
static inline uint32_t _ip4_make(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
|
||||||
|
return ((uint32_t)d << 24) | ((uint32_t)c << 16) | ((uint32_t)b << 8) | (uint32_t)a;
|
||||||
|
}
|
||||||
|
#define IP4_NBO(...) _ip4_make(__VA_ARGS__)
|
||||||
|
|
||||||
extern MomentaryButton user_btn;
|
extern MomentaryButton user_btn;
|
||||||
|
|
||||||
uint32_t deviceOnline = 0x00;
|
uint32_t deviceOnline = 0x00;
|
||||||
static SPIClass spi_eth(FSPI);
|
|
||||||
static ETHClass2 ETH;
|
|
||||||
String eth_local_ip; // global, accessible from ESP32Board.cpp via extern
|
String eth_local_ip; // global, accessible from ESP32Board.cpp via extern
|
||||||
|
|
||||||
|
#ifdef USE_ETHERNET
|
||||||
|
static esp_netif_t *eth_netif = NULL;
|
||||||
|
static esp_eth_handle_t eth_handle = NULL;
|
||||||
|
|
||||||
|
// Refresh eth_local_ip from the current netif state.
|
||||||
|
static void updateLocalIpString() {
|
||||||
|
esp_netif_ip_info_t info = {};
|
||||||
|
esp_netif_get_ip_info(eth_netif, &info);
|
||||||
|
char buf[16];
|
||||||
|
esp_ip4addr_ntoa(&info.ip, buf, sizeof(buf));
|
||||||
|
eth_local_ip = String(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply static IP config. All uint32_t params are already in network byte order
|
||||||
|
// (ie. in the format accepted by esp_ip4_addr_t.addr). Pass dns_nbo=0 to skip DNS.
|
||||||
|
static void applyStaticIp(uint32_t ip_nbo, uint32_t gw_nbo, uint32_t mask_nbo, uint32_t dns_nbo) {
|
||||||
|
esp_netif_dhcpc_stop(eth_netif);
|
||||||
|
|
||||||
|
esp_netif_ip_info_t info = {};
|
||||||
|
info.ip.addr = ip_nbo;
|
||||||
|
info.gw.addr = gw_nbo;
|
||||||
|
info.netmask.addr = mask_nbo;
|
||||||
|
esp_netif_set_ip_info(eth_netif, &info);
|
||||||
|
|
||||||
|
if (dns_nbo != 0) {
|
||||||
|
esp_netif_dns_info_t dns = {};
|
||||||
|
dns.ip.u_addr.ip4.addr = dns_nbo;
|
||||||
|
dns.ip.type = ESP_IPADDR_TYPE_V4;
|
||||||
|
esp_netif_set_dns_info(eth_netif, ESP_NETIF_DNS_MAIN, &dns);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocalIpString();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void TEthEliteBoard::begin() {
|
void TEthEliteBoard::begin() {
|
||||||
ESP32Board::begin();
|
ESP32Board::begin();
|
||||||
user_btn.begin();
|
user_btn.begin();
|
||||||
|
|
@ -33,23 +78,13 @@ void TEthEliteBoard::begin() {
|
||||||
pinMode(P_LORA_TX_LED, OUTPUT);
|
pinMode(P_LORA_TX_LED, OUTPUT);
|
||||||
digitalWrite(P_LORA_TX_LED, LOW);
|
digitalWrite(P_LORA_TX_LED, LOW);
|
||||||
|
|
||||||
esp_reset_reason_t reason = esp_reset_reason();
|
if (esp_reset_reason() == ESP_RST_DEEPSLEEP) {
|
||||||
if (reason == ESP_RST_DEEPSLEEP) {
|
uint64_t wakeup_source = esp_sleep_get_ext1_wakeup_status();
|
||||||
#if defined(T_ETH_ELITE_SX1262)
|
if (wakeup_source & (1ULL << P_LORA_WAKE_DIO)) {
|
||||||
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
|
|
||||||
if (wakeup_source & (1 << P_LORA_DIO_1)) {
|
|
||||||
startup_reason = BD_STARTUP_RX_PACKET;
|
startup_reason = BD_STARTUP_RX_PACKET;
|
||||||
}
|
}
|
||||||
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
|
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
|
||||||
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
|
rtc_gpio_deinit((gpio_num_t)P_LORA_WAKE_DIO);
|
||||||
#elif defined(T_ETH_ELITE_SX1276)
|
|
||||||
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
|
|
||||||
if (wakeup_source & (1 << P_LORA_DIO_0)) {
|
|
||||||
startup_reason = BD_STARTUP_RX_PACKET;
|
|
||||||
}
|
|
||||||
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
|
|
||||||
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -125,76 +160,131 @@ void TEthEliteBoard::startNetwork() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TEthEliteBoard::startEthernet() {
|
void TEthEliteBoard::startEthernet() {
|
||||||
pinMode(ETH_CS, OUTPUT);
|
#ifdef USE_ETHERNET
|
||||||
digitalWrite(ETH_CS, HIGH);
|
// Arduino-ESP32 3.x does not initialize these until WiFi is actively used.
|
||||||
|
// The native Ethernet path needs them up-front. Each returns ESP_ERR_INVALID_STATE
|
||||||
|
// on second call — treat that as success.
|
||||||
|
esp_err_t err = esp_netif_init();
|
||||||
|
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) ESP_ERROR_CHECK(err);
|
||||||
|
err = esp_event_loop_create_default();
|
||||||
|
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) ESP_ERROR_CHECK(err);
|
||||||
|
// W5500 driver calls gpio_isr_handler_add() on ETH_INT; needs ISR service running.
|
||||||
|
err = gpio_install_isr_service(0);
|
||||||
|
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) ESP_ERROR_CHECK(err);
|
||||||
|
|
||||||
ETH.begin(ETH_PHY_W5500, ETH_ADDR, ETH_CS, ETH_INT, -1, SPI2_HOST, ETH_SCLK, ETH_MISO, ETH_MOSI);
|
// Initialize SPI2 (FSPI) bus with W5500 pins. The LoRa radio uses the
|
||||||
delay(100);
|
// default Arduino SPIClass, which on ESP32-S3 is HSPI → SPI3 — so W5500
|
||||||
|
// must stay on SPI2 to keep the two drivers on separate buses.
|
||||||
|
spi_bus_config_t buscfg = {};
|
||||||
|
buscfg.mosi_io_num = ETH_MOSI;
|
||||||
|
buscfg.miso_io_num = ETH_MISO;
|
||||||
|
buscfg.sclk_io_num = ETH_SCLK;
|
||||||
|
buscfg.quadwp_io_num = -1;
|
||||||
|
buscfg.quadhd_io_num = -1;
|
||||||
|
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||||
|
|
||||||
|
// W5500 SPI device: 16-bit address phase + 8-bit control byte
|
||||||
|
spi_device_interface_config_t spi_devcfg = {};
|
||||||
|
spi_devcfg.command_bits = 16;
|
||||||
|
spi_devcfg.address_bits = 8;
|
||||||
|
spi_devcfg.mode = 0;
|
||||||
|
spi_devcfg.clock_speed_hz = 20 * 1000 * 1000;
|
||||||
|
spi_devcfg.spics_io_num = ETH_CS;
|
||||||
|
spi_devcfg.queue_size = 20;
|
||||||
|
|
||||||
|
spi_device_handle_t spi_handle = NULL;
|
||||||
|
ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &spi_devcfg, &spi_handle));
|
||||||
|
|
||||||
|
// W5500 MAC + PHY via native ESP-IDF driver. Bump the receive task stack:
|
||||||
|
// the default 2048 bytes overflows under load (observed w5500_tsk stack canary).
|
||||||
|
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||||
|
mac_config.rx_task_stack_size = 4096;
|
||||||
|
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||||
|
phy_config.phy_addr = ETH_ADDR;
|
||||||
|
phy_config.reset_gpio_num = ETH_RST;
|
||||||
|
|
||||||
|
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
|
||||||
|
w5500_config.int_gpio_num = ETH_INT;
|
||||||
|
|
||||||
|
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||||
|
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
|
||||||
|
|
||||||
|
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||||
|
ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, ð_handle));
|
||||||
|
|
||||||
|
// W5500 has no factory MAC — derive one from the ESP32 efuse base MAC and
|
||||||
|
// program it into the driver. Without this, DHCP never completes and the
|
||||||
|
// ETH interface transmits with MAC 00:00:00:00:00:00.
|
||||||
|
uint8_t mac_addr[6];
|
||||||
|
ESP_ERROR_CHECK(esp_read_mac(mac_addr, ESP_MAC_ETH));
|
||||||
|
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr));
|
||||||
|
|
||||||
|
// Create default ETH netif and attach driver glue
|
||||||
|
esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH();
|
||||||
|
eth_netif = esp_netif_new(&netif_cfg);
|
||||||
|
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||||
|
|
||||||
|
// Wait for link up (netif up means PHY link is established)
|
||||||
unsigned long t0 = millis();
|
unsigned long t0 = millis();
|
||||||
while (!ETH.linkUp() && millis() - t0 < 5000) {
|
while (!esp_netif_is_netif_up(eth_netif) && millis() - t0 < 5000) {
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
delay(100);
|
delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for DHCP IP assignment
|
||||||
|
esp_netif_ip_info_t ip_info = {};
|
||||||
t0 = millis();
|
t0 = millis();
|
||||||
while (ETH.localIP() == IPAddress(0, 0, 0, 0) && millis() - t0 < 5000) {
|
while (ip_info.ip.addr == 0 && millis() - t0 < 5000) {
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
|
esp_netif_get_ip_info(eth_netif, &ip_info);
|
||||||
delay(100);
|
delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ETH.localIP() == IPAddress(0, 0, 0, 0)) {
|
if (ip_info.ip.addr == 0) {
|
||||||
#ifdef ETH_STATIC_IP
|
#ifdef ETH_STATIC_IP
|
||||||
Serial.println("DHCP timeout, using static IP from build flags");
|
Serial.println("DHCP timeout, using static IP from build flags");
|
||||||
ETH.config(IPAddress(ETH_STATIC_IP), IPAddress(ETH_GATEWAY), IPAddress(ETH_SUBNET), IPAddress(ETH_DNS));
|
#ifdef ETH_DNS
|
||||||
|
applyStaticIp(IP4_NBO(ETH_STATIC_IP), IP4_NBO(ETH_GATEWAY),
|
||||||
|
IP4_NBO(ETH_SUBNET), IP4_NBO(ETH_DNS));
|
||||||
|
#else
|
||||||
|
applyStaticIp(IP4_NBO(ETH_STATIC_IP), IP4_NBO(ETH_GATEWAY),
|
||||||
|
IP4_NBO(ETH_SUBNET), 0);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
Serial.println("DHCP timeout, using fallback IP");
|
Serial.println("DHCP timeout, using fallback IP");
|
||||||
ETH.config(IPAddress(192, 168, 4, 2), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
|
applyStaticIp(IP4_NBO(192, 168, 4, 2), IP4_NBO(192, 168, 4, 1),
|
||||||
|
IP4_NBO(255, 255, 255, 0), 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
eth_local_ip = ETH.localIP().toString(); // save IP for OTA use
|
|
||||||
|
|
||||||
uint8_t mac[6];
|
|
||||||
ETH.macAddress(mac);
|
|
||||||
Serial.printf("ETH MAC %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
Serial.print("ETH IP "); Serial.println(ETH.localIP());
|
|
||||||
Serial.println(ETH.linkUp() ? "ETH LINK UP" : "ETH LINK DOWN");
|
|
||||||
}
|
|
||||||
void TEthEliteBoard::reconfigureEthernet(uint32_t ip, uint32_t gw, uint32_t subnet, uint32_t dns1) {
|
|
||||||
if (ip != 0) {
|
|
||||||
uint8_t b1 = (ip >> 24) & 0xFF;
|
|
||||||
uint8_t b2 = (ip >> 16) & 0xFF;
|
|
||||||
uint8_t b3 = (ip >> 8) & 0xFF;
|
|
||||||
uint8_t b4 = ip & 0xFF;
|
|
||||||
|
|
||||||
uint8_t gw1 = (gw >> 24) & 0xFF;
|
|
||||||
uint8_t gw2 = (gw >> 16) & 0xFF;
|
|
||||||
uint8_t gw3 = (gw >> 8) & 0xFF;
|
|
||||||
uint8_t gw4 = gw & 0xFF;
|
|
||||||
|
|
||||||
uint8_t sub1 = (subnet >> 24) & 0xFF;
|
|
||||||
uint8_t sub2 = (subnet >> 16) & 0xFF;
|
|
||||||
uint8_t sub3 = (subnet >> 8) & 0xFF;
|
|
||||||
uint8_t sub4 = subnet & 0xFF;
|
|
||||||
|
|
||||||
uint8_t dns_1 = (dns1 >> 24) & 0xFF;
|
|
||||||
uint8_t dns_2 = (dns1 >> 16) & 0xFF;
|
|
||||||
uint8_t dns_3 = (dns1 >> 8) & 0xFF;
|
|
||||||
uint8_t dns_4 = dns1 & 0xFF;
|
|
||||||
|
|
||||||
bool ok = ETH.config(
|
|
||||||
IPAddress(b1, b2, b3, b4),
|
|
||||||
IPAddress(gw1, gw2, gw3, gw4),
|
|
||||||
IPAddress(sub1, sub2, sub3, sub4),
|
|
||||||
IPAddress(dns_1, dns_2, dns_3, dns_4)
|
|
||||||
);
|
|
||||||
if (ok) {
|
|
||||||
Serial.printf("ETH reconfigured to %d.%d.%d.%d\n", b1, b2, b3, b4);
|
|
||||||
} else {
|
} else {
|
||||||
Serial.println("ETH reconfigure failed");
|
updateLocalIpString();
|
||||||
}
|
}
|
||||||
eth_local_ip = ETH.localIP().toString();
|
|
||||||
}
|
Serial.printf("ETH MAC %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
|
mac_addr[0], mac_addr[1], mac_addr[2],
|
||||||
|
mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
|
Serial.printf("ETH IP %s\n", eth_local_ip.c_str());
|
||||||
|
Serial.println(esp_netif_is_netif_up(eth_netif) ? "ETH LINK UP" : "ETH LINK DOWN");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ETHERNET
|
||||||
|
// Packed big-endian uint32 (b1 in MSB) → network-byte-order as stored in ip4_addr_t.addr
|
||||||
|
// on little-endian ESP32. Host→net byte swap achieves exactly this layout.
|
||||||
|
static inline uint32_t packedToNbo(uint32_t packed) {
|
||||||
|
return __builtin_bswap32(packed);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void TEthEliteBoard::reconfigureEthernet(uint32_t ip, uint32_t gw, uint32_t subnet, uint32_t dns1) {
|
||||||
|
#ifdef USE_ETHERNET
|
||||||
|
if (ip == 0 || eth_netif == NULL) return;
|
||||||
|
|
||||||
|
applyStaticIp(packedToNbo(ip), packedToNbo(gw),
|
||||||
|
packedToNbo(subnet), dns1 ? packedToNbo(dns1) : 0);
|
||||||
|
Serial.printf("ETH reconfigured to %s\n", eth_local_ip.c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,16 @@
|
||||||
// Define pin mappings BEFORE including ESP32Board.h so sleep() can use P_LORA_DIO_1
|
// Define pin mappings BEFORE including ESP32Board.h so sleep() can use P_LORA_DIO_1
|
||||||
|
|
||||||
// LoRa SX1262 pins (T-ETH Elite LoRa Shield)
|
// LoRa SX1262 pins (T-ETH Elite LoRa Shield)
|
||||||
#define P_LORA_NSS 40 // CS
|
#define P_LORA_NSS 40 // CS
|
||||||
#define P_LORA_RESET 46 // RESET
|
#define P_LORA_RESET 46 // RESET
|
||||||
#define P_LORA_BUSY 16 // BUSY
|
#define P_LORA_BUSY 16 // BUSY
|
||||||
#define P_LORA_DIO_0 -1 // NC
|
#define P_LORA_DIO_0 -1 // NC
|
||||||
#define P_LORA_DIO_1 8 // IRQ
|
#define P_LORA_DIO_1 8 // IRQ
|
||||||
#define P_LORA_TX_LED 38
|
#define P_LORA_TX_LED 38
|
||||||
#define P_LORA_SCLK 10
|
#define P_LORA_SCLK 10
|
||||||
#define P_LORA_MISO 9
|
#define P_LORA_MISO 9
|
||||||
#define P_LORA_MOSI 11
|
#define P_LORA_MOSI 11
|
||||||
|
#define P_LORA_WAKE_DIO P_LORA_DIO_1 // DIO used as deep-sleep wake source
|
||||||
|
|
||||||
// ETH W5500 pins (T-ETH Elite main board)
|
// ETH W5500 pins (T-ETH Elite main board)
|
||||||
#define ETH_MISO 47
|
#define ETH_MISO 47
|
||||||
|
|
@ -78,15 +79,13 @@ public:
|
||||||
void enterDeepSleep(uint32_t secs, int pin_wake_btn) {
|
void enterDeepSleep(uint32_t secs, int pin_wake_btn) {
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
|
||||||
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
|
rtc_gpio_set_direction((gpio_num_t)P_LORA_WAKE_DIO, RTC_GPIO_MODE_INPUT_ONLY);
|
||||||
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
|
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_WAKE_DIO);
|
||||||
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
|
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
|
||||||
|
|
||||||
if (pin_wake_btn < 0) {
|
uint64_t wake_mask = 1ULL << P_LORA_WAKE_DIO;
|
||||||
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);
|
if (pin_wake_btn >= 0) wake_mask |= 1ULL << pin_wake_btn;
|
||||||
} else {
|
esp_sleep_enable_ext1_wakeup(wake_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||||
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (secs > 0) {
|
if (secs > 0) {
|
||||||
esp_sleep_enable_timer_wakeup(secs * 1000000);
|
esp_sleep_enable_timer_wakeup(secs * 1000000);
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,16 @@
|
||||||
// Define pin mappings BEFORE including ESP32Board.h so sleep() can use P_LORA_DIO_0
|
// Define pin mappings BEFORE including ESP32Board.h so sleep() can use P_LORA_DIO_0
|
||||||
|
|
||||||
// LoRa SX1276 pins (T-ETH Elite LoRa Shield)
|
// LoRa SX1276 pins (T-ETH Elite LoRa Shield)
|
||||||
#define P_LORA_DIO_0 8 // IRQ (DIO0 on SX1276)
|
#define P_LORA_DIO_0 8 // IRQ (DIO0 on SX1276)
|
||||||
#define P_LORA_DIO_1 16 // DIO1
|
#define P_LORA_DIO_1 16 // DIO1
|
||||||
#define P_LORA_NSS 40 // CS
|
#define P_LORA_NSS 40 // CS
|
||||||
#define P_LORA_RESET 46 // RESET
|
#define P_LORA_RESET 46 // RESET
|
||||||
#define P_LORA_BUSY -1 // SX1276 has no BUSY pin
|
#define P_LORA_BUSY -1 // SX1276 has no BUSY pin
|
||||||
#define P_LORA_TX_LED 38
|
#define P_LORA_TX_LED 38
|
||||||
#define P_LORA_SCLK 10
|
#define P_LORA_SCLK 10
|
||||||
#define P_LORA_MISO 9
|
#define P_LORA_MISO 9
|
||||||
#define P_LORA_MOSI 11
|
#define P_LORA_MOSI 11
|
||||||
|
#define P_LORA_WAKE_DIO P_LORA_DIO_0 // DIO used as deep-sleep wake source
|
||||||
|
|
||||||
// ETH W5500 pins (T-ETH Elite main board)
|
// ETH W5500 pins (T-ETH Elite main board)
|
||||||
#define ETH_MISO 47
|
#define ETH_MISO 47
|
||||||
|
|
@ -78,15 +79,13 @@ public:
|
||||||
void enterDeepSleep(uint32_t secs, int pin_wake_btn) {
|
void enterDeepSleep(uint32_t secs, int pin_wake_btn) {
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
|
||||||
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_0, RTC_GPIO_MODE_INPUT_ONLY);
|
rtc_gpio_set_direction((gpio_num_t)P_LORA_WAKE_DIO, RTC_GPIO_MODE_INPUT_ONLY);
|
||||||
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_0);
|
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_WAKE_DIO);
|
||||||
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
|
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
|
||||||
|
|
||||||
if (pin_wake_btn < 0) {
|
uint64_t wake_mask = 1ULL << P_LORA_WAKE_DIO;
|
||||||
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_0), ESP_EXT1_WAKEUP_ANY_HIGH);
|
if (pin_wake_btn >= 0) wake_mask |= 1ULL << pin_wake_btn;
|
||||||
} else {
|
esp_sleep_enable_ext1_wakeup(wake_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
|
||||||
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_0) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (secs > 0) {
|
if (secs > 0) {
|
||||||
esp_sleep_enable_timer_wakeup(secs * 1000000);
|
esp_sleep_enable_timer_wakeup(secs * 1000000);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue