cache_sram_mmu.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright 2010-2018 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 <stdint.h>
  15. #include "soc/soc.h"
  16. #include "soc/dport_reg.h"
  17. #include "string.h"
  18. #include "esp_spi_flash.h"
  19. //Errors that can be returned
  20. #define MMU_SET_ADDR_ALIGNED_ERROR 1
  21. #define MMU_SET_PAGE_SIZE_ERROR 3
  22. #define MMU_SET_VADDR_OUT_RANGE 5
  23. #define PROCACHE_MMU_ADDR_BASE 0x3FF10000
  24. #define APPCACHE_MMU_ADDR_BASE 0x3FF12000
  25. //sram
  26. #define PRO_DRAM1_START_ADDR 0x3F800000
  27. #define PRO_DRAM1_END_ADDR(psize) (PRO_DRAM1_START_ADDR + ((psize) << 17))
  28. //cache mmu register file address
  29. #define CACHE_MMU_ADDRESS_BASE(cpu_no) ((cpu_no) ? (APPCACHE_MMU_ADDR_BASE) : (PROCACHE_MMU_ADDR_BASE))
  30. //virtual address, physical address check
  31. #define ADDRESS_CHECK(addr,psize) (((addr) & (0xFFFF >>((64/(psize))-1))) != 0)
  32. //CPU number check
  33. #define CPU_NUMBER_CHECK(cpu_no) (((cpu_no)<0) || ((cpu_no)>1))
  34. //PID check
  35. #define PID_CHECK(pid) (((pid)<0) || ((pid)>7))
  36. //flash MMU edge check (flash size default : 16*1024 K)
  37. #define FLASH_MMU_EDGE_CHECK(mmu_val,num) (((mmu_val) + (num)) > 256)
  38. //sram MMU edge check (sram size default : 8*1024 K)
  39. #define SRAM_MMU_EDGE_CHECK(mmu_val,num,psize) (((mmu_val) + (num)) > ((8*1024)/(psize)))
  40. //We can relegate to the ROM version if the 2nd core isn't running (yet) and the RTOS is not started yet, for instance
  41. //in the bootloader and in the app start process. The ROM code manually disables the cache, without using
  42. //cache guards.
  43. unsigned int cache_sram_mmu_set_rom(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);
  44. #ifndef BOOTLOADER_BUILD
  45. /*
  46. Note that this function is a replacement for the ROM function with the same name, with these differences:
  47. - It uses the DPORT workarounds
  48. - It fixes a bug where the ROM version throws an error when vaddr is more than 2MiB into the memory region
  49. - It uses the SPI cache guards to make sure the MMU is idle
  50. */
  51. unsigned int IRAM_ATTR cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num)
  52. {
  53. const spi_flash_guard_funcs_t *guard=spi_flash_guard_get();
  54. if (!guard) {
  55. //Still starting up; guards not available yet. Use ROM version of code.
  56. return cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num);
  57. }
  58. unsigned int i,shift,mask_s;
  59. unsigned int mmu_addr;
  60. unsigned int mmu_table_val;
  61. //address check
  62. if( (ADDRESS_CHECK(vaddr,psize)) || (ADDRESS_CHECK(paddr,psize)) ){
  63. return MMU_SET_ADDR_ALIGNED_ERROR;
  64. }
  65. //psize check
  66. if(psize == 32) {
  67. shift = 15;
  68. mask_s = 0;
  69. } else if(psize == 16) {
  70. shift = 14;
  71. mask_s = 1;
  72. } else if(psize == 8) {
  73. shift = 13;
  74. mask_s = 2;
  75. } else if(psize == 4) {
  76. shift = 12;
  77. mask_s = 3;
  78. } else if(psize == 2) {
  79. shift = 11;
  80. mask_s = 4;
  81. } else {
  82. return MMU_SET_PAGE_SIZE_ERROR;
  83. }
  84. //mmu value
  85. mmu_table_val = paddr >> shift;
  86. //mmu_addr
  87. if(pid == 0 || pid == 1){
  88. if(vaddr >= PRO_DRAM1_START_ADDR && vaddr < PRO_DRAM1_END_ADDR(psize)){
  89. mmu_addr = 1152 + ((vaddr & (0x3FFFFF >> mask_s)) >> shift);
  90. } else{
  91. return MMU_SET_VADDR_OUT_RANGE;
  92. }
  93. } else {
  94. if(vaddr >= PRO_DRAM1_START_ADDR && vaddr < PRO_DRAM1_END_ADDR(psize)){
  95. mmu_addr = (1024 + (pid<<7)) + ((vaddr & (0x3FFFFF >> mask_s)) >> shift);
  96. } else{
  97. return MMU_SET_VADDR_OUT_RANGE;
  98. }
  99. }
  100. //The MMU registers are implemented in such a way that lookups from the cache subsystem may collide with
  101. //CPU access to the MMU registers. We use the flash guards to make sure the cache is disabled.
  102. guard->start();
  103. //mmu change
  104. for ( i = 0; i < num; i++){
  105. *(volatile unsigned int *)(CACHE_MMU_ADDRESS_BASE(cpu_no) + mmu_addr * 4) = mmu_table_val + i; //write table
  106. mmu_addr++;
  107. }
  108. if(cpu_no == 0){
  109. DPORT_REG_SET_FIELD(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CMMU_SRAM_PAGE_MODE, mask_s);
  110. } else {
  111. DPORT_REG_SET_FIELD(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CMMU_SRAM_PAGE_MODE, mask_s);
  112. }
  113. guard->end();
  114. return 0;
  115. }
  116. #else
  117. //For the bootloader, we can always use the ROM version of this: it works well enough and keeps the size of the bootloader binary down.
  118. unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num) {
  119. return cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num);
  120. }
  121. #endif