ESPHome  2025.2.0
debug_esp32.cpp
Go to the documentation of this file.
1 #include "debug_component.h"
2 #ifdef USE_ESP32
3 #include "esphome/core/log.h"
4 
5 #include <esp_heap_caps.h>
6 #include <esp_system.h>
7 #include <esp_chip_info.h>
8 #include <esp_partition.h>
9 
10 #if defined(USE_ESP32_VARIANT_ESP32)
11 #include <esp32/rom/rtc.h>
12 #elif defined(USE_ESP32_VARIANT_ESP32C3)
13 #include <esp32c3/rom/rtc.h>
14 #elif defined(USE_ESP32_VARIANT_ESP32C6)
15 #include <esp32c6/rom/rtc.h>
16 #elif defined(USE_ESP32_VARIANT_ESP32S2)
17 #include <esp32s2/rom/rtc.h>
18 #elif defined(USE_ESP32_VARIANT_ESP32S3)
19 #include <esp32s3/rom/rtc.h>
20 #elif defined(USE_ESP32_VARIANT_ESP32H2)
21 #include <esp32h2/rom/rtc.h>
22 #endif
23 #ifdef USE_ARDUINO
24 #include <Esp.h>
25 #endif
26 
27 namespace esphome {
28 namespace debug {
29 
30 static const char *const TAG = "debug";
31 
33  ESP_LOGCONFIG(TAG, "Partition table:");
34  ESP_LOGCONFIG(TAG, " %-12s %-4s %-8s %-10s %-10s", "Name", "Type", "Subtype", "Address", "Size");
35  esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
36  while (it != NULL) {
37  const esp_partition_t *partition = esp_partition_get(it);
38  ESP_LOGCONFIG(TAG, " %-12s %-4d %-8d 0x%08" PRIX32 " 0x%08" PRIX32, partition->label, partition->type,
39  partition->subtype, partition->address, partition->size);
40  it = esp_partition_next(it);
41  }
42  esp_partition_iterator_release(it);
43 }
44 
46  std::string reset_reason;
47  switch (esp_reset_reason()) {
48  case ESP_RST_POWERON:
49  reset_reason = "Reset due to power-on event";
50  break;
51  case ESP_RST_EXT:
52  reset_reason = "Reset by external pin";
53  break;
54  case ESP_RST_SW:
55  reset_reason = "Software reset via esp_restart";
56  break;
57  case ESP_RST_PANIC:
58  reset_reason = "Software reset due to exception/panic";
59  break;
60  case ESP_RST_INT_WDT:
61  reset_reason = "Reset (software or hardware) due to interrupt watchdog";
62  break;
63  case ESP_RST_TASK_WDT:
64  reset_reason = "Reset due to task watchdog";
65  break;
66  case ESP_RST_WDT:
67  reset_reason = "Reset due to other watchdogs";
68  break;
69  case ESP_RST_DEEPSLEEP:
70  reset_reason = "Reset after exiting deep sleep mode";
71  break;
72  case ESP_RST_BROWNOUT:
73  reset_reason = "Brownout reset (software or hardware)";
74  break;
75  case ESP_RST_SDIO:
76  reset_reason = "Reset over SDIO";
77  break;
78 #ifdef USE_ESP32_VARIANT_ESP32
79 #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 4))
80  case ESP_RST_USB:
81  reset_reason = "Reset by USB peripheral";
82  break;
83  case ESP_RST_JTAG:
84  reset_reason = "Reset by JTAG";
85  break;
86  case ESP_RST_EFUSE:
87  reset_reason = "Reset due to efuse error";
88  break;
89  case ESP_RST_PWR_GLITCH:
90  reset_reason = "Reset due to power glitch detected";
91  break;
92  case ESP_RST_CPU_LOCKUP:
93  reset_reason = "Reset due to CPU lock up (double exception)";
94  break;
95 #endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 4)
96 #endif // USE_ESP32_VARIANT_ESP32
97  default: // Includes ESP_RST_UNKNOWN
98  switch (rtc_get_reset_reason(0)) {
99  case POWERON_RESET:
100  reset_reason = "Power On Reset";
101  break;
102 #if defined(USE_ESP32_VARIANT_ESP32)
103  case SW_RESET:
104 #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \
105  defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
106  case RTC_SW_SYS_RESET:
107 #endif
108  reset_reason = "Software Reset Digital Core";
109  break;
110 #if defined(USE_ESP32_VARIANT_ESP32)
111  case OWDT_RESET:
112  reset_reason = "Watch Dog Reset Digital Core";
113  break;
114 #endif
115  case DEEPSLEEP_RESET:
116  reset_reason = "Deep Sleep Reset Digital Core";
117  break;
118 #if defined(USE_ESP32_VARIANT_ESP32)
119  case SDIO_RESET:
120  reset_reason = "SLC Module Reset Digital Core";
121  break;
122 #endif
123  case TG0WDT_SYS_RESET:
124  reset_reason = "Timer Group 0 Watch Dog Reset Digital Core";
125  break;
126  case TG1WDT_SYS_RESET:
127  reset_reason = "Timer Group 1 Watch Dog Reset Digital Core";
128  break;
129  case RTCWDT_SYS_RESET:
130  reset_reason = "RTC Watch Dog Reset Digital Core";
131  break;
132 #if !defined(USE_ESP32_VARIANT_ESP32C6) && !defined(USE_ESP32_VARIANT_ESP32H2)
133  case INTRUSION_RESET:
134  reset_reason = "Intrusion Reset CPU";
135  break;
136 #endif
137 #if defined(USE_ESP32_VARIANT_ESP32)
138  case TGWDT_CPU_RESET:
139  reset_reason = "Timer Group Reset CPU";
140  break;
141 #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \
142  defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
143  case TG0WDT_CPU_RESET:
144  reset_reason = "Timer Group 0 Reset CPU";
145  break;
146 #endif
147 #if defined(USE_ESP32_VARIANT_ESP32)
148  case SW_CPU_RESET:
149 #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || \
150  defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
151  case RTC_SW_CPU_RESET:
152 #endif
153  reset_reason = "Software Reset CPU";
154  break;
155  case RTCWDT_CPU_RESET:
156  reset_reason = "RTC Watch Dog Reset CPU";
157  break;
158 #if defined(USE_ESP32_VARIANT_ESP32)
159  case EXT_CPU_RESET:
160  reset_reason = "External CPU Reset";
161  break;
162 #endif
163  case RTCWDT_BROWN_OUT_RESET:
164  reset_reason = "Voltage Unstable Reset";
165  break;
166  case RTCWDT_RTC_RESET:
167  reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module";
168  break;
169 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \
170  defined(USE_ESP32_VARIANT_ESP32C6)
171  case TG1WDT_CPU_RESET:
172  reset_reason = "Timer Group 1 Reset CPU";
173  break;
174  case SUPER_WDT_RESET:
175  reset_reason = "Super Watchdog Reset Digital Core And RTC Module";
176  break;
177  case EFUSE_RESET:
178  reset_reason = "eFuse Reset Digital Core";
179  break;
180 #endif
181 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
182  case GLITCH_RTC_RESET:
183  reset_reason = "Glitch Reset Digital Core And RTC Module";
184  break;
185 #endif
186 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C6)
187  case USB_UART_CHIP_RESET:
188  reset_reason = "USB UART Reset Digital Core";
189  break;
190  case USB_JTAG_CHIP_RESET:
191  reset_reason = "USB JTAG Reset Digital Core";
192  break;
193 #endif
194 #if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
195  case POWER_GLITCH_RESET:
196  reset_reason = "Power Glitch Reset Digital Core And RTC Module";
197  break;
198 #endif
199  default:
200  reset_reason = "Unknown Reset Reason";
201  }
202  break;
203  }
204  ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
205  return reset_reason;
206 }
207 
208 uint32_t DebugComponent::get_free_heap_() { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); }
209 
210 void DebugComponent::get_device_info_(std::string &device_info) {
211 #if defined(USE_ARDUINO)
212  const char *flash_mode;
213  switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance)
214  case FM_QIO:
215  flash_mode = "QIO";
216  break;
217  case FM_QOUT:
218  flash_mode = "QOUT";
219  break;
220  case FM_DIO:
221  flash_mode = "DIO";
222  break;
223  case FM_DOUT:
224  flash_mode = "DOUT";
225  break;
226  case FM_FAST_READ:
227  flash_mode = "FAST_READ";
228  break;
229  case FM_SLOW_READ:
230  flash_mode = "SLOW_READ";
231  break;
232  default:
233  flash_mode = "UNKNOWN";
234  }
235  ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s",
236  ESP.getFlashChipSize() / 1024, // NOLINT
237  ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT
238  device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT
239  "kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT
240  device_info += flash_mode;
241 #endif
242 
243  esp_chip_info_t info;
244  esp_chip_info(&info);
245  const char *model;
246 #if defined(USE_ESP32_VARIANT_ESP32)
247  model = "ESP32";
248 #elif defined(USE_ESP32_VARIANT_ESP32C3)
249  model = "ESP32-C3";
250 #elif defined(USE_ESP32_VARIANT_ESP32C6)
251  model = "ESP32-C6";
252 #elif defined(USE_ESP32_VARIANT_ESP32S2)
253  model = "ESP32-S2";
254 #elif defined(USE_ESP32_VARIANT_ESP32S3)
255  model = "ESP32-S3";
256 #elif defined(USE_ESP32_VARIANT_ESP32H2)
257  model = "ESP32-H2";
258 #else
259  model = "UNKNOWN";
260 #endif
261  std::string features;
262  if (info.features & CHIP_FEATURE_EMB_FLASH) {
263  features += "EMB_FLASH,";
264  info.features &= ~CHIP_FEATURE_EMB_FLASH;
265  }
266  if (info.features & CHIP_FEATURE_WIFI_BGN) {
267  features += "WIFI_BGN,";
268  info.features &= ~CHIP_FEATURE_WIFI_BGN;
269  }
270  if (info.features & CHIP_FEATURE_BLE) {
271  features += "BLE,";
272  info.features &= ~CHIP_FEATURE_BLE;
273  }
274  if (info.features & CHIP_FEATURE_BT) {
275  features += "BT,";
276  info.features &= ~CHIP_FEATURE_BT;
277  }
278  if (info.features & CHIP_FEATURE_EMB_PSRAM) {
279  features += "EMB_PSRAM,";
280  info.features &= ~CHIP_FEATURE_EMB_PSRAM;
281  }
282  if (info.features)
283  features += "Other:" + format_hex(info.features);
284  ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores,
285  info.revision);
286  device_info += "|Chip: ";
287  device_info += model;
288  device_info += " Features:";
289  device_info += features;
290  device_info += " Cores:" + to_string(info.cores);
291  device_info += " Revision:" + to_string(info.revision);
292 
293  // Framework detection
294  device_info += "|Framework: ";
295 #ifdef USE_ARDUINO
296  ESP_LOGD(TAG, "Framework: Arduino");
297  device_info += "Arduino";
298 #elif defined(USE_ESP_IDF)
299  ESP_LOGD(TAG, "Framework: ESP-IDF");
300  device_info += "ESP-IDF";
301 #else
302  ESP_LOGW(TAG, "Framework: UNKNOWN");
303  device_info += "UNKNOWN";
304 #endif
305 
306  ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version());
307  device_info += "|ESP-IDF: ";
308  device_info += esp_get_idf_version();
309 
310  std::string mac = get_mac_address_pretty();
311  ESP_LOGD(TAG, "EFuse MAC: %s", mac.c_str());
312  device_info += "|EFuse MAC: ";
313  device_info += mac;
314 
315  device_info += "|Reset: ";
316  device_info += get_reset_reason_();
317 
318  const char *wakeup_reason;
319  switch (rtc_get_wakeup_cause()) {
320  case NO_SLEEP:
321  wakeup_reason = "No Sleep";
322  break;
323  case EXT_EVENT0_TRIG:
324  wakeup_reason = "External Event 0";
325  break;
326  case EXT_EVENT1_TRIG:
327  wakeup_reason = "External Event 1";
328  break;
329  case GPIO_TRIG:
330  wakeup_reason = "GPIO";
331  break;
332  case TIMER_EXPIRE:
333  wakeup_reason = "Wakeup Timer";
334  break;
335  case SDIO_TRIG:
336  wakeup_reason = "SDIO";
337  break;
338  case MAC_TRIG:
339  wakeup_reason = "MAC";
340  break;
341  case UART0_TRIG:
342  wakeup_reason = "UART0";
343  break;
344  case UART1_TRIG:
345  wakeup_reason = "UART1";
346  break;
347  case TOUCH_TRIG:
348  wakeup_reason = "Touch";
349  break;
350  case SAR_TRIG:
351  wakeup_reason = "SAR";
352  break;
353  case BT_TRIG:
354  wakeup_reason = "BT";
355  break;
356  default:
357  wakeup_reason = "Unknown";
358  }
359  ESP_LOGD(TAG, "Wakeup Reason: %s", wakeup_reason);
360  device_info += "|Wakeup: ";
361  device_info += wakeup_reason;
362 }
363 
365 #ifdef USE_SENSOR
366  if (this->block_sensor_ != nullptr) {
367  this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL));
368  }
369  if (this->psram_sensor_ != nullptr) {
370  this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
371  }
372 #endif
373 }
374 
375 } // namespace debug
376 } // namespace esphome
377 #endif // USE_ESP32
void log_partition_info_()
Logs information about the device&#39;s partition table.
Definition: debug_esp32.cpp:32
std::string format_hex(const uint8_t *data, size_t length)
Format the byte array data of length len in lowercased hex.
Definition: helpers.cpp:361
void get_device_info_(std::string &device_info)
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
std::string to_string(int value)
Definition: helpers.cpp:83
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
Definition: helpers.cpp:733