[esp32] Use arduino as an idf component (#10647)

Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Jonathan Swoboda
2025-09-17 17:23:34 -05:00
committed by GitHub
co-authored by J. Nick Koston J. Nick Koston
parent ff2df278d6
commit b8cee477fe
26 changed files with 328 additions and 759 deletions
File diff suppressed because it is too large Load Diff
+31 -34
View File
@@ -12,7 +12,7 @@ from esphome.const import (
CONF_NAME,
CONF_NAME_ADD_MAC_SUFFIX,
)
from esphome.core import CORE, TimePeriod
from esphome.core import TimePeriod
import esphome.final_validate as fv
DEPENDENCIES = ["esp32"]
@@ -261,43 +261,40 @@ async def to_code(config):
cg.add(var.set_name(name))
await cg.register_component(var, config)
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
# Register the core BLE loggers that are always needed
register_bt_logger(BTLoggers.GAP, BTLoggers.BTM, BTLoggers.HCI)
# Register the core BLE loggers that are always needed
register_bt_logger(BTLoggers.GAP, BTLoggers.BTM, BTLoggers.HCI)
# Apply logger settings if log disabling is enabled
if config.get(CONF_DISABLE_BT_LOGS, False):
# Disable all Bluetooth loggers that are not required
for logger in BTLoggers:
if logger not in _required_loggers:
add_idf_sdkconfig_option(f"{logger.value}_NONE", True)
# Apply logger settings if log disabling is enabled
if config.get(CONF_DISABLE_BT_LOGS, False):
# Disable all Bluetooth loggers that are not required
for logger in BTLoggers:
if logger not in _required_loggers:
add_idf_sdkconfig_option(f"{logger.value}_NONE", True)
# Set BLE connection establishment timeout to match aioesphomeapi/bleak-retry-connector
# Default is 20 seconds instead of ESP-IDF's 30 seconds. Because there is no way to
# cancel a BLE connection in progress, when aioesphomeapi times out at 20 seconds,
# the connection slot remains occupied for the remaining time, preventing new connection
# attempts and wasting valuable connection slots.
if CONF_CONNECTION_TIMEOUT in config:
timeout_seconds = int(config[CONF_CONNECTION_TIMEOUT].total_seconds)
add_idf_sdkconfig_option(
"CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT", timeout_seconds
)
# Increase GATT client connection retry count for problematic devices
# Default in ESP-IDF is 3, we increase to 10 for better reliability with
# low-power/timing-sensitive devices
add_idf_sdkconfig_option("CONFIG_BT_GATTC_CONNECT_RETRY_COUNT", 10)
# Set BLE connection establishment timeout to match aioesphomeapi/bleak-retry-connector
# Default is 20 seconds instead of ESP-IDF's 30 seconds. Because there is no way to
# cancel a BLE connection in progress, when aioesphomeapi times out at 20 seconds,
# the connection slot remains occupied for the remaining time, preventing new connection
# attempts and wasting valuable connection slots.
if CONF_CONNECTION_TIMEOUT in config:
timeout_seconds = int(config[CONF_CONNECTION_TIMEOUT].total_seconds)
add_idf_sdkconfig_option("CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT", timeout_seconds)
# Increase GATT client connection retry count for problematic devices
# Default in ESP-IDF is 3, we increase to 10 for better reliability with
# low-power/timing-sensitive devices
add_idf_sdkconfig_option("CONFIG_BT_GATTC_CONNECT_RETRY_COUNT", 10)
# Set the maximum number of notification registrations
# This controls how many BLE characteristics can have notifications enabled
# across all connections for a single GATT client interface
# https://github.com/esphome/issues/issues/6808
if CONF_MAX_NOTIFICATIONS in config:
add_idf_sdkconfig_option(
"CONFIG_BT_GATTC_NOTIF_REG_MAX", config[CONF_MAX_NOTIFICATIONS]
)
# Set the maximum number of notification registrations
# This controls how many BLE characteristics can have notifications enabled
# across all connections for a single GATT client interface
# https://github.com/esphome/issues/issues/6808
if CONF_MAX_NOTIFICATIONS in config:
add_idf_sdkconfig_option(
"CONFIG_BT_GATTC_NOTIF_REG_MAX", config[CONF_MAX_NOTIFICATIONS]
)
cg.add_define("USE_ESP32_BLE")
@@ -4,7 +4,7 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
from esphome.components.esp32_ble import CONF_BLE_ID
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_TX_POWER, CONF_TYPE, CONF_UUID
from esphome.core import CORE, TimePeriod
from esphome.core import TimePeriod
AUTO_LOAD = ["esp32_ble"]
DEPENDENCIES = ["esp32"]
@@ -86,6 +86,5 @@ async def to_code(config):
cg.add_define("USE_ESP32_BLE_ADVERTISING")
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_BT_BLE_42_FEATURES_SUPPORTED", True)
@@ -573,8 +573,7 @@ async def to_code(config):
)
cg.add_define("USE_ESP32_BLE_SERVER")
cg.add_define("USE_ESP32_BLE_ADVERTISING")
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
@automation.register_action(
@@ -342,19 +342,18 @@ async def to_code(config):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
if config.get(CONF_SOFTWARE_COEXISTENCE):
add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", True)
# https://github.com/espressif/esp-idf/issues/4101
# https://github.com/espressif/esp-idf/issues/2503
# Match arduino CONFIG_BTU_TASK_STACK_SIZE
# https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866
add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192)
add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9)
add_idf_sdkconfig_option(
"CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS]
)
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
if config.get(CONF_SOFTWARE_COEXISTENCE):
add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", True)
# https://github.com/espressif/esp-idf/issues/4101
# https://github.com/espressif/esp-idf/issues/2503
# Match arduino CONFIG_BTU_TASK_STACK_SIZE
# https://github.com/espressif/arduino-esp32/blob/fd72cf46ad6fc1a6de99c1d83ba8eba17d80a4ee/tools/sdk/esp32/sdkconfig#L1866
add_idf_sdkconfig_option("CONFIG_BT_BTU_TASK_STACK_SIZE", 8192)
add_idf_sdkconfig_option("CONFIG_BT_ACL_CONNECTIONS", 9)
add_idf_sdkconfig_option(
"CONFIG_BTDM_CTRL_BLE_MAX_CONN", config[CONF_MAX_CONNECTIONS]
)
cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts
cg.add_define("USE_ESP32_BLE_CLIENT")
+1 -3
View File
@@ -21,7 +21,6 @@ from esphome.const import (
CONF_TRIGGER_ID,
CONF_VSYNC_PIN,
)
from esphome.core import CORE
from esphome.core.entity_helpers import setup_entity
import esphome.final_validate as fv
@@ -344,8 +343,7 @@ async def to_code(config):
cg.add_define("USE_CAMERA")
if CORE.using_esp_idf:
add_idf_component(name="espressif/esp32-camera", ref="2.1.1")
add_idf_component(name="espressif/esp32-camera", ref="2.1.1")
for conf in config.get(CONF_ON_STREAM_START, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
+5 -9
View File
@@ -322,11 +322,8 @@ async def to_code(config):
cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED]))
cg.add_define("USE_ETHERNET_SPI")
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True)
add_idf_sdkconfig_option(
f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True
)
add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True)
add_idf_sdkconfig_option(f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True)
elif config[CONF_TYPE] == "OPENETH":
cg.add_define("USE_ETHERNET_OPENETH")
add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True)
@@ -359,10 +356,9 @@ async def to_code(config):
cg.add_define("USE_ETHERNET")
# Disable WiFi when using Ethernet to save memory
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False)
# Also disable WiFi/BT coexistence since WiFi is disabled
add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False)
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False)
# Also disable WiFi/BT coexistence since WiFi is disabled
add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False)
if CORE.using_arduino:
cg.add_library("WiFi", None)
+1 -2
View File
@@ -262,8 +262,7 @@ async def to_code(config):
cg.add_define("USE_I2S_LEGACY")
# Helps avoid callbacks being skipped due to processor load
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True)
add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True)
cg.add(var.set_lrclk_pin(config[CONF_I2S_LRCLK_PIN]))
if CONF_I2S_BCLK_PIN in config:
@@ -15,11 +15,10 @@ static const char *const TAG = "improv_serial";
void ImprovSerialComponent::setup() {
global_improv_serial_component = this;
#ifdef USE_ARDUINO
this->hw_serial_ = logger::global_logger->get_hw_serial();
#endif
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
this->uart_num_ = logger::global_logger->get_uart_num();
#elif defined(USE_ARDUINO)
this->hw_serial_ = logger::global_logger->get_hw_serial();
#endif
if (wifi::global_wifi_component->has_sta()) {
@@ -34,13 +33,7 @@ void ImprovSerialComponent::dump_config() { ESP_LOGCONFIG(TAG, "Improv Serial:")
optional<uint8_t> ImprovSerialComponent::read_byte_() {
optional<uint8_t> byte;
uint8_t data = 0;
#ifdef USE_ARDUINO
if (this->hw_serial_->available()) {
this->hw_serial_->readBytes(&data, 1);
byte = data;
}
#endif
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
switch (logger::global_logger->get_uart()) {
case logger::UART_SELECTION_UART0:
case logger::UART_SELECTION_UART1:
@@ -76,16 +69,18 @@ optional<uint8_t> ImprovSerialComponent::read_byte_() {
default:
break;
}
#elif defined(USE_ARDUINO)
if (this->hw_serial_->available()) {
this->hw_serial_->readBytes(&data, 1);
byte = data;
}
#endif
return byte;
}
void ImprovSerialComponent::write_data_(std::vector<uint8_t> &data) {
data.push_back('\n');
#ifdef USE_ARDUINO
this->hw_serial_->write(data.data(), data.size());
#endif
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
switch (logger::global_logger->get_uart()) {
case logger::UART_SELECTION_UART0:
case logger::UART_SELECTION_UART1:
@@ -112,6 +107,8 @@ void ImprovSerialComponent::write_data_(std::vector<uint8_t> &data) {
default:
break;
}
#elif defined(USE_ARDUINO)
this->hw_serial_->write(data.data(), data.size());
#endif
}
@@ -9,10 +9,7 @@
#include <improv.h>
#include <vector>
#ifdef USE_ARDUINO
#include <HardwareSerial.h>
#endif
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
#include <driver/uart.h>
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3) || \
defined(USE_ESP32_VARIANT_ESP32H2)
@@ -22,6 +19,8 @@
#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
#include <esp_private/usb_console.h>
#endif
#elif defined(USE_ARDUINO)
#include <HardwareSerial.h>
#endif
namespace esphome {
@@ -60,11 +59,10 @@ class ImprovSerialComponent : public Component, public improv_base::ImprovBase {
optional<uint8_t> read_byte_();
void write_data_(std::vector<uint8_t> &data);
#ifdef USE_ARDUINO
Stream *hw_serial_{nullptr};
#endif
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
uart_port_t uart_num_;
#elif defined(USE_ARDUINO)
Stream *hw_serial_{nullptr};
#endif
std::vector<uint8_t> rx_buffer_;
+6 -25
View File
@@ -117,8 +117,6 @@ UART_SELECTION_LIBRETINY = {
COMPONENT_RTL87XX: [DEFAULT, UART0, UART1, UART2],
}
ESP_ARDUINO_UNSUPPORTED_USB_UARTS = [USB_SERIAL_JTAG]
UART_SELECTION_RP2040 = [USB_CDC, UART0, UART1]
UART_SELECTION_NRF52 = [USB_CDC, UART0]
@@ -153,13 +151,7 @@ is_log_level = cv.one_of(*LOG_LEVELS, upper=True)
def uart_selection(value):
if CORE.is_esp32:
if CORE.using_arduino and value.upper() in ESP_ARDUINO_UNSUPPORTED_USB_UARTS:
raise cv.Invalid(f"Arduino framework does not support {value}.")
variant = get_esp32_variant()
if CORE.using_esp_idf and variant == VARIANT_ESP32C3 and value == USB_CDC:
raise cv.Invalid(
f"{value} is not supported for variant {variant} when using ESP-IDF."
)
if variant in UART_SELECTION_ESP32:
return cv.one_of(*UART_SELECTION_ESP32[variant], upper=True)(value)
if CORE.is_esp8266:
@@ -226,14 +218,11 @@ CONFIG_SCHEMA = cv.All(
esp8266=UART0,
esp32=UART0,
esp32_s2=USB_CDC,
esp32_s3_arduino=USB_CDC,
esp32_s3_idf=USB_SERIAL_JTAG,
esp32_c3_arduino=USB_CDC,
esp32_c3_idf=USB_SERIAL_JTAG,
esp32_c5_idf=USB_SERIAL_JTAG,
esp32_c6_arduino=USB_CDC,
esp32_c6_idf=USB_SERIAL_JTAG,
esp32_p4_idf=USB_SERIAL_JTAG,
esp32_s3=USB_SERIAL_JTAG,
esp32_c3=USB_SERIAL_JTAG,
esp32_c5=USB_SERIAL_JTAG,
esp32_c6=USB_SERIAL_JTAG,
esp32_p4=USB_SERIAL_JTAG,
rp2040=USB_CDC,
bk72xx=DEFAULT,
ln882x=DEFAULT,
@@ -346,15 +335,7 @@ async def to_code(config):
if config.get(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH):
cg.add_build_flag("-DUSE_STORE_LOG_STR_IN_FLASH")
if CORE.using_arduino and config[CONF_HARDWARE_UART] == USB_CDC:
cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1")
if CORE.is_esp32 and get_esp32_variant() in (
VARIANT_ESP32C3,
VARIANT_ESP32C6,
):
cg.add_build_flag("-DARDUINO_USB_MODE=1")
if CORE.using_esp_idf:
if CORE.is_esp32:
if config[CONF_HARDWARE_UART] == USB_CDC:
add_idf_sdkconfig_option("CONFIG_ESP_CONSOLE_USB_CDC", True)
elif config[CONF_HARDWARE_UART] == USB_SERIAL_JTAG:
+2 -18
View File
@@ -173,24 +173,8 @@ void Logger::init_log_buffer(size_t total_buffer_size) {
}
#endif
#ifndef USE_ZEPHYR
#if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32)
void Logger::loop() {
#if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO)
if (this->uart_ == UART_SELECTION_USB_CDC) {
static bool opened = false;
if (opened == Serial) {
return;
}
if (false == opened) {
App.schedule_dump_config();
}
opened = !opened;
}
#endif
this->process_messages_();
}
#endif
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
void Logger::loop() { this->process_messages_(); }
#endif
void Logger::process_messages_() {
+9 -21
View File
@@ -16,18 +16,18 @@
#endif
#ifdef USE_ARDUINO
#if defined(USE_ESP8266) || defined(USE_ESP32)
#if defined(USE_ESP8266)
#include <HardwareSerial.h>
#endif // USE_ESP8266 || USE_ESP32
#endif // USE_ESP8266
#ifdef USE_RP2040
#include <HardwareSerial.h>
#include <SerialUSB.h>
#endif // USE_RP2040
#endif // USE_ARDUINO
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
#include <driver/uart.h>
#endif // USE_ESP_IDF
#endif // USE_ESP32
#ifdef USE_ZEPHYR
#include <zephyr/kernel.h>
@@ -110,19 +110,17 @@ class Logger : public Component {
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
void init_log_buffer(size_t total_buffer_size);
#endif
#if defined(USE_LOGGER_USB_CDC) || defined(USE_ESP32) || defined(USE_ZEPHYR)
#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC))
void loop() override;
#endif
/// Manually set the baud rate for serial, set to 0 to disable.
void set_baud_rate(uint32_t baud_rate);
uint32_t get_baud_rate() const { return baud_rate_; }
#ifdef USE_ARDUINO
#if defined(USE_ARDUINO) && !defined(USE_ESP32)
Stream *get_hw_serial() const { return hw_serial_; }
#endif
#ifdef USE_ESP_IDF
uart_port_t get_uart_num() const { return uart_num_; }
#endif
#ifdef USE_ESP32
uart_port_t get_uart_num() const { return uart_num_; }
void create_pthread_key() { pthread_key_create(&log_recursion_key_, nullptr); }
#endif
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
@@ -232,7 +230,7 @@ class Logger : public Component {
// Group 4-byte aligned members first
uint32_t baud_rate_;
char *tx_buffer_{nullptr};
#ifdef USE_ARDUINO
#if defined(USE_ARDUINO) && !defined(USE_ESP32)
Stream *hw_serial_{nullptr};
#endif
#if defined(USE_ZEPHYR)
@@ -246,9 +244,7 @@ class Logger : public Component {
// - Main task uses a dedicated member variable for efficiency
// - Other tasks use pthread TLS with a dynamically created key via pthread_key_create
pthread_key_t log_recursion_key_; // 4 bytes
#endif
#ifdef USE_ESP_IDF
uart_port_t uart_num_; // 4 bytes (enum defaults to int size)
uart_port_t uart_num_; // 4 bytes (enum defaults to int size)
#endif
// Large objects (internally aligned)
@@ -380,15 +376,7 @@ class Logger : public Component {
// will be processed on the next main loop iteration since:
// - disable_loop() takes effect immediately
// - enable_loop_soon_any_context() sets a pending flag that's checked at loop start
#if defined(USE_LOGGER_USB_CDC) && defined(USE_ARDUINO)
// Only disable if not using USB CDC (which needs loop for connection detection)
if (this->uart_ != UART_SELECTION_USB_CDC) {
this->disable_loop();
}
#else
// No USB CDC support, always safe to disable
this->disable_loop();
#endif
}
#endif
};
@@ -1,11 +1,8 @@
#ifdef USE_ESP32
#include "logger.h"
#if defined(USE_ESP32_FRAMEWORK_ARDUINO) || defined(USE_ESP_IDF)
#include <esp_log.h>
#endif // USE_ESP32_FRAMEWORK_ARDUINO || USE_ESP_IDF
#ifdef USE_ESP_IDF
#include <driver/uart.h>
#ifdef USE_LOGGER_USB_SERIAL_JTAG
@@ -25,16 +22,12 @@
#include <cstdint>
#include <cstdio>
#endif // USE_ESP_IDF
#include "esphome/core/log.h"
namespace esphome::logger {
static const char *const TAG = "logger";
#ifdef USE_ESP_IDF
#ifdef USE_LOGGER_USB_SERIAL_JTAG
static void init_usb_serial_jtag_() {
setvbuf(stdin, NULL, _IONBF, 0); // Disable buffering on stdin
@@ -89,42 +82,8 @@ void init_uart(uart_port_t uart_num, uint32_t baud_rate, int tx_buffer_size) {
uart_driver_install(uart_num, uart_buffer_size, uart_buffer_size, 10, nullptr, 0);
}
#endif // USE_ESP_IDF
void Logger::pre_setup() {
if (this->baud_rate_ > 0) {
#ifdef USE_ARDUINO
switch (this->uart_) {
case UART_SELECTION_UART0:
#if ARDUINO_USB_CDC_ON_BOOT
this->hw_serial_ = &Serial0;
Serial0.begin(this->baud_rate_);
#else
this->hw_serial_ = &Serial;
Serial.begin(this->baud_rate_);
#endif
break;
case UART_SELECTION_UART1:
this->hw_serial_ = &Serial1;
Serial1.begin(this->baud_rate_);
break;
#ifdef USE_ESP32_VARIANT_ESP32
case UART_SELECTION_UART2:
this->hw_serial_ = &Serial2;
Serial2.begin(this->baud_rate_);
break;
#endif
#ifdef USE_LOGGER_USB_CDC
case UART_SELECTION_USB_CDC:
this->hw_serial_ = &Serial;
Serial.begin(this->baud_rate_);
break;
#endif
}
#endif // USE_ARDUINO
#ifdef USE_ESP_IDF
this->uart_num_ = UART_NUM_0;
switch (this->uart_) {
case UART_SELECTION_UART0:
@@ -151,21 +110,17 @@ void Logger::pre_setup() {
break;
#endif
}
#endif // USE_ESP_IDF
}
global_logger = this;
#if defined(USE_ESP_IDF) || defined(USE_ESP32_FRAMEWORK_ARDUINO)
esp_log_set_vprintf(esp_idf_log_vprintf_);
if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE) {
esp_log_level_set("*", ESP_LOG_VERBOSE);
}
#endif // USE_ESP_IDF || USE_ESP32_FRAMEWORK_ARDUINO
ESP_LOGI(TAG, "Log initialized");
}
#ifdef USE_ESP_IDF
void HOT Logger::write_msg_(const char *msg) {
if (
#if defined(USE_LOGGER_USB_CDC) && !defined(USE_LOGGER_USB_SERIAL_JTAG)
@@ -186,9 +141,6 @@ void HOT Logger::write_msg_(const char *msg) {
uart_write_bytes(this->uart_num_, "\n", 1);
}
}
#else
void HOT Logger::write_msg_(const char *msg) { this->hw_serial_->println(msg); }
#endif
const LogString *Logger::get_uart_selection_() {
switch (this->uart_) {
+2 -3
View File
@@ -12,8 +12,8 @@ namespace esphome::logger {
static const char *const TAG = "logger";
void Logger::loop() {
#ifdef USE_LOGGER_USB_CDC
void Logger::loop() {
if (this->uart_ != UART_SELECTION_USB_CDC || nullptr == this->uart_dev_) {
return;
}
@@ -30,9 +30,8 @@ void Logger::loop() {
App.schedule_dump_config();
}
opened = !opened;
#endif
this->process_messages_();
}
#endif
void Logger::pre_setup() {
if (this->baud_rate_ > 0) {
+7 -3
View File
@@ -47,9 +47,13 @@ async def to_code(config):
cg.add_define(
"USE_NETWORK_MIN_IPV6_ADDR_COUNT", config[CONF_MIN_IPV6_ADDR_COUNT]
)
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6)
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6)
if CORE.is_esp32:
if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", enable_ipv6)
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", enable_ipv6)
else:
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", True)
add_idf_sdkconfig_option("CONFIG_LWIP_IPV6_AUTOCONFIG", True)
elif enable_ipv6:
cg.add_build_flag("-DCONFIG_LWIP_IPV6")
cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG")
+4 -4
View File
@@ -153,10 +153,10 @@ async def to_code(config):
if CONF_TFT_URL in config:
cg.add_define("USE_NEXTION_TFT_UPLOAD")
cg.add(var.set_tft_url(config[CONF_TFT_URL]))
if CORE.is_esp32 and CORE.using_arduino:
cg.add_library("NetworkClientSecure", None)
cg.add_library("HTTPClient", None)
elif CORE.is_esp32 and CORE.using_esp_idf:
if CORE.is_esp32:
if CORE.using_arduino:
cg.add_library("NetworkClientSecure", None)
cg.add_library("HTTPClient", None)
esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True)
esp32.add_idf_sdkconfig_option(
"CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True
+22 -25
View File
@@ -121,33 +121,30 @@ async def to_code(config):
if config[CONF_MODE] == TYPE_OCTAL:
cg.add_platformio_option("board_build.arduino.memory_type", "qio_opi")
if CORE.using_esp_idf:
add_idf_sdkconfig_option(
f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True
)
add_idf_sdkconfig_option("CONFIG_SOC_SPIRAM_SUPPORTED", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True)
add_idf_sdkconfig_option(
f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True
)
add_idf_sdkconfig_option("CONFIG_SOC_SPIRAM_SUPPORTED", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True)
add_idf_sdkconfig_option(
f"CONFIG_SPIRAM_MODE_{SDK_MODES[config[CONF_MODE]]}", True
)
add_idf_sdkconfig_option(f"CONFIG_SPIRAM_MODE_{SDK_MODES[config[CONF_MODE]]}", True)
# Remove MHz suffix, convert to int
speed = int(config[CONF_SPEED][:-3])
add_idf_sdkconfig_option(f"CONFIG_SPIRAM_SPEED_{speed}M", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_SPEED", speed)
if config[CONF_MODE] == TYPE_OCTAL and speed == 120:
add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True)
add_idf_sdkconfig_option("CONFIG_BOOTLOADER_FLASH_DC_AWARE", True)
if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 4, 0):
add_idf_sdkconfig_option(
"CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True
)
if config[CONF_ENABLE_ECC]:
add_idf_sdkconfig_option("CONFIG_SPIRAM_ECC_ENABLE", True)
# Remove MHz suffix, convert to int
speed = int(config[CONF_SPEED][:-3])
add_idf_sdkconfig_option(f"CONFIG_SPIRAM_SPEED_{speed}M", True)
add_idf_sdkconfig_option("CONFIG_SPIRAM_SPEED", speed)
if config[CONF_MODE] == TYPE_OCTAL and speed == 120:
add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True)
add_idf_sdkconfig_option("CONFIG_BOOTLOADER_FLASH_DC_AWARE", True)
if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 4, 0):
add_idf_sdkconfig_option(
"CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True
)
if config[CONF_ENABLE_ECC]:
add_idf_sdkconfig_option("CONFIG_SPIRAM_ECC_ENABLE", True)
cg.add_define("USE_PSRAM")
+5 -26
View File
@@ -16,7 +16,6 @@ from esphome.const import (
CONF_DUMMY_RECEIVER_ID,
CONF_ID,
CONF_INVERT,
CONF_INVERTED,
CONF_LAMBDA,
CONF_NUMBER,
CONF_PORT,
@@ -39,9 +38,6 @@ uart_ns = cg.esphome_ns.namespace("uart")
UARTComponent = uart_ns.class_("UARTComponent")
IDFUARTComponent = uart_ns.class_("IDFUARTComponent", UARTComponent, cg.Component)
ESP32ArduinoUARTComponent = uart_ns.class_(
"ESP32ArduinoUARTComponent", UARTComponent, cg.Component
)
ESP8266UartComponent = uart_ns.class_(
"ESP8266UartComponent", UARTComponent, cg.Component
)
@@ -53,7 +49,6 @@ HostUartComponent = uart_ns.class_("HostUartComponent", UARTComponent, cg.Compon
NATIVE_UART_CLASSES = (
str(IDFUARTComponent),
str(ESP32ArduinoUARTComponent),
str(ESP8266UartComponent),
str(RP2040UartComponent),
str(LibreTinyUARTComponent),
@@ -119,20 +114,6 @@ def validate_rx_pin(value):
return value
def validate_invert_esp32(config):
if (
CORE.is_esp32
and CORE.using_arduino
and CONF_TX_PIN in config
and CONF_RX_PIN in config
and config[CONF_TX_PIN][CONF_INVERTED] != config[CONF_RX_PIN][CONF_INVERTED]
):
raise cv.Invalid(
"Different invert values for TX and RX pin are not supported for ESP32 when using Arduino."
)
return config
def validate_host_config(config):
if CORE.is_host:
if CONF_TX_PIN in config or CONF_RX_PIN in config:
@@ -151,10 +132,7 @@ def _uart_declare_type(value):
if CORE.is_esp8266:
return cv.declare_id(ESP8266UartComponent)(value)
if CORE.is_esp32:
if CORE.using_arduino:
return cv.declare_id(ESP32ArduinoUARTComponent)(value)
if CORE.using_esp_idf:
return cv.declare_id(IDFUARTComponent)(value)
return cv.declare_id(IDFUARTComponent)(value)
if CORE.is_rp2040:
return cv.declare_id(RP2040UartComponent)(value)
if CORE.is_libretiny:
@@ -255,7 +233,6 @@ CONFIG_SCHEMA = cv.All(
}
).extend(cv.COMPONENT_SCHEMA),
cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT),
validate_invert_esp32,
validate_host_config,
)
@@ -444,8 +421,10 @@ async def uart_write_to_code(config, action_id, template_arg, args):
FILTER_SOURCE_FILES = filter_source_files_from_platform(
{
"uart_component_esp32_arduino.cpp": {PlatformFramework.ESP32_ARDUINO},
"uart_component_esp_idf.cpp": {PlatformFramework.ESP32_IDF},
"uart_component_esp_idf.cpp": {
PlatformFramework.ESP32_IDF,
PlatformFramework.ESP32_ARDUINO,
},
"uart_component_esp8266.cpp": {PlatformFramework.ESP8266_ARDUINO},
"uart_component_host.cpp": {PlatformFramework.HOST_NATIVE},
"uart_component_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO},
@@ -1,214 +0,0 @@
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
#include "uart_component_esp32_arduino.h"
#include "esphome/core/application.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#ifdef USE_LOGGER
#include "esphome/components/logger/logger.h"
#endif
namespace esphome {
namespace uart {
static const char *const TAG = "uart.arduino_esp32";
static const uint32_t UART_PARITY_EVEN = 0 << 0;
static const uint32_t UART_PARITY_ODD = 1 << 0;
static const uint32_t UART_PARITY_ENABLE = 1 << 1;
static const uint32_t UART_NB_BIT_5 = 0 << 2;
static const uint32_t UART_NB_BIT_6 = 1 << 2;
static const uint32_t UART_NB_BIT_7 = 2 << 2;
static const uint32_t UART_NB_BIT_8 = 3 << 2;
static const uint32_t UART_NB_STOP_BIT_1 = 1 << 4;
static const uint32_t UART_NB_STOP_BIT_2 = 3 << 4;
static const uint32_t UART_TICK_APB_CLOCK = 1 << 27;
uint32_t ESP32ArduinoUARTComponent::get_config() {
uint32_t config = 0;
/*
* All bits numbers below come from
* framework-arduinoespressif32/cores/esp32/esp32-hal-uart.h
* And more specifically conf0 union in uart_dev_t.
*
* Below is bit used from conf0 union.
* <name>:<bits position> <values>
* parity:0 0:even 1:odd
* parity_en:1 Set this bit to enable uart parity check.
* bit_num:2-4 0:5bits 1:6bits 2:7bits 3:8bits
* stop_bit_num:4-6 stop bit. 1:1bit 2:1.5bits 3:2bits
* tick_ref_always_on:27 select the clock.1apb clockref_tick
*/
if (this->parity_ == UART_CONFIG_PARITY_EVEN) {
config |= UART_PARITY_EVEN | UART_PARITY_ENABLE;
} else if (this->parity_ == UART_CONFIG_PARITY_ODD) {
config |= UART_PARITY_ODD | UART_PARITY_ENABLE;
}
switch (this->data_bits_) {
case 5:
config |= UART_NB_BIT_5;
break;
case 6:
config |= UART_NB_BIT_6;
break;
case 7:
config |= UART_NB_BIT_7;
break;
case 8:
config |= UART_NB_BIT_8;
break;
}
if (this->stop_bits_ == 1) {
config |= UART_NB_STOP_BIT_1;
} else {
config |= UART_NB_STOP_BIT_2;
}
config |= UART_TICK_APB_CLOCK;
return config;
}
void ESP32ArduinoUARTComponent::setup() {
// Use Arduino HardwareSerial UARTs if all used pins match the ones
// preconfigured by the platform. For example if RX disabled but TX pin
// is 1 we still want to use Serial.
bool is_default_tx, is_default_rx;
#ifdef CONFIG_IDF_TARGET_ESP32C3
is_default_tx = tx_pin_ == nullptr || tx_pin_->get_pin() == 21;
is_default_rx = rx_pin_ == nullptr || rx_pin_->get_pin() == 20;
#else
is_default_tx = tx_pin_ == nullptr || tx_pin_->get_pin() == 1;
is_default_rx = rx_pin_ == nullptr || rx_pin_->get_pin() == 3;
#endif
static uint8_t next_uart_num = 0;
if (is_default_tx && is_default_rx && next_uart_num == 0) {
#if ARDUINO_USB_CDC_ON_BOOT
this->hw_serial_ = &Serial0;
#else
this->hw_serial_ = &Serial;
#endif
next_uart_num++;
} else {
#ifdef USE_LOGGER
bool logger_uses_hardware_uart = true;
#ifdef USE_LOGGER_USB_CDC
if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_CDC) {
// this is not a hardware UART, ignore it
logger_uses_hardware_uart = false;
}
#endif // USE_LOGGER_USB_CDC
#ifdef USE_LOGGER_USB_SERIAL_JTAG
if (logger::global_logger->get_uart() == logger::UART_SELECTION_USB_SERIAL_JTAG) {
// this is not a hardware UART, ignore it
logger_uses_hardware_uart = false;
}
#endif // USE_LOGGER_USB_SERIAL_JTAG
if (logger_uses_hardware_uart && logger::global_logger->get_baud_rate() > 0 &&
logger::global_logger->get_uart() == next_uart_num) {
next_uart_num++;
}
#endif // USE_LOGGER
if (next_uart_num >= SOC_UART_NUM) {
ESP_LOGW(TAG, "Maximum number of UART components created already.");
this->mark_failed();
return;
}
this->number_ = next_uart_num;
this->hw_serial_ = new HardwareSerial(next_uart_num++); // NOLINT(cppcoreguidelines-owning-memory)
}
this->load_settings(false);
}
void ESP32ArduinoUARTComponent::load_settings(bool dump_config) {
int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1;
int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1;
bool invert = false;
if (tx_pin_ != nullptr && tx_pin_->is_inverted())
invert = true;
if (rx_pin_ != nullptr && rx_pin_->is_inverted())
invert = true;
this->hw_serial_->setRxBufferSize(this->rx_buffer_size_);
this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert);
if (dump_config) {
ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->number_);
this->dump_config();
}
}
void ESP32ArduinoUARTComponent::dump_config() {
ESP_LOGCONFIG(TAG, "UART Bus %d:", this->number_);
LOG_PIN(" TX Pin: ", tx_pin_);
LOG_PIN(" RX Pin: ", rx_pin_);
if (this->rx_pin_ != nullptr) {
ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
}
ESP_LOGCONFIG(TAG,
" Baud Rate: %u baud\n"
" Data Bits: %u\n"
" Parity: %s\n"
" Stop bits: %u",
this->baud_rate_, this->data_bits_, LOG_STR_ARG(parity_to_str(this->parity_)), this->stop_bits_);
this->check_logger_conflict();
}
void ESP32ArduinoUARTComponent::write_array(const uint8_t *data, size_t len) {
this->hw_serial_->write(data, len);
#ifdef USE_UART_DEBUGGER
for (size_t i = 0; i < len; i++) {
this->debug_callback_.call(UART_DIRECTION_TX, data[i]);
}
#endif
}
bool ESP32ArduinoUARTComponent::peek_byte(uint8_t *data) {
if (!this->check_read_timeout_())
return false;
*data = this->hw_serial_->peek();
return true;
}
bool ESP32ArduinoUARTComponent::read_array(uint8_t *data, size_t len) {
if (!this->check_read_timeout_(len))
return false;
this->hw_serial_->readBytes(data, len);
#ifdef USE_UART_DEBUGGER
for (size_t i = 0; i < len; i++) {
this->debug_callback_.call(UART_DIRECTION_RX, data[i]);
}
#endif
return true;
}
int ESP32ArduinoUARTComponent::available() { return this->hw_serial_->available(); }
void ESP32ArduinoUARTComponent::flush() {
ESP_LOGVV(TAG, " Flushing");
this->hw_serial_->flush();
}
void ESP32ArduinoUARTComponent::check_logger_conflict() {
#ifdef USE_LOGGER
if (this->hw_serial_ == nullptr || logger::global_logger->get_baud_rate() == 0) {
return;
}
if (this->hw_serial_ == logger::global_logger->get_hw_serial()) {
ESP_LOGW(TAG, " You're using the same serial port for logging and the UART component. Please "
"disable logging over the serial port by setting logger->baud_rate to 0.");
}
#endif
}
} // namespace uart
} // namespace esphome
#endif // USE_ESP32_FRAMEWORK_ARDUINO
@@ -1,60 +0,0 @@
#pragma once
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
#include <driver/uart.h>
#include <HardwareSerial.h>
#include <vector>
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include "uart_component.h"
namespace esphome {
namespace uart {
class ESP32ArduinoUARTComponent : public UARTComponent, public Component {
public:
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::BUS; }
void write_array(const uint8_t *data, size_t len) override;
bool peek_byte(uint8_t *data) override;
bool read_array(uint8_t *data, size_t len) override;
int available() override;
void flush() override;
uint32_t get_config();
HardwareSerial *get_hw_serial() { return this->hw_serial_; }
uint8_t get_hw_serial_number() { return this->number_; }
/**
* Load the UART with the current settings.
* @param dump_config (Optional, default `true`): True for displaying new settings or
* false to change it quitely
*
* Example:
* ```cpp
* id(uart1).load_settings();
* ```
*
* This will load the current UART interface with the latest settings (baud_rate, parity, etc).
*/
void load_settings(bool dump_config) override;
void load_settings() override { this->load_settings(true); }
protected:
void check_logger_conflict() override;
HardwareSerial *hw_serial_{nullptr};
uint8_t number_{0};
};
} // namespace uart
} // namespace esphome
#endif // USE_ESP32_FRAMEWORK_ARDUINO
@@ -1,4 +1,4 @@
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
#include "uart_component_esp_idf.h"
#include <cinttypes>
@@ -1,6 +1,6 @@
#pragma once
#ifdef USE_ESP_IDF
#ifdef USE_ESP32
#include <driver/uart.h>
#include "esphome/core/component.h"
@@ -55,4 +55,4 @@ class IDFUARTComponent : public UARTComponent, public Component {
} // namespace uart
} // namespace esphome
#endif // USE_ESP_IDF
#endif // USE_ESP32
+1 -1
View File
@@ -402,7 +402,7 @@ async def to_code(config):
add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False)
# Disable Enterprise WiFi support if no EAP is configured
if CORE.is_esp32 and CORE.using_esp_idf and not has_eap:
if CORE.is_esp32 and not has_eap:
add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT", False)
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
+1 -1
View File
@@ -118,7 +118,7 @@ async def to_code(config):
# Workaround for crash on IDF 5+
# See https://github.com/trombik/esp_wireguard/issues/33#issuecomment-1568503651
if CORE.using_esp_idf:
if CORE.is_esp32:
add_idf_sdkconfig_option("CONFIG_LWIP_PPP_SUPPORT", True)
# This flag is added here because the esp_wireguard library statically
+2
View File
@@ -70,6 +70,8 @@ FILTER_PLATFORMIO_LINES = [
r" - tool-esptool.* \(.*\)",
r" - toolchain-.* \(.*\)",
r"Creating BIN file .*",
r"Warning! Could not find file \".*.crt\"",
r"Warning! Arduino framework as an ESP-IDF component doesn't handle the `variant` field! The default `esp32` variant will be used.",
]