Merge branch 'fix_logger_loop_disable' into integration

This commit is contained in:
J. Nick Koston
2026-02-20 13:21:08 -06:00
14 changed files with 137 additions and 20 deletions

View File

@@ -87,6 +87,7 @@ IS_TARGET_PLATFORM = True
CONF_ASSERTION_LEVEL = "assertion_level"
CONF_COMPILER_OPTIMIZATION = "compiler_optimization"
CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES = "enable_idf_experimental_features"
CONF_ENGINEERING_SAMPLE = "engineering_sample"
CONF_INCLUDE_BUILTIN_IDF_COMPONENTS = "include_builtin_idf_components"
CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert"
CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback"
@@ -785,6 +786,15 @@ def _detect_variant(value):
# variant has already been validated against the known set
value = value.copy()
value[CONF_BOARD] = STANDARD_BOARDS[variant]
if variant == VARIANT_ESP32P4:
engineering_sample = value.get(CONF_ENGINEERING_SAMPLE)
if engineering_sample is None:
_LOGGER.warning(
"No board specified for ESP32-P4. Defaulting to production silicon (rev3). "
"If you have an early engineering sample (pre-rev3), set 'engineering_sample: true'."
)
elif engineering_sample:
value[CONF_BOARD] = "esp32-p4-evboard"
elif board in BOARDS:
variant = variant or BOARDS[board][KEY_VARIANT]
if variant != BOARDS[board][KEY_VARIANT]:
@@ -848,6 +858,30 @@ def final_validate(config):
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_MINIMUM_CHIP_REVISION],
)
)
if (
config[CONF_VARIANT] != VARIANT_ESP32P4
and config.get(CONF_ENGINEERING_SAMPLE) is not None
):
errs.append(
cv.Invalid(
f"'{CONF_ENGINEERING_SAMPLE}' is only supported on {VARIANT_ESP32P4}",
path=[CONF_ENGINEERING_SAMPLE],
)
)
if (
config[CONF_VARIANT] == VARIANT_ESP32P4
and config.get(CONF_ENGINEERING_SAMPLE) is not None
):
board_is_es = BOARDS.get(config[CONF_BOARD], {}).get(
"engineering_sample", False
)
if config[CONF_ENGINEERING_SAMPLE] != board_is_es:
errs.append(
cv.Invalid(
f"'{CONF_ENGINEERING_SAMPLE}' does not match board '{config[CONF_BOARD]}'",
path=[CONF_ENGINEERING_SAMPLE],
)
)
if advanced[CONF_EXECUTE_FROM_PSRAM]:
if config[CONF_VARIANT] != VARIANT_ESP32S3:
errs.append(
@@ -1197,6 +1231,7 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_CPU_FREQUENCY): cv.one_of(
*FULL_CPU_FREQUENCIES, upper=True
),
cv.Optional(CONF_ENGINEERING_SAMPLE): cv.boolean,
cv.Optional(CONF_FLASH_SIZE, default="4MB"): cv.one_of(
*FLASH_SIZES, upper=True
),
@@ -1482,10 +1517,12 @@ async def to_code(config):
# ESP32-P4: ESP-IDF 5.5.3 changed the default of ESP32P4_SELECTS_REV_LESS_V3
# from y to n. PlatformIO uses sections.ld.in (for rev <3) or
# sections.rev3.ld.in (for rev >=3) based on board definition.
# Set the sdkconfig option to match the board's revision.
# Set the sdkconfig option to match the board's chip revision.
if variant == VARIANT_ESP32P4:
is_rev3 = "_r3" in config[CONF_BOARD]
add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", not is_rev3)
is_eng_sample = BOARDS.get(config[CONF_BOARD], {}).get(
"engineering_sample", False
)
add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", is_eng_sample)
# Set minimum chip revision for ESP32 variant
# Setting this to 3.0 or higher reduces flash size by excluding workaround code,

View File

@@ -20,7 +20,7 @@ STANDARD_BOARDS = {
VARIANT_ESP32C6: "esp32-c6-devkitm-1",
VARIANT_ESP32C61: "esp32-c61-devkitc1-n8r2",
VARIANT_ESP32H2: "esp32-h2-devkitm-1",
VARIANT_ESP32P4: "esp32-p4-evboard",
VARIANT_ESP32P4: "esp32-p4_r3-evboard",
VARIANT_ESP32S2: "esp32-s2-kaluga-1",
VARIANT_ESP32S3: "esp32-s3-devkitc-1",
}
@@ -1713,10 +1713,12 @@ BOARDS = {
"esp32-p4": {
"name": "Espressif ESP32-P4 ES (pre rev.300) generic",
"variant": VARIANT_ESP32P4,
"engineering_sample": True,
},
"esp32-p4-evboard": {
"name": "Espressif ESP32-P4 Function EV Board (ES pre rev.300)",
"variant": VARIANT_ESP32P4,
"engineering_sample": True,
},
"esp32-p4_r3": {
"name": "Espressif ESP32-P4 rev.300 generic",
@@ -2141,6 +2143,7 @@ BOARDS = {
"m5stack-tab5-p4": {
"name": "M5STACK Tab5 esp32-p4 Board (ES pre rev.300)",
"variant": VARIANT_ESP32P4,
"engineering_sample": True,
},
"m5stack-timer-cam": {
"name": "M5Stack Timer CAM",

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

@@ -5,7 +5,12 @@ from esphome import automation
from esphome.automation import Condition
import esphome.codegen as cg
from esphome.components.const import CONF_USE_PSRAM
from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant
from esphome.components.esp32 import (
add_idf_sdkconfig_option,
const,
get_esp32_variant,
only_on_variant,
)
from esphome.components.network import (
has_high_performance_networking,
ip_address_literal,
@@ -64,6 +69,7 @@ _LOGGER = logging.getLogger(__name__)
NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4]
CONF_SAVE = "save"
CONF_BAND_MODE = "band_mode"
CONF_MIN_AUTH_MODE = "min_auth_mode"
CONF_POST_CONNECT_ROAMING = "post_connect_roaming"
@@ -90,6 +96,13 @@ WIFI_POWER_SAVE_MODES = {
"HIGH": WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH,
}
WiFiBandMode = cg.global_ns.enum("wifi_band_mode_t")
WIFI_BAND_MODES = {
"AUTO": WiFiBandMode.WIFI_BAND_MODE_AUTO,
"2.4GHZ": WiFiBandMode.WIFI_BAND_MODE_2G_ONLY,
"5GHZ": WiFiBandMode.WIFI_BAND_MODE_5G_ONLY,
}
WifiMinAuthMode = wifi_ns.enum("WifiMinAuthMode")
WIFI_MIN_AUTH_MODES = {
"WPA": WifiMinAuthMode.WIFI_MIN_AUTH_MODE_WPA,
@@ -353,6 +366,11 @@ CONFIG_SCHEMA = cv.All(
cv.SplitDefault(CONF_ENABLE_RRM, esp32=False): cv.All(
cv.boolean, cv.only_on_esp32
),
cv.Optional(CONF_BAND_MODE): cv.All(
cv.enum(WIFI_BAND_MODES, upper=True),
cv.only_on_esp32,
only_on_variant(supported=[const.VARIANT_ESP32C5]),
),
cv.Optional(CONF_PASSIVE_SCAN, default=False): cv.boolean,
cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean,
cv.Optional(CONF_POST_CONNECT_ROAMING, default=True): cv.boolean,
@@ -527,6 +545,8 @@ async def to_code(config):
cg.add(var.set_btm(config[CONF_ENABLE_BTM]))
if config[CONF_ENABLE_RRM]:
cg.add(var.set_rrm(config[CONF_ENABLE_RRM]))
if CONF_BAND_MODE in config:
cg.add(var.set_band_mode(config[CONF_BAND_MODE]))
if config.get(CONF_USE_PSRAM):
add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True)

View File

@@ -1511,6 +1511,22 @@ void WiFiComponent::dump_config() {
ESP_LOGCONFIG(TAG, " Disabled");
return;
}
#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G)
const char *band_mode_s;
switch (this->band_mode_) {
case WIFI_BAND_MODE_2G_ONLY:
band_mode_s = "2.4GHz";
break;
case WIFI_BAND_MODE_5G_ONLY:
band_mode_s = "5GHz";
break;
case WIFI_BAND_MODE_AUTO:
default:
band_mode_s = "Auto";
break;
}
ESP_LOGCONFIG(TAG, " Band Mode: %s", band_mode_s);
#endif
if (this->is_connected()) {
this->print_connect_params_();
}

View File

@@ -46,6 +46,10 @@ extern "C" {
#include <WiFi.h>
#endif
#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G)
#include <esp_wifi_types.h>
#endif
#if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE)
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
@@ -444,6 +448,9 @@ class WiFiComponent : public Component {
void set_power_save_mode(WiFiPowerSaveMode power_save);
void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; }
void set_output_power(float output_power) { output_power_ = output_power; }
#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G)
void set_band_mode(wifi_band_mode_t band_mode) { this->band_mode_ = band_mode; }
#endif
void set_passive_scan(bool passive);
@@ -661,6 +668,9 @@ class WiFiComponent : public Component {
bool wifi_sta_pre_setup_();
bool wifi_apply_output_power_(float output_power);
bool wifi_apply_power_save_();
#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G)
bool wifi_apply_band_mode_();
#endif
bool wifi_sta_ip_config_(const optional<ManualIP> &manual_ip);
bool wifi_apply_hostname_();
bool wifi_sta_connect_(const WiFiAP &ap);
@@ -783,6 +793,9 @@ class WiFiComponent : public Component {
// 1-byte enums and integers
WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF};
WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE};
#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G)
wifi_band_mode_t band_mode_{WIFI_BAND_MODE_AUTO};
#endif
WifiMinAuthMode min_auth_mode_{WIFI_MIN_AUTH_MODE_WPA2};
WiFiRetryPhase retry_phase_{WiFiRetryPhase::INITIAL_CONNECT};
uint8_t num_retried_{0};

View File

@@ -292,6 +292,10 @@ bool WiFiComponent::wifi_apply_power_save_() {
return success;
}
#ifdef SOC_WIFI_SUPPORT_5G
bool WiFiComponent::wifi_apply_band_mode_() { return esp_wifi_set_band_mode(this->band_mode_) == ESP_OK; }
#endif
bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
// enable STA
if (!this->wifi_mode_(true, {}))
@@ -726,6 +730,9 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) {
s_sta_started = true;
// re-apply power save mode
wifi_apply_power_save_();
#ifdef SOC_WIFI_SUPPORT_5G
wifi_apply_band_mode_();
#endif
} else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_STOP) {
ESP_LOGV(TAG, "STA stop");

View File

@@ -272,10 +272,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
@@ -336,6 +338,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

View File

@@ -43,10 +43,14 @@ def get_boards():
name = board_info["name"]
board = fname.stem
variant = mcu.upper()
boards[board] = {
chip_variant = board_info["build"].get("chip_variant", "")
entry = {
"name": name,
"variant": f"VARIANT_{variant}",
}
if chip_variant.endswith("_es"):
entry["engineering_sample"] = True
boards[board] = entry
return boards
@@ -55,6 +59,12 @@ TEMPLATE = """ "%s": {
"variant": %s,
},"""
TEMPLATE_ES = """ "%s": {
"name": "%s",
"variant": %s,
"engineering_sample": True,
},"""
def main(check: bool):
boards = get_boards()
@@ -66,7 +76,8 @@ def main(check: bool):
if line == "BOARDS = {":
parts.append(line)
parts.extend(
TEMPLATE % (board, info["name"], info["variant"])
(TEMPLATE_ES if info.get("engineering_sample") else TEMPLATE)
% (board, info["name"], info["variant"])
for board, info in sorted(boards.items())
)
parts.append("}")

View File

@@ -1,5 +1,6 @@
esp32:
variant: esp32p4
engineering_sample: true
flash_size: 32MB
cpu_frequency: 400MHz
framework:

View File

@@ -0,0 +1,5 @@
wifi:
band_mode: 5GHZ
packages:
- !include common.yaml