cache_utils.c 35 KB

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