From 644f27997265126d050be035da20ed07ea379a3e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 3 Aug 2026 19:53:51 -0500 Subject: [PATCH] [logger] Stub out ROM ets_putc on ESP8266 when serial logging is disabled (#17970) --- esphome/components/logger/__init__.py | 10 ++++++++-- esphome/components/logger/logger_esp8266.cpp | 13 +++++++++++++ .../logger/test-uart0_no_logging.esp8266-ard.yaml | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/components/logger/test-uart0_no_logging.esp8266-ard.yaml diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 77a875dd8f..f307f5d5d1 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -410,10 +410,16 @@ async def _late_logger_init(config: ConfigType) -> None: 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): + if not has_serial_logging: + # No serial logging: stub out ROM ets_putc so stray output (newlib + # stdout, lwIP diagnostics) cannot block on a slow or shared UART0. + # ets_putc always writes to the physical UART and cannot be disabled + # through uart_set_debug(); see __wrap_ets_putc in logger_esp8266.cpp. + cg.add_build_flag("-Wl,--wrap=ets_putc") + elif hw_uart in (UART0, UART0_SWAP): cg.add_define("USE_ESP8266_LOGGER_SERIAL") enable_serial() - elif has_serial_logging and hw_uart == UART1: + elif hw_uart == UART1: cg.add_define("USE_ESP8266_LOGGER_SERIAL1") enable_serial1() diff --git a/esphome/components/logger/logger_esp8266.cpp b/esphome/components/logger/logger_esp8266.cpp index 5797b03ba7..ac71ba8e3b 100644 --- a/esphome/components/logger/logger_esp8266.cpp +++ b/esphome/components/logger/logger_esp8266.cpp @@ -49,4 +49,17 @@ const LogString *Logger::get_uart_selection_() { } } // namespace esphome::logger + +#if !defined(USE_ESP8266_LOGGER_SERIAL) && !defined(USE_ESP8266_LOGGER_SERIAL1) +// With serial logging disabled, ROM ets_putc still writes to the physical UART0 +// at whatever baud rate a uart bus configured there; uart_set_debug(UART_NO) +// only silences the installable putc1 hook, not ets_putc itself. Blocking +// writes at a low baud rate (for example 4800 for a power monitoring chip) can +// starve the soft watchdog. All linked callers (newlib stdout, lwIP +// diagnostics, postmortem dumps) are redirected here by -Wl,--wrap=ets_putc. +// IRAM_ATTR because the ROM original is callable with the flash cache +// disabled (for example from newlib's _write_r, which is placed in IRAM). +extern "C" void IRAM_ATTR __wrap_ets_putc(char) {} +#endif + #endif diff --git a/tests/components/logger/test-uart0_no_logging.esp8266-ard.yaml b/tests/components/logger/test-uart0_no_logging.esp8266-ard.yaml new file mode 100644 index 0000000000..76444a2e89 --- /dev/null +++ b/tests/components/logger/test-uart0_no_logging.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common-uart0_no_logging.yaml