ESPHome 2025.6.2
Loading...
Searching...
No Matches
debug_esp32.cpp
Go to the documentation of this file.
1#include "debug_component.h"
2
3#ifdef USE_ESP32
5#include "esphome/core/log.h"
6#include "esphome/core/hal.h"
7#include <esp_sleep.h>
8
9#include <esp_heap_caps.h>
10#include <esp_system.h>
11#include <esp_chip_info.h>
12#include <esp_partition.h>
13
14#include <map>
15
16#ifdef USE_ARDUINO
17#include <Esp.h>
18#endif
19
20namespace esphome {
21namespace debug {
22
23static const char *const TAG = "debug";
24
25// index by values returned by esp_reset_reason
26
27static const char *const RESET_REASONS[] = {
28 "unknown source",
29 "power-on event",
30 "external pin",
31 "software via esp_restart",
32 "exception/panic",
33 "interrupt watchdog",
34 "task watchdog",
35 "other watchdogs",
36 "exiting deep sleep mode",
37 "brownout",
38 "SDIO",
39 "USB peripheral",
40 "JTAG",
41 "efuse error",
42 "power glitch detected",
43 "CPU lock up",
44};
45
46static const char *const REBOOT_KEY = "reboot_source";
47static const size_t REBOOT_MAX_LEN = 24;
48
49// on shutdown, store the source of the reboot request
51 auto *component = App.get_current_component();
52 char buffer[REBOOT_MAX_LEN]{};
53 auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name()));
54 if (component != nullptr) {
55 strncpy(buffer, component->get_component_source(), REBOOT_MAX_LEN - 1);
56 }
57 ESP_LOGD(TAG, "Storing reboot source: %s", buffer);
58 pref.save(&buffer);
60}
61
63 std::string reset_reason;
64 unsigned reason = esp_reset_reason();
65 if (reason < sizeof(RESET_REASONS) / sizeof(RESET_REASONS[0])) {
66 reset_reason = RESET_REASONS[reason];
67 if (reason == ESP_RST_SW) {
68 auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name()));
69 char buffer[REBOOT_MAX_LEN]{};
70 if (pref.load(&buffer)) {
71 reset_reason = "Reboot request from " + std::string(buffer);
72 }
73 }
74 } else {
75 reset_reason = "unknown source";
76 }
77 ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
78 return reset_reason;
79}
80
81static const char *const WAKEUP_CAUSES[] = {
82 "undefined",
83 "undefined",
84 "external signal using RTC_IO",
85 "external signal using RTC_CNTL",
86 "timer",
87 "touchpad",
88 "ULP program",
89 "GPIO",
90 "UART",
91 "WIFI",
92 "COCPU int",
93 "COCPU crash",
94 "BT",
95};
96
98 const char *wake_reason;
99 unsigned reason = esp_sleep_get_wakeup_cause();
100 if (reason < sizeof(WAKEUP_CAUSES) / sizeof(WAKEUP_CAUSES[0])) {
101 wake_reason = WAKEUP_CAUSES[reason];
102 } else {
103 wake_reason = "unknown source";
104 }
105 ESP_LOGD(TAG, "Wakeup Reason: %s", wake_reason);
106 return wake_reason;
107}
108
110 ESP_LOGCONFIG(TAG,
111 "Partition table:\n"
112 " %-12s %-4s %-8s %-10s %-10s",
113 "Name", "Type", "Subtype", "Address", "Size");
114 esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
115 while (it != NULL) {
116 const esp_partition_t *partition = esp_partition_get(it);
117 ESP_LOGCONFIG(TAG, " %-12s %-4d %-8d 0x%08" PRIX32 " 0x%08" PRIX32, partition->label, partition->type,
118 partition->subtype, partition->address, partition->size);
119 it = esp_partition_next(it);
120 }
121 esp_partition_iterator_release(it);
122}
123
124uint32_t DebugComponent::get_free_heap_() { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); }
125
126static const std::map<int, const char *> CHIP_FEATURES = {
127 {CHIP_FEATURE_BLE, "BLE"},
128 {CHIP_FEATURE_BT, "BT"},
129 {CHIP_FEATURE_EMB_FLASH, "EMB Flash"},
130 {CHIP_FEATURE_EMB_PSRAM, "EMB PSRAM"},
131 {CHIP_FEATURE_WIFI_BGN, "2.4GHz WiFi"},
132};
133
134void DebugComponent::get_device_info_(std::string &device_info) {
135#if defined(USE_ARDUINO)
136 const char *flash_mode;
137 switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance)
138 case FM_QIO:
139 flash_mode = "QIO";
140 break;
141 case FM_QOUT:
142 flash_mode = "QOUT";
143 break;
144 case FM_DIO:
145 flash_mode = "DIO";
146 break;
147 case FM_DOUT:
148 flash_mode = "DOUT";
149 break;
150 case FM_FAST_READ:
151 flash_mode = "FAST_READ";
152 break;
153 case FM_SLOW_READ:
154 flash_mode = "SLOW_READ";
155 break;
156 default:
157 flash_mode = "UNKNOWN";
158 }
159 ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s",
160 ESP.getFlashChipSize() / 1024, // NOLINT
161 ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT
162 device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT
163 "kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT
164 device_info += flash_mode;
165#endif
166
167 esp_chip_info_t info;
168 esp_chip_info(&info);
169 const char *model = ESPHOME_VARIANT;
170 std::string features;
171 for (auto feature : CHIP_FEATURES) {
172 if (info.features & feature.first) {
173 features += feature.second;
174 features += ", ";
175 info.features &= ~feature.first;
176 }
177 }
178 if (info.features != 0)
179 features += "Other:" + format_hex(info.features);
180 ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores,
181 info.revision);
182 device_info += "|Chip: ";
183 device_info += model;
184 device_info += " Features:";
185 device_info += features;
186 device_info += " Cores:" + to_string(info.cores);
187 device_info += " Revision:" + to_string(info.revision);
188 device_info += str_sprintf("|CPU Frequency: %" PRIu32 " MHz", arch_get_cpu_freq_hz() / 1000000);
189 ESP_LOGD(TAG, "CPU Frequency: %" PRIu32 " MHz", arch_get_cpu_freq_hz() / 1000000);
190
191 // Framework detection
192 device_info += "|Framework: ";
193#ifdef USE_ARDUINO
194 ESP_LOGD(TAG, "Framework: Arduino");
195 device_info += "Arduino";
196#elif defined(USE_ESP_IDF)
197 ESP_LOGD(TAG, "Framework: ESP-IDF");
198 device_info += "ESP-IDF";
199#else
200 ESP_LOGW(TAG, "Framework: UNKNOWN");
201 device_info += "UNKNOWN";
202#endif
203
204 ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version());
205 device_info += "|ESP-IDF: ";
206 device_info += esp_get_idf_version();
207
208 std::string mac = get_mac_address_pretty();
209 ESP_LOGD(TAG, "EFuse MAC: %s", mac.c_str());
210 device_info += "|EFuse MAC: ";
211 device_info += mac;
212
213 device_info += "|Reset: ";
214 device_info += get_reset_reason_();
215
216 std::string wakeup_reason = this->get_wakeup_cause_();
217 device_info += "|Wakeup: ";
218 device_info += wakeup_reason;
219}
220
222#ifdef USE_SENSOR
223 if (this->block_sensor_ != nullptr) {
224 this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL));
225 }
226 if (this->psram_sensor_ != nullptr) {
227 this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
228 }
229#endif
230}
231
232} // namespace debug
233} // namespace esphome
234#endif // USE_ESP32
Component * get_current_component()
const std::string & get_name() const
Get the name of this Application set by pre_setup().
virtual bool sync()=0
Commit pending writes to flash.
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
void log_partition_info_()
Logs information about the device's partition table.
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
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t fnv1_hash(const std::string &str)
Calculate a FNV-1 hash of str.
Definition helpers.cpp:186
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:360
ESPPreferences * global_preferences
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
Definition helpers.cpp:732
uint32_t arch_get_cpu_freq_hz()
Definition core.cpp:64
std::string to_string(int value)
Definition helpers.cpp:82
std::string str_sprintf(const char *fmt,...)
Definition helpers.cpp:323
Application App
Global storage of Application pointer - only one Application can exist.