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