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