cache_utils.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdlib.h>
  15. #include <assert.h>
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <freertos/FreeRTOS.h>
  19. #include <freertos/task.h>
  20. #include <freertos/semphr.h>
  21. #if CONFIG_IDF_TARGET_ESP32
  22. #include "soc/dport_reg.h"
  23. #include <esp32/rom/spi_flash.h>
  24. #include <esp32/rom/cache.h>
  25. #elif CONFIG_IDF_TARGET_ESP32S2
  26. #include "esp32s2/rom/spi_flash.h"
  27. #include "esp32s2/rom/cache.h"
  28. #include "soc/extmem_reg.h"
  29. #include "soc/cache_memory.h"
  30. #elif CONFIG_IDF_TARGET_ESP32S3
  31. #include "esp32s3/rom/spi_flash.h"
  32. #include "esp32s3/rom/cache.h"
  33. #include "soc/extmem_reg.h"
  34. #include "soc/cache_memory.h"
  35. #elif CONFIG_IDF_TARGET_ESP32C3
  36. #include "esp32c3/rom/spi_flash.h"
  37. #include "esp32c3/rom/cache.h"
  38. #include "soc/extmem_reg.h"
  39. #include "soc/cache_memory.h"
  40. #elif CONFIG_IDF_TARGET_ESP32H2
  41. #include "esp32h2/rom/spi_flash.h"
  42. #include "esp32h2/rom/cache.h"
  43. #include "soc/extmem_reg.h"
  44. #include "soc/cache_memory.h"
  45. #endif
  46. #include <soc/soc.h>
  47. #include "sdkconfig.h"
  48. #ifndef CONFIG_FREERTOS_UNICORE
  49. #include "esp_ipc.h"
  50. #endif
  51. #include "esp_attr.h"
  52. #include "esp_intr_alloc.h"
  53. #include "esp_spi_flash.h"
  54. #include "esp_log.h"
  55. static __attribute__((unused)) const char *TAG = "cache";
  56. #define DPORT_CACHE_BIT(cpuid, regid) DPORT_ ## cpuid ## regid
  57. #define DPORT_CACHE_MASK(cpuid) (DPORT_CACHE_BIT(cpuid, _CACHE_MASK_OPSDRAM) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DROM0) | \
  58. DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DRAM1) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IROM0) | \
  59. DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM1) | DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM0) )
  60. #define DPORT_CACHE_VAL(cpuid) (~(DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DROM0) | \
  61. DPORT_CACHE_BIT(cpuid, _CACHE_MASK_DRAM1) | \
  62. DPORT_CACHE_BIT(cpuid, _CACHE_MASK_IRAM0)))
  63. #define DPORT_CACHE_GET_VAL(cpuid) (cpuid == 0) ? DPORT_CACHE_VAL(PRO) : DPORT_CACHE_VAL(APP)
  64. #define DPORT_CACHE_GET_MASK(cpuid) (cpuid == 0) ? DPORT_CACHE_MASK(PRO) : DPORT_CACHE_MASK(APP)
  65. static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state);
  66. static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
  67. static uint32_t s_flash_op_cache_state[2];
  68. #ifndef CONFIG_FREERTOS_UNICORE
  69. static SemaphoreHandle_t s_flash_op_mutex;
  70. static volatile bool s_flash_op_can_start = false;
  71. static volatile bool s_flash_op_complete = false;
  72. #ifndef NDEBUG
  73. static volatile int s_flash_op_cpu = -1;
  74. #endif
  75. void spi_flash_init_lock(void)
  76. {
  77. s_flash_op_mutex = xSemaphoreCreateRecursiveMutex();
  78. assert(s_flash_op_mutex != NULL);
  79. }
  80. void spi_flash_op_lock(void)
  81. {
  82. xSemaphoreTakeRecursive(s_flash_op_mutex, portMAX_DELAY);
  83. }
  84. void spi_flash_op_unlock(void)
  85. {
  86. xSemaphoreGiveRecursive(s_flash_op_mutex);
  87. }
  88. /*
  89. If you're going to modify this, keep in mind that while the flash caches of the pro and app
  90. cpu are separate, the psram cache is *not*. If one of the CPUs returns from a flash routine
  91. with its cache enabled but the other CPUs cache is not enabled yet, you will have problems
  92. when accessing psram from the former CPU.
  93. */
  94. void IRAM_ATTR spi_flash_op_block_func(void *arg)
  95. {
  96. // Disable scheduler on this CPU
  97. vTaskSuspendAll();
  98. // Restore interrupts that aren't located in IRAM
  99. esp_intr_noniram_disable();
  100. uint32_t cpuid = (uint32_t) arg;
  101. // s_flash_op_complete flag is cleared on *this* CPU, otherwise the other
  102. // CPU may reset the flag back to false before IPC task has a chance to check it
  103. // (if it is preempted by an ISR taking non-trivial amount of time)
  104. s_flash_op_complete = false;
  105. s_flash_op_can_start = true;
  106. while (!s_flash_op_complete) {
  107. // busy loop here and wait for the other CPU to finish flash operation
  108. }
  109. // Flash operation is complete, re-enable cache
  110. spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
  111. // Restore interrupts that aren't located in IRAM
  112. esp_intr_noniram_enable();
  113. // Re-enable scheduler
  114. xTaskResumeAll();
  115. }
  116. void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
  117. {
  118. assert(esp_ptr_in_dram((const void *)esp_cpu_get_sp()));
  119. spi_flash_op_lock();
  120. const int cpuid = xPortGetCoreID();
  121. const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
  122. #ifndef NDEBUG
  123. // For sanity check later: record the CPU which has started doing flash operation
  124. assert(s_flash_op_cpu == -1);
  125. s_flash_op_cpu = cpuid;
  126. #endif
  127. if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
  128. // Scheduler hasn't been started yet, it means that spi_flash API is being
  129. // called from the 2nd stage bootloader or from user_start_cpu0, i.e. from
  130. // PRO CPU. APP CPU is either in reset or spinning inside user_start_cpu1,
  131. // which is in IRAM. So it is safe to disable cache for the other_cpuid after
  132. // esp_intr_noniram_disable.
  133. assert(other_cpuid == 1);
  134. } else {
  135. // Temporarily raise current task priority to prevent a deadlock while
  136. // waiting for IPC task to start on the other CPU
  137. int old_prio = uxTaskPriorityGet(NULL);
  138. vTaskPrioritySet(NULL, configMAX_PRIORITIES - 1);
  139. // Signal to the spi_flash_op_block_task on the other CPU that we need it to
  140. // disable cache there and block other tasks from executing.
  141. s_flash_op_can_start = false;
  142. ESP_ERROR_CHECK(esp_ipc_call(other_cpuid, &spi_flash_op_block_func, (void *) other_cpuid));
  143. while (!s_flash_op_can_start) {
  144. // Busy loop and wait for spi_flash_op_block_func to disable cache
  145. // on the other CPU
  146. }
  147. // Disable scheduler on the current CPU
  148. vTaskSuspendAll();
  149. // Can now set the priority back to the normal one
  150. vTaskPrioritySet(NULL, old_prio);
  151. // This is guaranteed to run on CPU <cpuid> because the other CPU is now
  152. // occupied by highest priority task
  153. assert(xPortGetCoreID() == cpuid);
  154. }
  155. // Kill interrupts that aren't located in IRAM
  156. esp_intr_noniram_disable();
  157. // This CPU executes this routine, with non-IRAM interrupts and the scheduler
  158. // disabled. The other CPU is spinning in the spi_flash_op_block_func task, also
  159. // with non-iram interrupts and the scheduler disabled. None of these CPUs will
  160. // touch external RAM or flash this way, so we can safely disable caches.
  161. spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
  162. spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]);
  163. }
  164. void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu(void)
  165. {
  166. const int cpuid = xPortGetCoreID();
  167. const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
  168. #ifndef NDEBUG
  169. // Sanity check: flash operation ends on the same CPU as it has started
  170. assert(cpuid == s_flash_op_cpu);
  171. // More sanity check: if scheduler isn't started, only CPU0 can call this.
  172. assert(!(xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED && cpuid != 0));
  173. s_flash_op_cpu = -1;
  174. #endif
  175. // Re-enable cache on both CPUs. After this, cache (flash and external RAM) should work again.
  176. spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
  177. spi_flash_restore_cache(other_cpuid, s_flash_op_cache_state[other_cpuid]);
  178. if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
  179. // Signal to spi_flash_op_block_task that flash operation is complete
  180. s_flash_op_complete = true;
  181. }
  182. // Re-enable non-iram interrupts
  183. esp_intr_noniram_enable();
  184. // Resume tasks on the current CPU, if the scheduler has started.
  185. // NOTE: enabling non-IRAM interrupts has to happen before this,
  186. // because once the scheduler has started, due to preemption the
  187. // current task can end up being moved to the other CPU.
  188. // But esp_intr_noniram_enable has to be called on the same CPU which
  189. // called esp_intr_noniram_disable
  190. if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
  191. xTaskResumeAll();
  192. }
  193. // Release API lock
  194. spi_flash_op_unlock();
  195. }
  196. void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_no_os(void)
  197. {
  198. const uint32_t cpuid = xPortGetCoreID();
  199. const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
  200. // do not care about other CPU, it was halted upon entering panic handler
  201. spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]);
  202. // Kill interrupts that aren't located in IRAM
  203. esp_intr_noniram_disable();
  204. // Disable cache on this CPU as well
  205. spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
  206. }
  207. void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os(void)
  208. {
  209. const uint32_t cpuid = xPortGetCoreID();
  210. // Re-enable cache on this CPU
  211. spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
  212. // Re-enable non-iram interrupts
  213. esp_intr_noniram_enable();
  214. }
  215. #else // CONFIG_FREERTOS_UNICORE
  216. void spi_flash_init_lock(void)
  217. {
  218. }
  219. void spi_flash_op_lock(void)
  220. {
  221. vTaskSuspendAll();
  222. }
  223. void spi_flash_op_unlock(void)
  224. {
  225. xTaskResumeAll();
  226. }
  227. void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
  228. {
  229. spi_flash_op_lock();
  230. esp_intr_noniram_disable();
  231. spi_flash_disable_cache(0, &s_flash_op_cache_state[0]);
  232. }
  233. void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu(void)
  234. {
  235. spi_flash_restore_cache(0, s_flash_op_cache_state[0]);
  236. esp_intr_noniram_enable();
  237. spi_flash_op_unlock();
  238. }
  239. void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_no_os(void)
  240. {
  241. // Kill interrupts that aren't located in IRAM
  242. esp_intr_noniram_disable();
  243. // Disable cache on this CPU as well
  244. spi_flash_disable_cache(0, &s_flash_op_cache_state[0]);
  245. }
  246. void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os(void)
  247. {
  248. // Re-enable cache on this CPU
  249. spi_flash_restore_cache(0, s_flash_op_cache_state[0]);
  250. // Re-enable non-iram interrupts
  251. esp_intr_noniram_enable();
  252. }
  253. #endif // CONFIG_FREERTOS_UNICORE
  254. /**
  255. * The following two functions are replacements for Cache_Read_Disable and Cache_Read_Enable
  256. * function in ROM. They are used to work around a bug where Cache_Read_Disable requires a call to
  257. * Cache_Flush before Cache_Read_Enable, even if cached data was not modified.
  258. */
  259. static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state)
  260. {
  261. #if CONFIG_IDF_TARGET_ESP32
  262. uint32_t ret = 0;
  263. const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
  264. if (cpuid == 0) {
  265. ret |= DPORT_GET_PERI_REG_BITS2(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, 0);
  266. while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) {
  267. ;
  268. }
  269. DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
  270. }
  271. #if !CONFIG_FREERTOS_UNICORE
  272. else {
  273. ret |= DPORT_GET_PERI_REG_BITS2(DPORT_APP_CACHE_CTRL1_REG, cache_mask, 0);
  274. while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1) {
  275. ;
  276. }
  277. DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
  278. }
  279. #endif
  280. *saved_state = ret;
  281. #elif CONFIG_IDF_TARGET_ESP32S2
  282. *saved_state = Cache_Suspend_ICache();
  283. #elif CONFIG_IDF_TARGET_ESP32S3
  284. uint32_t icache_state, dcache_state;
  285. icache_state = Cache_Suspend_ICache() << 16;
  286. dcache_state = Cache_Suspend_DCache();
  287. *saved_state = icache_state | dcache_state;
  288. #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
  289. uint32_t icache_state;
  290. icache_state = Cache_Suspend_ICache() << 16;
  291. *saved_state = icache_state;
  292. #endif
  293. }
  294. static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
  295. {
  296. #if CONFIG_IDF_TARGET_ESP32
  297. const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
  298. if (cpuid == 0) {
  299. DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
  300. DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
  301. }
  302. #if !CONFIG_FREERTOS_UNICORE
  303. else {
  304. DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
  305. DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
  306. }
  307. #endif
  308. #elif CONFIG_IDF_TARGET_ESP32S2
  309. Cache_Resume_ICache(saved_state);
  310. #elif CONFIG_IDF_TARGET_ESP32S3
  311. Cache_Resume_DCache(saved_state & 0xffff);
  312. Cache_Resume_ICache(saved_state >> 16);
  313. #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
  314. Cache_Resume_ICache(saved_state >> 16);
  315. #endif
  316. }
  317. IRAM_ATTR bool spi_flash_cache_enabled(void)
  318. {
  319. #if CONFIG_IDF_TARGET_ESP32
  320. bool result = (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE) != 0);
  321. #if portNUM_PROCESSORS == 2
  322. result = result && (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE) != 0);
  323. #endif
  324. #elif CONFIG_IDF_TARGET_ESP32S2
  325. bool result = (REG_GET_BIT(EXTMEM_PRO_ICACHE_CTRL_REG, EXTMEM_PRO_ICACHE_ENABLE) != 0);
  326. #elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
  327. bool result = (REG_GET_BIT(EXTMEM_ICACHE_CTRL_REG, EXTMEM_ICACHE_ENABLE) != 0);
  328. #endif
  329. return result;
  330. }
  331. #if CONFIG_IDF_TARGET_ESP32S2
  332. IRAM_ATTR void esp_config_instruction_cache_mode(void)
  333. {
  334. cache_size_t cache_size;
  335. cache_ways_t cache_ways;
  336. cache_line_size_t cache_line_size;
  337. #if CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB
  338. Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
  339. cache_size = CACHE_SIZE_8KB;
  340. #else
  341. Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
  342. cache_size = CACHE_SIZE_16KB;
  343. #endif
  344. cache_ways = CACHE_4WAYS_ASSOC;
  345. #if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B
  346. cache_line_size = CACHE_LINE_SIZE_16B;
  347. #else
  348. cache_line_size = CACHE_LINE_SIZE_32B;
  349. #endif
  350. ESP_EARLY_LOGI(TAG, "Instruction cache \t: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_8KB ? 8 : 16, 4, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : 32);
  351. Cache_Suspend_ICache();
  352. Cache_Set_ICache_Mode(cache_size, cache_ways, cache_line_size);
  353. Cache_Invalidate_ICache_All();
  354. Cache_Resume_ICache(0);
  355. }
  356. IRAM_ATTR void esp_config_data_cache_mode(void)
  357. {
  358. cache_size_t cache_size;
  359. cache_ways_t cache_ways;
  360. cache_line_size_t cache_line_size;
  361. #if CONFIG_ESP32S2_INSTRUCTION_CACHE_8KB
  362. #if CONFIG_ESP32S2_DATA_CACHE_8KB
  363. Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
  364. cache_size = CACHE_SIZE_8KB;
  365. #else
  366. Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_DCACHE_HIGH, CACHE_MEMORY_INVALID);
  367. cache_size = CACHE_SIZE_16KB;
  368. #endif
  369. #else
  370. #if CONFIG_ESP32S2_DATA_CACHE_8KB
  371. Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_INVALID);
  372. cache_size = CACHE_SIZE_8KB;
  373. #else
  374. Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_DCACHE_HIGH);
  375. cache_size = CACHE_SIZE_16KB;
  376. #endif
  377. #endif
  378. cache_ways = CACHE_4WAYS_ASSOC;
  379. #if CONFIG_ESP32S2_DATA_CACHE_LINE_16B
  380. cache_line_size = CACHE_LINE_SIZE_16B;
  381. #else
  382. cache_line_size = CACHE_LINE_SIZE_32B;
  383. #endif
  384. ESP_EARLY_LOGI(TAG, "Data cache \t\t: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_8KB ? 8 : 16, 4, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : 32);
  385. Cache_Set_DCache_Mode(cache_size, cache_ways, cache_line_size);
  386. Cache_Invalidate_DCache_All();
  387. }
  388. static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache, bool dcache)
  389. {
  390. uint32_t i_autoload, d_autoload;
  391. if (icache) {
  392. i_autoload = Cache_Suspend_ICache();
  393. }
  394. if (dcache) {
  395. d_autoload = Cache_Suspend_DCache();
  396. }
  397. REG_SET_BIT(EXTMEM_PRO_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_PRO_CACHE_FLASH_WRAP_AROUND);
  398. if (icache) {
  399. Cache_Resume_ICache(i_autoload);
  400. }
  401. if (dcache) {
  402. Cache_Resume_DCache(d_autoload);
  403. }
  404. }
  405. #if CONFIG_ESP32S2_SPIRAM_SUPPORT
  406. static IRAM_ATTR void esp_enable_cache_spiram_wrap(bool icache, bool dcache)
  407. {
  408. uint32_t i_autoload, d_autoload;
  409. if (icache) {
  410. i_autoload = Cache_Suspend_ICache();
  411. }
  412. if (dcache) {
  413. d_autoload = Cache_Suspend_DCache();
  414. }
  415. REG_SET_BIT(EXTMEM_PRO_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_PRO_CACHE_SRAM_RD_WRAP_AROUND);
  416. if (icache) {
  417. Cache_Resume_ICache(i_autoload);
  418. }
  419. if (dcache) {
  420. Cache_Resume_DCache(d_autoload);
  421. }
  422. }
  423. #endif
  424. esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable)
  425. {
  426. int icache_wrap_size = 0, dcache_wrap_size = 0;
  427. int flash_wrap_sizes[2] = {-1, -1}, spiram_wrap_sizes[2] = {-1, -1};
  428. int flash_wrap_size = 0, spiram_wrap_size = 0;
  429. int flash_count = 0, spiram_count = 0;
  430. int i;
  431. bool flash_spiram_wrap_together, flash_support_wrap = true, spiram_support_wrap = true;
  432. uint32_t drom0_in_icache = 1;//always 1 in esp32s2
  433. #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
  434. drom0_in_icache = 0;
  435. #endif
  436. if (icache_wrap_enable) {
  437. #if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32C3_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32H2_INSTRUCTION_CACHE_LINE_16B
  438. icache_wrap_size = 16;
  439. #else
  440. icache_wrap_size = 32;
  441. #endif
  442. }
  443. if (dcache_wrap_enable) {
  444. #if CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B || CONFIG_ESP32C3_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32H2_INSTRUCTION_CACHE_LINE_16B
  445. dcache_wrap_size = 16;
  446. #else
  447. dcache_wrap_size = 32;
  448. #endif
  449. }
  450. uint32_t instruction_use_spiram = 0;
  451. uint32_t rodata_use_spiram = 0;
  452. #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
  453. extern uint32_t esp_spiram_instruction_access_enabled(void);
  454. instruction_use_spiram = esp_spiram_instruction_access_enabled();
  455. #endif
  456. #if CONFIG_SPIRAM_RODATA
  457. extern uint32_t esp_spiram_rodata_access_enabled(void);
  458. rodata_use_spiram = esp_spiram_rodata_access_enabled();
  459. #endif
  460. if (instruction_use_spiram) {
  461. spiram_wrap_sizes[0] = icache_wrap_size;
  462. } else {
  463. flash_wrap_sizes[0] = icache_wrap_size;
  464. }
  465. if (rodata_use_spiram) {
  466. if (drom0_in_icache) {
  467. spiram_wrap_sizes[0] = icache_wrap_size;
  468. } else {
  469. spiram_wrap_sizes[1] = dcache_wrap_size;
  470. flash_wrap_sizes[1] = dcache_wrap_size;
  471. }
  472. #ifdef CONFIG_EXT_RODATA_SUPPORT
  473. spiram_wrap_sizes[1] = dcache_wrap_size;
  474. #endif
  475. } else {
  476. if (drom0_in_icache) {
  477. flash_wrap_sizes[0] = icache_wrap_size;
  478. } else {
  479. flash_wrap_sizes[1] = dcache_wrap_size;
  480. }
  481. #ifdef CONFIG_EXT_RODATA_SUPPORT
  482. flash_wrap_sizes[1] = dcache_wrap_size;
  483. #endif
  484. }
  485. #ifdef CONFIG_ESP32S2_SPIRAM_SUPPORT
  486. spiram_wrap_sizes[1] = dcache_wrap_size;
  487. #endif
  488. for (i = 0; i < 2; i++) {
  489. if (flash_wrap_sizes[i] != -1) {
  490. flash_count++;
  491. flash_wrap_size = flash_wrap_sizes[i];
  492. }
  493. }
  494. for (i = 0; i < 2; i++) {
  495. if (spiram_wrap_sizes[i] != -1) {
  496. spiram_count++;
  497. spiram_wrap_size = spiram_wrap_sizes[i];
  498. }
  499. }
  500. if (flash_count + spiram_count <= 2) {
  501. flash_spiram_wrap_together = false;
  502. } else {
  503. flash_spiram_wrap_together = true;
  504. }
  505. ESP_EARLY_LOGI(TAG, "flash_count=%d, size=%d, spiram_count=%d, size=%d,together=%d", flash_count, flash_wrap_size, spiram_count, spiram_wrap_size, flash_spiram_wrap_together);
  506. if (flash_count > 1 && flash_wrap_sizes[0] != flash_wrap_sizes[1]) {
  507. ESP_EARLY_LOGW(TAG, "Flash wrap with different length %d and %d, abort wrap.", flash_wrap_sizes[0], flash_wrap_sizes[1]);
  508. if (spiram_wrap_size == 0) {
  509. return ESP_FAIL;
  510. }
  511. if (flash_spiram_wrap_together) {
  512. ESP_EARLY_LOGE(TAG, "Abort spiram wrap because flash wrap length not fixed.");
  513. return ESP_FAIL;
  514. }
  515. }
  516. if (spiram_count > 1 && spiram_wrap_sizes[0] != spiram_wrap_sizes[1]) {
  517. ESP_EARLY_LOGW(TAG, "SPIRAM wrap with different length %d and %d, abort wrap.", spiram_wrap_sizes[0], spiram_wrap_sizes[1]);
  518. if (flash_wrap_size == 0) {
  519. return ESP_FAIL;
  520. }
  521. if (flash_spiram_wrap_together) {
  522. ESP_EARLY_LOGW(TAG, "Abort flash wrap because spiram wrap length not fixed.");
  523. return ESP_FAIL;
  524. }
  525. }
  526. if (flash_spiram_wrap_together && flash_wrap_size != spiram_wrap_size) {
  527. ESP_EARLY_LOGW(TAG, "SPIRAM has different wrap length with flash, %d and %d, abort wrap.", spiram_wrap_size, flash_wrap_size);
  528. return ESP_FAIL;
  529. }
  530. #ifdef CONFIG_FLASHMODE_QIO
  531. flash_support_wrap = true;
  532. extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
  533. if (!spi_flash_support_wrap_size(flash_wrap_size)) {
  534. flash_support_wrap = false;
  535. ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
  536. }
  537. #else
  538. ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
  539. #endif
  540. #ifdef CONFIG_ESP32S2_SPIRAM_SUPPORT
  541. extern bool psram_support_wrap_size(uint32_t wrap_size);
  542. if (!psram_support_wrap_size(spiram_wrap_size)) {
  543. spiram_support_wrap = false;
  544. ESP_EARLY_LOGW(TAG, "SPIRAM do not support wrap size %d.", spiram_wrap_size);
  545. }
  546. #endif
  547. if (flash_spiram_wrap_together && !(flash_support_wrap && spiram_support_wrap)) {
  548. ESP_EARLY_LOGW(TAG, "Flash and SPIRAM should support wrap together.");
  549. return ESP_FAIL;
  550. }
  551. extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
  552. if (flash_support_wrap && flash_wrap_size > 0) {
  553. ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
  554. spi_flash_enable_wrap(flash_wrap_size);
  555. esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
  556. }
  557. #if CONFIG_ESP32S2_SPIRAM_SUPPORT
  558. extern esp_err_t psram_enable_wrap(uint32_t wrap_size);
  559. if (spiram_support_wrap && spiram_wrap_size > 0) {
  560. ESP_EARLY_LOGI(TAG, "SPIRAM wrap enabled, size = %d.", spiram_wrap_size);
  561. psram_enable_wrap(spiram_wrap_size);
  562. esp_enable_cache_spiram_wrap((spiram_wrap_sizes[0] > 0), (spiram_wrap_sizes[1] > 0));
  563. }
  564. #endif
  565. return ESP_OK;
  566. }
  567. #endif
  568. #if CONFIG_IDF_TARGET_ESP32S3
  569. IRAM_ATTR void esp_config_instruction_cache_mode(void)
  570. {
  571. cache_size_t cache_size;
  572. cache_ways_t cache_ways;
  573. cache_line_size_t cache_line_size;
  574. #if CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB
  575. Cache_Occupy_ICache_MEMORY(CACHE_MEMORY_IBANK0, CACHE_MEMORY_INVALID);
  576. cache_size = CACHE_SIZE_HALF;
  577. #else
  578. Cache_Occupy_ICache_MEMORY(CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1);
  579. cache_size = CACHE_SIZE_FULL;
  580. #endif
  581. #if CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS
  582. cache_ways = CACHE_4WAYS_ASSOC;
  583. #else
  584. cache_ways = CACHE_8WAYS_ASSOC;
  585. #endif
  586. #if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
  587. cache_line_size = CACHE_LINE_SIZE_16B;
  588. #elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B
  589. cache_line_size = CACHE_LINE_SIZE_32B;
  590. #else
  591. cache_line_size = CACHE_LINE_SIZE_64B;
  592. #endif
  593. ESP_EARLY_LOGI(TAG, "Instruction cache: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_HALF ? 16 : 32, cache_ways == CACHE_4WAYS_ASSOC ? 4 : 8, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : (cache_line_size == CACHE_LINE_SIZE_32B ? 32 : 64));
  594. Cache_Set_ICache_Mode(cache_size, cache_ways, cache_line_size);
  595. Cache_Invalidate_ICache_All();
  596. extern void Cache_Enable_ICache(uint32_t autoload);
  597. Cache_Enable_ICache(0);
  598. }
  599. IRAM_ATTR void esp_config_data_cache_mode(void)
  600. {
  601. cache_size_t cache_size;
  602. cache_ways_t cache_ways;
  603. cache_line_size_t cache_line_size;
  604. #if CONFIG_ESP32S3_DATA_CACHE_32KB
  605. Cache_Occupy_DCache_MEMORY(CACHE_MEMORY_DBANK1, CACHE_MEMORY_INVALID);
  606. cache_size = CACHE_SIZE_HALF;
  607. #else
  608. Cache_Occupy_DCache_MEMORY(CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1);
  609. cache_size = CACHE_SIZE_FULL;
  610. #endif
  611. #if CONFIG_ESP32S3_DATA_CACHE_4WAYS
  612. cache_ways = CACHE_4WAYS_ASSOC;
  613. #else
  614. cache_ways = CACHE_8WAYS_ASSOC;
  615. #endif
  616. #if CONFIG_ESP32S3_DATA_CACHE_LINE_16B
  617. cache_line_size = CACHE_LINE_SIZE_16B;
  618. #elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B
  619. cache_line_size = CACHE_LINE_SIZE_32B;
  620. #else
  621. cache_line_size = CACHE_LINE_SIZE_64B;
  622. #endif
  623. // ESP_EARLY_LOGI(TAG, "Data cache: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_HALF ? 32 : 64, cache_ways == CACHE_4WAYS_ASSOC ? 4 : 8, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : (cache_line_size == CACHE_LINE_SIZE_32B ? 32 : 64));
  624. Cache_Set_DCache_Mode(cache_size, cache_ways, cache_line_size);
  625. Cache_Invalidate_DCache_All();
  626. }
  627. static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache, bool dcache)
  628. {
  629. uint32_t i_autoload, d_autoload;
  630. if (icache) {
  631. i_autoload = Cache_Suspend_ICache();
  632. }
  633. if (dcache) {
  634. d_autoload = Cache_Suspend_DCache();
  635. }
  636. REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_FLASH_WRAP_AROUND);
  637. if (icache) {
  638. Cache_Resume_ICache(i_autoload);
  639. }
  640. if (dcache) {
  641. Cache_Resume_DCache(d_autoload);
  642. }
  643. }
  644. #if CONFIG_ESP32S3_SPIRAM_SUPPORT
  645. static IRAM_ATTR void esp_enable_cache_spiram_wrap(bool icache, bool dcache)
  646. {
  647. uint32_t i_autoload, d_autoload;
  648. if (icache) {
  649. i_autoload = Cache_Suspend_ICache();
  650. }
  651. if (dcache) {
  652. d_autoload = Cache_Suspend_DCache();
  653. }
  654. REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_SRAM_RD_WRAP_AROUND);
  655. if (icache) {
  656. Cache_Resume_ICache(i_autoload);
  657. }
  658. if (dcache) {
  659. Cache_Resume_DCache(d_autoload);
  660. }
  661. }
  662. #endif
  663. esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable)
  664. {
  665. int icache_wrap_size = 0, dcache_wrap_size = 0;
  666. int flash_wrap_sizes[2] = {-1, -1}, spiram_wrap_sizes[2] = {-1, -1};
  667. int flash_wrap_size = 0, spiram_wrap_size = 0;
  668. int flash_count = 0, spiram_count = 0;
  669. int i;
  670. bool flash_spiram_wrap_together, flash_support_wrap = false, spiram_support_wrap = true;
  671. uint32_t drom0_in_icache = 0;//always 0 in chip7.2.4
  672. if (icache_wrap_enable) {
  673. #if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
  674. icache_wrap_size = 16;
  675. #elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B
  676. icache_wrap_size = 32;
  677. #else
  678. icache_wrap_size = 64;
  679. #endif
  680. }
  681. if (dcache_wrap_enable) {
  682. #if CONFIG_ESP32S3_DATA_CACHE_LINE_16B
  683. dcache_wrap_size = 16;
  684. #elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B
  685. dcache_wrap_size = 32;
  686. #else
  687. dcache_wrap_size = 64;
  688. #endif
  689. }
  690. uint32_t instruction_use_spiram = 0;
  691. uint32_t rodata_use_spiram = 0;
  692. #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
  693. extern uint32_t esp_spiram_instruction_access_enabled();
  694. instruction_use_spiram = esp_spiram_instruction_access_enabled();
  695. #endif
  696. #if CONFIG_SPIRAM_RODATA
  697. extern uint32_t esp_spiram_rodata_access_enabled();
  698. rodata_use_spiram = esp_spiram_rodata_access_enabled();
  699. #endif
  700. if (instruction_use_spiram) {
  701. spiram_wrap_sizes[0] = icache_wrap_size;
  702. } else {
  703. flash_wrap_sizes[0] = icache_wrap_size;
  704. }
  705. if (rodata_use_spiram) {
  706. if (drom0_in_icache) {
  707. spiram_wrap_sizes[0] = icache_wrap_size;
  708. } else {
  709. spiram_wrap_sizes[1] = dcache_wrap_size;
  710. }
  711. #ifdef CONFIG_EXT_RODATA_SUPPORT
  712. spiram_wrap_sizes[1] = dcache_wrap_size;
  713. #endif
  714. } else {
  715. if (drom0_in_icache) {
  716. flash_wrap_sizes[0] = icache_wrap_size;
  717. } else {
  718. flash_wrap_sizes[1] = dcache_wrap_size;
  719. }
  720. #ifdef CONFIG_EXT_RODATA_SUPPORT
  721. flash_wrap_sizes[1] = dcache_wrap_size;
  722. #endif
  723. }
  724. #ifdef CONFIG_ESP32S3_SPIRAM_SUPPORT
  725. spiram_wrap_sizes[1] = dcache_wrap_size;
  726. #endif
  727. for (i = 0; i < 2; i++) {
  728. if (flash_wrap_sizes[i] != -1) {
  729. flash_count++;
  730. flash_wrap_size = flash_wrap_sizes[i];
  731. }
  732. }
  733. for (i = 0; i < 2; i++) {
  734. if (spiram_wrap_sizes[i] != -1) {
  735. spiram_count++;
  736. spiram_wrap_size = spiram_wrap_sizes[i];
  737. }
  738. }
  739. if (flash_count + spiram_count <= 2) {
  740. flash_spiram_wrap_together = false;
  741. } else {
  742. flash_spiram_wrap_together = true;
  743. }
  744. if (flash_count > 1 && flash_wrap_sizes[0] != flash_wrap_sizes[1]) {
  745. ESP_EARLY_LOGW(TAG, "Flash wrap with different length %d and %d, abort wrap.", flash_wrap_sizes[0], flash_wrap_sizes[1]);
  746. if (spiram_wrap_size == 0) {
  747. return ESP_FAIL;
  748. }
  749. if (flash_spiram_wrap_together) {
  750. ESP_EARLY_LOGE(TAG, "Abort spiram wrap because flash wrap length not fixed.");
  751. return ESP_FAIL;
  752. }
  753. }
  754. if (spiram_count > 1 && spiram_wrap_sizes[0] != spiram_wrap_sizes[1]) {
  755. ESP_EARLY_LOGW(TAG, "SPIRAM wrap with different length %d and %d, abort wrap.", spiram_wrap_sizes[0], spiram_wrap_sizes[1]);
  756. if (flash_wrap_size == 0) {
  757. return ESP_FAIL;
  758. }
  759. if (flash_spiram_wrap_together) {
  760. ESP_EARLY_LOGW(TAG, "Abort flash wrap because spiram wrap length not fixed.");
  761. return ESP_FAIL;
  762. }
  763. }
  764. if (flash_spiram_wrap_together && flash_wrap_size != spiram_wrap_size) {
  765. ESP_EARLY_LOGW(TAG, "SPIRAM has different wrap length with flash, %d and %d, abort wrap.", spiram_wrap_size, flash_wrap_size);
  766. return ESP_FAIL;
  767. }
  768. #ifdef CONFIG_FLASHMODE_QIO
  769. flash_support_wrap = true;
  770. extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
  771. if (!spi_flash_support_wrap_size(flash_wrap_size)) {
  772. flash_support_wrap = false;
  773. ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
  774. }
  775. #else
  776. ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
  777. #endif
  778. #ifdef CONFIG_ESP32S3_SPIRAM_SUPPORT
  779. extern bool psram_support_wrap_size(uint32_t wrap_size);
  780. if (!psram_support_wrap_size(spiram_wrap_size)) {
  781. spiram_support_wrap = false;
  782. ESP_EARLY_LOGW(TAG, "SPIRAM do not support wrap size %d.", spiram_wrap_size);
  783. }
  784. #endif
  785. if (flash_spiram_wrap_together && !(flash_support_wrap && spiram_support_wrap)) {
  786. ESP_EARLY_LOGW(TAG, "Flash and SPIRAM should support wrap together.");
  787. return ESP_FAIL;
  788. }
  789. extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
  790. if (flash_support_wrap && flash_wrap_size > 0) {
  791. ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
  792. spi_flash_enable_wrap(flash_wrap_size);
  793. esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
  794. }
  795. #if CONFIG_ESP32S3_SPIRAM_SUPPORT
  796. extern esp_err_t psram_enable_wrap(uint32_t wrap_size);
  797. if (spiram_support_wrap && spiram_wrap_size > 0) {
  798. ESP_EARLY_LOGI(TAG, "SPIRAM wrap enabled, size = %d.", spiram_wrap_size);
  799. psram_enable_wrap(spiram_wrap_size);
  800. esp_enable_cache_spiram_wrap((spiram_wrap_sizes[0] > 0), (spiram_wrap_sizes[1] > 0));
  801. }
  802. #endif
  803. return ESP_OK;
  804. }
  805. #endif
  806. #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
  807. static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache)
  808. {
  809. uint32_t i_autoload;
  810. if (icache) {
  811. i_autoload = Cache_Suspend_ICache();
  812. }
  813. REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_FLASH_WRAP_AROUND);
  814. if (icache) {
  815. Cache_Resume_ICache(i_autoload);
  816. }
  817. }
  818. esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable)
  819. {
  820. int flash_wrap_size = 0;
  821. bool flash_support_wrap = false;
  822. if (icache_wrap_enable) {
  823. flash_wrap_size = 32;
  824. }
  825. #ifdef CONFIG_FLASHMODE_QIO
  826. flash_support_wrap = true;
  827. extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
  828. if (!spi_flash_support_wrap_size(flash_wrap_size)) {
  829. flash_support_wrap = false;
  830. ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
  831. }
  832. #else
  833. ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
  834. #endif // CONFIG_FLASHMODE_QIO
  835. extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
  836. if (flash_support_wrap && flash_wrap_size > 0) {
  837. ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
  838. spi_flash_enable_wrap(flash_wrap_size);
  839. esp_enable_cache_flash_wrap((flash_wrap_size > 0));
  840. }
  841. return ESP_OK;
  842. }
  843. #endif // CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
  844. void IRAM_ATTR spi_flash_enable_cache(uint32_t cpuid)
  845. {
  846. #if CONFIG_IDF_TARGET_ESP32
  847. uint32_t cache_value = DPORT_CACHE_GET_VAL(cpuid);
  848. cache_value &= DPORT_CACHE_GET_MASK(cpuid);
  849. // Re-enable cache on this CPU
  850. spi_flash_restore_cache(cpuid, cache_value);
  851. #else
  852. spi_flash_restore_cache(0, 0); // TODO cache_value should be non-zero
  853. #endif
  854. }