bootloader_flash.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stddef.h>
  7. #include <bootloader_flash_priv.h>
  8. #include <esp_log.h>
  9. #include <esp_flash_encrypt.h>
  10. #include "sdkconfig.h"
  11. #include "soc/soc_caps.h"
  12. #if CONFIG_IDF_TARGET_ESP32
  13. # include "soc/spi_struct.h"
  14. # include "soc/spi_reg.h"
  15. /* SPI flash controller */
  16. # define SPIFLASH SPI1
  17. #else
  18. # include "soc/spi_mem_struct.h"
  19. # include "soc/spi_mem_reg.h"
  20. /* SPI flash controller */
  21. # define SPIFLASH SPIMEM1
  22. #endif
  23. #if CONFIG_IDF_TARGET_ESP32S2
  24. #include "esp32s2/rom/spi_flash.h"
  25. #elif CONFIG_IDF_TARGET_ESP32S3
  26. #include "esp32s3/rom/spi_flash.h"
  27. #elif CONFIG_IDF_TARGET_ESP32C3
  28. #include "esp32c3/rom/spi_flash.h"
  29. #endif
  30. #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
  31. #define ENCRYPTION_IS_VIRTUAL 1
  32. #else
  33. #define ENCRYPTION_IS_VIRTUAL 0
  34. #endif
  35. #ifndef BOOTLOADER_BUILD
  36. /* Normal app version maps to esp_spi_flash.h operations...
  37. */
  38. static const char *TAG = "bootloader_mmap";
  39. static spi_flash_mmap_handle_t map;
  40. uint32_t bootloader_mmap_get_free_pages(void)
  41. {
  42. return spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
  43. }
  44. const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
  45. {
  46. if (map) {
  47. ESP_LOGE(TAG, "tried to bootloader_mmap twice");
  48. return NULL; /* existing mapping in use... */
  49. }
  50. const void *result = NULL;
  51. uint32_t src_page = src_addr & ~(SPI_FLASH_MMU_PAGE_SIZE - 1);
  52. size += (src_addr - src_page);
  53. esp_err_t err = spi_flash_mmap(src_page, size, SPI_FLASH_MMAP_DATA, &result, &map);
  54. if (err != ESP_OK) {
  55. ESP_LOGE(TAG, "spi_flash_mmap failed: 0x%x", err);
  56. return NULL;
  57. }
  58. return (void *)((intptr_t)result + (src_addr - src_page));
  59. }
  60. void bootloader_munmap(const void *mapping)
  61. {
  62. if (mapping && map) {
  63. spi_flash_munmap(map);
  64. }
  65. map = 0;
  66. }
  67. esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_decrypt)
  68. {
  69. if (allow_decrypt && esp_flash_encryption_enabled()) {
  70. return spi_flash_read_encrypted(src, dest, size);
  71. } else {
  72. return spi_flash_read(src, dest, size);
  73. }
  74. }
  75. esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
  76. {
  77. if (write_encrypted && !ENCRYPTION_IS_VIRTUAL) {
  78. #if CONFIG_IDF_TARGET_ESP32
  79. return spi_flash_write_encrypted(dest_addr, src, size);
  80. #else
  81. return esp_rom_spiflash_write_encrypted(dest_addr, src, size);
  82. #endif
  83. } else {
  84. return spi_flash_write(dest_addr, src, size);
  85. }
  86. }
  87. esp_err_t bootloader_flash_erase_sector(size_t sector)
  88. {
  89. return spi_flash_erase_sector(sector);
  90. }
  91. esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
  92. {
  93. return spi_flash_erase_range(start_addr, size);
  94. }
  95. #else
  96. /* Bootloader version, uses ROM functions only */
  97. #if CONFIG_IDF_TARGET_ESP32
  98. #include "esp32/rom/spi_flash.h"
  99. #include "esp32/rom/cache.h"
  100. #elif CONFIG_IDF_TARGET_ESP32S2
  101. #include "esp32s2/rom/spi_flash.h"
  102. #include "esp32s2/rom/cache.h"
  103. #include "soc/cache_memory.h"
  104. #elif CONFIG_IDF_TARGET_ESP32S3
  105. #include "esp32s3/rom/spi_flash.h"
  106. #include "esp32s3/rom/cache.h"
  107. #include "soc/cache_memory.h"
  108. #elif CONFIG_IDF_TARGET_ESP32C3
  109. #include "esp32c3/rom/spi_flash.h"
  110. #include "esp32c3/rom/cache.h"
  111. #include "soc/cache_memory.h"
  112. #endif
  113. static const char *TAG = "bootloader_flash";
  114. #if CONFIG_IDF_TARGET_ESP32
  115. /* Use first 50 blocks in MMU for bootloader_mmap,
  116. 50th block for bootloader_flash_read
  117. */
  118. #define MMU_BLOCK0_VADDR SOC_DROM_LOW
  119. #define MMU_SIZE (0x320000)
  120. #define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
  121. #define FLASH_READ_VADDR MMU_BLOCK50_VADDR
  122. #else // !CONFIG_IDF_TARGET_ESP32
  123. /* Use first 63 blocks in MMU for bootloader_mmap,
  124. 63th block for bootloader_flash_read
  125. */
  126. #define MMU_BLOCK0_VADDR SOC_DROM_LOW
  127. #define MMU_SIZE (0x3f0000)
  128. #define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
  129. #define FLASH_READ_VADDR MMU_BLOCK63_VADDR
  130. #endif
  131. #define MMU_FREE_PAGES (MMU_SIZE / FLASH_BLOCK_SIZE)
  132. static bool mapped;
  133. // Current bootloader mapping (ab)used for bootloader_read()
  134. static uint32_t current_read_mapping = UINT32_MAX;
  135. uint32_t bootloader_mmap_get_free_pages(void)
  136. {
  137. /**
  138. * Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
  139. * Since, bootloader_mmap function below assumes it to be 0x320000 (50 pages), we can safely do this.
  140. */
  141. return MMU_FREE_PAGES;
  142. }
  143. const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
  144. {
  145. if (mapped) {
  146. ESP_LOGE(TAG, "tried to bootloader_mmap twice");
  147. return NULL; /* can't map twice */
  148. }
  149. if (size > MMU_SIZE) {
  150. ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
  151. return NULL;
  152. }
  153. uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
  154. uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
  155. #if CONFIG_IDF_TARGET_ESP32
  156. Cache_Read_Disable(0);
  157. Cache_Flush(0);
  158. #elif CONFIG_IDF_TARGET_ESP32S2
  159. uint32_t autoload = Cache_Suspend_ICache();
  160. Cache_Invalidate_ICache_All();
  161. #elif CONFIG_IDF_TARGET_ESP32S3
  162. uint32_t autoload = Cache_Suspend_DCache();
  163. Cache_Invalidate_DCache_All();
  164. #elif CONFIG_IDF_TARGET_ESP32C3
  165. uint32_t autoload = Cache_Suspend_ICache();
  166. Cache_Invalidate_ICache_All();
  167. #endif
  168. ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
  169. src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
  170. #if CONFIG_IDF_TARGET_ESP32
  171. int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
  172. #elif CONFIG_IDF_TARGET_ESP32S2
  173. int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
  174. #else // S3, C3
  175. int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
  176. #endif
  177. if (e != 0) {
  178. ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
  179. #if CONFIG_IDF_TARGET_ESP32
  180. Cache_Read_Enable(0);
  181. #elif CONFIG_IDF_TARGET_ESP32S2
  182. Cache_Resume_ICache(autoload);
  183. #elif CONFIG_IDF_TARGET_ESP32S3
  184. Cache_Resume_DCache(autoload);
  185. #elif CONFIG_IDF_TARGET_ESP32C3
  186. Cache_Resume_ICache(autoload);
  187. #endif
  188. return NULL;
  189. }
  190. #if CONFIG_IDF_TARGET_ESP32
  191. Cache_Read_Enable(0);
  192. #elif CONFIG_IDF_TARGET_ESP32S2
  193. Cache_Resume_ICache(autoload);
  194. #elif CONFIG_IDF_TARGET_ESP32S3
  195. Cache_Resume_DCache(autoload);
  196. #elif CONFIG_IDF_TARGET_ESP32C3
  197. Cache_Resume_ICache(autoload);
  198. #endif
  199. mapped = true;
  200. return (void *)(MMU_BLOCK0_VADDR + (src_addr - src_addr_aligned));
  201. }
  202. void bootloader_munmap(const void *mapping)
  203. {
  204. if (mapped) {
  205. #if CONFIG_IDF_TARGET_ESP32
  206. /* Full MMU reset */
  207. Cache_Read_Disable(0);
  208. Cache_Flush(0);
  209. mmu_init(0);
  210. #elif CONFIG_IDF_TARGET_ESP32S2
  211. //TODO, save the autoload value.
  212. Cache_Suspend_ICache();
  213. Cache_Invalidate_ICache_All();
  214. Cache_MMU_Init();
  215. #elif CONFIG_IDF_TARGET_ESP32S3
  216. Cache_Suspend_DCache();
  217. Cache_Invalidate_DCache_All();
  218. Cache_MMU_Init();
  219. #elif CONFIG_IDF_TARGET_ESP32C3
  220. //TODO, save the autoload value.
  221. Cache_Suspend_ICache();
  222. Cache_Invalidate_ICache_All();
  223. Cache_MMU_Init();
  224. #endif
  225. mapped = false;
  226. current_read_mapping = UINT32_MAX;
  227. }
  228. }
  229. static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
  230. {
  231. switch (r) {
  232. case ESP_ROM_SPIFLASH_RESULT_OK:
  233. return ESP_OK;
  234. case ESP_ROM_SPIFLASH_RESULT_ERR:
  235. return ESP_ERR_FLASH_OP_FAIL;
  236. case ESP_ROM_SPIFLASH_RESULT_TIMEOUT:
  237. return ESP_ERR_FLASH_OP_TIMEOUT;
  238. default:
  239. return ESP_FAIL;
  240. }
  241. }
  242. static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size)
  243. {
  244. #if CONFIG_IDF_TARGET_ESP32
  245. Cache_Read_Disable(0);
  246. Cache_Flush(0);
  247. #elif CONFIG_IDF_TARGET_ESP32S2
  248. uint32_t autoload = Cache_Suspend_ICache();
  249. #elif CONFIG_IDF_TARGET_ESP32S3
  250. uint32_t autoload = Cache_Suspend_DCache();
  251. #elif CONFIG_IDF_TARGET_ESP32C3
  252. uint32_t autoload = Cache_Suspend_ICache();
  253. #endif
  254. esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
  255. #if CONFIG_IDF_TARGET_ESP32
  256. Cache_Read_Enable(0);
  257. #elif CONFIG_IDF_TARGET_ESP32S2
  258. Cache_Resume_ICache(autoload);
  259. #elif CONFIG_IDF_TARGET_ESP32S3
  260. Cache_Resume_DCache(autoload);
  261. #elif CONFIG_IDF_TARGET_ESP32C3
  262. Cache_Resume_ICache(autoload);
  263. #endif
  264. return spi_to_esp_err(r);
  265. }
  266. static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest, size_t size)
  267. {
  268. uint32_t *dest_words = (uint32_t *)dest;
  269. for (size_t word = 0; word < size / 4; word++) {
  270. uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */
  271. uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */
  272. uint32_t *map_ptr;
  273. if (map_at != current_read_mapping) {
  274. /* Move the 64KB mmu mapping window to fit map_at */
  275. #if CONFIG_IDF_TARGET_ESP32
  276. Cache_Read_Disable(0);
  277. Cache_Flush(0);
  278. #elif CONFIG_IDF_TARGET_ESP32S2
  279. uint32_t autoload = Cache_Suspend_ICache();
  280. Cache_Invalidate_ICache_All();
  281. #elif CONFIG_IDF_TARGET_ESP32S3
  282. uint32_t autoload = Cache_Suspend_DCache();
  283. Cache_Invalidate_DCache_All();
  284. #elif CONFIG_IDF_TARGET_ESP32C3
  285. uint32_t autoload = Cache_Suspend_ICache();
  286. Cache_Invalidate_ICache_All();
  287. #endif
  288. ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
  289. #if CONFIG_IDF_TARGET_ESP32
  290. int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
  291. #elif CONFIG_IDF_TARGET_ESP32S2
  292. int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
  293. #elif CONFIG_IDF_TARGET_ESP32S3
  294. int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
  295. #elif CONFIG_IDF_TARGET_ESP32C3
  296. int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
  297. #endif
  298. if (e != 0) {
  299. ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
  300. #if CONFIG_IDF_TARGET_ESP32
  301. Cache_Read_Enable(0);
  302. #elif CONFIG_IDF_TARGET_ESP32S2
  303. Cache_Resume_ICache(autoload);
  304. #elif CONFIG_IDF_TARGET_ESP32S3
  305. Cache_Resume_DCache(autoload);
  306. #elif CONFIG_IDF_TARGET_ESP32C3
  307. Cache_Resume_ICache(autoload);
  308. #endif
  309. return ESP_FAIL;
  310. }
  311. current_read_mapping = map_at;
  312. #if CONFIG_IDF_TARGET_ESP32
  313. Cache_Read_Enable(0);
  314. #elif CONFIG_IDF_TARGET_ESP32S2
  315. Cache_Resume_ICache(autoload);
  316. #elif CONFIG_IDF_TARGET_ESP32S3
  317. Cache_Resume_DCache(autoload);
  318. #elif CONFIG_IDF_TARGET_ESP32C3
  319. Cache_Resume_ICache(autoload);
  320. #endif
  321. }
  322. map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
  323. dest_words[word] = *map_ptr;
  324. }
  325. return ESP_OK;
  326. }
  327. esp_err_t bootloader_flash_read(size_t src_addr, void *dest, size_t size, bool allow_decrypt)
  328. {
  329. if (src_addr & 3) {
  330. ESP_LOGE(TAG, "bootloader_flash_read src_addr 0x%x not 4-byte aligned", src_addr);
  331. return ESP_FAIL;
  332. }
  333. if (size & 3) {
  334. ESP_LOGE(TAG, "bootloader_flash_read size 0x%x not 4-byte aligned", size);
  335. return ESP_FAIL;
  336. }
  337. if ((intptr_t)dest & 3) {
  338. ESP_LOGE(TAG, "bootloader_flash_read dest 0x%x not 4-byte aligned", (intptr_t)dest);
  339. return ESP_FAIL;
  340. }
  341. if (allow_decrypt) {
  342. return bootloader_flash_read_allow_decrypt(src_addr, dest, size);
  343. } else {
  344. return bootloader_flash_read_no_decrypt(src_addr, dest, size);
  345. }
  346. }
  347. esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
  348. {
  349. esp_err_t err;
  350. size_t alignment = write_encrypted ? 32 : 4;
  351. if ((dest_addr % alignment) != 0) {
  352. ESP_LOGE(TAG, "bootloader_flash_write dest_addr 0x%x not %d-byte aligned", dest_addr, alignment);
  353. return ESP_FAIL;
  354. }
  355. if ((size % alignment) != 0) {
  356. ESP_LOGE(TAG, "bootloader_flash_write size 0x%x not %d-byte aligned", size, alignment);
  357. return ESP_FAIL;
  358. }
  359. if (((intptr_t)src % 4) != 0) {
  360. ESP_LOGE(TAG, "bootloader_flash_write src 0x%x not 4 byte aligned", (intptr_t)src);
  361. return ESP_FAIL;
  362. }
  363. err = spi_to_esp_err(esp_rom_spiflash_unlock());
  364. if (err != ESP_OK) {
  365. return err;
  366. }
  367. if (write_encrypted && !ENCRYPTION_IS_VIRTUAL) {
  368. return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
  369. } else {
  370. return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
  371. }
  372. }
  373. esp_err_t bootloader_flash_erase_sector(size_t sector)
  374. {
  375. return spi_to_esp_err(esp_rom_spiflash_erase_sector(sector));
  376. }
  377. esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
  378. {
  379. if (start_addr % FLASH_SECTOR_SIZE != 0) {
  380. return ESP_ERR_INVALID_ARG;
  381. }
  382. if (size % FLASH_SECTOR_SIZE != 0) {
  383. return ESP_ERR_INVALID_SIZE;
  384. }
  385. size_t start = start_addr / FLASH_SECTOR_SIZE;
  386. size_t end = start + size / FLASH_SECTOR_SIZE;
  387. const size_t sectors_per_block = FLASH_BLOCK_SIZE / FLASH_SECTOR_SIZE;
  388. esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
  389. for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
  390. if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) {
  391. rc = esp_rom_spiflash_erase_block(sector / sectors_per_block);
  392. sector += sectors_per_block;
  393. } else {
  394. rc = esp_rom_spiflash_erase_sector(sector);
  395. ++sector;
  396. }
  397. }
  398. return spi_to_esp_err(rc);
  399. }
  400. #endif
  401. #ifndef g_rom_spiflash_dummy_len_plus // ESP32-C3 uses a macro to access ROM data here
  402. extern uint8_t g_rom_spiflash_dummy_len_plus[];
  403. #endif
  404. uint32_t bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
  405. {
  406. uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
  407. #if CONFIG_IDF_TARGET_ESP32
  408. SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
  409. #else
  410. SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
  411. #endif
  412. SPIFLASH.user.usr_dummy = 0;
  413. SPIFLASH.user.usr_addr = 0;
  414. SPIFLASH.user.usr_command = 1;
  415. SPIFLASH.user2.usr_command_bitlen = 7;
  416. SPIFLASH.user2.usr_command_value = command;
  417. SPIFLASH.user.usr_miso = miso_len > 0;
  418. #if CONFIG_IDF_TARGET_ESP32
  419. SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
  420. #else
  421. SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
  422. #endif
  423. SPIFLASH.user.usr_mosi = mosi_len > 0;
  424. #if CONFIG_IDF_TARGET_ESP32
  425. SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
  426. #else
  427. SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
  428. #endif
  429. SPIFLASH.data_buf[0] = mosi_data;
  430. if (g_rom_spiflash_dummy_len_plus[1]) {
  431. /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
  432. if (miso_len > 0) {
  433. SPIFLASH.user.usr_dummy = 1;
  434. SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
  435. } else {
  436. SPIFLASH.user.usr_dummy = 0;
  437. SPIFLASH.user1.usr_dummy_cyclelen = 0;
  438. }
  439. }
  440. SPIFLASH.cmd.usr = 1;
  441. while (SPIFLASH.cmd.usr != 0) {
  442. }
  443. SPIFLASH.ctrl.val = old_ctrl_reg;
  444. return SPIFLASH.data_buf[0];
  445. }
  446. void bootloader_enable_wp(void)
  447. {
  448. bootloader_execute_flash_command(CMD_WRDI, 0, 0, 0); /* Exit OTP mode */
  449. }
  450. #if SOC_CACHE_SUPPORT_WRAP
  451. esp_err_t bootloader_flash_wrap_set(spi_flash_wrap_mode_t mode)
  452. {
  453. uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
  454. uint32_t reg_bkp_usr = SPIFLASH.user.val;
  455. SPIFLASH.user.fwrite_dio = 0;
  456. SPIFLASH.user.fwrite_dual = 0;
  457. SPIFLASH.user.fwrite_qio = 1;
  458. SPIFLASH.user.fwrite_quad = 0;
  459. SPIFLASH.ctrl.fcmd_dual = 0;
  460. SPIFLASH.ctrl.fcmd_quad = 0;
  461. SPIFLASH.user.usr_dummy = 0;
  462. SPIFLASH.user.usr_addr = 1;
  463. SPIFLASH.user.usr_command = 1;
  464. SPIFLASH.user2.usr_command_bitlen = 7;
  465. SPIFLASH.user2.usr_command_value = CMD_WRAP;
  466. SPIFLASH.user1.usr_addr_bitlen = 23;
  467. SPIFLASH.addr = 0;
  468. SPIFLASH.user.usr_miso = 0;
  469. SPIFLASH.user.usr_mosi = 1;
  470. SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
  471. SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
  472. SPIFLASH.cmd.usr = 1;
  473. while(SPIFLASH.cmd.usr != 0)
  474. { }
  475. SPIFLASH.ctrl.val = reg_bkp_ctrl;
  476. SPIFLASH.user.val = reg_bkp_usr;
  477. return ESP_OK;
  478. }
  479. #endif //SOC_CACHE_SUPPORT_WRAP