mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
refactor(espcoredump): simplify uart/flash write flow
This commit is contained in:
parent
91586bbc85
commit
434b096c72
@ -376,14 +376,8 @@ void esp_panic_handler(panic_info_t *info)
|
||||
} else {
|
||||
disable_all_wdts();
|
||||
s_dumping_core = true;
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
|
||||
esp_core_dump_to_flash(info);
|
||||
#endif
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
||||
esp_core_dump_to_uart(info);
|
||||
#endif
|
||||
esp_core_dump_write(info);
|
||||
s_dumping_core = false;
|
||||
|
||||
esp_panic_handler_reconfigure_wdts(1000);
|
||||
}
|
||||
#endif /* CONFIG_ESP_COREDUMP_ENABLE */
|
||||
|
@ -106,9 +106,9 @@ menu "Core dump"
|
||||
int "Reserved stack size"
|
||||
depends on ESP_COREDUMP_ENABLE
|
||||
range 0 4096 if !ESP_COREDUMP_USE_STACK_SIZE
|
||||
range 1280 4096 if ESP_COREDUMP_USE_STACK_SIZE
|
||||
range 1792 4096 if ESP_COREDUMP_USE_STACK_SIZE
|
||||
default 0 if !ESP_COREDUMP_USE_STACK_SIZE
|
||||
default 1280 if ESP_COREDUMP_USE_STACK_SIZE
|
||||
default 1792 if ESP_COREDUMP_USE_STACK_SIZE
|
||||
help
|
||||
Size of the memory to be reserved for core dump stack. If 0 core dump process will run on
|
||||
the stack of crashed task/ISR, otherwise special stack will be allocated.
|
||||
|
@ -47,51 +47,49 @@ typedef struct {
|
||||
*/
|
||||
void esp_core_dump_init(void);
|
||||
|
||||
/**
|
||||
* @brief Saves core dump to flash.
|
||||
*
|
||||
* The structure of data stored in flash is as follows:
|
||||
*
|
||||
* | TOTAL_LEN | VERSION | TASKS_NUM | TCB_SIZE |
|
||||
* | TCB_ADDR_1 | STACK_TOP_1 | STACK_END_1 | TCB_1 | STACK_1 |
|
||||
* . . . .
|
||||
* . . . .
|
||||
* | TCB_ADDR_N | STACK_TOP_N | STACK_END_N | TCB_N | STACK_N |
|
||||
* | CHECKSUM |
|
||||
*
|
||||
* Core dump in flash consists of header and data for every task in the system at the moment of crash.
|
||||
* For flash data integrity, a checksum is used at the end of core the dump data.
|
||||
* The structure of core dump data is described below in details.
|
||||
* 1) Core dump starts with header:
|
||||
* 1.1) TOTAL_LEN is total length of core dump data in flash including the checksum. Size is 4 bytes.
|
||||
* 1.2) VERSION field keeps 4 byte version of core dump.
|
||||
* 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes.
|
||||
* 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes.
|
||||
* 2) Core dump header is followed by the data for every task in the system.
|
||||
* Task data are started with task header:
|
||||
* 2.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes.
|
||||
* 2.2) STACK_TOP is the top of task's stack (address of the topmost stack item). Size is 4 bytes.
|
||||
* 2.2) STACK_END is the end of task's stack (address from which task's stack starts). Size is 4 bytes.
|
||||
* 3) Task header is followed by TCB data. Size is TCB_SIZE bytes.
|
||||
* 4) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
|
||||
* 5) The checksum is placed at the end of the data.
|
||||
*/
|
||||
void esp_core_dump_to_flash(panic_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Print base64-encoded core dump to UART.
|
||||
*
|
||||
* The structure of core dump data is the same as for data stored in flash (@see esp_core_dump_to_flash) with some notes:
|
||||
* 1) The checksum is not present in core dump printed to UART.
|
||||
* 2) Since checksum is omitted TOTAL_LEN does not include its size.
|
||||
* 3) Printed base64 data are surrounded with special messages to help user recognize the start and end of actual data.
|
||||
*/
|
||||
void esp_core_dump_to_uart(panic_info_t *info);
|
||||
|
||||
/**************************************************************************************/
|
||||
/*********************************** USER MODE API ************************************/
|
||||
/**************************************************************************************/
|
||||
|
||||
/**
|
||||
* Core dump file consists of header and data (in binary or ELF format) for every task in the system at the moment of crash.
|
||||
* For the data integrity, a checksum is used at the end of core the dump data.
|
||||
* The structure of core dump file is described below in details.
|
||||
* 1) Core dump starts with header:
|
||||
* 1.1) TOTAL_LEN is total length of core dump data in flash including the checksum. Size is 4 bytes.
|
||||
* 1.2) VERSION field keeps 4 byte version of core dump.
|
||||
* 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes. Unused in ELF format
|
||||
* 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes. Unused in ELF format
|
||||
* 1.4) MEM_SEG_NUM is the number of memory segment. Size is 4 bytes. Unused in ELF format
|
||||
* 1.5) CHIP_REV is the revision of the chip. Size is 4 bytes.
|
||||
* 2) Core dump header is followed by the data for every task in the system. Data part is differs for the binary
|
||||
* and elf formats.
|
||||
* 2.1) The core dump file uses a subset of the ELF structures to store the crash information.
|
||||
* Loadable ELF segments and ELF notes (ELF.PT_NOTE) used with a special name and type (CORE, NT_PRSTATUS type)
|
||||
* 2.2) In Binary format task data are started with the task header:
|
||||
* 2.2.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes.
|
||||
* 2.2.2) STACK_TOP is the top of task's stack (address of the topmost stack item). Size is 4 bytes.
|
||||
* 2.2.3) STACK_END is the end of task's stack (address from which task's stack starts). Size is 4 bytes.
|
||||
* 2.2.4) Task header is followed by TCB data. Size is TCB_SIZE bytes.
|
||||
* 2.2.5) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
|
||||
* 2.3) The checksum is placed at the end of the data.
|
||||
* 3) The structure of the uart data is the same as the data stored in flash
|
||||
* 3.1) Uart data is printed in base64 format surrounded with special messages to help user recognize the start and
|
||||
* end of actual data.
|
||||
*
|
||||
* For more information about the implementation please check api-guides/core_dump_internals.rst
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Print/store coredump data to the selected destination uart or flash.
|
||||
*
|
||||
* @param info Pointer to the panic information. It contains the execution frame.
|
||||
*
|
||||
* @return ESP_OK on success, otherwise \see esp_err_t
|
||||
*/
|
||||
void esp_core_dump_write(panic_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Check integrity of coredump data in flash.
|
||||
* This function reads the coredump data while calculating their checksum. If it
|
||||
|
@ -92,25 +92,45 @@ bool esp_core_dump_in_isr_context(void);
|
||||
uint32_t esp_core_dump_get_user_ram_size(void);
|
||||
|
||||
/**
|
||||
* @brief Function called to prepare flash/uart for the data storage
|
||||
* @brief Prints write start info string according to destination.
|
||||
*/
|
||||
void esp_core_dump_print_write_start(void);
|
||||
|
||||
/**
|
||||
* @brief Prints write end info string according to destination.
|
||||
*/
|
||||
void esp_core_dump_print_write_end(void);
|
||||
|
||||
/**
|
||||
* @brief Initializes the flash/UART hardware for data storage.
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_init(void);
|
||||
|
||||
/**
|
||||
* @brief Prepares the flash/UART for data storage
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len);
|
||||
|
||||
/**
|
||||
* @brief Function called at the beginning of data writing
|
||||
* @brief Initiates the beginning of data writing.
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data);
|
||||
|
||||
/**
|
||||
* @brief Function called to write data chunk
|
||||
* @brief Writes a data chunk to the flash/UART
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_data(core_dump_write_data_t *wr_data, void *data, uint32_t data_len);
|
||||
|
||||
/**
|
||||
* @brief Function called once all data have been written
|
||||
* @brief Finalizes the data writing process
|
||||
*/
|
||||
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data);
|
||||
|
||||
/**
|
||||
* @brief Stores the core dump in either binary or ELF format.
|
||||
*/
|
||||
esp_err_t esp_core_dump_store(void);
|
||||
|
||||
/**
|
||||
* @brief Get TCB length, in bytes.
|
||||
*
|
||||
|
@ -171,16 +171,6 @@ typedef struct _core_dump_mem_seg_header_t {
|
||||
uint32_t size; /*!< Memory region size */
|
||||
} core_dump_mem_seg_header_t;
|
||||
|
||||
/**
|
||||
* @brief Core dump flash init function
|
||||
*/
|
||||
void esp_core_dump_flash_init(void);
|
||||
|
||||
/**
|
||||
* @brief Common core dump write function
|
||||
*/
|
||||
void esp_core_dump_write(panic_info_t *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
const static char TAG[] __attribute__((unused)) = "esp_core_dump_binary";
|
||||
|
||||
esp_err_t esp_core_dump_store(void) __attribute__((alias("esp_core_dump_write_binary")));
|
||||
|
||||
static esp_err_t esp_core_dump_save_task(core_dump_write_data_t *write_data, core_dump_task_header_t *task)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
@ -79,9 +81,8 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_data_t* write_da
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_core_dump_write_binary(void)
|
||||
static esp_err_t esp_core_dump_write_binary(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
uint32_t tcb_sz = esp_core_dump_get_tcb_len();
|
||||
uint32_t data_len = 0;
|
||||
uint32_t bad_tasks_num = 0;
|
||||
@ -92,6 +93,12 @@ esp_err_t esp_core_dump_write_binary(void)
|
||||
TaskIterator_t task_iter;
|
||||
void *cur_task = NULL;
|
||||
|
||||
esp_err_t err = esp_core_dump_write_init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Binary write init failed!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Verifies all tasks in the snapshot
|
||||
esp_core_dump_reset_tasks_snapshots_iter();
|
||||
esp_core_dump_task_iterator_init(&task_iter);
|
||||
|
@ -140,28 +140,19 @@ FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)
|
||||
|
||||
static void* s_exc_frame = NULL;
|
||||
|
||||
inline void esp_core_dump_write(panic_info_t *info)
|
||||
inline static void esp_core_dump_write_internal(panic_info_t *info)
|
||||
{
|
||||
#ifndef CONFIG_ESP_COREDUMP_ENABLE_TO_NONE
|
||||
esp_err_t err = ESP_ERR_NOT_SUPPORTED;
|
||||
s_exc_frame = (void*) info->frame;
|
||||
|
||||
bool isr_context = esp_core_dump_in_isr_context();
|
||||
|
||||
s_exc_frame = (void *)info->frame;
|
||||
|
||||
esp_core_dump_setup_stack();
|
||||
esp_core_dump_port_init(info, isr_context);
|
||||
#if CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN
|
||||
esp_err_t esp_core_dump_write_binary(void);
|
||||
err = esp_core_dump_write_binary();
|
||||
#elif CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
esp_err_t esp_core_dump_write_elf(void);
|
||||
err = esp_core_dump_write_elf();
|
||||
#endif
|
||||
esp_err_t err = esp_core_dump_store();
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Core dump write binary failed with error=%d", err);
|
||||
ESP_COREDUMP_LOGE("Core dump write failed with error=%d", err);
|
||||
}
|
||||
esp_core_dump_report_stack_usage();
|
||||
#endif
|
||||
}
|
||||
|
||||
void __attribute__((weak)) esp_core_dump_init(void)
|
||||
@ -311,4 +302,15 @@ inline bool esp_core_dump_in_isr_context(void)
|
||||
#endif // CONFIG_ESP_TASK_WDT_EN
|
||||
}
|
||||
|
||||
void esp_core_dump_write(panic_info_t *info)
|
||||
{
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
|
||||
return;
|
||||
#endif
|
||||
|
||||
esp_core_dump_print_write_start();
|
||||
esp_core_dump_write_internal(info);
|
||||
esp_core_dump_print_write_end();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -97,6 +97,8 @@ typedef struct {
|
||||
#endif
|
||||
#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
esp_err_t esp_core_dump_store(void) __attribute__((alias("esp_core_dump_write_elf")));
|
||||
|
||||
// Builds elf header and check all data offsets
|
||||
static int elf_write_file_header(core_dump_elf_t *self, uint32_t seg_count)
|
||||
{
|
||||
@ -667,14 +669,19 @@ static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self)
|
||||
return tot_len;
|
||||
}
|
||||
|
||||
esp_err_t esp_core_dump_write_elf(void)
|
||||
static esp_err_t esp_core_dump_write_elf(void)
|
||||
{
|
||||
core_dump_elf_t self = { 0 };
|
||||
core_dump_header_t dump_hdr = { 0 };
|
||||
esp_err_t err = ESP_OK;
|
||||
int tot_len = sizeof(dump_hdr);
|
||||
int write_len = sizeof(dump_hdr);
|
||||
|
||||
esp_err_t err = esp_core_dump_write_init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_COREDUMP_LOGE("Elf write init failed!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// On first pass (do not write actual data), but calculate data length needed to allocate memory
|
||||
self.elf_stage = ELF_STAGE_CALC_SPACE;
|
||||
ESP_COREDUMP_LOG_PROCESS("================= Calc data size ===============");
|
||||
|
@ -42,6 +42,9 @@ typedef struct _core_dump_flash_config_t {
|
||||
/* Core dump flash data. */
|
||||
static core_dump_flash_config_t s_core_flash_config;
|
||||
|
||||
void esp_core_dump_print_write_start(void) __attribute__((alias("esp_core_dump_flash_print_write_start")));
|
||||
void esp_core_dump_print_write_end(void) __attribute__((alias("esp_core_dump_flash_print_write_end")));
|
||||
esp_err_t esp_core_dump_write_init(void) __attribute__((alias("esp_core_dump_flash_hw_init")));
|
||||
esp_err_t esp_core_dump_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len) __attribute__((alias("esp_core_dump_flash_write_prepare")));
|
||||
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_flash_write_start")));
|
||||
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_flash_write_end")));
|
||||
@ -54,6 +57,16 @@ esp_err_t esp_core_dump_write_data(core_dump_write_data_t *wr_data, void *data,
|
||||
esp_err_t esp_core_dump_image_check(void);
|
||||
static esp_err_t esp_core_dump_partition_and_size_get(const esp_partition_t **partition, uint32_t* size);
|
||||
|
||||
static void esp_core_dump_flash_print_write_start(void)
|
||||
{
|
||||
ESP_COREDUMP_LOGI("Save core dump to flash...");
|
||||
}
|
||||
|
||||
static void esp_core_dump_flash_print_write_end(void)
|
||||
{
|
||||
ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
|
||||
}
|
||||
|
||||
static esp_err_t esp_core_dump_flash_custom_write(uint32_t address, const void *buffer, uint32_t length)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
@ -72,7 +85,35 @@ static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
|
||||
return esp_rom_crc32_le(0, (uint8_t const *)&s_core_flash_config.partition, sizeof(s_core_flash_config.partition));
|
||||
}
|
||||
|
||||
void esp_core_dump_flash_init(void)
|
||||
static esp_err_t esp_core_dump_flash_hw_init(void)
|
||||
{
|
||||
/* Check core dump partition configuration. */
|
||||
core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc();
|
||||
if (s_core_flash_config.partition_config_crc != crc) {
|
||||
ESP_COREDUMP_LOGE("Core dump flash config is corrupted! CRC=0x%x instead of 0x%x", crc, s_core_flash_config.partition_config_crc);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Make sure that the partition can at least hold the data length. */
|
||||
if (s_core_flash_config.partition.start == 0 || s_core_flash_config.partition.size < sizeof(uint32_t)) {
|
||||
ESP_COREDUMP_LOGE("Invalid flash partition config!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_FLASH_NO_OVERWRITE
|
||||
if (!s_core_flash_config.partition.empty) {
|
||||
ESP_COREDUMP_LOGW("Core dump already exists in flash, will not overwrite it with a new core dump");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize non-OS flash access critical section. */
|
||||
spi_flash_guard_set(&g_flash_guard_no_os_ops);
|
||||
esp_flash_app_disable_protect(true);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void esp_core_dump_partition_init(void)
|
||||
{
|
||||
const esp_partition_t *core_part = NULL;
|
||||
|
||||
@ -314,40 +355,9 @@ static esp_err_t esp_core_dump_flash_write_end(core_dump_write_data_t *wr_data)
|
||||
return err;
|
||||
}
|
||||
|
||||
void esp_core_dump_to_flash(panic_info_t *info)
|
||||
{
|
||||
/* Check core dump partition configuration. */
|
||||
core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc();
|
||||
if (s_core_flash_config.partition_config_crc != crc) {
|
||||
ESP_COREDUMP_LOGE("Core dump flash config is corrupted! CRC=0x%x instead of 0x%x", crc, s_core_flash_config.partition_config_crc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure that the partition can at least hold the data length. */
|
||||
if (s_core_flash_config.partition.start == 0 || s_core_flash_config.partition.size < sizeof(uint32_t)) {
|
||||
ESP_COREDUMP_LOGE("Invalid flash partition config!");
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_FLASH_NO_OVERWRITE
|
||||
if (!s_core_flash_config.partition.empty) {
|
||||
ESP_COREDUMP_LOGW("Core dump already exists in flash, will not overwrite it with a new core dump");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize non-OS flash access critical section. */
|
||||
spi_flash_guard_set(&g_flash_guard_no_os_ops);
|
||||
esp_flash_app_disable_protect(true);
|
||||
|
||||
ESP_COREDUMP_LOGI("Save core dump to flash...");
|
||||
esp_core_dump_write(info);
|
||||
ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
|
||||
}
|
||||
|
||||
void esp_core_dump_init(void)
|
||||
{
|
||||
esp_core_dump_flash_init();
|
||||
esp_core_dump_partition_init();
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_CHECK_BOOT
|
||||
const esp_partition_t *partition = 0;
|
||||
|
@ -17,6 +17,9 @@ const static char TAG[] __attribute__((unused)) = "esp_core_dump_uart";
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART
|
||||
|
||||
void esp_core_dump_print_write_start(void) __attribute__((alias("esp_core_dump_uart_print_write_start")));
|
||||
void esp_core_dump_print_write_end(void) __attribute__((alias("esp_core_dump_uart_print_write_end")));
|
||||
esp_err_t esp_core_dump_write_init(void) __attribute__((alias("esp_core_dump_uart_hw_init")));
|
||||
esp_err_t esp_core_dump_write_prepare(core_dump_write_data_t *wr_data, uint32_t *data_len) __attribute__((alias("esp_core_dump_uart_write_prepare")));
|
||||
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_uart_write_start")));
|
||||
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data) __attribute__((alias("esp_core_dump_uart_write_end")));
|
||||
@ -52,6 +55,16 @@ static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8
|
||||
dst[j++] = '\0';
|
||||
}
|
||||
|
||||
static void esp_core_dump_uart_print_write_start(void)
|
||||
{
|
||||
ESP_COREDUMP_LOGI("Print core dump to uart...");
|
||||
}
|
||||
|
||||
static void esp_core_dump_uart_print_write_end(void)
|
||||
{
|
||||
ESP_COREDUMP_LOGI("Core dump has been written to uart.");
|
||||
}
|
||||
|
||||
static esp_err_t esp_core_dump_uart_write_start(core_dump_write_data_t *wr_data)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
@ -128,7 +141,7 @@ static int esp_core_dump_uart_get_char(void)
|
||||
return i;
|
||||
}
|
||||
|
||||
void esp_core_dump_to_uart(panic_info_t *info)
|
||||
static esp_err_t esp_core_dump_uart_hw_init(void)
|
||||
{
|
||||
uint32_t tm_end = 0;
|
||||
uint32_t tm_cur = 0;
|
||||
@ -156,9 +169,8 @@ void esp_core_dump_to_uart(panic_info_t *info)
|
||||
}
|
||||
ch = esp_core_dump_uart_get_char();
|
||||
}
|
||||
ESP_COREDUMP_LOGI("Print core dump to uart...");
|
||||
esp_core_dump_write(info);
|
||||
ESP_COREDUMP_LOGI("Core dump has been written to uart.");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void esp_core_dump_init(void)
|
||||
|
Loading…
Reference in New Issue
Block a user