Skip to content

Commit

Permalink
feat(espcoredump): Allow writing to both flash and UART
Browse files Browse the repository at this point in the history
  • Loading branch information
nebkat committed Jun 18, 2024
1 parent 0479494 commit 91fc98d
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 166 deletions.
24 changes: 10 additions & 14 deletions components/espcoredump/Kconfig
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
menu "Core dump"

choice ESP_COREDUMP_TO_FLASH_OR_UART
prompt "Data destination"
default ESP_COREDUMP_ENABLE_TO_NONE
config ESP_COREDUMP_ENABLE_TO_FLASH
bool "Write to flash"
default n
select ESP_COREDUMP_ENABLE
help
Select place to store core dump: flash, uart or none (to disable core dumps generation).

Core dumps to Flash are not available if PSRAM is used for task stacks.

If core dump is configured to be stored in flash and custom partition table is used add
corresponding entry to your CSV. For examples, please see predefined partition table CSV descriptions
in the components/partition_table directory.

config ESP_COREDUMP_ENABLE_TO_FLASH
bool "Flash"
select ESP_COREDUMP_ENABLE
config ESP_COREDUMP_ENABLE_TO_UART
bool "UART"
select ESP_COREDUMP_ENABLE
config ESP_COREDUMP_ENABLE_TO_NONE
bool "None"
endchoice
config ESP_COREDUMP_ENABLE_TO_UART
bool "Print to UART"
default n
select ESP_COREDUMP_ENABLE
help
Print core dump to UART console for processing with esp-coredump.py tool.

choice ESP_COREDUMP_DATA_FORMAT
prompt "Core dump data format"
Expand Down
61 changes: 26 additions & 35 deletions components/espcoredump/include_core_dump/esp_core_dump_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,40 +101,31 @@ bool esp_core_dump_in_isr_context(void);
*/
uint32_t esp_core_dump_get_user_ram_size(void);

/**
* @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 Initiates the beginning of data writing.
*/
esp_err_t esp_core_dump_write_start(core_dump_write_data_t *wr_data);

/**
* @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 Finalizes the data writing process
*/
esp_err_t esp_core_dump_write_end(core_dump_write_data_t *wr_data);
typedef struct esp_core_dump_output {
// @brief Prints write start info string according to destination.
void (*print_write_start)(void);
// @brief Prints write end info string according to destination.
void (*print_write_end)(void);
// @brief Initializes the flash/UART hardware for data storage.
esp_err_t (*write_init)(void);
// @brief Prepares the flash/UART for data storage
esp_err_t (*write_prepare)(core_dump_write_data_t *wr_data, uint32_t *data_len);
// @brief Initiates the beginning of data writing.
esp_err_t (*write_start)(core_dump_write_data_t *wr_data);
// @brief Writes a data chunk to the flash/UART
esp_err_t (*write_data)(core_dump_write_data_t *wr_data, void *data, uint32_t data_len);
// @brief Finalizes the data writing process
esp_err_t (*write_end)(core_dump_write_data_t *wr_data);
} esp_core_dump_output_t;

#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART
extern esp_core_dump_output_t esp_core_dump_output_uart;
void esp_core_dump_uart_init(void);
#endif
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
extern esp_core_dump_output_t esp_core_dump_output_flash;
void esp_core_dump_flash_init(void);
#endif

/**
* @brief Retrieve the stack information which will be used from the coredump module itself.
Expand All @@ -145,7 +136,7 @@ void esp_core_dump_get_own_stack_info(uint32_t *addr, uint32_t *size);
/**
* @brief Stores the core dump in either binary or ELF format.
*/
esp_err_t esp_core_dump_store(void);
esp_err_t esp_core_dump_store(esp_core_dump_output_t *output);

/**
* @brief Get TCB length, in bytes.
Expand Down
37 changes: 19 additions & 18 deletions components/espcoredump/src/core_dump_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

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")));
esp_err_t esp_core_dump_store(esp_core_dump_output_t *output) __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)
static esp_err_t esp_core_dump_save_task(esp_core_dump_output_t *output, core_dump_write_data_t *write_data, core_dump_task_header_t *task)
{
esp_err_t err = ESP_FAIL;
uint32_t stk_vaddr = 0;
Expand All @@ -27,19 +27,19 @@ static esp_err_t esp_core_dump_save_task(core_dump_write_data_t *write_data, cor
stk_len = esp_core_dump_get_memory_len(stk_vaddr, stk_vaddr + stk_len);

// Save memory segment header
err = esp_core_dump_write_data(write_data, task, sizeof(core_dump_task_header_t));
err = output->write_data(write_data, task, sizeof(core_dump_task_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write task header, error=%d!", err);
return err;
}
// Save TCB block
err = esp_core_dump_write_data(write_data, task->tcb_addr, esp_core_dump_get_tcb_len());
err = output->write_data(write_data, task->tcb_addr, esp_core_dump_get_tcb_len());
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write TCB, error=%d!", err);
return err;
}
// Save task stack
err = esp_core_dump_write_data(write_data, (void *)stk_paddr, stk_len);
err = output->write_data(write_data, (void *)stk_paddr, stk_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write stack for task (TCB:%p), stack_start=%" PRIx32 ", error=%d!",
task->tcb_addr,
Expand All @@ -53,7 +53,8 @@ static esp_err_t esp_core_dump_save_task(core_dump_write_data_t *write_data, cor
return ESP_OK;
}

static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_data_t* write_data,
static esp_err_t esp_core_dump_save_mem_segment(esp_core_dump_output_t *output,
core_dump_write_data_t* write_data,
core_dump_mem_seg_header_t* seg)
{
esp_err_t err = ESP_FAIL;
Expand All @@ -64,13 +65,13 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_data_t* write_da
return ESP_FAIL;
}
// Save TCB address, stack base and stack top addrq
err = esp_core_dump_write_data(write_data, seg, sizeof(core_dump_mem_seg_header_t));
err = output->write_data(write_data, seg, sizeof(core_dump_mem_seg_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write memory segment header, error=%d!", err);
return err;
}
// Save memory contents
err = esp_core_dump_write_data(write_data, (void *)seg->start, seg->size);
err = output->write_data(write_data, (void *)seg->start, seg->size);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write memory segment, (%" PRIx32 ", %" PRIu32 "), error=%d!",
seg->start, seg->size, err);
Expand All @@ -81,7 +82,7 @@ static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_data_t* write_da
return ESP_OK;
}

static esp_err_t esp_core_dump_write_binary(void)
static esp_err_t esp_core_dump_write_binary(esp_core_dump_output_t *output)
{
uint32_t tcb_sz = esp_core_dump_get_tcb_len();
uint32_t data_len = 0;
Expand All @@ -93,7 +94,7 @@ static 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();
esp_err_t err = output->write_init();
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Binary write init failed!");
return ESP_FAIL;
Expand Down Expand Up @@ -167,14 +168,14 @@ static esp_err_t esp_core_dump_write_binary(void)
ESP_COREDUMP_LOG_PROCESS("Core dump length=%" PRIu32 ", tasks processed: %" PRIu32 ", broken tasks: %" PRIu32,
data_len, hdr.tasks_num, bad_tasks_num);
// Prepare write
err = esp_core_dump_write_prepare(&write_data, &data_len);
err = output->write_prepare(&write_data, &data_len);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to prepare core dump, error=%d!", err);
return err;
}

// Write start
err = esp_core_dump_write_start(&write_data);
err = output->write_start(&write_data);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to start core dump, error=%d!", err);
return err;
Expand All @@ -185,7 +186,7 @@ static esp_err_t esp_core_dump_write_binary(void)
hdr.version = COREDUMP_VERSION_BIN_CURRENT;
hdr.tcb_sz = tcb_sz;
hdr.chip_rev = efuse_hal_chip_revision();
err = esp_core_dump_write_data(&write_data, &hdr, sizeof(core_dump_header_t));
err = output->write_data(&write_data, &hdr, sizeof(core_dump_header_t));
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to write core dump header error=%d!", err);
return err;
Expand All @@ -196,7 +197,7 @@ static esp_err_t esp_core_dump_write_binary(void)
// Write first crashed task data first (not always first task in the snapshot)
ESP_COREDUMP_LOGD("Save first crashed task %p", cur_task);
if (esp_core_dump_get_task_snapshot(cur_task, &task_hdr, NULL)) {
err = esp_core_dump_save_task(&write_data, &task_hdr);
err = esp_core_dump_save_task(output, &write_data, &task_hdr);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save first crashed task %p, error=%d!",
task_hdr.tcb_addr, err);
Expand All @@ -215,7 +216,7 @@ static esp_err_t esp_core_dump_write_binary(void)
}
ESP_COREDUMP_LOGD("Save task %p (TCB:%p, stack:%" PRIx32 "..%" PRIx32 ")",
task_iter.pxTaskHandle, task_hdr.tcb_addr, task_hdr.stack_start, task_hdr.stack_end);
err = esp_core_dump_save_task(&write_data, &task_hdr);
err = esp_core_dump_save_task(output, &write_data, &task_hdr);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save core dump task %p, error=%d!",
task_hdr.tcb_addr, err);
Expand All @@ -234,7 +235,7 @@ static esp_err_t esp_core_dump_write_binary(void)
if (mem_seg.size > 0) {
ESP_COREDUMP_LOG_PROCESS("Save interrupted task stack %" PRIu32 " bytes @ %" PRIx32,
mem_seg.size, mem_seg.start);
err = esp_core_dump_save_mem_segment(&write_data, &mem_seg);
err = esp_core_dump_save_mem_segment(output, &write_data, &mem_seg);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err);
return err;
Expand All @@ -258,7 +259,7 @@ static esp_err_t esp_core_dump_write_binary(void)
mem_seg.size = esp_core_dump_get_memory_len(start, start + data_sz);;
ESP_COREDUMP_LOG_PROCESS("Save user memory region %" PRIu32 " bytes @ %" PRIx32,
mem_seg.size, mem_seg.start);
err = esp_core_dump_save_mem_segment(&write_data, &mem_seg);
err = esp_core_dump_save_mem_segment(output, &write_data, &mem_seg);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to save user memory region, error=%d!", err);
return err;
Expand All @@ -268,7 +269,7 @@ static esp_err_t esp_core_dump_write_binary(void)
}

// Write end
err = esp_core_dump_write_end(&write_data);
err = output->write_end(&write_data);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to end core dump error=%d!", err);
return err;
Expand Down
28 changes: 18 additions & 10 deletions components/espcoredump/src/core_dump_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,24 +184,29 @@ FORCE_INLINE_ATTR void esp_core_dump_report_stack_usage(void)

static void* s_exc_frame = NULL;

inline static void esp_core_dump_write_internal(panic_info_t *info)
inline static void esp_core_dump_write_internal(esp_core_dump_output_t *output, panic_info_t *info)
{
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);
esp_err_t err = esp_core_dump_store();
esp_err_t err = esp_core_dump_store(output);
if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Core dump write failed with error=%d", err);
}
esp_core_dump_report_stack_usage();
}

void __attribute__((weak)) esp_core_dump_init(void)
void esp_core_dump_init(void)
{
/* do nothing by default */
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART
esp_core_dump_uart_init();
#endif
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
esp_core_dump_flash_init();
#endif
}

/**
Expand Down Expand Up @@ -356,13 +361,16 @@ inline bool esp_core_dump_in_isr_context(void)

void esp_core_dump_write(panic_info_t *info)
{
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
return;
#if CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH
esp_core_dump_output_flash.print_write_start();
esp_core_dump_write_internal(&esp_core_dump_output_flash, info);
esp_core_dump_output_flash.print_write_end();
#endif
#if CONFIG_ESP_COREDUMP_ENABLE_TO_UART && !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
esp_core_dump_output_uart.print_write_start();
esp_core_dump_write_internal(&esp_core_dump_output_uart, info);
esp_core_dump_output_uart.print_write_end();
#endif

esp_core_dump_print_write_start();
esp_core_dump_write_internal(info);
esp_core_dump_print_write_end();
}

#endif
Loading

0 comments on commit 91fc98d

Please sign in to comment.