Merge branch 'feature/core_dump_crc' into 'master'

Core Dump CRC

See merge request idf/esp-idf!1290
This commit is contained in:
Ivan Grokhotkov 2018-11-15 15:05:43 +08:00
commit fb56ce7d5c
13 changed files with 1463 additions and 1252 deletions

View file

@ -272,8 +272,10 @@ config TRACEMEM_RESERVE_DRAM
default 0x4000 if MEMMAP_TRACEMEM && !MEMMAP_TRACEMEM_TWOBANKS default 0x4000 if MEMMAP_TRACEMEM && !MEMMAP_TRACEMEM_TWOBANKS
default 0x0 default 0x0
menu "Core dump"
choice ESP32_COREDUMP_TO_FLASH_OR_UART choice ESP32_COREDUMP_TO_FLASH_OR_UART
prompt "Core dump destination" prompt "Data destination"
default ESP32_ENABLE_COREDUMP_TO_NONE default ESP32_ENABLE_COREDUMP_TO_NONE
help help
Select place to store core dump: flash, uart or none (to disable core dumps generation). Select place to store core dump: flash, uart or none (to disable core dumps generation).
@ -298,20 +300,22 @@ config ESP32_ENABLE_COREDUMP
help help
Enables/disable core dump module. Enables/disable core dump module.
config ESP32_CORE_DUMP_MAX_TASKS_NUM
int "Maximum number of tasks"
depends on ESP32_ENABLE_COREDUMP
default 64
help
Maximum number of tasks snapshots in core dump.
config ESP32_CORE_DUMP_UART_DELAY config ESP32_CORE_DUMP_UART_DELAY
int "Core dump print to UART delay" int "Delay before print to UART"
depends on ESP32_ENABLE_COREDUMP_TO_UART depends on ESP32_ENABLE_COREDUMP_TO_UART
default 0 default 0
help help
Config delay (in ms) before printing core dump to UART. Config delay (in ms) before printing core dump to UART.
Delay can be interrupted by pressing Enter key. Delay can be interrupted by pressing Enter key.
config ESP32_CORE_DUMP_LOG_LEVEL endmenu
int "Core dump module logging level"
depends on ESP32_ENABLE_COREDUMP
default 1
help
Config core dump module logging level (0-5).
choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS
bool "Number of universally administered (by IEEE) MAC address" bool "Number of universally administered (by IEEE) MAC address"

View file

@ -24,12 +24,14 @@
#include "esp_panic.h" #include "esp_panic.h"
#include "esp_partition.h" #include "esp_partition.h"
#include "esp_clk.h" #include "esp_clk.h"
#include "esp_core_dump.h"
#include "esp_log.h"
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump";
typedef uint32_t core_dump_crc_t;
#if CONFIG_ESP32_ENABLE_COREDUMP #if CONFIG_ESP32_ENABLE_COREDUMP
#define LOG_LOCAL_LEVEL CONFIG_ESP32_CORE_DUMP_LOG_LEVEL
#include "esp_log.h"
const static DRAM_ATTR char TAG[] = "esp_core_dump";
#define ESP_COREDUMP_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { ets_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); } #define ESP_COREDUMP_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { ets_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); }
#define ESP_COREDUMP_LOGE( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__) #define ESP_COREDUMP_LOGE( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__)
#define ESP_COREDUMP_LOGW( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_WARN, LOG_FORMAT(W, format), ##__VA_ARGS__) #define ESP_COREDUMP_LOGW( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_WARN, LOG_FORMAT(W, format), ##__VA_ARGS__)
@ -43,9 +45,9 @@ const static DRAM_ATTR char TAG[] = "esp_core_dump";
#define ESP_COREDUMP_LOG_PROCESS( format, ... ) do{/*(__VA_ARGS__);*/}while(0) #define ESP_COREDUMP_LOG_PROCESS( format, ... ) do{/*(__VA_ARGS__);*/}while(0)
#endif #endif
// TODO: allow user to set this in menuconfig or get tasks iteratively
#define COREDUMP_MAX_TASKS_NUM 32
#define COREDUMP_MAX_TASK_STACK_SIZE (64*1024) #define COREDUMP_MAX_TASK_STACK_SIZE (64*1024)
#define COREDUMP_VERSION 1
typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len); typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len);
typedef esp_err_t (*esp_core_dump_write_start_t)(void *priv); typedef esp_err_t (*esp_core_dump_write_start_t)(void *priv);
@ -74,6 +76,7 @@ typedef struct _core_dump_write_config_t
typedef struct _core_dump_header_t typedef struct _core_dump_header_t
{ {
uint32_t data_len; // data length uint32_t data_len; // data length
uint32_t version; // core dump struct version
uint32_t tasks_num; // number of tasks uint32_t tasks_num; // number of tasks
uint32_t tcb_sz; // size of TCB uint32_t tcb_sz; // size of TCB
} core_dump_header_t; } core_dump_header_t;
@ -101,7 +104,7 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
{ {
int cur_task_bad = 0; int cur_task_bad = 0;
esp_err_t err; esp_err_t err;
TaskSnapshot_t tasks[COREDUMP_MAX_TASKS_NUM]; TaskSnapshot_t tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM];
UBaseType_t tcb_sz, tcb_sz_padded, task_num; UBaseType_t tcb_sz, tcb_sz_padded, task_num;
uint32_t data_len = 0, i, len; uint32_t data_len = 0, i, len;
union union
@ -110,7 +113,7 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
core_dump_task_header_t task_hdr; core_dump_task_header_t task_hdr;
} dump_data; } dump_data;
task_num = uxTaskGetSnapshotAll(tasks, COREDUMP_MAX_TASKS_NUM, &tcb_sz); task_num = uxTaskGetSnapshotAll(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM, &tcb_sz);
// take TCB padding into account, actual TCB size will be stored in header // take TCB padding into account, actual TCB size will be stored in header
if (tcb_sz % sizeof(uint32_t)) if (tcb_sz % sizeof(uint32_t))
tcb_sz_padded = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t); tcb_sz_padded = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t);
@ -143,9 +146,9 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
else { else {
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
XtExcFrame *task_frame2 = (XtExcFrame *)tasks[i].pxTopOfStack; XtExcFrame *task_frame2 = (XtExcFrame *)tasks[i].pxTopOfStack;
#endif
ESP_COREDUMP_LOG_PROCESS("Task EXIT/PC/PS/A0/SP %x %x %x %x %x", ESP_COREDUMP_LOG_PROCESS("Task EXIT/PC/PS/A0/SP %x %x %x %x %x",
task_frame2->exit, task_frame2->pc, task_frame2->ps, task_frame2->a0, task_frame2->a1); task_frame2->exit, task_frame2->pc, task_frame2->ps, task_frame2->a0, task_frame2->a1);
#endif
} }
} }
len = (uint32_t)tasks[i].pxEndOfStack - (uint32_t)tasks[i].pxTopOfStack; len = (uint32_t)tasks[i].pxEndOfStack - (uint32_t)tasks[i].pxTopOfStack;
@ -188,6 +191,7 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
} }
// write header // write header
dump_data.hdr.data_len = data_len; dump_data.hdr.data_len = data_len;
dump_data.hdr.version = COREDUMP_VERSION;
dump_data.hdr.tasks_num = task_num - write_cfg->bad_tasks_num; dump_data.hdr.tasks_num = task_num - write_cfg->bad_tasks_num;
dump_data.hdr.tcb_sz = tcb_sz; dump_data.hdr.tcb_sz = tcb_sz;
err = write_cfg->write(write_cfg->priv, &dump_data, sizeof(core_dump_header_t)); err = write_cfg->write(write_cfg->priv, &dump_data, sizeof(core_dump_header_t));
@ -248,13 +252,10 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
// magic numbers to control core dump data consistency
#define COREDUMP_FLASH_MAGIC_START 0xE32C04EDUL
#define COREDUMP_FLASH_MAGIC_END 0xE32C04EDUL
typedef struct _core_dump_write_flash_data_t typedef struct _core_dump_write_flash_data_t
{ {
uint32_t off; uint32_t off; // current offset in partition
core_dump_crc_t crc; // CRC of dumped data
} core_dump_write_flash_data_t; } core_dump_write_flash_data_t;
typedef struct _core_dump_partition_t typedef struct _core_dump_partition_t
@ -267,15 +268,20 @@ typedef struct _core_dump_partition_t
typedef struct _core_dump_flash_config_t typedef struct _core_dump_flash_config_t
{ {
// core dump partition start // core dump partition config
core_dump_partition_t partition; core_dump_partition_t partition;
// core dump partition size // CRC of core dump partition config
uint32_t crc; core_dump_crc_t partition_config_crc;
} core_dump_flash_config_t; } core_dump_flash_config_t;
// core dump flash data // core dump flash data
static core_dump_flash_config_t s_core_flash_config; static core_dump_flash_config_t s_core_flash_config;
static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
{
return crc32_le(0, (uint8_t const *)&s_core_flash_config.partition, sizeof(s_core_flash_config.partition));
}
static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint32_t data_size) static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint32_t data_size)
{ {
esp_err_t err; esp_err_t err;
@ -302,8 +308,9 @@ static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint
if (len) { if (len) {
// write last bytes with padding, actual TCB len can be retrieved by esptool from core dump header // write last bytes with padding, actual TCB len can be retrieved by esptool from core dump header
rom_data.data32 = 0; rom_data.data32 = 0;
for (k = 0; k < len; k++) for (k = 0; k < len; k++) {
rom_data.data8[k] = *(data + data_len + k); rom_data.data8[k] = *(data + data_len + k);
}
err = spi_flash_write(off + data_len, &rom_data, sizeof(uint32_t)); err = spi_flash_write(off + data_len, &rom_data, sizeof(uint32_t));
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to finish write data to flash (%d)!", err); ESP_COREDUMP_LOGE("Failed to finish write data to flash (%d)!", err);
@ -322,18 +329,19 @@ static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_le
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv; core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
// check for available space in partition // check for available space in partition
// add space for 2 magics. TODO: change to CRC if ((*data_len + sizeof(uint32_t)) > s_core_flash_config.partition.size) {
if ((*data_len + 2*sizeof(uint32_t)) > s_core_flash_config.partition.size) {
ESP_COREDUMP_LOGE("Not enough space to save core dump!"); ESP_COREDUMP_LOGE("Not enough space to save core dump!");
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
*data_len += 2*sizeof(uint32_t); // add space for CRC
*data_len += sizeof(core_dump_crc_t);
wr_data->off = 0; memset(wr_data, 0, sizeof(*wr_data));
sec_num = *data_len / SPI_FLASH_SEC_SIZE; sec_num = *data_len / SPI_FLASH_SEC_SIZE;
if (*data_len % SPI_FLASH_SEC_SIZE) if (*data_len % SPI_FLASH_SEC_SIZE) {
sec_num++; sec_num++;
}
assert(sec_num * SPI_FLASH_SEC_SIZE <= s_core_flash_config.partition.size); assert(sec_num * SPI_FLASH_SEC_SIZE <= s_core_flash_config.partition.size);
err = spi_flash_erase_range(s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE); err = spi_flash_erase_range(s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE);
if (err != ESP_OK) { if (err != ESP_OK) {
@ -362,9 +370,7 @@ static esp_err_t esp_core_dump_flash_write_word(core_dump_write_flash_data_t *wr
static esp_err_t esp_core_dump_flash_write_start(void *priv) static esp_err_t esp_core_dump_flash_write_start(void *priv)
{ {
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv; return ESP_OK;
// save magic 1
return esp_core_dump_flash_write_word(wr_data, COREDUMP_FLASH_MAGIC_START);
} }
static esp_err_t esp_core_dump_flash_write_end(void *priv) static esp_err_t esp_core_dump_flash_write_end(void *priv)
@ -381,17 +387,16 @@ static esp_err_t esp_core_dump_flash_write_end(void *priv)
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_COREDUMP_LOGE("Failed to read flash (%d)!", err); ESP_COREDUMP_LOGE("Failed to read flash (%d)!", err);
return err; return err;
} } else {
else {
ESP_COREDUMP_LOG_PROCESS("Data from flash:"); ESP_COREDUMP_LOG_PROCESS("Data from flash:");
for (uint32_t i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) { for (uint32_t i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) {
ESP_COREDUMP_LOG_PROCESS("%x", rom_data.data32[i]); ESP_COREDUMP_LOG_PROCESS("%x", rom_data.data32[i]);
} }
} }
#endif #endif
// write core dump CRC
// save magic 2 ESP_COREDUMP_LOG_PROCESS("Dump data CRC = 0x%x", wr_data->crc);
return esp_core_dump_flash_write_word(wr_data, COREDUMP_FLASH_MAGIC_END); return esp_core_dump_flash_write_word(wr_data, wr_data->crc);
} }
static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_t data_len) static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_t data_len)
@ -400,10 +405,12 @@ static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv; core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
uint32_t len = esp_core_dump_write_flash_padded(s_core_flash_config.partition.start + wr_data->off, data, data_len); uint32_t len = esp_core_dump_write_flash_padded(s_core_flash_config.partition.start + wr_data->off, data, data_len);
if (len != data_len) if (len != data_len) {
return ESP_FAIL; return ESP_FAIL;
}
wr_data->off += len; wr_data->off += len;
wr_data->crc = crc32_le(wr_data->crc, data, data_len);
return err; return err;
} }
@ -413,10 +420,14 @@ void esp_core_dump_to_flash(XtExcFrame *frame)
core_dump_write_config_t wr_cfg; core_dump_write_config_t wr_cfg;
core_dump_write_flash_data_t wr_data; core_dump_write_flash_data_t wr_data;
uint32_t crc = crc32_le(UINT32_MAX, (uint8_t const *)&s_core_flash_config.partition, core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc();
sizeof(s_core_flash_config.partition)); if (s_core_flash_config.partition_config_crc != crc) {
if (s_core_flash_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);
ESP_COREDUMP_LOGE("Core dump flash config is corrupted! CRC=0x%x instead of 0x%x", crc, s_core_flash_config.crc); return;
}
// check that partition can hold at least core dump 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; return;
} }
@ -500,10 +511,11 @@ static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t
static int esp_core_dump_uart_get_char() { static int esp_core_dump_uart_get_char() {
int i; int i;
uint32_t reg = (READ_PERI_REG(UART_STATUS_REG(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT; uint32_t reg = (READ_PERI_REG(UART_STATUS_REG(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
if (reg) if (reg) {
i = READ_PERI_REG(UART_FIFO_REG(0)); i = READ_PERI_REG(UART_FIFO_REG(0));
else } else {
i = -1; i = -1;
}
return i; return i;
} }
@ -532,8 +544,9 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
ch = esp_core_dump_uart_get_char(); ch = esp_core_dump_uart_get_char();
while (!(ch == '\n' || ch == '\r')) { while (!(ch == '\n' || ch == '\r')) {
tm_cur = xthal_get_ccount() / cpu_ticks_per_ms; tm_cur = xthal_get_ccount() / cpu_ticks_per_ms;
if (tm_cur >= tm_end) if (tm_cur >= tm_end){
break; break;
}
ch = esp_core_dump_uart_get_char(); ch = esp_core_dump_uart_get_char();
} }
ESP_COREDUMP_LOGI("Print core dump to uart..."); ESP_COREDUMP_LOGI("Print core dump to uart...");
@ -554,15 +567,66 @@ void esp_core_dump_init()
return; return;
} }
ESP_COREDUMP_LOGI("Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size); ESP_COREDUMP_LOGI("Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
s_core_flash_config.partition.start = core_part->address; s_core_flash_config.partition.start = core_part->address;
s_core_flash_config.partition.size = core_part->size; s_core_flash_config.partition.size = core_part->size;
s_core_flash_config.crc = crc32_le(UINT32_MAX, (uint8_t const *)&s_core_flash_config.partition, s_core_flash_config.partition_config_crc = esp_core_dump_calc_flash_config_crc();
sizeof(s_core_flash_config.partition));
#endif #endif
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
ESP_COREDUMP_LOGI("Init core dump to UART"); ESP_COREDUMP_LOGI("Init core dump to UART");
#endif #endif
} }
#endif esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
{
esp_err_t err;
const void *core_data;
spi_flash_mmap_handle_t core_data_handle;
if (out_addr == NULL || out_size == NULL) {
return ESP_ERR_INVALID_ARG;
}
const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
if (!core_part) {
ESP_LOGE(TAG, "No core dump partition found!");
return ESP_FAIL;
}
if (core_part->size < sizeof(uint32_t)) {
ESP_LOGE(TAG, "Too small core dump partition!");
return ESP_FAIL;
}
err = esp_partition_mmap(core_part, 0, sizeof(uint32_t),
SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
return err;
}
uint32_t *dw = (uint32_t *)core_data;
*out_size = *dw;
spi_flash_munmap(core_data_handle);
// remap full core dump with CRC
err = esp_partition_mmap(core_part, 0, *out_size,
SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
return err;
}
uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size);
crc--; // Point to CRC field
// Calc CRC over core dump data except for CRC field
core_dump_crc_t cur_crc = crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t));
if (*crc != cur_crc) {
ESP_LOGE(TAG, "Core dump data CRC check failed: 0x%x -> 0x%x!", *crc, cur_crc);
spi_flash_munmap(core_data_handle);
return ESP_FAIL;
}
spi_flash_munmap(core_data_handle);
*out_addr = core_part->address;
return ESP_OK;
}
#endif

View file

@ -382,6 +382,11 @@ void start_cpu0_default(void)
#if CONFIG_ESP32_ENABLE_COREDUMP #if CONFIG_ESP32_ENABLE_COREDUMP
esp_core_dump_init(); esp_core_dump_init();
size_t core_data_sz = 0;
size_t core_data_addr = 0;
if (esp_core_dump_image_get(&core_data_addr, &core_data_sz) == ESP_OK && core_data_sz > 0) {
ESP_LOGI(TAG, "Found core dump %d bytes in flash @ 0x%x", core_data_sz, core_data_addr);
}
#endif #endif
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",

View file

@ -14,6 +14,11 @@
#ifndef ESP_CORE_DUMP_H_ #ifndef ESP_CORE_DUMP_H_
#define ESP_CORE_DUMP_H_ #define ESP_CORE_DUMP_H_
/**************************************************************************************/
/******************************** EXCEPTION MODE API **********************************/
/**************************************************************************************/
/** /**
* @brief Initializes core dump module internal data. * @brief Initializes core dump module internal data.
* *
@ -25,29 +30,29 @@ void esp_core_dump_init();
* @brief Saves core dump to flash. * @brief Saves core dump to flash.
* *
* The structure of data stored in flash is as follows: * The structure of data stored in flash is as follows:
* | MAGIC1 | *
* | TOTAL_LEN | TASKS_NUM | TCB_SIZE | * | TOTAL_LEN | TASKS_NUM | TCB_SIZE |
* | TCB_ADDR_1 | STACK_TOP_1 | STACK_END_1 | TCB_1 | STACK_1 | * | 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 | * | TCB_ADDR_N | STACK_TOP_N | STACK_END_N | TCB_N | STACK_N |
* | MAGIC2 | * | CRC32 |
*
* Core dump in flash consists of header and data for every task in the system at the moment of crash. * Core dump in flash consists of header and data for every task in the system at the moment of crash.
* For flash data integrity control two magic numbers are used at the beginning and the end of core dump. * For flash data integrity control CRC is used at the end of core the dump data.
* The structure of core dump data is described below in details. * The structure of core dump data is described below in details.
* 1) MAGIC1 and MAGIC2 are special numbers stored at the beginning and the end of core dump. * 1) Core dump starts with header:
* They are used to control core dump data integrity. Size of every number is 4 bytes. * 1.1) TOTAL_LEN is total length of core dump data in flash including CRC. Size is 4 bytes.
* 2) Core dump starts with header: * 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes.
* 2.1) TOTAL_LEN is total length of core dump data in flash including magic numbers. Size is 4 bytes. * 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes.
* 2.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes. * 2) Core dump header is followed by the data for every task in the system.
* 2.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes.
* 3) Core dump header is followed by the data for every task in the system.
* Task data are started with task header: * Task data are started with task header:
* 3.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes. * 2.1) TCB_ADDR is the address of TCB in memory. Size is 4 bytes.
* 3.2) STACK_TOP is the top of task's stack (address of the topmost stack item). 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.
* 3.2) STACK_END is the end of task's stack (address from which task's stack starts). 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.
* 4) Task header is followed by TCB data. Size is TCB_SIZE bytes. * 3) Task header is followed by TCB data. Size is TCB_SIZE bytes.
* 5) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes. * 4) Task's stack is placed after TCB data. Size is (STACK_END - STACK_TOP) bytes.
* 5) CRC is placed at the end of the data.
*/ */
void esp_core_dump_to_flash(); void esp_core_dump_to_flash();
@ -55,10 +60,26 @@ void esp_core_dump_to_flash();
* @brief Print base64-encoded core dump to UART. * @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: * 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) Magic numbers are not present in core dump printed to UART. * 1) CRC is not present in core dump printed to UART.
* 2) Since magic numbers are omitted TOTAL_LEN does not include their size. * 2) Since CRC 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. * 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(); void esp_core_dump_to_uart();
/**************************************************************************************/
/*********************************** USER MODE API ************************************/
/**************************************************************************************/
/**
* @brief Retrieves address and size of coredump data in flash.
* This function is always available, even when core dump is disabled in menuconfig.
*
* @param out_addr pointer to store image address in flash.
* @param out_size pointer to store image size in flash (including CRC). In bytes.
*
* @return ESP_OK on success, otherwise \see esp_err_t
*/
esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size);
#endif #endif

View file

@ -24,6 +24,8 @@ import struct
import array import array
import errno import errno
import base64 import base64
import binascii
import logging
idf_path = os.getenv('IDF_PATH') idf_path = os.getenv('IDF_PATH')
if idf_path: if idf_path:
@ -35,7 +37,7 @@ except ImportError:
print("Esptool is not found! Set proper $IDF_PATH in environment.") print("Esptool is not found! Set proper $IDF_PATH in environment.")
sys.exit(2) sys.exit(2)
__version__ = "0.2-dev" __version__ = "0.3-dev"
if os.name == 'nt': if os.name == 'nt':
CLOSE_FDS = False CLOSE_FDS = False
@ -327,7 +329,7 @@ class ESPCoreDumpElfFile(esptool.ELFFile):
if len(section_header) == 0: if len(section_header) == 0:
raise ESPCoreDumpError("No section header found at offset %04x in ELF file." % section_header_offs) raise ESPCoreDumpError("No section header found at offset %04x in ELF file." % section_header_offs)
if len(section_header) % LEN_SEC_HEADER != 0: if len(section_header) % LEN_SEC_HEADER != 0:
print('WARNING: Unexpected ELF section header length %04x is not mod-%02x' % (len(section_header),LEN_SEC_HEADER)) logging.warning('Unexpected ELF section header length %04x is not mod-%02x' % (len(section_header),LEN_SEC_HEADER))
# walk through the section header and extract all sections # walk through the section header and extract all sections
section_header_offsets = range(0, len(section_header), LEN_SEC_HEADER) section_header_offsets = range(0, len(section_header), LEN_SEC_HEADER)
@ -343,7 +345,7 @@ class ESPCoreDumpElfFile(esptool.ELFFile):
raise ESPCoreDumpError("ELF file has no STRTAB section at shstrndx %d" % shstrndx) raise ESPCoreDumpError("ELF file has no STRTAB section at shstrndx %d" % shstrndx)
_,sec_type,_,_,sec_size,sec_offs = read_section_header(shstrndx * LEN_SEC_HEADER) _,sec_type,_,_,sec_size,sec_offs = read_section_header(shstrndx * LEN_SEC_HEADER)
if sec_type != esptool.ELFFile.SEC_TYPE_STRTAB: if sec_type != esptool.ELFFile.SEC_TYPE_STRTAB:
print('WARNING: ELF file has incorrect STRTAB section type 0x%02x' % sec_type) logging.warning('ELF file has incorrect STRTAB section type 0x%02x' % sec_type)
f.seek(sec_offs) f.seek(sec_offs)
string_table = f.read(sec_size) string_table = f.read(sec_size)
@ -370,7 +372,7 @@ class ESPCoreDumpElfFile(esptool.ELFFile):
if len(seg_table) == 0: if len(seg_table) == 0:
raise ESPCoreDumpError("No program header table found at offset %04x in ELF file." % seg_table_offs) raise ESPCoreDumpError("No program header table found at offset %04x in ELF file." % seg_table_offs)
if len(seg_table) % LEN_SEG_HEADER != 0: if len(seg_table) % LEN_SEG_HEADER != 0:
print('WARNING: Unexpected ELF program header table length %04x is not mod-%02x' % (len(seg_table),LEN_SEG_HEADER)) logging.warning('Unexpected ELF program header table length %04x is not mod-%02x' % (len(seg_table),LEN_SEG_HEADER))
# walk through the program segment table and extract all segments # walk through the program segment table and extract all segments
seg_table_offs = range(0, len(seg_table), LEN_SEG_HEADER) seg_table_offs = range(0, len(seg_table), LEN_SEG_HEADER)
@ -456,7 +458,8 @@ class ESPCoreDumpLoaderError(ESPCoreDumpError):
class ESPCoreDumpLoader(object): class ESPCoreDumpLoader(object):
"""Core dump loader base class """Core dump loader base class
""" """
ESP32_COREDUMP_HDR_FMT = '<3L' ESP32_COREDUMP_VESION = 1
ESP32_COREDUMP_HDR_FMT = '<4L'
ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT) ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT)
ESP32_COREDUMP_TSK_HDR_FMT = '<3L' ESP32_COREDUMP_TSK_HDR_FMT = '<3L'
ESP32_COREDUMP_TSK_HDR_SZ = struct.calcsize(ESP32_COREDUMP_TSK_HDR_FMT) ESP32_COREDUMP_TSK_HDR_SZ = struct.calcsize(ESP32_COREDUMP_TSK_HDR_FMT)
@ -564,7 +567,7 @@ class ESPCoreDumpLoader(object):
os.remove(fname) os.remove(fname)
except OSError as e: except OSError as e:
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
print("Warning failed to remove temp file '%s' (%d)!" % (fname, e.errno)) logging.warning("Failed to remove temp file '%s' (%d)!" % (fname, e.errno))
def cleanup(self): def cleanup(self):
"""Cleans up loader resources """Cleans up loader resources
@ -579,7 +582,9 @@ class ESPCoreDumpLoader(object):
""" """
core_off = off core_off = off
data = self.read_data(core_off, self.ESP32_COREDUMP_HDR_SZ) data = self.read_data(core_off, self.ESP32_COREDUMP_HDR_SZ)
tot_len,task_num,tcbsz = struct.unpack_from(self.ESP32_COREDUMP_HDR_FMT, data) tot_len,coredump_ver,task_num,tcbsz = struct.unpack_from(self.ESP32_COREDUMP_HDR_FMT, data)
if coredump_ver > self.ESP32_COREDUMP_VESION:
raise ESPCoreDumpLoaderError("Core dump version '%d' is not supported! Should be up to '%d'." % (coredump_ver, self.ESP32_COREDUMP_VESION))
tcbsz_aligned = tcbsz tcbsz_aligned = tcbsz
if tcbsz_aligned % 4: if tcbsz_aligned % 4:
tcbsz_aligned = 4*(old_div(tcbsz_aligned,4) + 1) tcbsz_aligned = 4*(old_div(tcbsz_aligned,4) + 1)
@ -601,16 +606,25 @@ class ESPCoreDumpLoader(object):
stack_len_aligned = 4*(old_div(stack_len_aligned,4) + 1) stack_len_aligned = 4*(old_div(stack_len_aligned,4) + 1)
core_off += self.ESP32_COREDUMP_TSK_HDR_SZ core_off += self.ESP32_COREDUMP_TSK_HDR_SZ
logging.info("Read TCB %d bytes @ 0x%x" % (tcbsz_aligned, tcb_addr))
data = self.read_data(core_off, tcbsz_aligned) data = self.read_data(core_off, tcbsz_aligned)
if tcbsz != tcbsz_aligned: try:
core_elf.add_program_segment(tcb_addr, data[:tcbsz - tcbsz_aligned], ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) if tcbsz != tcbsz_aligned:
else: core_elf.add_program_segment(tcb_addr, data[:tcbsz - tcbsz_aligned], ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
core_elf.add_program_segment(tcb_addr, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) else:
core_elf.add_program_segment(tcb_addr, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
except ESPCoreDumpError as e:
logging.warning("Skip TCB %d bytes @ 0x%x. (Reason: %s)" % (tcbsz_aligned, tcb_addr, e))
core_off += tcbsz_aligned core_off += tcbsz_aligned
logging.info("Read stack %d bytes @ 0x%x" % (stack_len_aligned, stack_base))
data = self.read_data(core_off, stack_len_aligned) data = self.read_data(core_off, stack_len_aligned)
if stack_len != stack_len_aligned: if stack_len != stack_len_aligned:
data = data[:stack_len - stack_len_aligned] data = data[:stack_len - stack_len_aligned]
core_elf.add_program_segment(stack_base, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) try:
core_elf.add_program_segment(stack_base, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
except ESPCoreDumpError as e:
logging.warning("Skip task's (%x) stack %d bytes @ 0x%x. (Reason: %s)" % (tcb_addr, stack_len_aligned, stack_base, e))
core_off += stack_len_aligned core_off += stack_len_aligned
try: try:
task_regs = self._get_registers_from_stack(data, stack_end > stack_top) task_regs = self._get_registers_from_stack(data, stack_end > stack_top)
@ -624,12 +638,18 @@ class ESPCoreDumpLoader(object):
notes += note notes += note
# add notes # add notes
core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0) try:
core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0)
except ESPCoreDumpError as e:
logging.warning("Skip NOTES segment %d bytes @ 0x%x. (Reason: %s)" % (len(notes), 0, e))
# add ROM text sections # add ROM text sections
if rom_elf: if rom_elf:
for ps in rom_elf.program_segments: for ps in rom_elf.program_segments:
if ps.flags & ESPCoreDumpSegment.PF_X: if ps.flags & ESPCoreDumpSegment.PF_X:
core_elf.add_program_segment(ps.addr, ps.data, ESPCoreDumpElfFile.PT_LOAD, ps.flags) try:
core_elf.add_program_segment(ps.addr, ps.data, ESPCoreDumpElfFile.PT_LOAD, ps.flags)
except ESPCoreDumpError as e:
logging.warning("Skip ROM segment %d bytes @ 0x%x. (Reason: %s)" % (len(ps.data), ps.addr, e))
core_elf.e_type = ESPCoreDumpElfFile.ET_CORE core_elf.e_type = ESPCoreDumpElfFile.ET_CORE
core_elf.e_machine = ESPCoreDumpElfFile.EM_XTENSA core_elf.e_machine = ESPCoreDumpElfFile.EM_XTENSA
@ -690,12 +710,10 @@ class ESPCoreDumpFileLoader(ESPCoreDumpLoader):
class ESPCoreDumpFlashLoader(ESPCoreDumpLoader): class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
"""Core dump flash loader class """Core dump flash loader class
""" """
ESP32_COREDUMP_FLASH_MAGIC_START = 0xE32C04ED ESP32_COREDUMP_FLASH_CRC_FMT = '<L'
ESP32_COREDUMP_FLASH_MAGIC_END = 0xE32C04ED ESP32_COREDUMP_FLASH_CRC_SZ = struct.calcsize(ESP32_COREDUMP_FLASH_CRC_FMT)
ESP32_COREDUMP_FLASH_MAGIC_FMT = '<L' ESP32_COREDUMP_FLASH_LEN_FMT = '<L'
ESP32_COREDUMP_FLASH_MAGIC_SZ = struct.calcsize(ESP32_COREDUMP_FLASH_MAGIC_FMT) ESP32_COREDUMP_FLASH_LEN_SZ = struct.calcsize(ESP32_COREDUMP_FLASH_LEN_FMT)
ESP32_COREDUMP_FLASH_HDR_FMT = '<4L'
ESP32_COREDUMP_FLASH_HDR_SZ = struct.calcsize(ESP32_COREDUMP_FLASH_HDR_FMT)
def __init__(self, off, tool_path=None, chip='esp32', port=None, baud=None): def __init__(self, off, tool_path=None, chip='esp32', port=None, baud=None):
"""Constructor for core dump flash loader """Constructor for core dump flash loader
@ -722,7 +740,7 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
tool_args.extend(['-p', self.port]) tool_args.extend(['-p', self.port])
if self.baud: if self.baud:
tool_args.extend(['-b', str(self.baud)]) tool_args.extend(['-b', str(self.baud)])
tool_args.extend(['read_flash', str(off), str(self.ESP32_COREDUMP_FLASH_HDR_SZ), '']) tool_args.extend(['read_flash', str(off), str(self.ESP32_COREDUMP_FLASH_LEN_SZ), ''])
self.fcore_name = None self.fcore_name = None
try: try:
@ -737,11 +755,11 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
tool_args[-2] = str(self. dump_sz) tool_args[-2] = str(self. dump_sz)
et_out = subprocess.check_output(tool_args) et_out = subprocess.check_output(tool_args)
print(et_out.decode('utf-8')) print(et_out.decode('utf-8'))
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print("esptool script execution failed with err %d" % e.returncode) logging.error("esptool script execution failed with err %d" % e.returncode)
print("Command ran: '%s'" % e.cmd) logging.info("Command ran: '%s'" % e.cmd)
print("Command out:") logging.info("Command out:")
print(e.output) logging.info(e.output)
if self.fcore_name: if self.fcore_name:
self.remove_tmp_file(self.fcore_name) self.remove_tmp_file(self.fcore_name)
raise e raise e
@ -750,26 +768,20 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
def _read_core_dump_length(self, f): def _read_core_dump_length(self, f):
"""Reads core dump length """Reads core dump length
""" """
data = f.read(4*4) data = f.read(self.ESP32_COREDUMP_FLASH_LEN_SZ)
mag1,tot_len,task_num,tcbsz = struct.unpack_from(self.ESP32_COREDUMP_FLASH_HDR_FMT, data) tot_len, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_LEN_FMT, data)
if mag1 != self.ESP32_COREDUMP_FLASH_MAGIC_START:
raise ESPCoreDumpLoaderError("Invalid start magic number!")
return tot_len return tot_len
def create_corefile(self, core_fname=None, rom_elf=None): def create_corefile(self, core_fname=None, rom_elf=None):
"""Checks flash coredump data integrity and creates ELF file """Checks flash coredump data integrity and creates ELF file
""" """
data = self.read_data(0, self.ESP32_COREDUMP_FLASH_MAGIC_SZ) data = self.read_data(self.dump_sz - self.ESP32_COREDUMP_FLASH_CRC_SZ, self.ESP32_COREDUMP_FLASH_CRC_SZ)
mag1, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_MAGIC_FMT, data) dump_crc, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_CRC_FMT, data)
if mag1 != self.ESP32_COREDUMP_FLASH_MAGIC_START: data = self.read_data(0, self.dump_sz - self.ESP32_COREDUMP_FLASH_CRC_SZ)
raise ESPCoreDumpLoaderError("Invalid start marker %x" % mag1) data_crc = binascii.crc32(data) & 0xffffffff
if dump_crc != data_crc:
data = self.read_data(self.dump_sz-self.ESP32_COREDUMP_FLASH_MAGIC_SZ, self.ESP32_COREDUMP_FLASH_MAGIC_SZ) raise ESPCoreDumpLoaderError("Invalid core dump CRC %x, should be %x" % (data_crc, dump_crc))
mag2, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_MAGIC_FMT, data) return super(ESPCoreDumpFlashLoader, self).create_corefile(core_fname)
if mag2 != self.ESP32_COREDUMP_FLASH_MAGIC_END:
raise ESPCoreDumpLoaderError("Invalid end marker %x" % mag2)
return super(ESPCoreDumpFlashLoader, self).create_corefile(core_fname, off=self.ESP32_COREDUMP_FLASH_MAGIC_SZ, rom_elf=rom_elf)
class GDBMIOutRecordHandler(object): class GDBMIOutRecordHandler(object):
@ -836,7 +848,7 @@ class GDBMIResultHandler(GDBMIOutRecordHandler):
if self.result_str.startswith(','): if self.result_str.startswith(','):
self.result_str = self.result_str[1:] self.result_str = self.result_str[1:]
else: else:
print("Invalid result format: '%s'" % ln) logging.error("Invalid result format: '%s'" % ln)
else: else:
self.result_str = '' self.result_str = ''
return True return True
@ -856,7 +868,7 @@ class GDBMIResultHandler(GDBMIOutRecordHandler):
return return
if self._parse_rc(ln, self.RC_EXIT): if self._parse_rc(ln, self.RC_EXIT):
return return
print("Unknown GDB/MI result: '%s'" % ln) logging.error("Unknown GDB/MI result: '%s'" % ln)
class GDBMIStreamConsoleHandler(GDBMIOutStreamHandler): class GDBMIStreamConsoleHandler(GDBMIOutStreamHandler):
@ -886,7 +898,7 @@ def dbg_corefile(args):
loader = ESPCoreDumpFlashLoader(args.off, port=args.port) loader = ESPCoreDumpFlashLoader(args.off, port=args.port)
core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf)
if not core_fname: if not core_fname:
print("Failed to create corefile!") logging.error("Failed to create corefile!")
loader.cleanup() loader.cleanup()
return return
else: else:
@ -895,7 +907,7 @@ def dbg_corefile(args):
loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64') loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64')
core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf)
if not core_fname: if not core_fname:
print("Failed to create corefile!") logging.error("Failed to create corefile!")
loader.cleanup() loader.cleanup()
return return
@ -964,12 +976,12 @@ def info_corefile(args):
p.stdin.write(bytearray("-interpreter-exec console \"%s\"\n" % gdb_cmd, encoding='utf-8')) p.stdin.write(bytearray("-interpreter-exec console \"%s\"\n" % gdb_cmd, encoding='utf-8'))
gdbmi_read2prompt(p.stdout, handlers) gdbmi_read2prompt(p.stdout, handlers)
if not handlers[GDBMIResultHandler.TAG].result_class or handlers[GDBMIResultHandler.TAG].result_class == GDBMIResultHandler.RC_EXIT: if not handlers[GDBMIResultHandler.TAG].result_class or handlers[GDBMIResultHandler.TAG].result_class == GDBMIResultHandler.RC_EXIT:
print("GDB exited (%s / %s)!" % (handlers[GDBMIResultHandler.TAG].result_class, handlers[GDBMIResultHandler.TAG].result_str)) logging.error("GDB exited (%s / %s)!" % (handlers[GDBMIResultHandler.TAG].result_class, handlers[GDBMIResultHandler.TAG].result_str))
p.wait() p.wait()
print("Problem occured! GDB exited, restart it.") logging.error("Problem occured! GDB exited, restart it.")
p = gdbmi_start(handlers, []) p = gdbmi_start(handlers, [])
elif handlers[GDBMIResultHandler.TAG].result_class != GDBMIResultHandler.RC_DONE: elif handlers[GDBMIResultHandler.TAG].result_class != GDBMIResultHandler.RC_DONE:
print("GDB/MI command failed (%s / %s)!" % (handlers[GDBMIResultHandler.TAG].result_class, handlers[GDBMIResultHandler.TAG].result_str)) logging.error("GDB/MI command failed (%s / %s)!" % (handlers[GDBMIResultHandler.TAG].result_class, handlers[GDBMIResultHandler.TAG].result_str))
return p return p
loader = None loader = None
@ -978,7 +990,7 @@ def info_corefile(args):
loader = ESPCoreDumpFlashLoader(args.off, port=args.port) loader = ESPCoreDumpFlashLoader(args.off, port=args.port)
core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf)
if not core_fname: if not core_fname:
print("Failed to create corefile!") logging.error("Failed to create corefile!")
loader.cleanup() loader.cleanup()
return return
else: else:
@ -987,7 +999,7 @@ def info_corefile(args):
loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64') loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64')
core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf)
if not core_fname: if not core_fname:
print("Failed to create corefile!") logging.error("Failed to create corefile!")
loader.cleanup() loader.cleanup()
return return
@ -1115,6 +1127,7 @@ def main():
parser_debug_coredump = subparsers.add_parser( parser_debug_coredump = subparsers.add_parser(
'dbg_corefile', 'dbg_corefile',
help='Starts GDB debugging session with specified corefile') help='Starts GDB debugging session with specified corefile')
parser_debug_coredump.add_argument('--debug', '-d', help='Log level (0..3)', type=int, default=2)
parser_debug_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb') parser_debug_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb')
parser_debug_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str) parser_debug_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str)
parser_debug_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), raw (raw) or base64-encoded (b64) binary', type=str, default='elf') parser_debug_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
@ -1126,6 +1139,7 @@ def main():
parser_info_coredump = subparsers.add_parser( parser_info_coredump = subparsers.add_parser(
'info_corefile', 'info_corefile',
help='Print core dump info from file') help='Print core dump info from file')
parser_info_coredump.add_argument('--debug', '-d', help='Log level (0..3)', type=int, default=0)
parser_info_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb') parser_info_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb')
parser_info_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str) parser_info_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str)
parser_info_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), raw (raw) or base64-encoded (b64) binary', type=str, default='elf') parser_info_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
@ -1141,6 +1155,21 @@ def main():
args = parser.parse_args() args = parser.parse_args()
log_level = logging.CRITICAL
if args.debug == 0:
log_level = logging.CRITICAL
elif args.debug == 1:
log_level = logging.ERROR
elif args.debug == 2:
log_level = logging.WARNING
elif args.debug == 3:
log_level = logging.INFO
else:
log_level = logging.DEBUG
# logging.warning('Watch out!') # will print a message to the console
# logging.info('I told you so') # will not print anything
logging.basicConfig(format='%(levelname)s:%(message)s', level=log_level)
print('espcoredump.py v%s' % __version__) print('espcoredump.py v%s' % __version__)
operation_func = globals()[args.operation] operation_func = globals()[args.operation]

View file

@ -1,158 +1,166 @@
lBoAAAkAAABkAQAA HBwAAAEAAAAJAAAAZAEAAA==
BD77PwB7+z/QfPs/ 9ID7P/B++z/sgPs/
cHv7P3B8+z9tAAAAPC37Pzwt+z8EPvs/NC37PxIAAAClpaWlpaWlpQQ++z8AAAAA QH/7P4CA+z9rAAAATC37P0wt+z/0gPs/RC37PxIAAACjT4txhJQrK/SA+z8AAAAA
BwAAANR0+z91bmFsaWduZWRfcHRyX3QAAQAAANB8+z8AAAAAIAgGAAcAAAAAAAAA BwAAAPB4+z91bmFsaWduZWRfcHRyX3QAAQAAAOyA+z8AAAAAIAgGAAcAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA= AAAAAAAAAAAAAAAAAAAAAADTDKk=
aDtAP20hDUAwBAYASCENgMB7+z8CAAAANjxAPwB8+z/06Po/AAAAAAAAAAAFAAAA HwAAAKkiDUAwBAYAhCINgLB/+z8CAAAAVi9AP/B/+z8U6fo/AAAAAAAAAAAFAAAA
rf///yAAAABsPvs/AQAAAIAAAAABAAAAAAAAAAAAAAAdAAAABQAAAP0UAEANFQBA rf///yAAAABcgfs/AQAAAIAAAAABAAAAAQAAAB8AAAAdAAAABQAAAP0UAEANFQBA
/////wEAAACAAAAAfCEIQIwP+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +P///wEAAACAAAAAoCEIQLAB+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAAAAABIIQ2A8Hv7PwEAAAD06Po/ AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAEAAACEIg2A4H/7PwEAAAAU6fo/
pycNgPB7+z8KAAAA9Oj6PwB8+z/06Po/AAAAAAAAAACQIQ2AIHz7PwoAAAABAAAA HygNgOB/+z8KAAAAFOn6P/B/+z8U6fo/AAAAAAAAAADMIg2AEID7PwoAAAABAAAA
kztAPx4AAAA1PEA/AQAAACMABgABAAAAIQAGAKA6+z8AAAAAUHz7PwAAAAAAAAAA sy5APx4AAABVL0A/AQAAAAAAAAAAd/s/QCINQAAAAABgTQiAQID7PwAAAAAAAAAA
AwAAAFB8+z8AAAAAAAAAAGwQ+z8EPvs/AAAAAAAAAAAAAAAAcHz7PwAAAAAAAAAA Y00IgECA+z8AAAAAAAAAAGgQ+z8BAAAAIQAGAPB2+z8AAAAAYID7P7QiDUAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHx8+z8AAAAA IwAGAPSA+z8AAAAAAAAAAAAAAACAgPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjID7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
/Fb7P5BV+z/0Vvs/
kFX7P5BW+z/ZclwZcFz7P7As+z/8Vvs/qCz7PxkAAADVIwJJEo189/xW+z8AAAAA
AAAAAPhS+z9JRExFMAAweiWIEpHwtvYAAAAAAPRW+z8AAAAAIAIGAAAAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAA8448=
2CEIQIZKDkAwAgYAuFcIgFBW+z8IAAAAAAAAAAEAAABoXPs/AAAAAAEAAACsK/s/
kCv7PwAAAAABAAAAAAAAAAEAAAAhAAYAIwgGAAAAAADcSwiAEFb7PwAAAAAAAAAA
AAAAANEjCEABAAAA6GQIQAHp+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAIQAGACMIBgAAAAAAcFb7PwAAAAAAAAAA
AQAAAGhc+z8AAAAAAQAAAAAAAACQVvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnFb7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA=
aFz7PwBb+z9gXPs/
AFv7PwBc+z9TsePnsCz7PwRX+z9oXPs/qCz7PxkAAACoWji9Rc4eO2hc+z8AAAAA
AAAAAGRY+z9JRExFMQBwjmCRXQvnOuwAAQAAAGBc+z8AAAAAIA4GAAAAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAACbsV8=
2CEIQIZKDkAwDgYAuFcIgMBb+z8IAAAAAQAAAAAAAAD8Vvs/AAAAAAEAAADMK/s/
kCv7PwAAAAABAACAAAAAAAEAAAAhAAYAAAAAAAAAAAAgAAYAAQAAAAAAAAAAAAAA
AAAAANEjCEABAAAA6GQIQBzv+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAIQAGAAAAAAAAAAAA4Fv7PwAAAAAAAAAA
AAAAAPxW+z8AAAAAAQAAAAAAAAAAXPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADFz7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAA==
nDz7P2Bz+z/MdPs/
YHP7P2B0+z/RAAAAnCz7P3Q/+z+cPPs/lCz7PxQAAAAkbPs/JGz7P5w8+z8AAAAA
BQAAANBs+z9iYWRfcHRyX3Rhc2sApaUA////f8x0+z8AAAAAIQAGAAUAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAClpaU=
2CEIQJ5VCEAwAgYAEyENgCB0+z/RAAAAAAAAAGwQ+z+cPPs/AAAAAAAAAACeVQiA
AHT7PwAAAADRAAAAIwAGAAEAAAAhAAYAcFv7PwAAAACkJw2A4HP7P/0UAEANFQBA
+f///9EjCEABAAAA6GQIQHwH+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAACMABgABAAAAIQAGAHBb+z8AAAAAQHT7PwAAAAAAAAAA
bBD7P5w8+z8AAAAAAAAAAAAAAABgdPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbHT7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
bD/7P3CD+z/UhPs/ 0Ff7PyBW+z/IV/s/
cIP7P3CE+z/RAAAApDz7P5ws+z9sP/s/lCz7Pw8AAAC4PPs/JGz7P2w/+z8AAAAA IFb7P2BX+z9IbutSRF/7P8As+z/QV/s/uCz7PxkAAACbAEY/rLGittBX+z8AAAAA
CgAAANh8+z9mYWlsZWRfYXNzZXJ0X3QAAAAAANSE+z8AAAAAIQAGAAoAAAAAAAAA AAAAAMxR+z9JRExFMADlCigSQ5E2PU0AAAAAAMhX+z8AAAAAIAAGAAAAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA= AAAAAAAAAAAAAAAAAAAAAADCNHc=
2CEIQJ5VCEAwAgYAoyANgDCE+z/RAAAAAAAAAGwQ+z9sP/s/AAAAAAAAAACeVQiA /CEIQKa/DUAwAgYAVhYNgOBW+z8AAAAAAQAAAAAAAAABAAAA4ADwPwEAAAA+Ew2A
EIT7PwAAAADRAAAAIwAGAAEAAAAhAAYAAAAAAAAAAACkJw2A8IP7P/0UAEANFQBA sFb7PwAAAAABAAAAX08IgGCI+z8DAAAAIwAGAAAAAABgK/s/OBMNQAAAAAAAAAAA
+P///9EjCEABAAAA6GQIQIwX+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA AAAAAPUjCEBgiPs/5GkIQJDY+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAACMABgABAAAAIQAGAAAAAAAAAAAAUIT7PwAAAAAAAAAA AQAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAADdXAiAAFf7PwgAAAAAAAAA
bBD7P2w/+z8AAAAAAAAAAAAAAABwhPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAEAAADgAPA/AQAAAGBNCIAgV/s/AAAAAAAAAAABAAAAAQAAACEABgAjBAYA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfIT7PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAEBX+z/UXAhAAAAAACMABgA8X/s/AAAAAAEAAAAAAAAAYFf7PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGxX+z8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA= AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
yGb7P0Bl+z/AZvs/ PF/7P5Bd+z80X/s/
QGX7P2Bm+z8AAAAAiCz7P4gs+z/IZvs/gCz7PxgAAAD8Xfs//F37P8hm+z/0Xfs/ kF37P9Be+z/fg6T1wCz7P9hX+z88X/s/uCz7PxkAAAC+waeWpT7XiDxf+z8AAAAA
AQAAAMRe+z9UbXIgU3ZjAFUPn9OBr6IAAAAAAMBm+z8AAAAAIQAGAAEAAAAAAAAA AAAAADhZ+z9JRExFMQDubL2eTufksFwAAQAAADRf+z8AAAAAIA4GAAAAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAADm+Zc= AAAAAAAAAAAAAAAAAAAAAACMeJk=
2CEIQJxiCEAwCAYAj2MIgABm+z+oLvs/AAAAAAEAAAAMUfs/AAAAAAEAAACcYgiA /CEIQKa/DUAwDgYAVhYNgFBe+z8AAAAAAQAAgAAAAAABAAAAAwAAACMABgA+Ew2A
4GX7PwAAAAAALPs/GF77PwAAAAAAAAAAAAAAAAAAAAClpaWlpaWlpQAAAAAAAAAA IF77PwAAAAAjCAYAIAgGAAEAAAAgCAYAIwAGAAAAAAAzEw2AAF77PwAAAAAAAAAA
AAAAANEjCEAAAAAA6GQIQHz5+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA AAAAAPUjCEABAAAA5GkIQADg+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMGb7PwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAF9PCICQNvs/AwAAACMABgDdXAiAcF77PwgAAAABAAAA
AAAAAAAAAAAAAAAAAAAAAHz5+j8AAAAAAAAAAAAAAAAAAAAAYGb7PwAAAAAAAAAA AAAAAAEAAAADAAAAIwAGAGBNCICQXvs/AAAAAAAAAAABAAAAAQAAACEABgAAAAAA
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAALBe+z/UXAhAAAAAACMABgDQV/s/AAAAAAEAAAAAAAAA0F77PwAAAAAAAAAA
AAAAAAAAAABsZvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANxe+z8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
iPr6PwD5+j+A+vo/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
APn6PyD6+j/akPlfPDv7P6D9+j+I+vo/JCz7PwMAAABc6vo/XOr6P4j6+j9U6vo/ iHf7PwB2+z+Ad/s/
FgAAAITq+j9lc3BfdGltZXIAH+HpXvQAAAAAAID6+j8AAAAAIQAGABYAAAAAAAAA AHb7PyB3+z/PAAAArCz7P2iK+z+Id/s/pCz7PxQAAAB0bvs/dG77P4h3+z8AAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA BQAAAIRv+z9iYWRfcHRyX3Rhc2sAciwA////f4B3+z8AAAAAIQAGAAUAAAAAAAAA
AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAACISzU= AAAAAAAAAAAAAAAAAAAAAAC6vHI=
2CEIQK1GCEAwAAYA+xQNgMD5+j8w6vo/AAAAAHjq+j8AAAAAAQAAAAEAAACtRgiA /CEIQMZaCEAwAgYATyINgMB2+z/PAAAAAAAAAGgQ+z8BAAAAIQAGACMIBgDGWgiA
oPn6PwAAAACcLvs/nC77PwEAAAAhAAYAAAAAAAAAAAClpaWlpaWlpQAAAAAAAAAA oHb7PwAAAADPAAAAIwAGAKg4+z8AAAAAAAAAAAAAAAAcKA2AgHb7P/0UAEANFQBA
AAAAANEjCEABAAAA6GQIQDyN+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +f////UjCECoOPs/5GkIQFD4+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPr6PwAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAACMABgCoOPs/AAAAAAAAAABgTQiA4Hb7PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA aBD7PwEAAAAhAAYAIwgGAAAAAAAAd/s/QCINQAAAAAAjAAYAiHf7PwAAAAAAAAAA
AAAAACD6+j8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAACB3+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAs+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAsd/s/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
NDv7P4A5+z8sO/s/ YIr7P9CI+z9Yivs/
gDn7P8A6+z/APAiILCz7P5D6+j80O/s/JCz7PwEAAAAs//o/LP/6PzQ7+z8k//o/ 0Ij7P/CJ+z/PAAAAkHf7P6ws+z9givs/pCz7Pw8AAACkd/s/dG77P2CK+z8AAAAA
GAAAADA3+z9pcGMxAMP571b2wMSsI4QAAQAAACw7+z8AAAAAIQAGABgAAAAAAAAA CgAAAFyC+z9mYWlsZWRfYXNzZXJ0X3QAAAAAAFiK+z8AAAAAIQAGAAoAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAADZjgQ= AAAAAAAAAAAAAAAAAAAAAACApb8=
2CEIQEoRCEAwAAYArUYIgEA6+z8BAAAAnC77P6Au+z+QfP4/AAAAACMHBgBKEQiA /CEIQMZaCEAwAgYA1yENgJCJ+z/PAAAAAAAAAGgQ+z8BAAAAIQAGAAAAAADGWgiA
IDr7P+AA8D8BAAAALBD7PwEAAAAgAAYAIwAGAAAAAABAOvs/AQAAAAAAAAAAAAAA cIn7PwAAAADPAAAA9QoNgIBP+z8ACAAAAQAAAAAAAAAcKA2AUIn7P/0UAEANFQBA
AAAAANEjCEABAAAA6GQIQNzN+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +P////UjCECAT/s/5GkIQCAL+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAACzEQiAYDr7PwD/+j8AAAAA AAAAAAAAAAAAAAAAAAAAAPUKDYCAT/s/AAgAAAEAAABgTQiAsIn7PwAAAAAAAAAA
AQAAAAEAAAAgAAYAIwAGAAAAAACgOvs/AQAAAPgvCEAAAAAACQAAAAAAAAAjBwYA aBD7PwEAAAAhAAYAAAAAAAAAAADQifs/yCENQAAAAAAjAAYAYIr7PwAAAAAAAAAA
/////6A6+z8BAAAA+C8IQEj/+j8AAAAAAQAAAAAAAAAAAAAAwDr7PwAAAAAAAAAA AAAAAPCJ+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AQAAAAAAAAAAAAAAAAAAACwPCICAff4/KAAAACgAAAAAAAAAAAAAAMw6+z8AAAAA AAAAAAAAAAD8ifs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
mP36P6A1+z8oN/s/
oDX7P8A2+z9UgfpzkPr6Pyws+z+Y/fo/JCz7PwEAAABw/fo/cP36P5j9+j9o/fo/
GAAAACwz+z9pcGMwAIY9HgrUf/61qBQAAAAAACg3+z8AAAAAIQAGABgAAAAAAAAA
AAAAAAAAAAAAAAAAjOj6P/To+j9c6fo/AAAAAAAAAAABAAAAAAAAAHg8QD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAADEsn4=
2CEIQK1GCEAwAAYAsxEIgGA2+z9E/fo/AAAAAIz9+j8AAAAAAQAAAAEAAACtRgiA
QDb7PwAAAACcLvs/nC77P/A6/j8AAAAAAgAAAAAAAAClpaWlpaWlpQAAAAAAAAAA
AAAAANEjCEDwOv4/6GQIQNzJ+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoDb7PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAMA2+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqDgiAoDv+Pwws+z/kLvs/
AAAAAAAAAADMNvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAA= AAAAAAAAAAA=
nGn7P9Bn+z+Uafs/
0Gf7PzBp+z8AAAAAmCz7P5gs+z+cafs/kCz7PxgAAADQYPs/0GD7P5xp+z/IYPs/
AQAAAJhh+z9UbXIgU3ZjAO3yYwslr9QAAAAAAJRp+z8AAAAAIQAGAAEAAAAAAAAA
AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAD/LIY=
/CEIQOobCEAwAgYAmGcIgJBo+z8AAAAAECz7P+xg+z8AAAAAAAAAACMABgDqGwiA
cGj7P9wA8D8BAAAAWBD7P6wu+z8DAAAAIwAGAAAAAACQaPs/AAAAAAAAAAAAAAAA
AAAAAPUjCECsLvs/5GkIQGDq+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLaAiAsGj7P7gu+z8AAAAA
AAAAAHxoCEAAAAAAAAAAAGBNCIDgaPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AQAAAAEAAAAhAAYAAAAAAAAAAAAQafs/fGgIQAAAAAABAAAAAAAAAAAAAAAAAAAA
IwAGAGRQ+z8AAAAAAQAAAAAAAAAwafs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGn7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA=
qPj6PwD3+j+g+Po/
APf6P0D4+j/Ae/kysDj7P0Qz+z+o+Po/NCz7PwMAAAB86vo/fOr6P6j4+j906vo/
FgAAAKTq+j9lc3BfdGltZXIACf0y2LkAAAAAAKD4+j8AAAAAIQAGABYAAAAAAAAA
AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAACndYo=
/CEIQO1LCEAwAAYAVw0NgMD3+j9Q6vo/AAAAAJjq+j8AAAAAAQAAAAAAAADtSwiA
oPf6PwAAAACsLvs/rC77P0D++j8DAAAAIw4GAAAAAAClpaWlpaWlpQAAAAAAAAAA
AAAAAPUjCEBA/vo/5GkIQHB5+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAABEDQ1AAAAAAAAAAABgTQiAAPj6PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACD4+j9EDQ1AAAAAACMABgCo+Po/AAAAAAEAAAAAAAAAQPj6PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEz4+j8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
qDj7P+A2+z+gOPs/
4Db7P0A4+z91SCX+PCz7P7D4+j+oOPs/NCz7PwEAAADM//o/zP/6P6g4+z/E//o/
GAAAAKQ0+z9pcGMxALIBlPDJy90p94EAAQAAAKA4+z8AAAAAIQAGABgAAAAAAAAA
AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAACbtaM=
/CEIQOobCEAwCAYA7UsIgKA3+z8BAAAArC77P7Au+z8KAAAAAACAABwA9D/qGwiA
gDf7P+AA8D8BAAAAWBD7PwEAAAAgCAYAIwAGAAAAAACgN/s/AQAAAAAAAAAAAAAA
AAAAAPUjCEABAAAA5GkIQHC5+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAAB3IAiAwDf7P6D/+j8AAAAA
AQAAAAEAAAAgCAYAIwAGAGBNCIAAOPs/AQAAAJQ2CEAAAAAABwAAAAAAgAAcAPQ/
/////wA4+z8BAAAAlDYIQOj/+j8AAAAAAQAAAAAAAAAAAAAAIDj7P0ggCEABAAAA
AQAAAKg4+z8AAAAAAAAAAAAAAABAOPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
oA8IgIB9/j8oAAAAKAAAAAAAAAAAAAAATDj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAA==
PDP7P/D9+j+Y//o/
8P36PzD/+j/93uTnsPj6Pzws+z88M/s/NCz7PwEAAAB0+/o/dPv6Pzwz+z9s+/o/
GAAAAJz7+j9pcGMwAAEM7FM1T1a8hf4AAAAAAJj/+j8AAAAAIQAGABgAAAAAAAAA
AAAAAAAAAAAAAAAArOj6PxTp+j986fo/AAAAAAAAAAABAAAAAAAAAFgvQD8AAAAA
SB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAACwrJk=
/CEIQO1LCEAwDgYAdyAIgLD++j9I+/o/AAAAAJD7+j8AAAAAAQAAAAIAAADtSwiA
kP76PwAAAACsLvs/rC77P83NAAABAAAAAAAAAAAAAAClpaWlpaWlpQAAAAAAAAAA
AAAAAPUjCEDNzQAA5GkIQGCA+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAABIIAhAAAAAAAAAAABgTQiA8P76PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAABD/+j9IIAhAAAAAACMDBgA8M/s/AQAAAAEAAAAAAAAAMP/6PwAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAB4PCICQO/4/HCz7P/Au+z8AAAAAAAAAADz/+j8AAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -300,7 +300,12 @@ extern void vPortCleanUpTCB ( void *pxTCB );
#define configXT_BOARD 1 /* Board mode */ #define configXT_BOARD 1 /* Board mode */
#define configXT_SIMULATOR 0 #define configXT_SIMULATOR 0
#define configENABLE_TASK_SNAPSHOT 1 #if CONFIG_ESP32_ENABLE_COREDUMP
#define configENABLE_TASK_SNAPSHOT 1
#endif
#ifndef configENABLE_TASK_SNAPSHOT
#define configENABLE_TASK_SNAPSHOT 1
#endif
#if CONFIG_SYSVIEW_ENABLE #if CONFIG_SYSVIEW_ENABLE
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__

View file

@ -69,19 +69,26 @@ static spi_flash_counters_t s_flash_stats;
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS #endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc); static esp_err_t spi_flash_translate_rc(esp_rom_spiflash_result_t rc);
static bool is_safe_write_address(size_t addr, size_t size);
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = { const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu, .start = spi_flash_disable_interrupts_caches_and_other_cpu,
.end = spi_flash_enable_interrupts_caches_and_other_cpu, .end = spi_flash_enable_interrupts_caches_and_other_cpu,
.op_lock = spi_flash_op_lock, .op_lock = spi_flash_op_lock,
.op_unlock = spi_flash_op_unlock .op_unlock = spi_flash_op_unlock,
#if !CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED
.is_safe_write_address = is_safe_write_address
#endif
}; };
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = { const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_no_os_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os, .start = spi_flash_disable_interrupts_caches_and_other_cpu_no_os,
.end = spi_flash_enable_interrupts_caches_no_os, .end = spi_flash_enable_interrupts_caches_no_os,
.op_lock = 0, .op_lock = 0,
.op_unlock = 0 .op_unlock = 0,
#if !CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED
.is_safe_write_address = 0
#endif
}; };
static const spi_flash_guard_funcs_t *s_flash_guard_ops; static const spi_flash_guard_funcs_t *s_flash_guard_ops;
@ -100,7 +107,7 @@ static const spi_flash_guard_funcs_t *s_flash_guard_ops;
#define CHECK_WRITE_ADDRESS(ADDR, SIZE) #define CHECK_WRITE_ADDRESS(ADDR, SIZE)
#else /* FAILS or ABORTS */ #else /* FAILS or ABORTS */
#define CHECK_WRITE_ADDRESS(ADDR, SIZE) do { \ #define CHECK_WRITE_ADDRESS(ADDR, SIZE) do { \
if (!is_safe_write_address(ADDR, SIZE)) { \ if (s_flash_guard_ops && s_flash_guard_ops->is_safe_write_address && !s_flash_guard_ops->is_safe_write_address(ADDR, SIZE)) { \
return ESP_ERR_INVALID_ARG; \ return ESP_ERR_INVALID_ARG; \
} \ } \
} while(0) } while(0)

View file

@ -313,6 +313,10 @@ typedef void (*spi_flash_op_lock_func_t)(void);
* @brief SPI flash operation unlock function. * @brief SPI flash operation unlock function.
*/ */
typedef void (*spi_flash_op_unlock_func_t)(void); typedef void (*spi_flash_op_unlock_func_t)(void);
/**
* @brief Function to protect SPI flash critical regions corruption.
*/
typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
/** /**
* Structure holding SPI flash access critical sections management functions. * Structure holding SPI flash access critical sections management functions.
@ -332,6 +336,9 @@ typedef void (*spi_flash_op_unlock_func_t)(void);
* - 'op_unlock' unlocks access to flash API internal data. * - 'op_unlock' unlocks access to flash API internal data.
* These two functions are recursive and can be used around the outside of multiple calls to * These two functions are recursive and can be used around the outside of multiple calls to
* 'start' & 'end', in order to create atomic multi-part flash operations. * 'start' & 'end', in order to create atomic multi-part flash operations.
* 3) When CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is disabled, flash writing/erasing
* API checks for addresses provided by user to avoid corruption of critical flash regions
* (bootloader, partition table, running application etc.).
* *
* Different versions of the guarding functions should be used depending on the context of * Different versions of the guarding functions should be used depending on the context of
* execution (with or without functional OS). In normal conditions when flash API is called * execution (with or without functional OS). In normal conditions when flash API is called
@ -343,10 +350,13 @@ typedef void (*spi_flash_op_unlock_func_t)(void);
* For example structure can be placed in DRAM and functions in IRAM sections. * For example structure can be placed in DRAM and functions in IRAM sections.
*/ */
typedef struct { typedef struct {
spi_flash_guard_start_func_t start; /**< critical section start function. */ spi_flash_guard_start_func_t start; /**< critical section start function. */
spi_flash_guard_end_func_t end; /**< critical section end function. */ spi_flash_guard_end_func_t end; /**< critical section end function. */
spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/ spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/
spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/ spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/
#if !CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED
spi_flash_is_safe_write_address_t is_safe_write_address; /**< checks flash write addresses.*/
#endif
} spi_flash_guard_funcs_t; } spi_flash_guard_funcs_t;
/** /**
@ -359,7 +369,6 @@ typedef struct {
*/ */
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs); void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
/** /**
* @brief Get the guard functions used for flash access * @brief Get the guard functions used for flash access
* *

View file

@ -18,15 +18,15 @@ Configuration
There are a number of core dump related configuration options which user can choose in configuration menu of the application (`make menuconfig`). There are a number of core dump related configuration options which user can choose in configuration menu of the application (`make menuconfig`).
1. Core dump data destination (`Components -> ESP32-specific config -> Core dump destination`): 1. Core dump data destination (`Components -> ESP32-specific config -> Core dump -> Data destination`):
* Disable core dump generation * Disable core dump generation
* Save core dump to flash * Save core dump to flash
* Print core dump to UART * Print core dump to UART
2. Logging level of core dump module (`Components -> ESP32-specific config -> Core dump module logging level`). Value is a number from 0 (no output) to 5 (most verbose). 2. Maximum number of tasks snapshots in core dump (`Components -> ESP32-specific config -> Core dump -> Maximum number of tasks`).
3. Delay before core dump will be printed to UART (`Components -> ESP32-specific config -> Core dump print to UART delay`). Value is in ms. 3. Delay before core dump is printed to UART (`Components -> ESP32-specific config -> Core dump -> Delay before print to UART`). Value is in ms.
Save core dump to flash Save core dump to flash
@ -89,6 +89,7 @@ Generic command syntax:
* info_corefile. Retrieve core dump and print useful info. * info_corefile. Retrieve core dump and print useful info.
* dbg_corefile. Retrieve core dump and start GDB session with it. * dbg_corefile. Retrieve core dump and start GDB session with it.
:Command Arguments: :Command Arguments:
* --debug,-d DEBUG. Log level (0..3).
* --gdb,-g GDB. Path to gdb to use for data retrieval. * --gdb,-g GDB. Path to gdb to use for data retrieval.
* --core,-c CORE. Path to core dump file to use (if skipped core dump will be read from flash). * --core,-c CORE. Path to core dump file to use (if skipped core dump will be read from flash).
* --core-format,-t CORE_FORMAT. Specifies that file passed with "-c" is an ELF ("elf"), dumped raw binary ("raw") or base64-encoded ("b64") format. * --core-format,-t CORE_FORMAT. Specifies that file passed with "-c" is an ELF ("elf"), dumped raw binary ("raw") or base64-encoded ("b64") format.