flash_api.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /******************************************************************************
  2. * Flash api for NodeMCU
  3. * NodeMCU Team
  4. * 2014-12-31
  5. *******************************************************************************/
  6. #include "flash_api.h"
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include "rom/spi_flash.h"
  11. #include "esp_image_format.h"
  12. #include "esp_flash_data_types.h"
  13. #include "esp_task_wdt.h"
  14. #define FLASH_HDR_ADDR 0x1000
  15. static inline esp_image_header_t flash_load_rom_header (void)
  16. {
  17. esp_image_header_t hdr;
  18. if (ESP_OK !=
  19. spi_flash_read (FLASH_HDR_ADDR, (uint32_t *)&hdr, sizeof (hdr)))
  20. {
  21. NODE_ERR("Failed to load flash header block!\n");
  22. abort();
  23. }
  24. return hdr;
  25. }
  26. #define IRAM_SECTION __attribute__((section(".iram1")))
  27. static void IRAM_SECTION update_flash_chip_size (uint32_t sz)
  28. {
  29. esp_rom_spiflash_config_param (
  30. g_rom_flashchip.device_id,
  31. sz,
  32. g_rom_flashchip.block_size,
  33. g_rom_flashchip.sector_size,
  34. g_rom_flashchip.page_size,
  35. g_rom_flashchip.status_mask);
  36. }
  37. static uint32_t __attribute__((section(".iram1"))) flash_detect_size_byte(void)
  38. {
  39. #define DETECT_SZ 32
  40. uint32_t detected_size = FLASH_SIZE_1MBYTE;
  41. uint8_t data_orig[DETECT_SZ] PLATFORM_ALIGNMENT = {0};
  42. uint8_t data_new[DETECT_SZ] PLATFORM_ALIGNMENT = {0};
  43. // Ensure we read something which isn't just 0xff...
  44. const uint32_t offs = ESP_PARTITION_TABLE_ADDR;
  45. // Detect read failure or wrap-around on flash read to find end of flash
  46. if (ESP_OK == spi_flash_read (offs, (uint32_t *)data_orig, DETECT_SZ))
  47. {
  48. update_flash_chip_size (FLASH_SIZE_16MBYTE);
  49. while ((detected_size < FLASH_SIZE_16MBYTE) &&
  50. (ESP_OK == spi_flash_read (
  51. detected_size + offs, (uint32_t *)data_new, DETECT_SZ)) &&
  52. (0 != memcmp(data_orig, data_new, DETECT_SZ)))
  53. {
  54. detected_size *= 2;
  55. }
  56. update_flash_chip_size (detected_size);
  57. };
  58. return detected_size;
  59. #undef FLASH_BUFFER_SIZE_DETECT
  60. }
  61. uint32_t flash_safe_get_size_byte(void)
  62. {
  63. static uint32_t flash_size = 0;
  64. if (flash_size == 0)
  65. {
  66. flash_size = flash_detect_size_byte();
  67. }
  68. return flash_size;
  69. }
  70. uint16_t flash_safe_get_sec_num(void)
  71. {
  72. return (flash_safe_get_size_byte() / (SPI_FLASH_SEC_SIZE));
  73. }
  74. uint32_t flash_rom_get_size_byte(void)
  75. {
  76. static uint32_t flash_size = 0;
  77. if (flash_size == 0)
  78. {
  79. switch (flash_load_rom_header ().spi_size)
  80. {
  81. default: // Unknown flash size, fall back mode.
  82. case ESP_IMAGE_FLASH_SIZE_1MB: flash_size = FLASH_SIZE_1MBYTE; break;
  83. case ESP_IMAGE_FLASH_SIZE_2MB: flash_size = FLASH_SIZE_2MBYTE; break;
  84. case ESP_IMAGE_FLASH_SIZE_4MB: flash_size = FLASH_SIZE_4MBYTE; break;
  85. case ESP_IMAGE_FLASH_SIZE_8MB: flash_size = FLASH_SIZE_8MBYTE; break;
  86. case ESP_IMAGE_FLASH_SIZE_16MB: flash_size = FLASH_SIZE_16MBYTE; break;
  87. }
  88. }
  89. return flash_size;
  90. }
  91. static bool flash_rom_set_size_type(uint8_t size_code)
  92. {
  93. // Dangerous, here are dinosaur infested!!!!!
  94. // Reboot required!!!
  95. // If you don't know what you're doing, your nodemcu may turn into stone ...
  96. NODE_DBG("\nBEGIN SET FLASH HEADER\n");
  97. esp_image_header_t *hdr = (esp_image_header_t *)malloc (SPI_FLASH_SEC_SIZE);
  98. if (!hdr)
  99. return false;
  100. if (ESP_OK == spi_flash_read (FLASH_HDR_ADDR, (uint32_t *)hdr, SPI_FLASH_SEC_SIZE))
  101. {
  102. hdr->spi_size = size_code;
  103. if (ESP_OK == spi_flash_erase_sector (FLASH_HDR_ADDR / SPI_FLASH_SEC_SIZE))
  104. {
  105. NODE_DBG("\nERASE SUCCESS\n");
  106. }
  107. if (ESP_OK == spi_flash_write(FLASH_HDR_ADDR, (uint32_t *)hdr, SPI_FLASH_SEC_SIZE))
  108. {
  109. NODE_DBG("\nWRITE SUCCESS, %u\n", size_code);
  110. }
  111. }
  112. free (hdr);
  113. NODE_DBG("\nEND SET FLASH HEADER\n");
  114. return true;
  115. }
  116. bool flash_rom_set_size_byte(uint32_t size)
  117. {
  118. // Dangerous, here are dinosaur infested!!!!!
  119. // Reboot required!!!
  120. bool ok = true;
  121. uint8_t size_code = 0;
  122. switch (size)
  123. {
  124. case FLASH_SIZE_1MBYTE: size_code = ESP_IMAGE_FLASH_SIZE_1MB; break;
  125. case FLASH_SIZE_2MBYTE: size_code = ESP_IMAGE_FLASH_SIZE_2MB; break;
  126. case FLASH_SIZE_4MBYTE: size_code = ESP_IMAGE_FLASH_SIZE_4MB; break;
  127. case FLASH_SIZE_8MBYTE: size_code = ESP_IMAGE_FLASH_SIZE_8MB; break;
  128. case FLASH_SIZE_16MBYTE: size_code = ESP_IMAGE_FLASH_SIZE_16MB; break;
  129. default: ok = false; break;
  130. }
  131. if (ok)
  132. ok = flash_rom_set_size_type (size_code);
  133. return ok;
  134. }
  135. uint16_t flash_rom_get_sec_num(void)
  136. {
  137. return ( flash_rom_get_size_byte() / (SPI_FLASH_SEC_SIZE) );
  138. }
  139. uint8_t flash_rom_get_mode(void)
  140. {
  141. return flash_load_rom_header ().spi_mode;
  142. }
  143. uint32_t flash_rom_get_speed(void)
  144. {
  145. switch (flash_load_rom_header ().spi_speed)
  146. {
  147. case ESP_IMAGE_SPI_SPEED_40M: return 40000000;
  148. case ESP_IMAGE_SPI_SPEED_26M: return 26700000; // TODO: verify 26.7MHz
  149. case ESP_IMAGE_SPI_SPEED_20M: return 20000000;
  150. case ESP_IMAGE_SPI_SPEED_80M: return 80000000;
  151. default: break;
  152. }
  153. return 0;
  154. }
  155. esp_err_t flash_erase(size_t sector)
  156. {
  157. #ifdef CONFIG_TASK_WDT
  158. // re-init the task WDT, simulates feeding for the IDLE task
  159. # ifdef CONFIG_TASK_WDT_PANIC
  160. esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, true);
  161. # else
  162. esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, false);
  163. # endif
  164. #endif
  165. return spi_flash_erase_sector(sector);
  166. }