esp32: Fixes several issues in core dump feature

1) PS is fixed up to allow GDB backtrace to work properly
2) MR!341 discussion: in core dump module: esp_panicPutXXX was replaced by ets_printf.
3) MR!341 discussion: core dump flash magic number was changed.
4) MR!341 discussion: SPI flash access API was redesigned to allow flexible critical section management.
5) test app for core dump feature was added
6) fixed base64 file reading issues on Windows platform
7) now raw bin core file is deleted upon core loader failure by epscoredump.py
This commit is contained in:
Alexey Gerenkov 2017-01-03 22:01:40 +03:00
parent 23f836659d
commit 39ddc7b836
10 changed files with 241 additions and 563 deletions

View file

@ -15,7 +15,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
//#include "esp_attr.h"
#include "esp_panic.h"
#include "esp_partition.h"
@ -26,10 +25,10 @@ const static char *TAG = "esp_core_dump";
// TODO: allow user to set this in menuconfig or get tasks iteratively
#define COREDUMP_MAX_TASKS_NUM 32
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_end_t)(void *priv);
typedef esp_err_t (*esp_core_dump_flash_write_data_t)(void *priv, void * data, uint32_t data_len);
typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len, int verb);
typedef esp_err_t (*esp_core_dump_write_start_t)(void *priv, int verb);
typedef esp_err_t (*esp_core_dump_write_end_t)(void *priv, int verb);
typedef esp_err_t (*esp_core_dump_flash_write_data_t)(void *priv, void * data, uint32_t data_len, int verb);
typedef struct _core_dump_write_config_t
{
@ -67,14 +66,19 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
if (tasks[i].pxTCB == xTaskGetCurrentTaskHandle()) {
// set correct stack top for current task
tasks[i].pxTopOfStack = (StackType_t *)frame;
if (verb)
ets_printf("Current task EXIT/PC/PS/A0/SP %x %x %x %x %x\r\n", frame->exit, frame->pc, frame->ps, frame->a0, frame->a1);
}
else {
if (verb) {
esp_panicPutStr("Current task PC/A0/SP ");
esp_panicPutHex(frame->pc);
esp_panicPutStr(" ");
esp_panicPutHex(frame->a0);
esp_panicPutStr(" ");
esp_panicPutHex(frame->a1);
esp_panicPutStr("\r\n");
XtSolFrame *task_frame = (XtSolFrame *)tasks[i].pxTopOfStack;
if (task_frame->exit == 0) {
ets_printf("Task EXIT/PC/PS/A0/SP %x %x %x %x %x\r\n", task_frame->exit, task_frame->pc, task_frame->ps, task_frame->a0, task_frame->a1);
}
else {
XtExcFrame *task_frame2 = (XtExcFrame *)tasks[i].pxTopOfStack;
ets_printf("Task EXIT/PC/PS/A0/SP %x %x %x %x %x\r\n", task_frame2->exit, task_frame2->pc, task_frame2->ps, task_frame2->a0, task_frame2->a1);
}
}
}
#if( portSTACK_GROWTH < 0 )
@ -83,13 +87,7 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
len = (uint32_t)tasks[i].pxTopOfStack - (uint32_t)tasks[i].pxEndOfStack;
#endif
if (verb) {
esp_panicPutStr("stack len = ");
esp_panicPutHex(len);
esp_panicPutStr(" ");
esp_panicPutHex((int)tasks[i].pxTopOfStack);
esp_panicPutStr(" ");
esp_panicPutHex((int)tasks[i].pxEndOfStack);
esp_panicPutStr("\r\n");
ets_printf("Stack len = %lu (%x %x)\r\n", len, tasks[i].pxTopOfStack, tasks[i].pxEndOfStack);
}
// take stack padding into account
if (len % sizeof(uint32_t))
@ -99,28 +97,22 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
// prepare write
if (write_cfg->prepare) {
err = write_cfg->prepare(write_cfg->priv, &data_len);
err = write_cfg->prepare(write_cfg->priv, &data_len, verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to prepare core dump ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to prepare core dump (%d)!\r\n", err);
return;
}
}
if (verb) {
esp_panicPutStr("Core dump len =");
esp_panicPutHex(data_len);
esp_panicPutStr("\r\n");
ets_printf("Core dump len = %lu\r\n", data_len);
}
// write start marker
// write start
if (write_cfg->start) {
err = write_cfg->start(write_cfg->priv);
err = write_cfg->start(write_cfg->priv, verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to start core dump ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to start core dump (%d)!\r\n", err);
return;
}
}
@ -129,49 +121,33 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
rom_data.data32[0] = data_len;
rom_data.data32[1] = task_num;
rom_data.data32[2] = tcb_sz;
err = write_cfg->write(write_cfg->priv, &rom_data, 3*sizeof(uint32_t));
err = write_cfg->write(write_cfg->priv, &rom_data, 3*sizeof(uint32_t), verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write core dump header ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to write core dump header (%d)!\r\n", err);
return;
}
// write tasks
for (i = 0; i < task_num; i++) {
if (verb) {
esp_panicPutStr("Dump task ");
esp_panicPutHex((int)tasks[i].pxTCB);
esp_panicPutStr("\r\n");
ets_printf("Dump task %x\r\n", tasks[i].pxTCB);
}
// save TCB address, stack base and stack top addr
rom_data.data32[0] = (uint32_t)tasks[i].pxTCB;
rom_data.data32[1] = (uint32_t)tasks[i].pxTopOfStack;
rom_data.data32[2] = (uint32_t)tasks[i].pxEndOfStack;
err = write_cfg->write(write_cfg->priv, &rom_data, 3*sizeof(uint32_t));
err = write_cfg->write(write_cfg->priv, &rom_data, 3*sizeof(uint32_t), verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write task header ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to write task header (%d)!\r\n", err);
return;
}
// save TCB
err = write_cfg->write(write_cfg->priv, tasks[i].pxTCB, tcb_sz);
err = write_cfg->write(write_cfg->priv, tasks[i].pxTCB, tcb_sz, verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write task header ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to write TCB (%d)!\r\n", err);
return;
}
// save task stack
/*int k;
for (k = 0; k < 8*4; k++) {
esp_panicPutStr("stack[");
esp_panicPutDec(k);
esp_panicPutStr("] = ");
esp_panicPutHex(((uint8_t *)tasks[i].pxTopOfStack)[k]);
esp_panicPutStr("\r\n");
}*/
err = write_cfg->write(write_cfg->priv,
#if( portSTACK_GROWTH < 0 )
tasks[i].pxTopOfStack,
@ -180,22 +156,18 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
tasks[i].pxEndOfStack,
(uint32_t)tasks[i].pxTopOfStack - (uint32_t)tasks[i].pxEndOfStack
#endif
);
, verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write task header ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to write task stack (%d)!\r\n", err);
return;
}
}
// write end marker
// write end
if (write_cfg->end) {
err = write_cfg->end(write_cfg->priv);
err = write_cfg->end(write_cfg->priv, verb);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to end core dump ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to end core dump (%d)!\r\n", err);
return;
}
}
@ -204,8 +176,8 @@ static void esp_core_dump_write(XtExcFrame *frame, core_dump_write_config_t *wri
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
// magic numbers to control core dump data consistency
#define COREDUMP_FLASH_MAGIC_START 0xDEADBEEFUL
#define COREDUMP_FLASH_MAGIC_END 0xACDCFEEDUL
#define COREDUMP_FLASH_MAGIC_START 0xE32C04EDUL
#define COREDUMP_FLASH_MAGIC_END 0xE32C04EDUL
typedef struct _core_dump_write_flash_data_t
{
@ -228,11 +200,9 @@ static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint
} rom_data;
data_len = (data_size / sizeof(uint32_t)) * sizeof(uint32_t);
err = spi_flash_write_panic(off, data, data_len);
err = spi_flash_write(off, data, data_len);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write data");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to write data to flash (%d)!\r\n", err);
return 0;
}
@ -242,11 +212,9 @@ static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint
rom_data.data32 = 0;
for (k = 0; k < len; k++)
rom_data.data8[k] = *(data + data_len + k);
err = spi_flash_write_panic(off + data_len, &rom_data, sizeof(uint32_t));
err = spi_flash_write(off + data_len, &rom_data, sizeof(uint32_t));
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write data end");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to finish write data to flash (%d)!\r\n", err);
return 0;
}
data_len += sizeof(uint32_t);
@ -255,37 +223,27 @@ static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint
return data_len;
}
static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_len)
static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_len, int verb)
{
esp_err_t err;
uint32_t sec_num;
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
esp_panicPutStr("Core dump len1 = ");
esp_panicPutHex(*data_len);
esp_panicPutStr("\r\n");
// add space for 2 magics. TODO: change to CRC
*data_len += 2*sizeof(uint32_t);
if (*data_len > s_core_part_size) {
esp_panicPutStr("ERROR: Not enough space to save core dump!");
if ((*data_len + 2*sizeof(uint32_t)) > s_core_part_size) {
ets_printf("ERROR: Not enough space to save core dump!\r\n");
return ESP_ERR_NO_MEM;
}
esp_panicPutStr("Core dump len2 = ");
esp_panicPutHex(*data_len);
esp_panicPutStr("\r\n");
*data_len += 2*sizeof(uint32_t);
wr_data->off = 0;
sec_num = *data_len / SPI_FLASH_SEC_SIZE;
if (*data_len % SPI_FLASH_SEC_SIZE)
sec_num++;
err = spi_flash_erase_range_panic(s_core_part_start + 0, sec_num * SPI_FLASH_SEC_SIZE);
err = spi_flash_erase_range(s_core_part_start + 0, sec_num * SPI_FLASH_SEC_SIZE);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to erase flash ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to erase flash (%d)!\r\n", err);
return err;
}
@ -297,11 +255,9 @@ static esp_err_t esp_core_dump_flash_write_word(core_dump_write_flash_data_t *wr
esp_err_t err = ESP_OK;
uint32_t data32 = word;
err = spi_flash_write_panic(s_core_part_start + wr_data->off, &data32, sizeof(uint32_t));
err = spi_flash_write(s_core_part_start + wr_data->off, &data32, sizeof(uint32_t));
if (err != ESP_OK) {
esp_panicPutStr("Failed to write to flash ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
ets_printf("ERROR: Failed to write to flash (%d)!\r\n", err);
return err;
}
wr_data->off += sizeof(uint32_t);
@ -309,14 +265,14 @@ static esp_err_t esp_core_dump_flash_write_word(core_dump_write_flash_data_t *wr
return err;
}
static esp_err_t esp_core_dump_flash_write_start(void *priv)
static esp_err_t esp_core_dump_flash_write_start(void *priv, int verb)
{
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
// 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, int verb)
{
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
uint32_t i;
@ -326,31 +282,27 @@ static esp_err_t esp_core_dump_flash_write_end(void *priv)
uint32_t data32[4];
} rom_data;
// TEST READ START
esp_err_t err = spi_flash_read_panic(s_core_part_start + 0, &rom_data, sizeof(rom_data));
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to read flash ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
return err;
}
else {
esp_panicPutStr("Data from flash:\r\n");
for (i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) {
esp_panicPutHex(rom_data.data32[i]);
esp_panicPutStr("\r\n");
if (verb) {
// TEST READ START
esp_err_t err = spi_flash_read(s_core_part_start + 0, &rom_data, sizeof(rom_data));
if (err != ESP_OK) {
ets_printf("ERROR: Failed to read flash (%d)!\r\n", err);
return err;
}
// rom_data[4] = 0;
// esp_panicPutStr(rom_data);
// esp_panicPutStr("\r\n");
else {
ets_printf("Data from flash:\r\n");
for (i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) {
ets_printf("%x\r\n", rom_data.data32[i]);
}
}
// TEST READ END
}
// TEST READ END
// save magic 2
return esp_core_dump_flash_write_word(wr_data, COREDUMP_FLASH_MAGIC_END);
}
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, int verb)
{
esp_err_t err = ESP_OK;
core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
@ -375,223 +327,25 @@ static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_
*/
void esp_core_dump_to_flash(XtExcFrame *frame)
{
#if 1
core_dump_write_config_t wr_cfg;
core_dump_write_flash_data_t wr_data;
/* init non-OS flash access critical section */
spi_flash_guard_set(&g_flash_guard_no_os_ops);
wr_cfg.prepare = esp_core_dump_flash_write_prepare;
wr_cfg.start = esp_core_dump_flash_write_start;
wr_cfg.end = esp_core_dump_flash_write_end;
wr_cfg.write = esp_core_dump_flash_write_data;
wr_cfg.priv = &wr_data;
esp_panicPutStr("Save core dump to flash...\r\n");
esp_core_dump_write(frame, &wr_cfg, 1);
#else
union
{
uint8_t data8[16];
uint32_t data32[4];
} rom_data;
//const esp_partition_t *core_part;
esp_err_t err;
TaskSnapshot_t tasks[COREDUMP_MAX_TASKS_NUM];
UBaseType_t tcb_sz, task_num;
uint32_t data_len = 0, i, len, sec_num;
size_t off;
esp_panicPutStr("Save core dump to flash...\r\n");
task_num = uxTaskGetSnapshotAll(tasks, COREDUMP_MAX_TASKS_NUM, &tcb_sz);
// take TCB padding into account, actual TCB size will be stored in header
if (tcb_sz % sizeof(uint32_t))
len = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t);
else
len = tcb_sz;
// header + magic2 + tasknum*(tcb + stack start/end + tcb addr)
data_len = 5*sizeof(uint32_t) + task_num*(len + 2*sizeof(uint32_t) + sizeof(uint32_t *));
for (i = 0; i < task_num; i++) {
if (tasks[i].pxTCB == xTaskGetCurrentTaskHandle()) {
// set correct stack top for current task
tasks[i].pxTopOfStack = (StackType_t *)frame;
esp_panicPutStr("Current task PC/A0/SP ");
esp_panicPutHex(frame->pc);
esp_panicPutStr(" ");
esp_panicPutHex(frame->a0);
esp_panicPutStr(" ");
esp_panicPutHex(frame->a1);
esp_panicPutStr("\r\n");
}
#if( portSTACK_GROWTH < 0 )
len = (uint32_t)tasks[i].pxEndOfStack - (uint32_t)tasks[i].pxTopOfStack;
#else
len = (uint32_t)tasks[i].pxTopOfStack - (uint32_t)tasks[i].pxEndOfStack;
#endif
esp_panicPutStr("stack len = ");
esp_panicPutHex(len);
esp_panicPutStr(" ");
esp_panicPutHex((int)tasks[i].pxTopOfStack);
esp_panicPutStr(" ");
esp_panicPutHex((int)tasks[i].pxEndOfStack);
esp_panicPutStr("\r\n");
// take stack padding into account
if (len % sizeof(uint32_t))
len = (len / sizeof(uint32_t) + 1) * sizeof(uint32_t);
data_len += len;
}
esp_panicPutStr("Core dump len =");
esp_panicPutHex(data_len);
esp_panicPutStr("\r\n");
if (data_len > s_core_part_size) {
esp_panicPutStr("ERROR: Not enough space to save core dump!");
return;
}
// TEST READ START
err = spi_flash_read_panic(s_core_part_start + 0, &rom_data, sizeof(rom_data));
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to read flash ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
return;
}
else {
esp_panicPutStr("Data from flash:\r\n");
for (i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) {
esp_panicPutHex(rom_data.data32[i]);
esp_panicPutStr("\r\n");
}
// rom_data[4] = 0;
// esp_panicPutStr(rom_data);
// esp_panicPutStr("\r\n");
}
// TEST READ END
sec_num = data_len / SPI_FLASH_SEC_SIZE;
if (data_len % SPI_FLASH_SEC_SIZE)
sec_num++;
err = spi_flash_erase_range_panic(s_core_part_start + 0, sec_num * SPI_FLASH_SEC_SIZE);
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to erase flash ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
return;
}
rom_data.data32[0] = COREDUMP_FLASH_MAGIC_START;
rom_data.data32[1] = data_len;
rom_data.data32[2] = task_num;
rom_data.data32[3] = tcb_sz;
err = spi_flash_write_panic(s_core_part_start + 0, &rom_data, sizeof(rom_data));
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write core dump header ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
return;
}
off = sizeof(rom_data);
for (i = 0; i < task_num; i++) {
esp_panicPutStr("Dump task ");
esp_panicPutHex((int)tasks[i].pxTCB);
esp_panicPutStr("\r\n");
// save TCB address, stack base and stack top addr
rom_data.data32[0] = (uint32_t)tasks[i].pxTCB;
rom_data.data32[1] = (uint32_t)tasks[i].pxTopOfStack;
rom_data.data32[2] = (uint32_t)tasks[i].pxEndOfStack;
err = spi_flash_write_panic(s_core_part_start + off, &rom_data, 3*sizeof(uint32_t));
if (err != ESP_OK) {
esp_panicPutStr("ERROR: Failed to write task header ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
return;
}
off += 3*sizeof(uint32_t);
// save TCB
len = esp_core_dump_write_flash_padded(s_core_part_start + off, tasks[i].pxTCB, tcb_sz);
if (len == 0)
return;
off += len;
// save task stack
/*int k;
for (k = 0; k < 8*4; k++) {
esp_panicPutStr("stack[");
esp_panicPutDec(k);
esp_panicPutStr("] = ");
esp_panicPutHex(((uint8_t *)tasks[i].pxTopOfStack)[k]);
esp_panicPutStr("\r\n");
}*/
len = esp_core_dump_write_flash_padded(s_core_part_start + off,
#if( portSTACK_GROWTH < 0 )
tasks[i].pxTopOfStack,
(uint32_t)tasks[i].pxEndOfStack - (uint32_t)tasks[i].pxTopOfStack
#else
tasks[i].pxEndOfStack,
(uint32_t)tasks[i].pxTopOfStack - (uint32_t)tasks[i].pxEndOfStack
#endif
);
if (len == 0)
return;
off += len;
}
rom_data.data32[0] = COREDUMP_FLASH_MAGIC_END;
err = spi_flash_write_panic(s_core_part_start + off, &rom_data, sizeof(uint32_t));
if (err != ESP_OK) {
esp_panicPutStr("Failed to write to flash ");
esp_panicPutHex(err);
esp_panicPutStr("!\r\n");
return;
}
#endif
esp_panicPutStr("Core dump has been saved to flash.\r\n");
ets_printf("Save core dump to flash...\r\n");
esp_core_dump_write(frame, &wr_cfg, 0);
ets_printf("Core dump has been saved to flash.\r\n");
}
#endif
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
#if 0
#define BASE64_ENCODE_BODY(_src, _src_len, _dst) \
do { \
static const char *b64 = \
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
int i, j, a, b, c; \
\
for (i = j = 0; i < _src_len; i += 3) { \
a = _src[i]; \
b = i + 1 >= _src_len ? 0 : _src[i + 1]; \
c = i + 2 >= _src_len ? 0 : _src[i + 2]; \
\
/*BASE64_OUT(b64[a >> 2], _dst[j]);*/ \
_dst[j++] = b64[a >> 2]; \
/*BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)], _dst[j]);*/ \
_dst[j++] = b64[((a & 3) << 4) | (b >> 4)]; \
j++; \
if (i + 1 < _src_len) { \
BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)], _dst[j]); \
j++; \
} \
if (i + 2 < _src_len) { \
BASE64_OUT(b64[c & 63], _dst[j]); \
j++; \
} \
} \
\
while (j % 4 != 0) { \
BASE64_OUT('=', _dst); \
} \
BASE64_FLUSH(_dst) \
} while(0)
#define BASE64_OUT(ch, _dst) \
do { \
_dst = (ch); \
} while (0)
#define BASE64_FLUSH(_dst) \
do { \
_dst = '\0'; \
} while (0)
#endif
static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8_t *dst) {
// BASE64_ENCODE_BODY(src, src_len, dst);
static const char *b64 =
@ -618,38 +372,26 @@ static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8
dst[j++] = '\0';
}
/*static esp_err_t esp_core_dump_uart_write_prepare(void *priv, uint32_t *data_len)
static esp_err_t esp_core_dump_uart_write_start(void *priv, int verb)
{
esp_err_t err = ESP_OK;
return err;
}*/
static esp_err_t esp_core_dump_uart_write_start(void *priv)
{
// core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
esp_err_t err = ESP_OK;
esp_panicPutStr("================= CORE DUMP START =================\r\n");
ets_printf("================= CORE DUMP START =================\r\n");
return err;
}
static esp_err_t esp_core_dump_uart_write_end(void *priv)
static esp_err_t esp_core_dump_uart_write_end(void *priv, int verb)
{
// core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
esp_err_t err = ESP_OK;
esp_panicPutStr("================= CORE DUMP END =================\r\n");
ets_printf("================= CORE DUMP END =================\r\n");
return err;
}
static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t data_len)
static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t data_len, int verb)
{
// core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv;
esp_err_t err = ESP_OK;
char buf[64 + 4], *addr = data;
char *end = addr + data_len;
// esp_panicPutStr("CORE DUMP SEC: ");
// esp_panicPutDec(data_len);
// esp_panicPutStr("bytes\r\n");
while (addr < end) {
size_t len = end - addr;
@ -659,15 +401,7 @@ static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t
memcpy(tmp, addr, len);
esp_core_dump_b64_encode((const uint8_t *)tmp, len, (uint8_t *)buf);
addr += len;
esp_panicPutStr(buf);
// for (size_t i = 0; buf[i] != '\0'; i++) {
// panicPutChar(buf[i]);
// }
//if (addr % 96 == 0)
esp_panicPutStr("\r\n");
/* Feed the Cerberus. */
// TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
// TIMERG0.wdt_feed = 1;
ets_printf("%s\r\n", buf);
}
return err;
@ -676,17 +410,16 @@ static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t
void esp_core_dump_to_uart(XtExcFrame *frame)
{
core_dump_write_config_t wr_cfg;
//core_dump_write_flash_data_t wr_data;
wr_cfg.prepare = NULL;//esp_core_dump_uart_write_prepare;
wr_cfg.prepare = NULL;
wr_cfg.start = esp_core_dump_uart_write_start;
wr_cfg.end = esp_core_dump_uart_write_end;
wr_cfg.write = esp_core_dump_uart_write_data;
wr_cfg.priv = NULL;
esp_panicPutStr("Save core dump to flash...\r\n");
ets_printf("Print core dump to uart...\r\n");
esp_core_dump_write(frame, &wr_cfg, 0);
esp_panicPutStr("Core dump has been written to uart.\r\n");
ets_printf("Core dump has been written to uart.\r\n");
}
#endif

View file

@ -203,6 +203,8 @@ void start_cpu0_default(void)
#endif
esp_ipc_init();
spi_flash_init();
/* init default OS-aware flash access critical section */
spi_flash_guard_set(&g_flash_guard_default_ops);
#if CONFIG_ESP32_PHY_AUTO_INIT
nvs_flash_init();

View file

@ -24,10 +24,6 @@
*/
void esp_set_breakpoint_if_jtag(void *fn);
void esp_panicPutChar(char c);
void esp_panicPutStr(const char *c);
void esp_panicPutHex(int a);
void esp_panicPutDec(int a);
#define ESP_WATCHPOINT_LOAD 0x40000000
#define ESP_WATCHPOINT_STORE 0x80000000

View file

@ -47,61 +47,61 @@
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
//printf may be broken, so we fix our own printing fns...
void esp_panicPutChar(char c)
static void panicPutChar(char c)
{
while (((READ_PERI_REG(UART_STATUS_REG(0)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ;
WRITE_PERI_REG(UART_FIFO_REG(0), c);
}
void esp_panicPutStr(const char *c)
static void panicPutStr(const char *c)
{
int x = 0;
while (c[x] != 0) {
esp_panicPutChar(c[x]);
panicPutChar(c[x]);
x++;
}
}
void esp_panicPutHex(int a)
static void panicPutHex(int a)
{
int x;
int c;
for (x = 0; x < 8; x++) {
c = (a >> 28) & 0xf;
if (c < 10) {
esp_panicPutChar('0' + c);
panicPutChar('0' + c);
} else {
esp_panicPutChar('a' + c - 10);
panicPutChar('a' + c - 10);
}
a <<= 4;
}
}
void esp_panicPutDec(int a)
static void panicPutDec(int a)
{
int n1, n2;
n1 = a % 10;
n2 = a / 10;
if (n2 == 0) {
esp_panicPutChar(' ');
panicPutChar(' ');
} else {
esp_panicPutChar(n2 + '0');
panicPutChar(n2 + '0');
}
esp_panicPutChar(n1 + '0');
panicPutChar(n1 + '0');
}
#else
//No printing wanted. Stub out these functions.
void esp_panicPutChar(char c) { }
void esp_panicPutStr(const char *c) { }
void esp_panicPutHex(int a) { }
void esp_panicPutDec(int a) { }
static void panicPutChar(char c) { }
static void panicPutStr(const char *c) { }
static void panicPutHex(int a) { }
static void panicPutDec(int a) { }
#endif
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
{
esp_panicPutStr("***ERROR*** A stack overflow in task ");
esp_panicPutStr((char *)pcTaskName);
esp_panicPutStr(" has been detected.\r\n");
panicPutStr("***ERROR*** A stack overflow in task ");
panicPutStr((char *)pcTaskName);
panicPutStr(" has been detected.\r\n");
abort();
}
@ -220,25 +220,25 @@ void xt_unhandled_exception(XtExcFrame *frame)
int x;
haltOtherCore();
esp_panicPutStr("Guru Meditation Error of type ");
panicPutStr("Guru Meditation Error of type ");
x = regs[20];
if (x < 40) {
esp_panicPutStr(edesc[x]);
panicPutStr(edesc[x]);
} else {
esp_panicPutStr("Unknown");
panicPutStr("Unknown");
}
esp_panicPutStr(" occurred on core ");
esp_panicPutDec(xPortGetCoreID());
panicPutStr(" occurred on core ");
panicPutDec(xPortGetCoreID());
if (esp_cpu_in_ocd_debug_mode()) {
esp_panicPutStr(" at pc=");
esp_panicPutHex(regs[1]);
esp_panicPutStr(". Setting bp and returning..\r\n");
panicPutStr(" at pc=");
panicPutHex(regs[1]);
panicPutStr(". Setting bp and returning..\r\n");
//Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
//will kick in exactly at the context the error happened.
setFirstBreakpoint(regs[1]);
return;
}
esp_panicPutStr(". Exception was unhandled.\r\n");
panicPutStr(". Exception was unhandled.\r\n");
commonErrorHandler(frame);
}
@ -293,16 +293,16 @@ static void putEntry(uint32_t pc, uint32_t sp)
if (pc & 0x80000000) {
pc = (pc & 0x3fffffff) | 0x40000000;
}
esp_panicPutStr(" 0x");
esp_panicPutHex(pc);
esp_panicPutStr(":0x");
esp_panicPutHex(sp);
panicPutStr(" 0x");
panicPutHex(pc);
panicPutStr(":0x");
panicPutHex(sp);
}
static void doBacktrace(XtExcFrame *frame)
{
uint32_t i = 0, pc = frame->pc, sp = frame->a1;
esp_panicPutStr("\r\nBacktrace:");
panicPutStr("\r\nBacktrace:");
/* Do not check sanity on first entry, PC could be smashed. */
putEntry(pc, sp);
pc = frame->a0;
@ -318,7 +318,7 @@ static void doBacktrace(XtExcFrame *frame)
break;
}
}
esp_panicPutStr("\r\n\r\n");
panicPutStr("\r\n\r\n");
}
/*
@ -342,17 +342,17 @@ static void commonErrorHandler(XtExcFrame *frame)
the register window is no longer useful.
*/
if (!abort_called) {
esp_panicPutStr("Register dump:\r\n");
panicPutStr("Register dump:\r\n");
for (x = 0; x < 24; x += 4) {
for (y = 0; y < 4; y++) {
if (sdesc[x + y][0] != 0) {
esp_panicPutStr(sdesc[x + y]);
esp_panicPutStr(": 0x");
esp_panicPutHex(regs[x + y + 1]);
esp_panicPutStr(" ");
panicPutStr(sdesc[x + y]);
panicPutStr(": 0x");
panicPutHex(regs[x + y + 1]);
panicPutStr(" ");
}
esp_panicPutStr("\r\n");
panicPutStr("\r\n");
}
}
}
@ -362,7 +362,7 @@ static void commonErrorHandler(XtExcFrame *frame)
#if CONFIG_ESP32_PANIC_GDBSTUB
disableAllWdts();
esp_panicPutStr("Entering gdb stub now.\r\n");
panicPutStr("Entering gdb stub now.\r\n");
esp_gdbstub_panic_handler(frame);
#else
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
@ -372,14 +372,14 @@ static void commonErrorHandler(XtExcFrame *frame)
esp_core_dump_to_uart(frame);
#endif
#if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
esp_panicPutStr("Rebooting...\r\n");
panicPutStr("Rebooting...\r\n");
for (x = 0; x < 100; x++) {
ets_delay_us(1000);
}
software_reset();
#else
disableAllWdts();
esp_panicPutStr("CPU halted.\r\n");
panicPutStr("CPU halted.\r\n");
while (1);
#endif
#endif

View file

@ -24,6 +24,11 @@ except ImportError:
__version__ = "0.1-dev"
if os.name == 'nt':
CLOSE_FDS = False
else:
CLOSE_FDS = True
class Struct(object):
def __init__(self, buf=None):
@ -492,6 +497,10 @@ class ESPCoreDumpLoader(object):
print "get_registers_from_stack: pc %x ps %x a0 %x a1 %x a2 %x a3 %x" % (
regs[REG_PC_IDX], regs[REG_PS_IDX], regs[REG_AR_NUM + 0],
regs[REG_AR_NUM + 1], regs[REG_AR_NUM + 2], regs[REG_AR_NUM + 3])
# FIXME: crashed and some running tasks (e.g. prvIdleTask) have EXCM bit set
# and GDB can not unwind callstack properly (it implies not windowed call0)
if regs[REG_PS_IDX] & (1 << 5):
regs[REG_PS_IDX] &= ~(1 << 4)
else:
print "SOLSTACKFRAME %d" % rc
regs[REG_PC_IDX] = stack[XT_SOL_PC]
@ -516,18 +525,18 @@ class ESPCoreDumpLoader(object):
os.remove(fname)
except OSError as e:
if e.errno != errno.ENOENT:
print "Warning failed to remove temp file '%s'!" % fname
print "Warning failed to remove temp file '%s' (%d)!" % (fname, e.errno)
def cleanup(self):
if self.fcore:
self.fcore.close()
self.remove_tmp_file(self.fcore.name)
if self.fcore_name:
self.remove_tmp_file(self.fcore_name)
def create_corefile(self, core_fname=None, off=0):
""" TBD
"""
core_off = off
print "Read core dump header"
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)
tcbsz_aligned = tcbsz
@ -538,7 +547,6 @@ class ESPCoreDumpLoader(object):
core_elf = ESPCoreDumpElfFile()
notes = b''
for i in range(task_num):
print "Read task[%d] header" % i
data = self.read_data(core_off, self.ESP32_COREDUMP_TSK_HDR_SZ)
tcb_addr,stack_top,stack_end = struct.unpack_from(self.ESP32_COREDUMP_TSK_HDR_FMT, data)
if stack_end > stack_top:
@ -554,7 +562,6 @@ class ESPCoreDumpLoader(object):
stack_len_aligned = 4*(stack_len_aligned/4 + 1)
core_off += self.ESP32_COREDUMP_TSK_HDR_SZ
print "Read task[%d] TCB" % i
data = self.read_data(core_off, 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)
@ -562,15 +569,17 @@ class ESPCoreDumpLoader(object):
core_elf.add_program_segment(tcb_addr, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
# print "tcb=%s" % data
core_off += tcbsz_aligned
print "Read task[%d] stack %d bytes" % (i,stack_len)
data = self.read_data(core_off, stack_len_aligned)
# print "stk=%s" % data
if 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)
core_off += stack_len_aligned
task_regs = self._get_registers_from_stack(data, stack_end > stack_top)
try:
task_regs = self._get_registers_from_stack(data, stack_end > stack_top)
except Exception as e:
print e
return None
prstatus = XtensaPrStatus()
prstatus.pr_cursig = 0 # TODO: set sig only for current/failed task
prstatus.pr_pid = i # TODO: use pid assigned by OS
@ -608,32 +617,38 @@ class ESPCoreDumpFileLoader(ESPCoreDumpLoader):
self.fcore = self._load_coredump(path, b64)
def _load_coredump(self, path, b64):
"""Loads core dump from (raw binary or base64-encoded) file
"""
self.fcore_name = None
if b64:
fhnd,fname = tempfile.mkstemp()
print "tmpname %s" % fname
fhnd,self.fcore_name = tempfile.mkstemp()
fcore = os.fdopen(fhnd, 'wb')
fb64 = open(path, 'r')
fb64 = open(path, 'rb')
try:
while True:
line = fb64.readline()
if len(line) == 0:
break
data = base64.b64decode(line.rstrip('\r\n'))#, validate=True)
data = base64.standard_b64decode(line.rstrip('\r\n'))
fcore.write(data)
fcore.close()
fcore = open(fname, 'r')
fcore = open(self.fcore_name, 'rb')
except Exception as e:
if self.fcore_name:
self.remove_tmp_file(self.fcore_name)
raise e
finally:
fb64.close()
else:
fcore = open(path, 'r')
fcore = open(path, 'rb')
return fcore
class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
""" TBD
"""
ESP32_COREDUMP_FLASH_MAGIC_START = 0xDEADBEEF
ESP32_COREDUMP_FLASH_MAGIC_END = 0xACDCFEED
ESP32_COREDUMP_FLASH_MAGIC_START = 0xE32C04ED
ESP32_COREDUMP_FLASH_MAGIC_END = 0xE32C04ED
ESP32_COREDUMP_FLASH_MAGIC_FMT = '<L'
ESP32_COREDUMP_FLASH_MAGIC_SZ = struct.calcsize(ESP32_COREDUMP_FLASH_MAGIC_FMT)
ESP32_COREDUMP_FLASH_HDR_FMT = '<4L'
@ -654,32 +669,35 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
self.fcore = self._load_coredump(off)
def _load_coredump(self, off):
args = [self.path, '-c', self.chip]
"""Loads core dump from flash
"""
tool_args = [sys.executable, self.path, '-c', self.chip]
if self.port:
args.extend(['-p', self.port])
tool_args.extend(['-p', self.port])
if self.baud:
args.extend(['-b', str(self.baud)])
args.extend(['read_flash', str(off), str(self.ESP32_COREDUMP_FLASH_HDR_SZ), ''])
tool_args.extend(['-b', str(self.baud)])
tool_args.extend(['read_flash', str(off), str(self.ESP32_COREDUMP_FLASH_HDR_SZ), ''])
fname = None
self.fcore_name = None
try:
fhnd,fname = tempfile.mkstemp()
args[-1] = fname
fhnd,self.fcore_name = tempfile.mkstemp()
tool_args[-1] = self.fcore_name
# read core dump length
et_out = subprocess.check_output(args)
et_out = subprocess.check_output(tool_args)
print et_out
f = os.fdopen(fhnd, 'r')
f = os.fdopen(fhnd, 'rb')
self.dump_sz = self._read_core_dump_length(f)
# read core dump
args[-2] = str(self. dump_sz)
et_out = subprocess.check_output(args)
tool_args[-2] = str(self. dump_sz)
et_out = subprocess.check_output(tool_args)
print et_out
except subprocess.CalledProcessError as e:
print "esptool script execution failed with err %d" % e.returncode
print "Command ran: '%s'" % e.cmd
print "Command out:"
print e.output
self.remove_tmp_file(fname)
if self.fcore_name:
self.remove_tmp_file(self.fcore_name)
raise e
return f
@ -694,14 +712,12 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
def create_corefile(self, core_fname=None):
""" TBD
"""
print "Read core dump start marker"
data = self.read_data(0, self.ESP32_COREDUMP_FLASH_MAGIC_SZ)
mag1, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_MAGIC_FMT, data)
if mag1 != self.ESP32_COREDUMP_FLASH_MAGIC_START:
print "Invalid start marker %x" % mag1
return None
print "Read core dump end marker"
data = self.read_data(self.dump_sz-self.ESP32_COREDUMP_FLASH_MAGIC_SZ, self.ESP32_COREDUMP_FLASH_MAGIC_SZ)
mag2, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_MAGIC_FMT, data)
if mag2 != self.ESP32_COREDUMP_FLASH_MAGIC_END:
@ -793,13 +809,14 @@ class GDBMIStreamConsoleHandler(GDBMIOutStreamHandler):
def dbg_corefile(args):
""" TBD
"""
print "dbg_corefile %s %s %s %s" % (args.gdb, args.prog, args.core, args.save_core)
global CLOSE_FDS
loader = None
if not args.core:
loader = ESPCoreDumpFlashLoader(args.off, port=args.port)
core_fname = loader.create_corefile(args.save_core)
if not core_fname:
print "Failed to create corefile!"
loader.cleanup()
return
else:
core_fname = args.core
@ -808,6 +825,7 @@ def dbg_corefile(args):
core_fname = loader.create_corefile(args.save_core)
if not core_fname:
print "Failed to create corefile!"
loader.cleanup()
return
p = subprocess.Popen(
@ -817,7 +835,7 @@ def dbg_corefile(args):
'--core=%s' % core_fname, # core file
args.prog],
stdin = None, stdout = None, stderr = None,
close_fds = True
close_fds = CLOSE_FDS
)
p.wait()
@ -832,9 +850,7 @@ def info_corefile(args):
# def info_corefile(args):
""" TBD
"""
print "info_corefile %s %s %s" % (args.gdb, args.prog, args.core)
global CLOSE_FDS
def gdbmi_console_stream_handler(ln):
# print ln
sys.stdout.write(ln)
@ -845,8 +861,7 @@ def info_corefile(args):
""" TBD
"""
while True:
ln = f.readline().rstrip(' \n')
# print "LINE='{0}'".format(ln)
ln = f.readline().rstrip(' \r\n')
if ln == '(gdb)':
break
elif len(ln) == 0:
@ -863,6 +878,7 @@ def info_corefile(args):
core_fname = loader.create_corefile(args.save_core)
if not core_fname:
print "Failed to create corefile!"
loader.cleanup()
return
else:
core_fname = args.core
@ -871,6 +887,7 @@ def info_corefile(args):
core_fname = loader.create_corefile(args.save_core)
if not core_fname:
print "Failed to create corefile!"
loader.cleanup()
return
handlers = {}
@ -885,11 +902,9 @@ def info_corefile(args):
'--interpreter=mi2', # use GDB/MI v2
'--core=%s' % core_fname, # core file
args.prog],
# ],
stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.STDOUT,
close_fds = True
close_fds = CLOSE_FDS
)
gdbmi_read2prompt(p.stdout, handlers)
exe_elf = ESPCoreDumpElfFile(args.prog)
core_elf = ESPCoreDumpElfFile(core_fname)
@ -958,14 +973,13 @@ def info_corefile(args):
print "Name Address Size Attrs"
for ms in merged_segs:
print "%s 0x%x 0x%x %s" % (ms[0], ms[1], ms[2], ms[3])
for cs in core_segs:
print ".coredump.tasks 0x%x 0x%x %s" % (cs.addr, len(cs.data), cs.attr_str())
if args.print_mem:
print "\n====================== MEMORY CONTENTS ========================"
for ms in merged_segs:
# if ms[3].find('W') == -1:
if not ms[4]:
continue
print "%s 0x%x 0x%x %s" % (ms[0], ms[1], ms[2], ms[3])
p.stdin.write("-interpreter-exec console \"x/%dx 0x%x\"\n" % (ms[2]/4, ms[1]))
print "\n====================== CORE DUMP MEMORY CONTENTS ========================"
for cs in core_elf.program_segments:
print ".coredump.tasks 0x%x 0x%x %s" % (cs.addr, len(cs.data), cs.attr_str())
p.stdin.write("-interpreter-exec console \"x/%dx 0x%x\"\n" % (len(cs.data)/4, cs.addr))
gdbmi_read2prompt(p.stdout, handlers)
if 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)
@ -973,7 +987,8 @@ def info_corefile(args):
print "\n===================== ESP32 CORE DUMP END ====================="
print "==============================================================="
p.terminate()
p.stdin.write('q\n')
p.wait()
p.stdin.close()
p.stdout.close()
@ -985,7 +1000,7 @@ def info_corefile(args):
def main():
parser = argparse.ArgumentParser(description='coredumper.py v%s - ESP32 Core Dump Utility' % __version__, prog='coredumper')
parser = argparse.ArgumentParser(description='espcoredump.py v%s - ESP32 Core Dump Utility' % __version__, prog='espcoredump')
parser.add_argument('--chip', '-c',
help='Target chip type',

View file

@ -4962,7 +4962,6 @@ TickType_t uxReturn;
*pxTcbSz = sizeof(TCB_t);
//vTaskSuspendAll(); //WARNING: This only suspends one CPU. ToDo: suspend others as well. Mux using taskQueueMutex maybe?
{
/* Fill in an TaskStatus_t structure with information on each
task in the Ready state. */
@ -4990,25 +4989,6 @@ TickType_t uxReturn;
}
#endif
}
//( void ) xTaskResumeAll();
#if 0
/* Convention: First num_cpus slots will have current task for that cpu. */
for (i = 0; i < portNUM_PROCESSORS; i++) {
if (pxCurrentTCB[i] == NULL || pxCurrentTCB == pxTaskSnapshotArray[i]) {
continue;
} else {
UBaseType_t j;
for (j = i; j < uxTask; j++) {
if (pxTaskSnapshotArray[j] == pxCurrentTCB[i]) {
TaskHandle_t tmp = pxTaskSnapshotArray[i];
pxTaskSnapshotArray[i] = pxTaskSnapshotArray[j];
pxTaskSnapshotArray[j] = tmp;
break;
}
}
}
}
#endif
return uxTask;
}

View file

@ -141,7 +141,7 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu()
esp_intr_noniram_enable();
}
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_panic()
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_no_os()
{
const uint32_t cpuid = xPortGetCoreID();
const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
@ -154,7 +154,7 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_panic()
spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
}
void IRAM_ATTR spi_flash_enable_interrupts_caches_panic()
void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os()
{
const uint32_t cpuid = xPortGetCoreID();
@ -195,7 +195,7 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu()
esp_intr_noniram_enable();
}
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_panic()
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_no_os()
{
// Kill interrupts that aren't located in IRAM
esp_intr_noniram_disable();
@ -203,7 +203,7 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_panic()
spi_flash_disable_cache(0, &s_flash_op_cache_state[0]);
}
void IRAM_ATTR spi_flash_enable_interrupts_caches_panic()
void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os()
{
// Re-enable cache on this CPU
spi_flash_restore_cache(0, s_flash_op_cache_state[0]);

View file

@ -41,13 +41,13 @@ void spi_flash_disable_interrupts_caches_and_other_cpu();
void spi_flash_enable_interrupts_caches_and_other_cpu();
// Disables non-IRAM interrupt handlers on current CPU and caches on both CPUs.
// This function is implied to be called from panic handler
// This function is implied to be called from panic handler or when no OS is present
// when non-current CPU is halted and can not execute code from flash.
void spi_flash_disable_interrupts_caches_and_other_cpu_panic();
void spi_flash_disable_interrupts_caches_and_other_cpu_no_os();
// Enable cache, enable interrupts (to be added in future) on current CPU.
// This function is implied to be called from panic handler
// This function is implied to be called from panic handler or when no OS is present
// when non-current CPU is halted and can not execute code from flash.
void spi_flash_enable_interrupts_caches_panic();
void spi_flash_enable_interrupts_caches_no_os();
#endif //ESP_SPI_FLASH_CACHE_UTILS_H

View file

@ -58,36 +58,23 @@ static spi_flash_counters_t s_flash_stats;
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
/* SPI flash access critical section management functions */
typedef void (*spi_flash_guard_start_func_t)(void);
typedef void (*spi_flash_guard_end_func_t)(void);
/**
* Structure holding SPI flash access critical section management functions
*/
typedef struct {
spi_flash_guard_start_func_t start; // critical section start func
spi_flash_guard_end_func_t end; // critical section end func
} spi_flash_guard_funcs_t;
#define FLASH_GUARD_START(_gp_) do{if((_gp_)) (_gp_)->start();}while(0)
#define FLASH_GUARD_END(_gp_) do{if((_gp_)) (_gp_)->end();}while(0)
static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc);
static esp_err_t spi_flash_erase_range_internal(uint32_t start_addr, uint32_t size, const spi_flash_guard_funcs_t *flash_guard);
static esp_err_t spi_flash_write_internal(size_t dst, const void *srcv, size_t size, const spi_flash_guard_funcs_t *flash_guard);
static esp_err_t spi_flash_read_internal(size_t src, void *dstv, size_t size, const spi_flash_guard_funcs_t *flash_guard);
const DRAM_ATTR spi_flash_guard_funcs_t s_flash_guard_ops = {
const DRAM_ATTR spi_flash_guard_funcs_t g_flash_guard_default_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu,
.end = spi_flash_enable_interrupts_caches_and_other_cpu
};
const DRAM_ATTR spi_flash_guard_funcs_t s_flash_guard_panic_ops = {
.start = spi_flash_disable_interrupts_caches_and_other_cpu_panic,
.end = spi_flash_enable_interrupts_caches_panic
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,
.end = spi_flash_enable_interrupts_caches_no_os
};
static const spi_flash_guard_funcs_t *s_flash_guard_ops;
void spi_flash_init()
{
spi_flash_init_lock();
@ -96,6 +83,11 @@ void spi_flash_init()
#endif
}
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs)
{
s_flash_guard_ops = funcs;
}
size_t spi_flash_get_chip_size()
{
return g_rom_flashchip.chip_size;
@ -120,16 +112,6 @@ esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sec)
}
esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size)
{
return spi_flash_erase_range_internal(start_addr, size, &s_flash_guard_ops);
}
esp_err_t IRAM_ATTR spi_flash_erase_range_panic(uint32_t start_addr, uint32_t size)
{
return spi_flash_erase_range_internal(start_addr, size, &s_flash_guard_panic_ops);
}
static esp_err_t IRAM_ATTR spi_flash_erase_range_internal(uint32_t start_addr, uint32_t size, const spi_flash_guard_funcs_t *flash_guard)
{
if (start_addr % SPI_FLASH_SEC_SIZE != 0) {
return ESP_ERR_INVALID_ARG;
@ -144,7 +126,7 @@ static esp_err_t IRAM_ATTR spi_flash_erase_range_internal(uint32_t start_addr, u
size_t end = start + size / SPI_FLASH_SEC_SIZE;
const size_t sectors_per_block = BLOCK_ERASE_SIZE / SPI_FLASH_SEC_SIZE;
COUNTER_START();
FLASH_GUARD_START(flash_guard);
FLASH_GUARD_START(s_flash_guard_ops);
SpiFlashOpResult rc;
rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
@ -160,22 +142,12 @@ static esp_err_t IRAM_ATTR spi_flash_erase_range_internal(uint32_t start_addr, u
}
}
}
FLASH_GUARD_END(flash_guard);
FLASH_GUARD_END(s_flash_guard_ops);
COUNTER_STOP(erase);
return spi_flash_translate_rc(rc);
}
esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size)
{
return spi_flash_write_internal(dst, srcv, size, &s_flash_guard_ops);
}
esp_err_t IRAM_ATTR spi_flash_write_panic(size_t dst, const void *srcv, size_t size)
{
return spi_flash_write_internal(dst, srcv, size, &s_flash_guard_panic_ops);
}
static esp_err_t IRAM_ATTR spi_flash_write_internal(size_t dst, const void *srcv, size_t size, const spi_flash_guard_funcs_t *flash_guard)
{
// Out of bound writes are checked in ROM code, but we can give better
// error code here
@ -208,9 +180,9 @@ static esp_err_t IRAM_ATTR spi_flash_write_internal(size_t dst, const void *srcv
if (left_size > 0) {
uint32_t t = 0xffffffff;
memcpy(((uint8_t *) &t) + (dst - left_off), srcc, left_size);
FLASH_GUARD_START(flash_guard);
FLASH_GUARD_START(s_flash_guard_ops);
rc = SPIWrite(left_off, &t, 4);
FLASH_GUARD_END(flash_guard);
FLASH_GUARD_END(s_flash_guard_ops);
if (rc != SPI_FLASH_RESULT_OK) {
goto out;
}
@ -226,9 +198,9 @@ static esp_err_t IRAM_ATTR spi_flash_write_internal(size_t dst, const void *srcv
bool in_dram = true;
#endif
if (in_dram && (((uintptr_t) srcc) + mid_off) % 4 == 0) {
FLASH_GUARD_START(flash_guard);
FLASH_GUARD_START(s_flash_guard_ops);
rc = SPIWrite(dst + mid_off, (const uint32_t *) (srcc + mid_off), mid_size);
FLASH_GUARD_END(flash_guard);
FLASH_GUARD_END(s_flash_guard_ops);
if (rc != SPI_FLASH_RESULT_OK) {
goto out;
}
@ -242,9 +214,9 @@ static esp_err_t IRAM_ATTR spi_flash_write_internal(size_t dst, const void *srcv
uint32_t t[8];
uint32_t write_size = MIN(mid_size, sizeof(t));
memcpy(t, srcc + mid_off, write_size);
FLASH_GUARD_START(flash_guard);
FLASH_GUARD_START(s_flash_guard_ops);
rc = SPIWrite(dst + mid_off, t, write_size);
FLASH_GUARD_END(flash_guard);
FLASH_GUARD_END(s_flash_guard_ops);
if (rc != SPI_FLASH_RESULT_OK) {
goto out;
}
@ -257,9 +229,9 @@ static esp_err_t IRAM_ATTR spi_flash_write_internal(size_t dst, const void *srcv
if (right_size > 0) {
uint32_t t = 0xffffffff;
memcpy(&t, srcc + right_off, right_size);
FLASH_GUARD_START(flash_guard);
FLASH_GUARD_START(s_flash_guard_ops);
rc = SPIWrite(dst + right_off, &t, 4);
FLASH_GUARD_END(flash_guard);
FLASH_GUARD_END(s_flash_guard_ops);
if (rc != SPI_FLASH_RESULT_OK) {
goto out;
}
@ -307,16 +279,6 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
}
esp_err_t IRAM_ATTR spi_flash_read(size_t src, void *dstv, size_t size)
{
return spi_flash_read_internal(src, dstv, size, &s_flash_guard_ops);
}
esp_err_t IRAM_ATTR spi_flash_read_panic(size_t src, void *dstv, size_t size)
{
return spi_flash_read_internal(src, dstv, size, &s_flash_guard_panic_ops);
}
static esp_err_t IRAM_ATTR spi_flash_read_internal(size_t src, void *dstv, size_t size, const spi_flash_guard_funcs_t *flash_guard)
{
// Out of bound reads are checked in ROM code, but we can give better
// error code here
@ -329,7 +291,7 @@ static esp_err_t IRAM_ATTR spi_flash_read_internal(size_t src, void *dstv, size_
SpiFlashOpResult rc = SPI_FLASH_RESULT_OK;
COUNTER_START();
FLASH_GUARD_START(flash_guard);
FLASH_GUARD_START(s_flash_guard_ops);
/* To simplify boundary checks below, we handle small reads separately. */
if (size < 16) {
uint32_t t[6]; /* Enough for 16 bytes + 4 on either side for padding. */
@ -403,7 +365,7 @@ static esp_err_t IRAM_ATTR spi_flash_read_internal(size_t src, void *dstv, size_
memcpy(dstc + pad_right_off, t, pad_right_size);
}
out:
FLASH_GUARD_END(flash_guard);
FLASH_GUARD_END(s_flash_guard_ops);
COUNTER_STOP(read);
return spi_flash_translate_rc(rc);
}

View file

@ -173,12 +173,26 @@ void spi_flash_munmap(spi_flash_mmap_handle_t handle);
*/
void spi_flash_mmap_dump();
/**
* @brief SPI flash critical section enter function.
*/
typedef void (*spi_flash_guard_start_func_t)(void);
/**
* @brief SPI flash critical section exit function.
*/
typedef void (*spi_flash_guard_end_func_t)(void);
/**
* Structure holding SPI flash access critical section management functions
*/
typedef struct {
spi_flash_guard_start_func_t start; /**< critical section start func */
spi_flash_guard_end_func_t end; /**< critical section end func */
} spi_flash_guard_funcs_t;
/**
* @brief Erase a range of flash sectors.
*
* @note This version of function is to be called from panic handler.
* It does not use any OS primitives and IPC and implies that
* only calling CPU is active.
*
* @param start_address Address where erase operation has to start.
* Must be 4kB-aligned
@ -186,42 +200,18 @@ void spi_flash_mmap_dump();
*
* @return esp_err_t
*/
esp_err_t spi_flash_erase_range_panic(size_t start_address, size_t size);
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
/** Default OS-aware flash access critical section functions */
extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
/**
* @brief Write data to Flash.
/** Non-OS flash access critical section functions
*
* @note This version of function is to be called from panic handler.
* @note This version of functions is to be used when no OS is present or from panic handler.
* It does not use any OS primitives and IPC and implies that
* only calling CPU is active.
* @note If source address is in DROM, this function will return
* ESP_ERR_INVALID_ARG.
*
* @param dest destination address in Flash. Must be a multiple of 4 bytes.
* @param src pointer to the source buffer.
* @param size length of data, in bytes. Must be a multiple of 4 bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write_panic(size_t dest, const void *src, size_t size);
/**
* @brief Read data from Flash.
*
* @note This version of function is to be called from panic handler.
* It does not use any OS primitives and IPC and implies that
* only calling CPU is active.
*
* @param src source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
*
* @return esp_err_t
*/
esp_err_t spi_flash_read_panic(size_t src, void *dest, size_t size);
extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS