Merge branch 'feature/core_dump_crc' into 'master'
Core Dump CRC See merge request idf/esp-idf!1290
This commit is contained in:
commit
fb56ce7d5c
13 changed files with 1463 additions and 1252 deletions
|
@ -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"
|
||||||
|
|
|
@ -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...");
|
||||||
|
@ -556,13 +569,64 @@ void esp_core_dump_init()
|
||||||
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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
try:
|
||||||
if tcbsz != tcbsz_aligned:
|
if tcbsz != tcbsz_aligned:
|
||||||
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[:tcbsz - tcbsz_aligned], ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
|
||||||
else:
|
else:
|
||||||
core_elf.add_program_segment(tcb_addr, data, 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)
|
||||||
|
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]
|
||||||
|
try:
|
||||||
core_elf.add_program_segment(stack_base, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
|
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
|
||||||
|
try:
|
||||||
core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0)
|
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:
|
||||||
|
try:
|
||||||
core_elf.add_program_segment(ps.addr, ps.data, ESPCoreDumpElfFile.PT_LOAD, ps.flags)
|
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:
|
||||||
|
@ -738,10 +756,10 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
|
||||||
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]
|
||||||
|
|
|
@ -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.
|
@ -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
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||||
#define configENABLE_TASK_SNAPSHOT 1
|
#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__
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
@ -347,6 +354,9 @@ typedef struct {
|
||||||
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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue