From 39ddc7b836c1fadccd99154f10da23203f1442b4 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Tue, 3 Jan 2017 22:01:40 +0300 Subject: [PATCH] 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 --- components/esp32/core_dump.c | 427 ++++--------------- components/esp32/cpu_start.c | 2 + components/esp32/include/esp_panic.h | 4 - components/esp32/panic.c | 82 ++-- components/espcoredump/espcoredump.py | 113 ++--- components/freertos/tasks.c | 20 - components/spi_flash/cache_utils.c | 8 +- components/spi_flash/cache_utils.h | 8 +- components/spi_flash/flash_ops.c | 84 +--- components/spi_flash/include/esp_spi_flash.h | 56 +-- 10 files changed, 241 insertions(+), 563 deletions(-) diff --git a/components/esp32/core_dump.c b/components/esp32/core_dump.c index eaab1871c3..e12fc1d71c 100644 --- a/components/esp32/core_dump.c +++ b/components/esp32/core_dump.c @@ -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 diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 1b8a95b75c..2ae4260bd5 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -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(); diff --git a/components/esp32/include/esp_panic.h b/components/esp32/include/esp_panic.h index 3dd5d4b185..aa83c6d381 100644 --- a/components/esp32/include/esp_panic.h +++ b/components/esp32/include/esp_panic.h @@ -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 diff --git a/components/esp32/panic.c b/components/esp32/panic.c index 94aebfbac4..09ce520ded 100644 --- a/components/esp32/panic.c +++ b/components/esp32/panic.c @@ -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 diff --git a/components/espcoredump/espcoredump.py b/components/espcoredump/espcoredump.py index 2f31d3f292..2942c609f8 100755 --- a/components/espcoredump/espcoredump.py +++ b/components/espcoredump/espcoredump.py @@ -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 = '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); } diff --git a/components/spi_flash/include/esp_spi_flash.h b/components/spi_flash/include/esp_spi_flash.h index e78c389b4e..402cd6e6f7 100644 --- a/components/spi_flash/include/esp_spi_flash.h +++ b/components/spi_flash/include/esp_spi_flash.h @@ -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