1 /* 2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * This file contains `spi_flash_mmap_xx` APIs, mainly for doing memory mapping 9 * to an SPI0-connected external Flash, as well as some helper functions to 10 * convert between virtual and physical address 11 **/ 12 13 #pragma once 14 15 #include <stdint.h> 16 #include <stdbool.h> 17 #include <stddef.h> 18 #include "esp_err.h" 19 #include "sdkconfig.h" 20 #include "esp_spi_flash_counters.h" 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 26 #define ESP_ERR_FLASH_OP_FAIL (ESP_ERR_FLASH_BASE + 1) 27 #define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2) 28 29 #define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */ 30 31 #define SPI_FLASH_MMU_PAGE_SIZE CONFIG_MMU_PAGE_SIZE /**< Flash cache MMU mapping page size */ 32 33 /** 34 * @brief Enumeration which specifies memory space requested in an mmap call 35 */ 36 typedef enum { 37 SPI_FLASH_MMAP_DATA, /**< map to data memory, allows byte-aligned access*/ 38 SPI_FLASH_MMAP_INST, /**< map to instruction memory, allows only 4-byte-aligned access*/ 39 } spi_flash_mmap_memory_t; 40 41 /** 42 * @brief Opaque handle for memory region obtained from spi_flash_mmap. 43 */ 44 typedef uint32_t spi_flash_mmap_handle_t; 45 46 /** 47 * @brief Map region of flash memory into data or instruction address space 48 * 49 * This function allocates sufficient number of 64kB MMU pages and configures 50 * them to map the requested region of flash memory into the address space. 51 * It may reuse MMU pages which already provide the required mapping. 52 * 53 * As with any allocator, if mmap/munmap are heavily used then the address space 54 * may become fragmented. To troubleshoot issues with page allocation, use 55 * spi_flash_mmap_dump() function. 56 * 57 * @param src_addr Physical address in flash where requested region starts. 58 * This address *must* be aligned to 64kB boundary 59 * (SPI_FLASH_MMU_PAGE_SIZE) 60 * @param size Size of region to be mapped. This size will be rounded 61 * up to a 64kB boundary 62 * @param memory Address space where the region should be mapped (data or instruction) 63 * @param[out] out_ptr Output, pointer to the mapped memory region 64 * @param[out] out_handle Output, handle which should be used for spi_flash_munmap call 65 * 66 * @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated 67 */ 68 esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory, 69 const void** out_ptr, spi_flash_mmap_handle_t* out_handle); 70 71 /** 72 * @brief Map sequences of pages of flash memory into data or instruction address space 73 * 74 * This function allocates sufficient number of 64kB MMU pages and configures 75 * them to map the indicated pages of flash memory contiguously into address space. 76 * In this respect, it works in a similar way as spi_flash_mmap() but it allows mapping 77 * a (maybe non-contiguous) set of pages into a contiguous region of memory. 78 * 79 * @param pages An array of numbers indicating the 64kB pages in flash to be mapped 80 * contiguously into memory. These indicate the indexes of the 64kB pages, 81 * not the byte-size addresses as used in other functions. 82 * Array must be located in internal memory. 83 * @param page_count Number of entries in the pages array 84 * @param memory Address space where the region should be mapped (instruction or data) 85 * @param[out] out_ptr Output, pointer to the mapped memory region 86 * @param[out] out_handle Output, handle which should be used for spi_flash_munmap call 87 * 88 * @return 89 * - ESP_OK on success 90 * - ESP_ERR_NO_MEM if pages can not be allocated 91 * - ESP_ERR_INVALID_ARG if pagecount is zero or pages array is not in 92 * internal memory 93 */ 94 esp_err_t spi_flash_mmap_pages(const int *pages, size_t page_count, spi_flash_mmap_memory_t memory, 95 const void** out_ptr, spi_flash_mmap_handle_t* out_handle); 96 97 98 /** 99 * @brief Release region previously obtained using spi_flash_mmap 100 * 101 * @note Calling this function will not necessarily unmap memory region. 102 * Region will only be unmapped when there are no other handles which 103 * reference this region. In case of partially overlapping regions 104 * it is possible that memory will be unmapped partially. 105 * 106 * @param handle Handle obtained from spi_flash_mmap 107 */ 108 void spi_flash_munmap(spi_flash_mmap_handle_t handle); 109 110 /** 111 * @brief Display information about mapped regions 112 * 113 * This function lists handles obtained using spi_flash_mmap, along with range 114 * of pages allocated to each handle. It also lists all non-zero entries of 115 * MMU table and corresponding reference counts. 116 */ 117 void spi_flash_mmap_dump(void); 118 119 /** 120 * @brief get free pages number which can be mmap 121 * 122 * This function will return number of free pages available in mmu table. This could be useful 123 * before calling actual spi_flash_mmap (maps flash range to DCache or ICache memory) to check 124 * if there is sufficient space available for mapping. 125 * 126 * @param memory memory type of MMU table free page 127 * 128 * @return number of free pages which can be mmaped 129 */ 130 uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory); 131 132 133 #define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */ 134 135 /** 136 * @brief Given a memory address where flash is mapped, return the corresponding physical flash offset. 137 * 138 * Cache address does not have have been assigned via spi_flash_mmap(), any address in memory mapped flash space can be looked up. 139 * 140 * @param cached Pointer to flashed cached memory. 141 * 142 * @return 143 * - SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped. 144 * - Otherwise, returns physical offset in flash 145 */ 146 size_t spi_flash_cache2phys(const void *cached); 147 148 /** @brief Given a physical offset in flash, return the address where it is mapped in the memory space. 149 * 150 * Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up. 151 * 152 * @note Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries 153 * point to the same physical address, there may be more than one cache address corresponding to that physical 154 * address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions. 155 * 156 * @note This function doesn't impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and 157 * phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash. 158 * 159 * @param phys_offs Physical offset in flash memory to look up. 160 * @param memory Address space type to look up a flash cache address mapping for (instruction or data) 161 * 162 * @return 163 * - NULL if the physical address is invalid or not mapped to flash cache of the specified memory type. 164 * - Cached memory address (in IROM or DROM space) corresponding to phys_offs. 165 */ 166 const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory); 167 168 #ifdef __cplusplus 169 } 170 #endif 171