esp8266/modesp: Run ets_loop_iter before/after doing flash erase/write.

A flash erase/write takes a while and during that time tasks may be
scheduled via an IRQ.  To prevent overflow of the task queue (and loss of
tasks) call ets_loop_iter() before and after slow flash operations.

Note: if a task is posted to a full queue while a flash operation is in
progress then this leads to a fault when trying to print out the error
message that the queue is full.  This patch doesn't try to fix this
particular issue, it just prevents it from happening in the first place.
This commit is contained in:
Damien George 2018-07-03 14:39:50 +10:00
parent a3c3dbd955
commit b6e5f82ba5
1 changed files with 8 additions and 0 deletions

View File

@ -34,6 +34,7 @@
#include "uart.h" #include "uart.h"
#include "user_interface.h" #include "user_interface.h"
#include "mem.h" #include "mem.h"
#include "ets_alt_task.h"
#include "espneopixel.h" #include "espneopixel.h"
#include "espapa102.h" #include "espapa102.h"
#include "modmachine.h" #include "modmachine.h"
@ -120,7 +121,9 @@ STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) {
if (bufinfo.len & 0x3) { if (bufinfo.len & 0x3) {
mp_raise_ValueError("len must be multiple of 4"); mp_raise_ValueError("len must be multiple of 4");
} }
ets_loop_iter(); // flash access takes time so run any pending tasks
SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, bufinfo.len); SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, bufinfo.len);
ets_loop_iter();
if (res == SPI_FLASH_RESULT_OK) { if (res == SPI_FLASH_RESULT_OK) {
return mp_const_none; return mp_const_none;
} }
@ -130,7 +133,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) { STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
mp_int_t sector = mp_obj_get_int(sector_in); mp_int_t sector = mp_obj_get_int(sector_in);
ets_loop_iter(); // flash access takes time so run any pending tasks
SpiFlashOpResult res = spi_flash_erase_sector(sector); SpiFlashOpResult res = spi_flash_erase_sector(sector);
ets_loop_iter();
if (res == SPI_FLASH_RESULT_OK) { if (res == SPI_FLASH_RESULT_OK) {
return mp_const_none; return mp_const_none;
} }
@ -305,14 +310,17 @@ void *esp_native_code_commit(void *buf, size_t len) {
} else { } else {
SpiFlashOpResult res; SpiFlashOpResult res;
while (esp_native_code_erased < esp_native_code_cur + len) { while (esp_native_code_erased < esp_native_code_cur + len) {
ets_loop_iter(); // flash access takes time so run any pending tasks
res = spi_flash_erase_sector(esp_native_code_erased / FLASH_SEC_SIZE); res = spi_flash_erase_sector(esp_native_code_erased / FLASH_SEC_SIZE);
if (res != SPI_FLASH_RESULT_OK) { if (res != SPI_FLASH_RESULT_OK) {
break; break;
} }
esp_native_code_erased += FLASH_SEC_SIZE; esp_native_code_erased += FLASH_SEC_SIZE;
} }
ets_loop_iter();
if (res == SPI_FLASH_RESULT_OK) { if (res == SPI_FLASH_RESULT_OK) {
res = spi_flash_write(esp_native_code_cur, buf, len); res = spi_flash_write(esp_native_code_cur, buf, len);
ets_loop_iter();
} }
if (res != SPI_FLASH_RESULT_OK) { if (res != SPI_FLASH_RESULT_OK) {
mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO); mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);