ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
debug_esp8266.cpp
Go to the documentation of this file.
1#include "debug_component.h"
2#ifdef USE_ESP8266
3#include "esphome/core/log.h"
5#include <Esp.h>
6
7extern "C" {
8#include <user_interface.h>
9
10// Global reset info struct populated by SDK at boot
11extern struct rst_info resetInfo;
12
13// Core version - either a string pointer or a version number to format as hex
15extern const char *core_release;
16}
17
18namespace esphome {
19namespace debug {
20
21static const char *const TAG = "debug";
22
23// PROGMEM string table for reset reasons, indexed by reason code (0-6), with "Unknown" as fallback
24// clang-format off
25PROGMEM_STRING_TABLE(ResetReasonStrings,
26 "Power On", // 0 = REASON_DEFAULT_RST
27 "Hardware Watchdog", // 1 = REASON_WDT_RST
28 "Exception", // 2 = REASON_EXCEPTION_RST
29 "Software Watchdog", // 3 = REASON_SOFT_WDT_RST
30 "Software/System restart", // 4 = REASON_SOFT_RESTART
31 "Deep-Sleep Wake", // 5 = REASON_DEEP_SLEEP_AWAKE
32 "External System", // 6 = REASON_EXT_SYS_RST
33 "Unknown" // 7 = fallback
34);
35// clang-format on
36static_assert(REASON_DEFAULT_RST == 0, "Reset reason enum values must match table indices");
37static_assert(REASON_WDT_RST == 1, "Reset reason enum values must match table indices");
38static_assert(REASON_EXCEPTION_RST == 2, "Reset reason enum values must match table indices");
39static_assert(REASON_SOFT_WDT_RST == 3, "Reset reason enum values must match table indices");
40static_assert(REASON_SOFT_RESTART == 4, "Reset reason enum values must match table indices");
41static_assert(REASON_DEEP_SLEEP_AWAKE == 5, "Reset reason enum values must match table indices");
42static_assert(REASON_EXT_SYS_RST == 6, "Reset reason enum values must match table indices");
43
44// PROGMEM string table for flash chip modes, indexed by mode code (0-3), with "UNKNOWN" as fallback
45PROGMEM_STRING_TABLE(FlashModeStrings, "QIO", "QOUT", "DIO", "DOUT", "UNKNOWN");
46static_assert(FM_QIO == 0, "Flash mode enum values must match table indices");
47static_assert(FM_QOUT == 1, "Flash mode enum values must match table indices");
48static_assert(FM_DIO == 2, "Flash mode enum values must match table indices");
49static_assert(FM_DOUT == 3, "Flash mode enum values must match table indices");
50
51// Get reset reason string from reason code (no heap allocation)
52// Returns LogString* pointing to flash (PROGMEM) on ESP8266
53static const LogString *get_reset_reason_str(uint32_t reason) {
54 return ResetReasonStrings::get_log_str(static_cast<uint8_t>(reason), ResetReasonStrings::LAST_INDEX);
55}
56
57// Size for core version hex buffer
58static constexpr size_t CORE_VERSION_BUFFER_SIZE = 12;
59
60// Get core version string (no heap allocation)
61// Returns either core_release directly or formats core_version as hex into provided buffer
62static const char *get_core_version_str(std::span<char, CORE_VERSION_BUFFER_SIZE> buffer) {
63 if (core_release != nullptr) {
64 return core_release;
65 }
66 snprintf_P(buffer.data(), CORE_VERSION_BUFFER_SIZE, PSTR("%08x"), core_version);
67 return buffer.data();
68}
69
70// Size for reset info buffer
71static constexpr size_t RESET_INFO_BUFFER_SIZE = 200;
72
73// Get detailed reset info string (no heap allocation)
74// For watchdog/exception resets, includes detailed exception info
75static const char *get_reset_info_str(std::span<char, RESET_INFO_BUFFER_SIZE> buffer, uint32_t reason) {
76 if (reason >= REASON_WDT_RST && reason <= REASON_SOFT_WDT_RST) {
77 snprintf_P(buffer.data(), RESET_INFO_BUFFER_SIZE,
78 PSTR("Fatal exception:%d flag:%d (%s) epc1:0x%08x epc2:0x%08x epc3:0x%08x excvaddr:0x%08x depc:0x%08x"),
79 static_cast<int>(resetInfo.exccause), static_cast<int>(reason),
80 LOG_STR_ARG(get_reset_reason_str(reason)), resetInfo.epc1, resetInfo.epc2, resetInfo.epc3,
81 resetInfo.excvaddr, resetInfo.depc);
82 return buffer.data();
83 }
84 return LOG_STR_ARG(get_reset_reason_str(reason));
85}
86
87const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) {
88 // Copy from flash to provided buffer
89 strncpy_P(buffer.data(), (PGM_P) get_reset_reason_str(resetInfo.reason), RESET_REASON_BUFFER_SIZE - 1);
90 buffer[RESET_REASON_BUFFER_SIZE - 1] = '\0';
91 return buffer.data();
92}
93
94const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) {
95 // ESP8266 doesn't have detailed wakeup cause like ESP32
96 return "";
97}
98
100 return ESP.getFreeHeap(); // NOLINT(readability-static-accessed-through-instance)
101}
102
103size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> buffer, size_t pos) {
104 constexpr size_t size = DEVICE_INFO_BUFFER_SIZE;
105 char *buf = buffer.data();
106
107 const LogString *flash_mode = FlashModeStrings::get_log_str(
108 static_cast<uint8_t>(ESP.getFlashChipMode()), // NOLINT(readability-static-accessed-through-instance)
109 FlashModeStrings::LAST_INDEX);
110 uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT(readability-static-accessed-through-instance)
111 uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT(readability-static-accessed-through-instance)
112 ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed,
113 LOG_STR_ARG(flash_mode));
114 pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed,
115 LOG_STR_ARG(flash_mode));
116
117 char reason_buffer[RESET_REASON_BUFFER_SIZE];
118 const char *reset_reason = get_reset_reason_(reason_buffer);
119 char core_version_buffer[CORE_VERSION_BUFFER_SIZE];
120 char reset_info_buffer[RESET_INFO_BUFFER_SIZE];
121 // NOLINTBEGIN(readability-static-accessed-through-instance)
122 uint32_t chip_id = ESP.getChipId();
123 uint8_t boot_version = ESP.getBootVersion();
124 uint8_t boot_mode = ESP.getBootMode();
125 uint8_t cpu_freq = ESP.getCpuFreqMHz();
126 uint32_t flash_chip_id = ESP.getFlashChipId();
127 const char *sdk_version = ESP.getSdkVersion();
128 // NOLINTEND(readability-static-accessed-through-instance)
129
130 ESP_LOGD(TAG,
131 "ESP8266 debug info:\n"
132 " Chip ID: 0x%08" PRIX32 "\n"
133 " SDK Version: %s\n"
134 " Core Version: %s\n"
135 " Boot Version: %u\n"
136 " Boot Mode: %u\n"
137 " CPU Frequency: %u\n"
138 " Flash Chip ID: 0x%08" PRIX32 "\n"
139 " Reset Reason: %s\n"
140 " Reset Info: %s",
141 chip_id, sdk_version, get_core_version_str(core_version_buffer), boot_version, boot_mode, cpu_freq,
142 flash_chip_id, reset_reason, get_reset_info_str(reset_info_buffer, resetInfo.reason));
143
144 pos = buf_append_printf(buf, size, pos, "|Chip: 0x%08" PRIX32, chip_id);
145 pos = buf_append_printf(buf, size, pos, "|SDK: %s", sdk_version);
146 pos = buf_append_printf(buf, size, pos, "|Core: %s", get_core_version_str(core_version_buffer));
147 pos = buf_append_printf(buf, size, pos, "|Boot: %u", boot_version);
148 pos = buf_append_printf(buf, size, pos, "|Mode: %u", boot_mode);
149 pos = buf_append_printf(buf, size, pos, "|CPU: %u", cpu_freq);
150 pos = buf_append_printf(buf, size, pos, "|Flash: 0x%08" PRIX32, flash_chip_id);
151 pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason);
152 pos = buf_append_printf(buf, size, pos, "|%s", get_reset_info_str(reset_info_buffer, resetInfo.reason));
153
154 return pos;
155}
156
158#ifdef USE_SENSOR
159 if (this->block_sensor_ != nullptr) {
160 // NOLINTNEXTLINE(readability-static-accessed-through-instance)
161 this->block_sensor_->publish_state(ESP.getMaxFreeBlockSize());
162 }
163#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2)
164 if (this->fragmentation_sensor_ != nullptr) {
165 // NOLINTNEXTLINE(readability-static-accessed-through-instance)
166 this->fragmentation_sensor_->publish_state(ESP.getHeapFragmentation());
167 }
168#endif
169
170#endif
171}
172
173} // namespace debug
174} // namespace esphome
175#endif
size_t get_device_info_(std::span< char, DEVICE_INFO_BUFFER_SIZE > buffer, size_t pos)
sensor::Sensor * fragmentation_sensor_
const char * get_wakeup_cause_(std::span< char, RESET_REASON_BUFFER_SIZE > buffer)
const char * get_reset_reason_(std::span< char, RESET_REASON_BUFFER_SIZE > buffer)
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
struct rst_info resetInfo
uint32_t core_version
const char * core_release
PROGMEM_STRING_TABLE(ResetReasonStrings, "Power On", "Hardware Watchdog", "Exception", "Software Watchdog", "Software/System restart", "Deep-Sleep Wake", "External System", "Unknown")
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
size_t size
Definition helpers.h:854
size_t size_t pos
Definition helpers.h:854