ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
debug_zephyr.cpp
Go to the documentation of this file.
1#include "debug_component.h"
2#ifdef USE_ZEPHYR
3#include <climits>
4#include "esphome/core/log.h"
5#include <zephyr/drivers/hwinfo.h>
6#include <hal/nrf_power.h>
7#include <cstdint>
8
9#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
10
11namespace esphome {
12namespace debug {
13
14static const char *const TAG = "debug";
15constexpr std::uintptr_t MBR_PARAM_PAGE_ADDR = 0xFFC;
16constexpr std::uintptr_t MBR_BOOTLOADER_ADDR = 0xFF8;
17
18static void show_reset_reason(std::string &reset_reason, bool set, const char *reason) {
19 if (!set) {
20 return;
21 }
22 if (!reset_reason.empty()) {
23 reset_reason += ", ";
24 }
25 reset_reason += reason;
26}
27
28inline uint32_t read_mem_u32(uintptr_t addr) {
29 return *reinterpret_cast<volatile uint32_t *>(addr); // NOLINT(performance-no-int-to-ptr)
30}
31
33 uint32_t cause;
34 auto ret = hwinfo_get_reset_cause(&cause);
35 if (ret) {
36 ESP_LOGE(TAG, "Unable to get reset cause: %d", ret);
37 return "";
38 }
39 std::string reset_reason;
40
41 show_reset_reason(reset_reason, cause & RESET_PIN, "External pin");
42 show_reset_reason(reset_reason, cause & RESET_SOFTWARE, "Software reset");
43 show_reset_reason(reset_reason, cause & RESET_BROWNOUT, "Brownout (drop in voltage)");
44 show_reset_reason(reset_reason, cause & RESET_POR, "Power-on reset (POR)");
45 show_reset_reason(reset_reason, cause & RESET_WATCHDOG, "Watchdog timer expiration");
46 show_reset_reason(reset_reason, cause & RESET_DEBUG, "Debug event");
47 show_reset_reason(reset_reason, cause & RESET_SECURITY, "Security violation");
48 show_reset_reason(reset_reason, cause & RESET_LOW_POWER_WAKE, "Waking up from low power mode");
49 show_reset_reason(reset_reason, cause & RESET_CPU_LOCKUP, "CPU lock-up detected");
50 show_reset_reason(reset_reason, cause & RESET_PARITY, "Parity error");
51 show_reset_reason(reset_reason, cause & RESET_PLL, "PLL error");
52 show_reset_reason(reset_reason, cause & RESET_CLOCK, "Clock error");
53 show_reset_reason(reset_reason, cause & RESET_HARDWARE, "Hardware reset");
54 show_reset_reason(reset_reason, cause & RESET_USER, "User reset");
55 show_reset_reason(reset_reason, cause & RESET_TEMPERATURE, "Temperature reset");
56
57 ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
58 return reset_reason;
59}
60
61uint32_t DebugComponent::get_free_heap_() { return INT_MAX; }
62
63void DebugComponent::get_device_info_(std::string &device_info) {
64 std::string supply = "Main supply status: ";
65 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) {
66 supply += "Normal voltage.";
67 } else {
68 supply += "High voltage.";
69 }
70 ESP_LOGD(TAG, "%s", supply.c_str());
71 device_info += "|" + supply;
72
73 std::string reg0 = "Regulator stage 0: ";
74 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) {
75 reg0 += nrf_power_dcdcen_vddh_get(NRF_POWER) ? "DC/DC" : "LDO";
76 reg0 += ", ";
77 switch (NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) {
78 case (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos):
79 reg0 += "1.8V (default)";
80 break;
81 case (UICR_REGOUT0_VOUT_1V8 << UICR_REGOUT0_VOUT_Pos):
82 reg0 += "1.8V";
83 break;
84 case (UICR_REGOUT0_VOUT_2V1 << UICR_REGOUT0_VOUT_Pos):
85 reg0 += "2.1V";
86 break;
87 case (UICR_REGOUT0_VOUT_2V4 << UICR_REGOUT0_VOUT_Pos):
88 reg0 += "2.4V";
89 break;
90 case (UICR_REGOUT0_VOUT_2V7 << UICR_REGOUT0_VOUT_Pos):
91 reg0 += "2.7V";
92 break;
93 case (UICR_REGOUT0_VOUT_3V0 << UICR_REGOUT0_VOUT_Pos):
94 reg0 += "3.0V";
95 break;
96 case (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos):
97 reg0 += "3.3V";
98 break;
99 default:
100 reg0 += "???V";
101 }
102 } else {
103 reg0 += "disabled";
104 }
105 ESP_LOGD(TAG, "%s", reg0.c_str());
106 device_info += "|" + reg0;
107
108 std::string reg1 = "Regulator stage 1: ";
109 reg1 += nrf_power_dcdcen_get(NRF_POWER) ? "DC/DC" : "LDO";
110 ESP_LOGD(TAG, "%s", reg1.c_str());
111 device_info += "|" + reg1;
112
113 std::string usb_power = "USB power state: ";
114 if (nrf_power_usbregstatus_vbusdet_get(NRF_POWER)) {
115 if (nrf_power_usbregstatus_outrdy_get(NRF_POWER)) {
117 usb_power += "ready";
118 } else {
120 usb_power += "connected (regulator is not ready)";
121 }
122 } else {
124 usb_power += "disconected";
125 }
126 ESP_LOGD(TAG, "%s", usb_power.c_str());
127 device_info += "|" + usb_power;
128
129 bool enabled;
130 nrf_power_pof_thr_t pof_thr;
131
132 pof_thr = nrf_power_pofcon_get(NRF_POWER, &enabled);
133 std::string pof = "Power-fail comparator: ";
134 if (enabled) {
135 switch (pof_thr) {
136 case POWER_POFCON_THRESHOLD_V17:
137 pof += "1.7V";
138 break;
139 case POWER_POFCON_THRESHOLD_V18:
140 pof += "1.8V";
141 break;
142 case POWER_POFCON_THRESHOLD_V19:
143 pof += "1.9V";
144 break;
145 case POWER_POFCON_THRESHOLD_V20:
146 pof += "2.0V";
147 break;
148 case POWER_POFCON_THRESHOLD_V21:
149 pof += "2.1V";
150 break;
151 case POWER_POFCON_THRESHOLD_V22:
152 pof += "2.2V";
153 break;
154 case POWER_POFCON_THRESHOLD_V23:
155 pof += "2.3V";
156 break;
157 case POWER_POFCON_THRESHOLD_V24:
158 pof += "2.4V";
159 break;
160 case POWER_POFCON_THRESHOLD_V25:
161 pof += "2.5V";
162 break;
163 case POWER_POFCON_THRESHOLD_V26:
164 pof += "2.6V";
165 break;
166 case POWER_POFCON_THRESHOLD_V27:
167 pof += "2.7V";
168 break;
169 case POWER_POFCON_THRESHOLD_V28:
170 pof += "2.8V";
171 break;
172 }
173
174 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) {
175 pof += ", VDDH: ";
176 switch (nrf_power_pofcon_vddh_get(NRF_POWER)) {
177 case NRF_POWER_POFTHRVDDH_V27:
178 pof += "2.7V";
179 break;
180 case NRF_POWER_POFTHRVDDH_V28:
181 pof += "2.8V";
182 break;
183 case NRF_POWER_POFTHRVDDH_V29:
184 pof += "2.9V";
185 break;
186 case NRF_POWER_POFTHRVDDH_V30:
187 pof += "3.0V";
188 break;
189 case NRF_POWER_POFTHRVDDH_V31:
190 pof += "3.1V";
191 break;
192 case NRF_POWER_POFTHRVDDH_V32:
193 pof += "3.2V";
194 break;
195 case NRF_POWER_POFTHRVDDH_V33:
196 pof += "3.3V";
197 break;
198 case NRF_POWER_POFTHRVDDH_V34:
199 pof += "3.4V";
200 break;
201 case NRF_POWER_POFTHRVDDH_V35:
202 pof += "3.5V";
203 break;
204 case NRF_POWER_POFTHRVDDH_V36:
205 pof += "3.6V";
206 break;
207 case NRF_POWER_POFTHRVDDH_V37:
208 pof += "3.7V";
209 break;
210 case NRF_POWER_POFTHRVDDH_V38:
211 pof += "3.8V";
212 break;
213 case NRF_POWER_POFTHRVDDH_V39:
214 pof += "3.9V";
215 break;
216 case NRF_POWER_POFTHRVDDH_V40:
217 pof += "4.0V";
218 break;
219 case NRF_POWER_POFTHRVDDH_V41:
220 pof += "4.1V";
221 break;
222 case NRF_POWER_POFTHRVDDH_V42:
223 pof += "4.2V";
224 break;
225 }
226 }
227 } else {
228 pof += "disabled";
229 }
230 ESP_LOGD(TAG, "%s", pof.c_str());
231 device_info += "|" + pof;
232
233 auto package = [](uint32_t value) {
234 switch (value) {
235 case 0x2004:
236 return "QIxx - 7x7 73-pin aQFN";
237 case 0x2000:
238 return "QFxx - 6x6 48-pin QFN";
239 case 0x2005:
240 return "CKxx - 3.544 x 3.607 WLCSP";
241 }
242 return "Unspecified";
243 };
244
245 ESP_LOGD(TAG, "Code page size: %u, code size: %u, device id: 0x%08x%08x", NRF_FICR->CODEPAGESIZE, NRF_FICR->CODESIZE,
246 NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
247 ESP_LOGD(TAG, "Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x", NRF_FICR->ER[0],
248 NRF_FICR->ER[1], NRF_FICR->ER[2], NRF_FICR->ER[3], NRF_FICR->IR[0], NRF_FICR->IR[1], NRF_FICR->IR[2],
249 NRF_FICR->IR[3]);
250 ESP_LOGD(TAG, "Device address type: %s, address: %s", (NRF_FICR->DEVICEADDRTYPE & 0x1 ? "Random" : "Public"),
251 get_mac_address_pretty().c_str());
252 ESP_LOGD(TAG, "Part code: nRF%x, version: %c%c%c%c, package: %s", NRF_FICR->INFO.PART,
253 NRF_FICR->INFO.VARIANT >> 24 & 0xFF, NRF_FICR->INFO.VARIANT >> 16 & 0xFF, NRF_FICR->INFO.VARIANT >> 8 & 0xFF,
254 NRF_FICR->INFO.VARIANT & 0xFF, package(NRF_FICR->INFO.PACKAGE));
255 ESP_LOGD(TAG, "RAM: %ukB, Flash: %ukB, production test: %sdone", NRF_FICR->INFO.RAM, NRF_FICR->INFO.FLASH,
256 (NRF_FICR->PRODTEST[0] == 0xBB42319F ? "" : "not "));
257 ESP_LOGD(
258 TAG, "GPIO as NFC pins: %s, GPIO as nRESET pin: %s",
259 YESNO((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)),
260 YESNO(((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) !=
261 (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
262 ((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) !=
263 (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))));
264
265#ifdef USE_BOOTLOADER_MCUBOOT
266 ESP_LOGD(TAG, "bootloader: mcuboot");
267#else
268 ESP_LOGD(TAG, "bootloader: Adafruit, version %u.%u.%u", (BOOTLOADER_VERSION_REGISTER >> 16) & 0xFF,
269 (BOOTLOADER_VERSION_REGISTER >> 8) & 0xFF, BOOTLOADER_VERSION_REGISTER & 0xFF);
270 ESP_LOGD(TAG, "MBR bootloader addr 0x%08x, UICR bootloader addr 0x%08x", read_mem_u32(MBR_BOOTLOADER_ADDR),
271 NRF_UICR->NRFFW[0]);
272 ESP_LOGD(TAG, "MBR param page addr 0x%08x, UICR param page addr 0x%08x", read_mem_u32(MBR_PARAM_PAGE_ADDR),
273 NRF_UICR->NRFFW[1]);
274#endif
275}
276
277void DebugComponent::update_platform_() {}
278
279} // namespace debug
280} // namespace esphome
281#endif
void get_device_info_(std::string &device_info)
constexpr std::uintptr_t MBR_PARAM_PAGE_ADDR
constexpr std::uintptr_t MBR_BOOTLOADER_ADDR
uint32_t read_mem_u32(uintptr_t addr)
Providing packet encoding functions for exchanging data with a remote host.
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:584