Merge branch 'logger_esp8266' into integration

This commit is contained in:
J. Nick Koston
2026-01-03 00:20:27 -10:00
7 changed files with 97 additions and 14 deletions

View File

@@ -28,6 +28,8 @@ from .const import (
KEY_ESP8266,
KEY_FLASH_SIZE,
KEY_PIN_INITIAL_STATES,
KEY_SERIAL1_REQUIRED,
KEY_SERIAL_REQUIRED,
KEY_WAVEFORM_REQUIRED,
esp8266_ns,
)
@@ -271,6 +273,7 @@ async def to_code(config):
CORE.add_job(add_pin_initial_states_array)
CORE.add_job(finalize_waveform_config)
CORE.add_job(finalize_serial_config)
@coroutine_with_priority(CoroPriority.WORKAROUNDS)
@@ -286,6 +289,24 @@ async def finalize_waveform_config() -> None:
cg.add_build_flag("-DUSE_ESP8266_WAVEFORM_STUBS")
@coroutine_with_priority(CoroPriority.WORKAROUNDS)
async def finalize_serial_config() -> None:
"""Exclude unused Arduino Serial objects from the build.
This runs at WORKAROUNDS priority (-999) to ensure all components
have had a chance to call enable_serial() or enable_serial1() first.
The Arduino ESP8266 core defines two global Serial objects (32 bytes each).
By adding NO_GLOBAL_SERIAL or NO_GLOBAL_SERIAL1 build flags, we prevent
unused Serial objects from being linked, saving 32 bytes each.
"""
esp8266_data = CORE.data.get(KEY_ESP8266, {})
if not esp8266_data.get(KEY_SERIAL_REQUIRED, False):
cg.add_build_flag("-DNO_GLOBAL_SERIAL")
if not esp8266_data.get(KEY_SERIAL1_REQUIRED, False):
cg.add_build_flag("-DNO_GLOBAL_SERIAL1")
# Called by writer.py
def copy_files() -> None:
dir = Path(__file__).parent

View File

@@ -8,6 +8,8 @@ CONF_RESTORE_FROM_FLASH = "restore_from_flash"
CONF_EARLY_PIN_INIT = "early_pin_init"
KEY_FLASH_SIZE = "flash_size"
KEY_WAVEFORM_REQUIRED = "waveform_required"
KEY_SERIAL_REQUIRED = "serial_required"
KEY_SERIAL1_REQUIRED = "serial1_required"
# esp8266 namespace is already defined by arduino, manually prefix esphome
esp8266_ns = cg.global_ns.namespace("esphome").namespace("esp8266")
@@ -29,3 +31,35 @@ def require_waveform() -> None:
require_waveform()
"""
CORE.data.setdefault(KEY_ESP8266, {})[KEY_WAVEFORM_REQUIRED] = True
def enable_serial() -> None:
"""Mark that Arduino Serial (UART0) is required.
Call this from components that use the global Serial object.
If no component calls this, Serial is excluded from the build
to save 32 bytes of RAM.
Example:
from esphome.components.esp8266.const import enable_serial
async def to_code(config):
enable_serial()
"""
CORE.data.setdefault(KEY_ESP8266, {})[KEY_SERIAL_REQUIRED] = True
def enable_serial1() -> None:
"""Mark that Arduino Serial1 (UART1) is required.
Call this from components that use the global Serial1 object.
If no component calls this, Serial1 is excluded from the build
to save 32 bytes of RAM.
Example:
from esphome.components.esp8266.const import enable_serial1
async def to_code(config):
enable_serial1()
"""
CORE.data.setdefault(KEY_ESP8266, {})[KEY_SERIAL1_REQUIRED] = True

View File

@@ -339,19 +339,15 @@ async def to_code(config):
# Add defines for which Serial object is needed (allows linker to exclude unused)
if CORE.is_esp8266:
from esphome.components.esp8266.const import enable_serial, enable_serial1
hw_uart = config.get(CONF_HARDWARE_UART, UART0)
if has_serial_logging and hw_uart in (UART0, UART0_SWAP):
cg.add_define("USE_ESP8266_LOGGER_SERIAL")
# Exclude Serial1 from Arduino build
cg.add_build_flag("-DNO_GLOBAL_SERIAL1")
enable_serial()
elif has_serial_logging and hw_uart == UART1:
cg.add_define("USE_ESP8266_LOGGER_SERIAL1")
# Exclude Serial from Arduino build
cg.add_build_flag("-DNO_GLOBAL_SERIAL")
else:
# No serial logging - exclude both
cg.add_build_flag("-DNO_GLOBAL_SERIAL")
cg.add_build_flag("-DNO_GLOBAL_SERIAL1")
enable_serial1()
if (
(CORE.is_esp8266 or CORE.is_rp2040)

View File

@@ -378,6 +378,28 @@ async def to_code(config):
if CONF_DEBUG in config:
await debug_to_code(config[CONF_DEBUG], var)
# ESP8266: Enable the Arduino Serial objects that might be used based on pin config
# The C++ code selects hardware serial at runtime based on these pin combinations:
# - Serial (UART0): TX=1 or null, RX=3 or null
# - Serial (UART0 swap): TX=15 or null, RX=13 or null
# - Serial1: TX=2 or null, RX=8 or null
if CORE.is_esp8266:
from esphome.components.esp8266.const import enable_serial, enable_serial1
tx_num = config[CONF_TX_PIN][CONF_NUMBER] if CONF_TX_PIN in config else None
rx_num = config[CONF_RX_PIN][CONF_NUMBER] if CONF_RX_PIN in config else None
# Check if this config could use Serial (UART0 regular or swap)
if (tx_num is None or tx_num in (1, 15)) and (
rx_num is None or rx_num in (3, 13)
):
enable_serial()
cg.add_define("USE_ESP8266_UART_SERIAL")
# Check if this config could use Serial1
if (tx_num is None or tx_num == 2) and (rx_num is None or rx_num == 8):
enable_serial1()
cg.add_define("USE_ESP8266_UART_SERIAL1")
CORE.add_job(final_step)

View File

@@ -189,10 +189,10 @@ class UARTComponent {
size_t rx_buffer_size_;
size_t rx_full_threshold_{1};
size_t rx_timeout_{0};
uint32_t baud_rate_;
uint8_t stop_bits_;
uint8_t data_bits_;
UARTParityOptions parity_;
uint32_t baud_rate_{0};
uint8_t stop_bits_{0};
uint8_t data_bits_{0};
UARTParityOptions parity_{UART_CONFIG_PARITY_NONE};
#ifdef USE_UART_DEBUGGER
CallbackManager<void(UARTDirection, uint8_t)> debug_callback_{};
#endif

View File

@@ -75,6 +75,7 @@ void ESP8266UartComponent::setup() {
// is 1 we still want to use Serial.
SerialConfig config = static_cast<SerialConfig>(get_config());
#ifdef USE_ESP8266_UART_SERIAL
if (!ESP8266UartComponent::serial0_in_use && (tx_pin_ == nullptr || tx_pin_->get_pin() == 1) &&
(rx_pin_ == nullptr || rx_pin_->get_pin() == 3)
#ifdef USE_LOGGER
@@ -100,11 +101,16 @@ void ESP8266UartComponent::setup() {
this->hw_serial_->setRxBufferSize(this->rx_buffer_size_);
this->hw_serial_->swap();
ESP8266UartComponent::serial0_in_use = true;
} else if ((tx_pin_ == nullptr || tx_pin_->get_pin() == 2) && (rx_pin_ == nullptr || rx_pin_->get_pin() == 8)) {
} else
#endif // USE_ESP8266_UART_SERIAL
#ifdef USE_ESP8266_UART_SERIAL1
if ((tx_pin_ == nullptr || tx_pin_->get_pin() == 2) && (rx_pin_ == nullptr || rx_pin_->get_pin() == 8)) {
this->hw_serial_ = &Serial1;
this->hw_serial_->begin(this->baud_rate_, config);
this->hw_serial_->setRxBufferSize(this->rx_buffer_size_);
} else {
} else
#endif // USE_ESP8266_UART_SERIAL1
{
this->sw_serial_ = new ESP8266SoftwareSerial(); // NOLINT
this->sw_serial_->setup(tx_pin_, rx_pin_, this->baud_rate_, this->stop_bits_, this->data_bits_, this->parity_,
this->rx_buffer_size_);

View File

@@ -248,7 +248,11 @@
#define USE_ADC_SENSOR_VCC
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 1, 2)
#define USE_CAPTIVE_PORTAL
#define USE_ESP8266_LOGGER_SERIAL
#define USE_ESP8266_LOGGER_SERIAL1
#define USE_ESP8266_PREFERENCES_FLASH
#define USE_ESP8266_UART_SERIAL
#define USE_ESP8266_UART_SERIAL1
#define USE_HTTP_REQUEST_ESP8266_HTTPS
#define USE_HTTP_REQUEST_RESPONSE
#define USE_I2C