[logger] Fix loop disable optimization using wrong preprocessor guard

The logger loop disable optimization was guarded by USE_LOGGER_USB_CDC,
which is a platform capability flag defined whenever the platform
supports USB CDC. This meant the optimization was disabled on all
ESP32-S2, S3, C3, C5, C6, C61, H2, and P4 variants regardless of
whether USB CDC was actually selected as the hardware UART.

Changed all guards to use USE_LOGGER_UART_SELECTION_USB_CDC which is
only defined when USB CDC is the selected hardware UART. Also changed
the guard logic from || to && so the loop only stays permanently active
when both Zephyr AND USB CDC is selected (the only case that needs
cdc_loop_() to poll port readiness).

Additionally set USE_LOGGER_UART_SELECTION_USB_CDC in the Zephyr
codepath when USB CDC is selected, and updated defines.h for static
analysis coverage.
This commit is contained in:
J. Nick Koston
2026-02-20 13:18:07 -06:00
parent 9c0eed8a67
commit 4a4fd8b92c
5 changed files with 17 additions and 13 deletions

View File

@@ -432,6 +432,7 @@ async def to_code(config):
if config[CONF_HARDWARE_UART] == UART1:
zephyr_add_overlay("""&uart1 { status = "okay";};""")
if config[CONF_HARDWARE_UART] == USB_CDC:
cg.add_define("USE_LOGGER_UART_SELECTION_USB_CDC")
zephyr_add_prj_conf("UART_LINE_CTRL", True)
zephyr_add_cdc_acm(config, 0)

View File

@@ -170,19 +170,19 @@ void Logger::init_log_buffer(size_t total_buffer_size) {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed
this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size);
// Zephyr needs loop working to check when CDC port is open
#if !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC))
// Start with loop disabled when using task buffer (unless using USB CDC on ESP32)
#if !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC))
// Start with loop disabled when using task buffer
// The loop will be enabled automatically when messages arrive
// Zephyr with USB CDC needs loop active to poll port readiness via cdc_loop_()
this->disable_loop_when_buffer_empty_();
#endif
}
#endif
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC))
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC))
void Logger::loop() {
this->process_messages_();
#if defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC)
#if defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)
this->cdc_loop_();
#endif
}
@@ -204,8 +204,7 @@ void Logger::process_messages_() {
this->write_log_buffer_to_console_(buf);
}
}
// Zephyr needs loop working to check when CDC port is open
#if !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC))
#if !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC))
else {
// No messages to process, disable loop if appropriate
// This reduces overhead when there's no async logging activity

View File

@@ -147,7 +147,7 @@ class Logger : public Component {
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
void init_log_buffer(size_t total_buffer_size);
#endif
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC))
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC))
void loop() override;
#endif
/// Manually set the baud rate for serial, set to 0 to disable.
@@ -229,7 +229,7 @@ class Logger : public Component {
void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args,
const char *thread_name);
#endif
#if defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC)
#if defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)
void cdc_loop_();
#endif
void process_messages_();
@@ -464,9 +464,9 @@ class Logger : public Component {
inline RecursionGuard make_non_main_task_guard_() { return RecursionGuard(non_main_task_recursion_guard_); }
#endif
// Zephyr needs loop working to check when CDC port is open
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) && !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC))
// Disable loop when task buffer is empty (with USB CDC check on ESP32)
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) && !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC))
// Disable loop when task buffer is empty
// Zephyr with USB CDC needs loop active to poll port readiness via cdc_loop_()
inline void disable_loop_when_buffer_empty_() {
// Thread safety note: This is safe even if another task calls enable_loop_soon_any_context()
// concurrently. If that happens between our check and disable_loop(), the enable request

View File

@@ -13,7 +13,7 @@ namespace esphome::logger {
static const char *const TAG = "logger";
#ifdef USE_LOGGER_USB_CDC
#ifdef USE_LOGGER_UART_SELECTION_USB_CDC
void Logger::cdc_loop_() {
if (this->uart_ != UART_SELECTION_USB_CDC || this->uart_dev_ == nullptr) {
return;

View File

@@ -270,10 +270,12 @@
#if defined(USE_ESP32_VARIANT_ESP32S2)
#define USE_LOGGER_USB_CDC
#define USE_LOGGER_UART_SELECTION_USB_CDC
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \
defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32H2) || \
defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S3)
#define USE_LOGGER_USB_CDC
#define USE_LOGGER_UART_SELECTION_USB_CDC
#define USE_LOGGER_USB_SERIAL_JTAG
#endif
#endif
@@ -334,6 +336,8 @@
#ifdef USE_NRF52
#define USE_ESPHOME_TASK_LOG_BUFFER
#define USE_LOGGER_UART_SELECTION_USB_CDC
#define USE_LOGGER_USB_CDC
#define USE_NRF52_DFU
#define USE_NRF52_REG0_VOUT 5
#define USE_NRF52_UICR_ERASE