esp_psram_extram_cache.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "soc/dport_reg.h"
  7. #include "esp_attr.h"
  8. #include "esp_psram.h"
  9. #include "esp_private/esp_psram_extram.h"
  10. #if CONFIG_FREERTOS_UNICORE
  11. #define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
  12. #else
  13. #define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
  14. #endif
  15. /*
  16. Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
  17. otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
  18. Note that this routine assumes some unique mapping for the first 2 banks of the PSRAM memory range, as well as the
  19. 2 banks after the 2 MiB mark.
  20. */
  21. void IRAM_ATTR esp_psram_extram_writeback_cache(void)
  22. {
  23. int x;
  24. volatile int i=0;
  25. volatile uint8_t *psram=(volatile uint8_t*)SOC_EXTRAM_DATA_LOW;
  26. int cache_was_disabled=0;
  27. if (!esp_psram_is_initialized()) return;
  28. //We need cache enabled for this to work. Re-enable it if needed; make sure we
  29. //disable it again on exit as well.
  30. if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
  31. cache_was_disabled|=(1<<0);
  32. DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
  33. }
  34. #ifndef CONFIG_FREERTOS_UNICORE
  35. if (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
  36. cache_was_disabled|=(1<<1);
  37. DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
  38. }
  39. #endif
  40. #if (PSRAM_MODE != PSRAM_VADDR_MODE_LOWHIGH)
  41. /*
  42. Single-core and even/odd mode only have 32K of cache evenly distributed over the address lines. We can clear
  43. the cache by just reading 64K worth of cache lines.
  44. */
  45. for (x=0; x<1024*64; x+=32) {
  46. i+=psram[x];
  47. }
  48. #else
  49. /*
  50. Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI flash and another 32K for the highest
  51. 2MiB. Clear this by reading from both regions.
  52. Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If
  53. we ever support external RAM chips of 2M or smaller, this may need adjusting.
  54. */
  55. for (x=0; x<1024*64; x+=32) {
  56. i+=psram[x];
  57. i+=psram[x+(1024*1024*2)];
  58. }
  59. #endif
  60. if (cache_was_disabled&(1<<0)) {
  61. while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) ;
  62. DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
  63. }
  64. #ifndef CONFIG_FREERTOS_UNICORE
  65. if (cache_was_disabled&(1<<1)) {
  66. while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1);
  67. DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
  68. }
  69. #endif
  70. }