mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-30 22:51:41 +01:00 
			
		
		
		
	
		
			
	
	
		
			142 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			142 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | // Copyright 2010-2018 Espressif Systems (Shanghai) PTE LTD
 | ||
|  | //
 | ||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||
|  | // you may not use this file except in compliance with the License.
 | ||
|  | // You may obtain a copy of the License at
 | ||
|  | //
 | ||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||
|  | //
 | ||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||
|  | // See the License for the specific language governing permissions and
 | ||
|  | // limitations under the License.
 | ||
|  | 
 | ||
|  | #include <stdint.h>
 | ||
|  | #include "soc/soc.h"
 | ||
|  | #include "soc/dport_reg.h"
 | ||
|  | #include "string.h"
 | ||
|  | #include "esp_spi_flash.h"
 | ||
|  | 
 | ||
|  | //Errors that can be returned
 | ||
|  | #define MMU_SET_ADDR_ALIGNED_ERROR 1
 | ||
|  | #define MMU_SET_PAGE_SIZE_ERROR 3
 | ||
|  | #define MMU_SET_VADDR_OUT_RANGE 5
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #define PROCACHE_MMU_ADDR_BASE 0x3FF10000
 | ||
|  | #define APPCACHE_MMU_ADDR_BASE 0x3FF12000
 | ||
|  | 
 | ||
|  | 
 | ||
|  | //sram
 | ||
|  | #define PRO_DRAM1_START_ADDR   0x3F800000
 | ||
|  | #define PRO_DRAM1_END_ADDR(psize)     (PRO_DRAM1_START_ADDR + ((psize) << 17))
 | ||
|  | //cache mmu register file address
 | ||
|  | #define CACHE_MMU_ADDRESS_BASE(cpu_no) ((cpu_no) ? (APPCACHE_MMU_ADDR_BASE) : (PROCACHE_MMU_ADDR_BASE))
 | ||
|  | //virtual address, physical address check
 | ||
|  | #define ADDRESS_CHECK(addr,psize) (((addr) & (0xFFFF >>((64/(psize))-1))) != 0)
 | ||
|  | //CPU number check
 | ||
|  | #define CPU_NUMBER_CHECK(cpu_no)  (((cpu_no)<0) || ((cpu_no)>1))
 | ||
|  | //PID check
 | ||
|  | #define PID_CHECK(pid)  (((pid)<0) || ((pid)>7))
 | ||
|  | //flash MMU edge check (flash size default : 16*1024 K)
 | ||
|  | #define FLASH_MMU_EDGE_CHECK(mmu_val,num) (((mmu_val) + (num)) > 256)
 | ||
|  | //sram MMU edge check (sram size default : 8*1024 K)
 | ||
|  | #define SRAM_MMU_EDGE_CHECK(mmu_val,num,psize) (((mmu_val) + (num)) > ((8*1024)/(psize)))
 | ||
|  | 
 | ||
|  | //We can relegate to the ROM version if the 2nd core isn't running (yet) and the RTOS is not started yet, for instance
 | ||
|  | //in the bootloader and in the app start process. The ROM code manually disables the cache, without using
 | ||
|  | //cache guards.
 | ||
|  | unsigned int cache_sram_mmu_set_rom(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num); | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifndef BOOTLOADER_BUILD
 | ||
|  | 
 | ||
|  | /*
 | ||
|  | Note that this function is a replacement for the ROM function with the same name, with these differences: | ||
|  | - It uses the DPORT workarounds | ||
|  | - It fixes a bug where the ROM version throws an error when vaddr is more than 2MiB into the memory region | ||
|  | - It uses the SPI cache guards to make sure the MMU is idle | ||
|  | */ | ||
|  | unsigned int IRAM_ATTR cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num) | ||
|  | { | ||
|  |     const spi_flash_guard_funcs_t *guard=spi_flash_guard_get(); | ||
|  |     if (!guard) { | ||
|  |         //Still starting up; guards not available yet. Use ROM version of code.
 | ||
|  |         return cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num); | ||
|  |     } | ||
|  | 
 | ||
|  |     unsigned int i,shift,mask_s; | ||
|  |     unsigned int mmu_addr; | ||
|  |     unsigned int mmu_table_val; | ||
|  |     //address check 
 | ||
|  |     if( (ADDRESS_CHECK(vaddr,psize)) || (ADDRESS_CHECK(paddr,psize)) ){ | ||
|  |         return MMU_SET_ADDR_ALIGNED_ERROR; | ||
|  |     } | ||
|  |     //psize check 
 | ||
|  |     if(psize == 32) { | ||
|  |         shift  = 15; | ||
|  |         mask_s = 0; | ||
|  |     } else if(psize == 16) { | ||
|  |         shift  = 14; | ||
|  |         mask_s = 1; | ||
|  |     } else if(psize == 8) { | ||
|  |         shift  = 13; | ||
|  |         mask_s = 2; | ||
|  |     } else if(psize == 4) { | ||
|  |         shift  = 12; | ||
|  |         mask_s = 3; | ||
|  |     } else if(psize == 2) { | ||
|  |         shift  = 11; | ||
|  |         mask_s = 4; | ||
|  |     } else { | ||
|  |         return MMU_SET_PAGE_SIZE_ERROR; | ||
|  |     } | ||
|  |     //mmu value
 | ||
|  |     mmu_table_val = paddr >> shift; | ||
|  |     //mmu_addr 
 | ||
|  |     if(pid == 0 || pid == 1){ | ||
|  |         if(vaddr >= PRO_DRAM1_START_ADDR && vaddr < PRO_DRAM1_END_ADDR(psize)){ | ||
|  |             mmu_addr = 1152 + ((vaddr & (0x3FFFFF >> mask_s)) >> shift); | ||
|  |         } else{ | ||
|  |             return MMU_SET_VADDR_OUT_RANGE; | ||
|  |         } | ||
|  |     } else { | ||
|  |         if(vaddr >= PRO_DRAM1_START_ADDR && vaddr < PRO_DRAM1_END_ADDR(psize)){ | ||
|  |             mmu_addr = (1024 + (pid<<7)) + ((vaddr & (0x3FFFFF >> mask_s)) >> shift); | ||
|  |         } else{ | ||
|  |             return MMU_SET_VADDR_OUT_RANGE; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     //The MMU registers are implemented in such a way that lookups from the cache subsystem may collide with
 | ||
|  |     //CPU access to the MMU registers. We use the flash guards to make sure the cache is disabled.
 | ||
|  |     guard->start(); | ||
|  | 
 | ||
|  |     //mmu change
 | ||
|  |     for ( i = 0; i < num; i++){ | ||
|  |         *(volatile unsigned int *)(CACHE_MMU_ADDRESS_BASE(cpu_no) + mmu_addr * 4) = mmu_table_val + i; //write table
 | ||
|  |         mmu_addr++; | ||
|  |     } | ||
|  | 
 | ||
|  |     if(cpu_no == 0){ | ||
|  |         DPORT_REG_SET_FIELD(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CMMU_SRAM_PAGE_MODE, mask_s); | ||
|  |     } else { | ||
|  |         DPORT_REG_SET_FIELD(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CMMU_SRAM_PAGE_MODE, mask_s); | ||
|  |     } | ||
|  | 
 | ||
|  |     guard->end(); | ||
|  | 
 | ||
|  |     return 0; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | #else
 | ||
|  | 
 | ||
|  | //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.
 | ||
|  | unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num) { | ||
|  |     return cache_sram_mmu_set_rom(cpu_no, pid, vaddr, paddr, psize, num); | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 |