From 088d2c3820711a8c0aa3afe9e6b6689092e9718a Mon Sep 17 00:00:00 2001 From: Johny Mattsson Date: Tue, 4 Oct 2016 12:04:09 +1100 Subject: [PATCH] Reimplemented esp_init_data_default. To work around the pesky "rf_cal[0] !=0x05" hang when booting on a chip which doesn't have esp_init_data written to it. It is no longer possible to do the writing of the esp_init_data_default from within nodemcu_init(), as the SDK now hangs long before it gets there. As such, I've had to reimplement this in our user_start_trampoline and get it all done before the SDK has a chance to look for the init data. It's unfortunate that we have to spend IRAM on this, but I see no better alternative at this point. --- app/include/rom.h | 2 ++ app/user/user_main.c | 45 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/app/include/rom.h b/app/include/rom.h index 7de1c5e0..c2ad7d3d 100644 --- a/app/include/rom.h +++ b/app/include/rom.h @@ -149,5 +149,7 @@ void uart_div_modify(int no, unsigned int freq); /* Returns 0 on success, 1 on failure */ uint8_t SPIRead(uint32_t src_addr, uint32_t *des_addr, uint32_t size); +uint8_t SPIWrite(uint32_t dst_addr, const uint32_t *src, uint32_t size); +uint8_t SPIEraseSector(uint32_t sector); #endif diff --git a/app/user/user_main.c b/app/user/user_main.c index dd7c9d75..5c72d53b 100644 --- a/app/user/user_main.c +++ b/app/user/user_main.c @@ -47,6 +47,49 @@ void TEXT_SECTION_ATTR user_start_trampoline (void) rtctime_early_startup (); #endif + /* Re-implementation of default init data deployment. The SDK does not + * appear to be laying down its own version of init data anymore, so + * we have to do it again. To see whether we need to, we read out + * the flash size and do a test for esp_init_data based on that size. + * If it's missing, we need to initialize it *right now* before the SDK + * starts up and gets stuck at "rf_cal[0] !=0x05,is 0xFF". + * If the size byte is wrong, then we'll end up fixing up the init data + * again on the next boot, after we've corrected the size byte. + * Only remaining issue is lack of spare code bytes in iram, so this + * is deliberately quite terse and not as readable as one might like. + */ + SPIFlashInfo sfi; + SPIRead (0, (uint32_t *)(&sfi), sizeof (sfi)); // Cache read not enabled yet, safe to use + if (sfi.size < 2) // Compensate for out-of-order 4mbit vs 2mbit values + sfi.size ^= 1; + uint32_t flash_end_addr = (256 * 1024) << sfi.size; + uint32_t init_data_hdr = 0xffffffff; + uint32_t init_data_addr = flash_end_addr - 4 * SPI_FLASH_SEC_SIZE; + SPIRead (init_data_addr, &init_data_hdr, sizeof (init_data_hdr)); + if (init_data_hdr == 0xffffffff) + { + // Note: ideally we should generate the actual init data from the + // SDK's bin/esp_init_data_default.bin during the build, and #include it + // straight into this array. E.g.: + // xxd -i esp_init_data_default | tail -n13 | head -n11 > eidd.h + static uint8_t flash_init_data[128] __attribute__((aligned(4))) = + { + 0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, + 0x05, 0x04, 0x05, 0x05, 0x04, 0xfe, 0xfd, 0xff, 0xf0, 0xf0, 0xf0, 0xe0, + 0xe0, 0xe0, 0xe1, 0x0a, 0xff, 0xff, 0xf8, 0x00, 0xf8, 0xf8, 0x52, 0x4e, + 0x4a, 0x44, 0x40, 0x38, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + SPIEraseSector (init_data_addr); + SPIWrite (init_data_addr, (const uint32_t *)flash_init_data, sizeof (flash_init_data)); + } + call_user_start (); } @@ -87,9 +130,7 @@ void nodemcu_init(void) // Fit hardware real flash size. flash_rom_set_size_byte(flash_safe_get_size_byte()); - // Reboot to get SDK to use (or write) init data at new location system_restart (); - // Don't post the start_lua task, we're about to reboot... return; }