mirror of
https://github.com/esphome/esphome.git
synced 2026-09-22 12:38:40 +00:00
Merge remote-tracking branch 'upstream/rp2040-crash-handler-fixes' into integration
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
#ifdef USE_ESP32_CRASH_HANDLER
|
||||
#include "esphome/components/esp32/crash_handler.h"
|
||||
#endif
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
#include "esphome/components/rp2040/crash_handler.h"
|
||||
#endif
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
@@ -240,6 +243,9 @@ class APIConnection final : public APIServerConnectionBase {
|
||||
App.schedule_dump_config();
|
||||
#ifdef USE_ESP32_CRASH_HANDLER
|
||||
esp32::crash_handler_log();
|
||||
#endif
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
rp2040::crash_handler_log();
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
||||
|
||||
@@ -105,7 +105,7 @@ async def to_code(config):
|
||||
if framework_ver >= cv.Version(5, 5, 0):
|
||||
esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.4.0")
|
||||
esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4")
|
||||
esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.0")
|
||||
esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.1")
|
||||
else:
|
||||
esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="0.13.0")
|
||||
esp32.add_idf_component(name="espressif/eppp_link", ref="0.2.0")
|
||||
|
||||
@@ -21,22 +21,6 @@
|
||||
|
||||
namespace esphome::ethernet {
|
||||
|
||||
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2)
|
||||
// work around IDF compile issue on P4 https://github.com/espressif/esp-idf/pull/15637
|
||||
#ifdef USE_ESP32_VARIANT_ESP32P4
|
||||
#undef ETH_ESP32_EMAC_DEFAULT_CONFIG
|
||||
#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
|
||||
{ \
|
||||
.smi_gpio = {.mdc_num = 31, .mdio_num = 52}, .interface = EMAC_DATA_INTERFACE_RMII, \
|
||||
.clock_config = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) 50}}, \
|
||||
.dma_burst_len = ETH_DMA_BURST_LEN_32, .intr_priority = 0, \
|
||||
.emac_dataif_gpio = \
|
||||
{.rmii = {.tx_en_num = 49, .txd0_num = 34, .txd1_num = 35, .crs_dv_num = 28, .rxd0_num = 29, .rxd1_num = 30}}, \
|
||||
.clock_config_out_in = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) -1}}, \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const char *const TAG = "ethernet";
|
||||
|
||||
// PHY register size for hex logging
|
||||
@@ -162,7 +146,7 @@ void EthernetComponent::setup() {
|
||||
phy_config.phy_addr = this->phy_addr_;
|
||||
phy_config.reset_gpio_num = this->power_pin_;
|
||||
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
eth_esp32_emac_config_t esp32_emac_config = eth_esp32_emac_default_config();
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
|
||||
esp32_emac_config.smi_gpio.mdc_num = this->mdc_pin_;
|
||||
esp32_emac_config.smi_gpio.mdio_num = this->mdio_pin_;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "esp_mac.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void);
|
||||
|
||||
namespace esphome::ethernet {
|
||||
|
||||
#ifdef USE_ETHERNET_IP_STATE_LISTENERS
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "esp_eth_mac_esp.h"
|
||||
|
||||
// ETH_ESP32_EMAC_DEFAULT_CONFIG() uses out-of-order designated initializers
|
||||
// which are valid in C but not in C++. This wrapper allows C++ code to get
|
||||
// the default config without replicating the macro's contents.
|
||||
eth_esp32_emac_config_t eth_esp32_emac_default_config(void) {
|
||||
return (eth_esp32_emac_config_t) ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifdef USE_RP2040
|
||||
#include "logger.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
#include "esphome/components/rp2040/crash_handler.h"
|
||||
#endif
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::logger {
|
||||
@@ -26,7 +29,9 @@ void Logger::pre_setup() {
|
||||
}
|
||||
global_logger = this;
|
||||
ESP_LOGI(TAG, "Log initialized");
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
rp2040::crash_handler_log();
|
||||
#endif
|
||||
}
|
||||
|
||||
void HOT Logger::write_msg_(const char *msg, uint16_t len) {
|
||||
|
||||
@@ -217,6 +217,7 @@ async def to_code(config):
|
||||
)
|
||||
|
||||
cg.add_define("USE_RP2040_WATCHDOG_TIMEOUT", config[CONF_WATCHDOG_TIMEOUT])
|
||||
cg.add_define("USE_RP2040_CRASH_HANDLER")
|
||||
|
||||
|
||||
def add_pio_file(component: str, key: str, data: str):
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#ifdef USE_RP2040
|
||||
|
||||
#include "core.h"
|
||||
#include "crash_handler.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
#include "crash_handler.h"
|
||||
#endif
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
@@ -25,7 +27,9 @@ void arch_restart() {
|
||||
}
|
||||
|
||||
void arch_init() {
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
rp2040::crash_handler_read_and_clear();
|
||||
#endif
|
||||
#if USE_RP2040_WATCHDOG_TIMEOUT > 0
|
||||
watchdog_enable(USE_RP2040_WATCHDOG_TIMEOUT, false);
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#ifdef USE_RP2040
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
|
||||
#include "crash_handler.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
@@ -13,13 +16,19 @@
|
||||
static constexpr uint32_t EF_LR = 5;
|
||||
static constexpr uint32_t EF_PC = 6;
|
||||
|
||||
static constexpr uint32_t CRASH_MAGIC = 0xDEADBEEF;
|
||||
// Version encoded in the magic value: upper 16 bits are sentinel (0xDEAD),
|
||||
// lower 16 bits are the version number. This avoids using a separate scratch
|
||||
// register for versioning (we only have 8 total). Future firmware reads the
|
||||
// sentinel to confirm it's crash data, then the version to know the layout.
|
||||
static constexpr uint32_t CRASH_MAGIC_SENTINEL = 0xDEAD0000;
|
||||
static constexpr uint32_t CRASH_DATA_VERSION = 1;
|
||||
static constexpr uint32_t CRASH_MAGIC_V1 = CRASH_MAGIC_SENTINEL | CRASH_DATA_VERSION;
|
||||
|
||||
// We only have 8 scratch registers (32 bytes) that survive watchdog reboot.
|
||||
// Use them for the most important data, then scan the stack for code addresses.
|
||||
//
|
||||
// Scratch register layout:
|
||||
// [0] = magic (CRASH_MAGIC)
|
||||
// [0] = versioned magic (upper 16 bits = 0xDEAD sentinel, lower 16 bits = version)
|
||||
// [1] = PC (program counter at fault)
|
||||
// [2] = LR (link register from exception frame)
|
||||
// [3] = SP (stack pointer at fault)
|
||||
@@ -57,9 +66,12 @@ static struct {
|
||||
uint8_t backtrace_count;
|
||||
} __attribute__((section(".noinit"))) s_crash_data;
|
||||
|
||||
bool crash_handler_has_data() { return s_crash_data.valid; }
|
||||
|
||||
void crash_handler_read_and_clear() {
|
||||
s_crash_data.valid = false;
|
||||
if (watchdog_hw->scratch[0] == CRASH_MAGIC) {
|
||||
uint32_t magic = watchdog_hw->scratch[0];
|
||||
if ((magic & 0xFFFF0000) == CRASH_MAGIC_SENTINEL && (magic & 0xFFFF) == CRASH_DATA_VERSION) {
|
||||
s_crash_data.valid = true;
|
||||
s_crash_data.pc = watchdog_hw->scratch[1];
|
||||
s_crash_data.lr = watchdog_hw->scratch[2];
|
||||
@@ -135,7 +147,7 @@ static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame
|
||||
// by a stacking error or corrupted SP, frame may be invalid. Write a minimal
|
||||
// crash marker so we at least know a crash occurred.
|
||||
if (!is_valid_sram_ptr(frame)) {
|
||||
watchdog_hw->scratch[0] = CRASH_MAGIC;
|
||||
watchdog_hw->scratch[0] = CRASH_MAGIC_V1;
|
||||
watchdog_hw->scratch[1] = 0; // PC unknown
|
||||
watchdog_hw->scratch[2] = 0; // LR unknown
|
||||
watchdog_hw->scratch[3] = reinterpret_cast<uintptr_t>(frame); // Record the bad SP for diagnosis
|
||||
@@ -157,7 +169,7 @@ static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame
|
||||
uint32_t pre_fault_sp = reinterpret_cast<uintptr_t>(post_frame);
|
||||
|
||||
// Write key registers
|
||||
watchdog_hw->scratch[0] = CRASH_MAGIC;
|
||||
watchdog_hw->scratch[0] = CRASH_MAGIC_V1;
|
||||
watchdog_hw->scratch[1] = frame[EF_PC];
|
||||
watchdog_hw->scratch[2] = frame[EF_LR];
|
||||
watchdog_hw->scratch[3] = pre_fault_sp;
|
||||
@@ -224,4 +236,5 @@ extern "C" void __attribute__((naked, used)) isr_hardfault() {
|
||||
: "i"(hard_fault_handler_c));
|
||||
}
|
||||
|
||||
#endif // USE_RP2040_CRASH_HANDLER
|
||||
#endif // USE_RP2040
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#ifdef USE_RP2040
|
||||
|
||||
#include <cstdint>
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#ifdef USE_RP2040_CRASH_HANDLER
|
||||
|
||||
namespace esphome::rp2040 {
|
||||
|
||||
@@ -12,6 +14,10 @@ void crash_handler_read_and_clear();
|
||||
/// Log crash data if a crash was detected on previous boot.
|
||||
void crash_handler_log();
|
||||
|
||||
/// Returns true if crash data was found this boot.
|
||||
bool crash_handler_has_data();
|
||||
|
||||
} // namespace esphome::rp2040
|
||||
|
||||
#endif // USE_RP2040_CRASH_HANDLER
|
||||
#endif // USE_RP2040
|
||||
|
||||
@@ -339,6 +339,7 @@
|
||||
#ifdef USE_RP2040
|
||||
#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0)
|
||||
#define USE_LOOP_PRIORITY
|
||||
#define USE_RP2040_CRASH_HANDLER
|
||||
#define USE_HTTP_REQUEST_RESPONSE
|
||||
#define USE_I2C
|
||||
#define USE_LOGGER_USB_CDC
|
||||
|
||||
@@ -20,7 +20,7 @@ dependencies:
|
||||
rules:
|
||||
- if: "target in [esp32h2, esp32p4]"
|
||||
espressif/esp_hosted:
|
||||
version: 2.12.0
|
||||
version: 2.12.1
|
||||
rules:
|
||||
- if: "target in [esp32h2, esp32p4]"
|
||||
zorxx/multipart-parser:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common-ip101.yaml
|
||||
Reference in New Issue
Block a user