6#include <zephyr/drivers/hwinfo.h>
7#include <hal/nrf_power.h>
9#include <zephyr/storage/flash_map.h>
11#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
15static const char *
const TAG =
"debug";
19static inline uint32_t read_mem_u32(uintptr_t addr) {
20 return *
reinterpret_cast<volatile uint32_t *
>(addr);
23static inline uint8_t read_mem_u8(uintptr_t addr) {
24 return *
reinterpret_cast<volatile uint8_t *
>(addr);
34static inline bool is_sd_present() {
43static inline uint32_t sd_version_get() {
52 ESP_LOGD(TAG,
"Reset Reason: %s", buf);
63static void fa_cb(
const struct flash_area *fa,
void *user_data) {
64#if CONFIG_FLASH_MAP_LABELS
65 const char *fa_label = flash_area_label(fa);
67 if (fa_label ==
nullptr) {
70 ESP_LOGCONFIG(TAG,
"%2d 0x%0*" PRIxPTR
" %-26s %-24.24s 0x%-10x 0x%-12x", (
int) fa->fa_id,
71 sizeof(uintptr_t) * 2, (uintptr_t) fa->fa_dev, fa->fa_dev->name, fa_label, (
uint32_t) fa->fa_off,
74 ESP_LOGCONFIG(TAG,
"%2d 0x%0*" PRIxPTR
" %-26s 0x%-10x 0x%-12x", (
int) fa->fa_id,
sizeof(uintptr_t) * 2,
75 (uintptr_t) fa->fa_dev, fa->fa_dev->name, (
uint32_t) fa->fa_off, fa->fa_size);
80#if CONFIG_FLASH_MAP_LABELS
81 ESP_LOGCONFIG(TAG,
"ID | Device | Device Name "
82 "| Label | Offset | Size");
83 ESP_LOGCONFIG(TAG,
"--------------------------------------------"
84 "-----------------------------------------------");
86 ESP_LOGCONFIG(TAG,
"ID | Device | Device Name "
88 ESP_LOGCONFIG(TAG,
"-----------------------------------------"
89 "------------------------------");
91 flash_area_foreach(fa_cb,
nullptr);
94#ifdef ESPHOME_LOG_HAS_VERBOSE
98#define NRF_PERIPH_ENABLED(periph, reg) \
99 YESNO(((reg)->ENABLE & periph##_ENABLE_ENABLE_Msk) == (periph##_ENABLE_ENABLE_Enabled << periph##_ENABLE_ENABLE_Pos))
101static void log_peripherals_info() {
103 ESP_LOGV(TAG,
"Peripherals status:");
104 ESP_LOGV(TAG,
" USBD: %-3s| UARTE0: %-3s| UARTE1: %-3s| UART0: %-3s",
105 NRF_PERIPH_ENABLED(USBD, NRF_USBD), NRF_PERIPH_ENABLED(UARTE, NRF_UARTE0),
106 NRF_PERIPH_ENABLED(UARTE, NRF_UARTE1), NRF_PERIPH_ENABLED(UART, NRF_UART0));
107 ESP_LOGV(TAG,
" TWIS0: %-3s| TWIS1: %-3s| TWIM0: %-3s| TWIM1: %-3s",
108 NRF_PERIPH_ENABLED(TWIS, NRF_TWIS0), NRF_PERIPH_ENABLED(TWIS, NRF_TWIS1),
109 NRF_PERIPH_ENABLED(TWIM, NRF_TWIM0), NRF_PERIPH_ENABLED(TWIM, NRF_TWIM1));
110 ESP_LOGV(TAG,
" TWI0: %-3s| TWI1: %-3s| COMP: %-3s| CCM: %-3s",
111 NRF_PERIPH_ENABLED(TWI, NRF_TWI0), NRF_PERIPH_ENABLED(TWI, NRF_TWI1), NRF_PERIPH_ENABLED(COMP, NRF_COMP),
112 NRF_PERIPH_ENABLED(CCM, NRF_CCM));
113 ESP_LOGV(TAG,
" PDM: %-3s| SPIS0: %-3s| SPIS1: %-3s| SPIS2: %-3s",
114 NRF_PERIPH_ENABLED(PDM, NRF_PDM), NRF_PERIPH_ENABLED(SPIS, NRF_SPIS0), NRF_PERIPH_ENABLED(SPIS, NRF_SPIS1),
115 NRF_PERIPH_ENABLED(SPIS, NRF_SPIS2));
116 ESP_LOGV(TAG,
" SPIM0: %-3s| SPIM1: %-3s| SPIM2: %-3s| SPIM3: %-3s",
117 NRF_PERIPH_ENABLED(SPIM, NRF_SPIM0), NRF_PERIPH_ENABLED(SPIM, NRF_SPIM1),
118 NRF_PERIPH_ENABLED(SPIM, NRF_SPIM2), NRF_PERIPH_ENABLED(SPIM, NRF_SPIM3));
119 ESP_LOGV(TAG,
" SPI0: %-3s| SPI1: %-3s| SPI2: %-3s| SAADC: %-3s",
120 NRF_PERIPH_ENABLED(SPI, NRF_SPI0), NRF_PERIPH_ENABLED(SPI, NRF_SPI1), NRF_PERIPH_ENABLED(SPI, NRF_SPI2),
121 NRF_PERIPH_ENABLED(SAADC, NRF_SAADC));
122 ESP_LOGV(TAG,
" QSPI: %-3s| QDEC: %-3s| LPCOMP: %-3s| I2S: %-3s",
123 NRF_PERIPH_ENABLED(QSPI, NRF_QSPI), NRF_PERIPH_ENABLED(QDEC, NRF_QDEC),
124 NRF_PERIPH_ENABLED(LPCOMP, NRF_LPCOMP), NRF_PERIPH_ENABLED(I2S, NRF_I2S));
125 ESP_LOGV(TAG,
" PWM0: %-3s| PWM1: %-3s| PWM2: %-3s| PWM3: %-3s",
126 NRF_PERIPH_ENABLED(PWM, NRF_PWM0), NRF_PERIPH_ENABLED(PWM, NRF_PWM1), NRF_PERIPH_ENABLED(PWM, NRF_PWM2),
127 NRF_PERIPH_ENABLED(PWM, NRF_PWM3));
128 ESP_LOGV(TAG,
" AAR: %-3s| QSPI deep power-down:%-3s| CRYPTOCELL: %-3s", NRF_PERIPH_ENABLED(AAR, NRF_AAR),
129 YESNO((NRF_QSPI->IFCONFIG0 & QSPI_IFCONFIG0_DPMENABLE_Msk) ==
130 (QSPI_IFCONFIG0_DPMENABLE_Enable << QSPI_IFCONFIG0_DPMENABLE_Pos)),
131 YESNO((NRF_CRYPTOCELL->ENABLE & CRYPTOCELL_ENABLE_ENABLE_Msk) ==
132 (CRYPTOCELL_ENABLE_ENABLE_Enabled << CRYPTOCELL_ENABLE_ENABLE_Pos)));
134#undef NRF_PERIPH_ENABLED
137static const char *regout0_to_str(
uint32_t value) {
139 case (UICR_REGOUT0_VOUT_DEFAULT):
140 return "1.8V (default)";
141 case (UICR_REGOUT0_VOUT_1V8):
143 case (UICR_REGOUT0_VOUT_2V1):
145 case (UICR_REGOUT0_VOUT_2V4):
147 case (UICR_REGOUT0_VOUT_2V7):
149 case (UICR_REGOUT0_VOUT_3V0):
151 case (UICR_REGOUT0_VOUT_3V3):
158 constexpr size_t size = DEVICE_INFO_BUFFER_SIZE;
159 char *buf = buffer.data();
162 const char *supply_status =
163 (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) ?
"Normal voltage." :
"High voltage.";
164 ESP_LOGD(TAG,
"Main supply status: %s", supply_status);
165 pos = buf_append_printf(buf,
size,
pos,
"|Main supply status: %s", supply_status);
168 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) {
169 const char *reg0_type = nrf_power_dcdcen_vddh_get(NRF_POWER) ?
"DC/DC" :
"LDO";
170 const char *reg0_voltage = regout0_to_str((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) >> UICR_REGOUT0_VOUT_Pos);
171 ESP_LOGD(TAG,
"Regulator stage 0: %s, %s", reg0_type, reg0_voltage);
172 pos = buf_append_printf(buf,
size,
pos,
"|Regulator stage 0: %s, %s", reg0_type, reg0_voltage);
173#ifdef USE_NRF52_REG0_VOUT
174 if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) >> UICR_REGOUT0_VOUT_Pos != USE_NRF52_REG0_VOUT) {
175 ESP_LOGE(TAG,
"Regulator stage 0: expected %s", regout0_to_str(USE_NRF52_REG0_VOUT));
179 ESP_LOGD(TAG,
"Regulator stage 0: disabled");
180 pos = buf_append_printf(buf,
size,
pos,
"|Regulator stage 0: disabled");
184 const char *reg1_type = nrf_power_dcdcen_get(NRF_POWER) ?
"DC/DC" :
"LDO";
185 ESP_LOGD(TAG,
"Regulator stage 1: %s", reg1_type);
186 pos = buf_append_printf(buf,
size,
pos,
"|Regulator stage 1: %s", reg1_type);
189 const char *usb_state;
190 if (nrf_power_usbregstatus_vbusdet_get(NRF_POWER)) {
191 if (nrf_power_usbregstatus_outrdy_get(NRF_POWER)) {
194 usb_state =
"connected (regulator is not ready)";
197 usb_state =
"disconnected";
199 ESP_LOGD(TAG,
"USB power state: %s", usb_state);
200 pos = buf_append_printf(buf,
size,
pos,
"|USB power state: %s", usb_state);
204 nrf_power_pof_thr_t pof_thr = nrf_power_pofcon_get(NRF_POWER, &enabled);
206 const char *pof_voltage;
208 case POWER_POFCON_THRESHOLD_V17:
209 pof_voltage =
"1.7V";
211 case POWER_POFCON_THRESHOLD_V18:
212 pof_voltage =
"1.8V";
214 case POWER_POFCON_THRESHOLD_V19:
215 pof_voltage =
"1.9V";
217 case POWER_POFCON_THRESHOLD_V20:
218 pof_voltage =
"2.0V";
220 case POWER_POFCON_THRESHOLD_V21:
221 pof_voltage =
"2.1V";
223 case POWER_POFCON_THRESHOLD_V22:
224 pof_voltage =
"2.2V";
226 case POWER_POFCON_THRESHOLD_V23:
227 pof_voltage =
"2.3V";
229 case POWER_POFCON_THRESHOLD_V24:
230 pof_voltage =
"2.4V";
232 case POWER_POFCON_THRESHOLD_V25:
233 pof_voltage =
"2.5V";
235 case POWER_POFCON_THRESHOLD_V26:
236 pof_voltage =
"2.6V";
238 case POWER_POFCON_THRESHOLD_V27:
239 pof_voltage =
"2.7V";
241 case POWER_POFCON_THRESHOLD_V28:
242 pof_voltage =
"2.8V";
245 pof_voltage =
"???V";
249 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) {
250 const char *vddh_voltage;
251 switch (nrf_power_pofcon_vddh_get(NRF_POWER)) {
252 case NRF_POWER_POFTHRVDDH_V27:
253 vddh_voltage =
"2.7V";
255 case NRF_POWER_POFTHRVDDH_V28:
256 vddh_voltage =
"2.8V";
258 case NRF_POWER_POFTHRVDDH_V29:
259 vddh_voltage =
"2.9V";
261 case NRF_POWER_POFTHRVDDH_V30:
262 vddh_voltage =
"3.0V";
264 case NRF_POWER_POFTHRVDDH_V31:
265 vddh_voltage =
"3.1V";
267 case NRF_POWER_POFTHRVDDH_V32:
268 vddh_voltage =
"3.2V";
270 case NRF_POWER_POFTHRVDDH_V33:
271 vddh_voltage =
"3.3V";
273 case NRF_POWER_POFTHRVDDH_V34:
274 vddh_voltage =
"3.4V";
276 case NRF_POWER_POFTHRVDDH_V35:
277 vddh_voltage =
"3.5V";
279 case NRF_POWER_POFTHRVDDH_V36:
280 vddh_voltage =
"3.6V";
282 case NRF_POWER_POFTHRVDDH_V37:
283 vddh_voltage =
"3.7V";
285 case NRF_POWER_POFTHRVDDH_V38:
286 vddh_voltage =
"3.8V";
288 case NRF_POWER_POFTHRVDDH_V39:
289 vddh_voltage =
"3.9V";
291 case NRF_POWER_POFTHRVDDH_V40:
292 vddh_voltage =
"4.0V";
294 case NRF_POWER_POFTHRVDDH_V41:
295 vddh_voltage =
"4.1V";
297 case NRF_POWER_POFTHRVDDH_V42:
298 vddh_voltage =
"4.2V";
301 vddh_voltage =
"???V";
304 ESP_LOGD(TAG,
"Power-fail comparator: %s, VDDH: %s", pof_voltage, vddh_voltage);
305 pos = buf_append_printf(buf,
size,
pos,
"|Power-fail comparator: %s, VDDH: %s", pof_voltage, vddh_voltage);
307 ESP_LOGD(TAG,
"Power-fail comparator: %s", pof_voltage);
308 pos = buf_append_printf(buf,
size,
pos,
"|Power-fail comparator: %s", pof_voltage);
311 ESP_LOGD(TAG,
"Power-fail comparator: disabled");
312 pos = buf_append_printf(buf,
size,
pos,
"|Power-fail comparator: disabled");
315 auto package = [](uint32_t value) {
318 return "QIxx - 7x7 73-pin aQFN";
320 return "QFxx - 6x6 48-pin QFN";
322 return "CKxx - 3.544 x 3.607 WLCSP";
324 return "Unspecified";
327 char mac_pretty[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
331 " Code page size: %u, code size: %u, device id: 0x%08x%08x\n"
332 " Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x\n"
333 " Device address type: %s, address: %s\n"
334 " Part code: nRF%x, version: %c%c%c%c, package: %s\n"
335 " RAM: %ukB, Flash: %ukB, production test: %sdone",
336 NRF_FICR->CODEPAGESIZE, NRF_FICR->CODESIZE, NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0], NRF_FICR->ER[0],
337 NRF_FICR->ER[1], NRF_FICR->ER[2], NRF_FICR->ER[3], NRF_FICR->IR[0], NRF_FICR->IR[1], NRF_FICR->IR[2],
338 NRF_FICR->IR[3], (NRF_FICR->DEVICEADDRTYPE & 0x1 ?
"Random" :
"Public"), mac_pretty, NRF_FICR->INFO.PART,
339 NRF_FICR->INFO.VARIANT >> 24 & 0xFF, NRF_FICR->INFO.VARIANT >> 16 & 0xFF, NRF_FICR->INFO.VARIANT >> 8 & 0xFF,
340 NRF_FICR->INFO.VARIANT & 0xFF, package(NRF_FICR->INFO.PACKAGE), NRF_FICR->INFO.RAM, NRF_FICR->INFO.FLASH,
341 (NRF_FICR->PRODTEST[0] == 0xBB42319F ?
"" :
"not "));
342 bool n_reset_enabled = NRF_UICR->PSELRESET[0] == NRF_UICR->PSELRESET[1] &&
343 (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) == UICR_PSELRESET_CONNECT_Connected
344 << UICR_PSELRESET_CONNECT_Pos;
346 TAG,
" GPIO as NFC pins: %s, GPIO as nRESET pin: %s",
347 YESNO((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)),
348 YESNO(n_reset_enabled));
349 if (n_reset_enabled) {
350 uint8_t port = (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_PORT_Msk) >> UICR_PSELRESET_PORT_Pos;
351 uint8_t pin = (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_PIN_Msk) >> UICR_PSELRESET_PIN_Pos;
352 ESP_LOGD(TAG,
" nRESET port P%u.%02u", port, pin);
354#ifdef USE_BOOTLOADER_MCUBOOT
355 ESP_LOGD(TAG,
" Bootloader: mcuboot");
357 ESP_LOGD(TAG,
" Bootloader: Adafruit, version %u.%u.%u", (BOOTLOADER_VERSION_REGISTER >> 16) & 0xFF,
358 (BOOTLOADER_VERSION_REGISTER >> 8) & 0xFF, BOOTLOADER_VERSION_REGISTER & 0xFF);
359 ESP_LOGD(TAG,
" MBR bootloader addr 0x%08x, UICR bootloader addr 0x%08x", read_mem_u32(
MBR_BOOTLOADER_ADDR),
361 ESP_LOGD(TAG,
" MBR param page addr 0x%08x, UICR param page addr 0x%08x", read_mem_u32(
MBR_PARAM_PAGE_ADDR),
363 if (is_sd_present()) {
365 uint32_t const sd_version = sd_version_get();
368 ver[0] = sd_version / 1000000;
369 ver[1] = (sd_version - ver[0] * 1000000) / 1000;
370 ver[2] = (sd_version - ver[0] * 1000000 - ver[1] * 1000);
372 ESP_LOGD(TAG,
" SoftDevice: S%u %u.%u.%u", sd_id, ver[0], ver[1], ver[2]);
373#ifdef USE_SOFTDEVICE_ID
374#ifdef USE_SOFTDEVICE_VERSION
375 if (USE_SOFTDEVICE_ID != sd_id || USE_SOFTDEVICE_VERSION != ver[0]) {
376 ESP_LOGE(TAG,
"Built for SoftDevice S%u %u.x.y. It may crash due to mismatch of bootloader version.",
377 USE_SOFTDEVICE_ID, USE_SOFTDEVICE_VERSION);
380 if (USE_SOFTDEVICE_ID != sd_id) {
381 ESP_LOGE(TAG,
"Built for SoftDevice S%u. It may crash due to mismatch of bootloader version.", USE_SOFTDEVICE_ID);
390 for (
size_t i = 0; i <
size; i++) {
398 ESP_LOGD(TAG,
" NRFFW %s", uicr(NRF_UICR->NRFFW, 13).c_str());
399 ESP_LOGD(TAG,
" NRFHW %s", uicr(NRF_UICR->NRFHW, 12).c_str());
400#ifdef ESPHOME_LOG_HAS_VERBOSE
401 log_peripherals_info();
406void DebugComponent::update_platform_() {}
const char * get_wakeup_cause_(std::span< char, WAKEUP_CAUSE_BUFFER_SIZE > buffer)
void log_partition_info_()
Logs information about the device's partition table.
size_t get_device_info_(std::span< char, DEVICE_INFO_BUFFER_SIZE > buffer, size_t pos)
uint32_t get_free_heap_()
const char * get_reset_reason_(std::span< char, RESET_REASON_BUFFER_SIZE > buffer)
constexpr std::uintptr_t MBR_PARAM_PAGE_ADDR
constexpr uintptr_t SD_ID_OFFSET
constexpr std::uintptr_t MBR_BOOTLOADER_ADDR
constexpr uintptr_t MBR_SIZE
constexpr uintptr_t SOFTDEVICE_INFO_STRUCT_OFFSET
constexpr uintptr_t SD_VERSION_OFFSET
constexpr uint32_t SD_MAGIC_NUMBER
const std::vector< uint8_t > & data
const char * get_reset_reason(std::span< char, RESET_REASON_BUFFER_SIZE > buffer)
const char * get_mac_address_pretty_into_buffer(std::span< char, MAC_ADDRESS_PRETTY_BUFFER_SIZE > buf)
Get the device MAC address into the given buffer, in colon-separated uppercase hex notation.
std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length)
Format a byte array in pretty-printed, human-readable hex format.