diff --git a/user/cgipins.c b/user/cgipins.c index d9e02f3..3159866 100644 --- a/user/cgipins.c +++ b/user/cgipins.c @@ -11,7 +11,7 @@ static char *map_names[] = { "esp-bridge", "jn-esp-v2", "esp-01(AVR)", "esp-01(ARM)", "esp-br-rev", }; static char* map_func[] = { "reset", "isp", "conn_led", "ser_led" }; -static int8_t map_asn[][4] = { +static int8_t map_asn[][5] = { { 12, 13, 0, 14 }, // esp-bridge { 12, 13, 0, 2 }, // jn-esp-v2 { 0, -1, 2, -1 }, // esp-01(AVR) @@ -92,7 +92,16 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) { serledInit(); statusInit(); - jsonHeader(connData, 200); + if (configSave()) { + os_printf("New config saved\n"); + httpdStartResponse(connData, 200); + httpdEndHeaders(connData); + } else { + os_printf("*** Failed to save config ***\n"); + httpdStartResponse(connData, 500); + httpdEndHeaders(connData); + httpdSend(connData, "Failed to save config", -1); + } return HTTPD_CGI_DONE; } diff --git a/user/config.c b/user/config.c index e6eec90..6163542 100644 --- a/user/config.c +++ b/user/config.c @@ -5,16 +5,84 @@ #include "config.h" #include "espfs.h" -FlashConfig flashConfig = { +FlashConfig flashConfig; +FlashConfig flashDefault = { + 33, 0, MCU_RESET_PIN, MCU_ISP_PIN, LED_CONN_PIN, LED_SERIAL_PIN, 115200, "esp-link\0 ", }; +#define FLASH_ADDR (0x3E000) +#define FLASH_SECT (4096) +static int flash_pri; // primary flash sector (0 or 1, or -1 for error) + bool ICACHE_FLASH_ATTR configSave(void) { + FlashConfig fc; + memcpy(&fc, &flashConfig, sizeof(FlashConfig)); + uint32_t seq = fc.seq+1; + // erase secondary + uint32_t addr = FLASH_ADDR + (1-flash_pri)*FLASH_SECT; + if (spi_flash_erase_sector(addr>>12) != SPI_FLASH_RESULT_OK) + return false; // no harm done, give up + // write primary with incorrect seq + fc.seq = 0xffffffff; + fc.crc = 0x55aa55aa; + if (spi_flash_write(addr, (void *)&fc, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK) + return false; // no harm done, give up + // fill in correct seq + fc.seq = seq; + if (spi_flash_write(addr, (void *)&fc, sizeof(uint32_t)) != SPI_FLASH_RESULT_OK) + return false; // most likely failed, but no harm if successful + // now that we have safely written the new version, erase old primary + addr = FLASH_ADDR + flash_pri*FLASH_SECT; + flash_pri = 1-flash_pri; + if (spi_flash_erase_sector(addr>>12) != SPI_FLASH_RESULT_OK) + return true; // no back-up but we're OK + // write secondary + fc.seq = 0xffffffff; + if (spi_flash_write(addr, (void *)&fc, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK) + return true; // no back-up but we're OK + fc.seq = seq; + spi_flash_write(addr, (void *)&fc, sizeof(uint32_t)); return true; } +void ICACHE_FLASH_ATTR configWipe(void) { + spi_flash_erase_sector(FLASH_ADDR>>12); + spi_flash_erase_sector((FLASH_ADDR+FLASH_SECT)>>12); +} + +static uint32_t ICACHE_FLASH_ATTR selectPrimary(FlashConfig *fc0, FlashConfig *fc1); + bool ICACHE_FLASH_ATTR configRestore(void) { + FlashConfig fc0, fc1; + // read both flash sectors + if (spi_flash_read(FLASH_ADDR, (void *)&fc0, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK) + memset(&fc0, sizeof(FlashConfig), 0); // clear in case of error + if (spi_flash_read(FLASH_ADDR+FLASH_SECT, (void *)&fc1, sizeof(FlashConfig)) != SPI_FLASH_RESULT_OK) + memset(&fc1, sizeof(FlashConfig), 0); // clear in case of error + // figure out which one is good + flash_pri = selectPrimary(&fc0, &fc1); + // if neither is OK, we revert to defaults + if (flash_pri < 0) { + memcpy(&flashConfig, &flashDefault, sizeof(FlashConfig)); + flash_pri = 0; + return false; + } + // copy good one into global var and return + memcpy(&flashConfig, flash_pri == 0 ? &fc0 : &fc1, sizeof(FlashConfig)); return true; } + +static uint32_t ICACHE_FLASH_ATTR selectPrimary(FlashConfig *fc0, FlashConfig *fc1) { + bool fc0_crc_ok = fc0->crc == 0x55aa55aa && fc0->seq != 0xffffffff; // need real crc checksum... + bool fc1_crc_ok = fc1->crc == 0x55aa55aa && fc1->seq != 0xffffffff; // need real crc checksum... + if (fc0_crc_ok) + if (!fc1_crc_ok || fc0->seq >= fc1->seq) + return 0; // use first sector as primary + else + return 1; // second sector is newer + else + return fc1_crc_ok ? 1 : -1; +} diff --git a/user/config.h b/user/config.h index 513f0c9..b4bed48 100644 --- a/user/config.h +++ b/user/config.h @@ -2,6 +2,8 @@ #define CONFIG_H typedef struct { + uint32_t seq; // flash write sequence number + uint32_t crc; // FlashConfig crc int8_t reset_pin, isp_pin, conn_led_pin, ser_led_pin; int32_t baud_rate; char hostname[32]; @@ -10,5 +12,6 @@ extern FlashConfig flashConfig; bool configSave(void); bool configRestore(void); +void configWipe(void); #endif diff --git a/user/user_main.c b/user/user_main.c index e6b40ec..b1b3f7c 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -24,6 +24,7 @@ #include "status.h" #include "serled.h" #include "console.h" +#include "config.h" #include "log.h" #define MCU_RESET 12 #define MCU_ISP 13 @@ -121,6 +122,9 @@ void user_init(void) { # define VERS_STR_STR(V) #V # define VERS_STR(V) VERS_STR_STR(V) os_printf("\n\nInitializing esp-link\n" VERS_STR(VERSION) "\n"); + //configWipe(); + if (configRestore()) os_printf("Flash config restored\n"); + else os_printf("*** Flash config restore failed, using defaults ***\n"); // Status LEDs statusInit(); serledInit();