1 /* 2 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #pragma once 7 8 #include <stdlib.h> 9 #include <stdint.h> 10 #include "esp_err.h" 11 #include "esp_bit_defs.h" 12 #include "hal/mmu_types.h" 13 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 /** 19 * MMU Memory Mapping Driver APIs for MMU supported memory 20 * 21 * 22 * Driver Backgrounds: 23 * 24 * -------------------------------------------------------------------------------------------------------- 25 * Memory Pool | 26 * -------------------------------------------------------------------------------------------------------- 27 * | Memory Region 0 | Memory Region 1 | ... | 28 * -------------------------------------------------------------------------------------------------------- 29 * | Block 0 | Slot 0 | Block 1 | Block 2 | ... | Slot 1 (final slot) | ... | 30 * -------------------------------------------------------------------------------------------------------- 31 * 32 * - A memory pool stands for the whole virtual address range that can be mapped to physical memory 33 * - A memory region is a range of virtual address with same attributes 34 * - A block is a piece of vaddr range that is dynamically mapped. 35 * - A Slot is the vaddr range between 2 blocks. 36 */ 37 38 39 /** 40 * MMAP flags 41 */ 42 /** 43 * @brief Share this mapping 44 * 45 * - If this flag is set, a paddr block can be mapped to multiple vaddr blocks. 46 * 1. This happens when: 47 * - the to-be-mapped paddr block is overlapped with an already mapped paddr block. 48 * - the to-be-mapped paddr block encloses an already mapped paddr block. 49 * 2. If the to-be-mapped paddr block is enclosed by an already mapped paddr block, no new mapping will happen, return ESP_ERR_INVALID_STATE. The out pointer will be the already mapped paddr corresponding vaddr. 50 * 3. If the to-be-mapped paddr block is identical with an already mapped paddr block, no new mapping will happen, return ESP_ERR_INVALID_STATE. The out pointer will be the corresponding vaddr. 51 * 52 * - If this flag isn't set, overlapped, enclosed or same to-be-mapped paddr block will lead to ESP_ERR_INVALID_ARG. 53 */ 54 #define ESP_MMU_MMAP_FLAG_PADDR_SHARED BIT(0) 55 56 /** 57 * @brief Physical memory type 58 */ 59 typedef uint32_t esp_paddr_t; 60 61 /** 62 * @brief Map a physical memory block to external virtual address block, with given capabilities. 63 * 64 * @note This API does not guarantee thread safety 65 * 66 * @param[in] paddr_start Start address of the physical memory block 67 * @param[in] size Size to be mapped. Size will be rounded up by to the nearest multiple of MMU page size 68 * @param[in] target Physical memory target you're going to map to, see `mmu_target_t` 69 * @param[in] caps Memory capabilities, see `mmu_mem_caps_t` 70 * @param[in] flags Mmap flags 71 * @param[out] out_ptr Start address of the mapped virtual memory 72 * 73 * @return 74 * - ESP_OK 75 * - ESP_ERR_INVALID_ARG: Invalid argument, see printed logs 76 * - ESP_ERR_NOT_SUPPORTED: Only on ESP32, PSRAM is not a supported physical memory target 77 * - ESP_ERR_NOT_FOUND: No enough size free block to use 78 * - ESP_ERR_NO_MEM: Out of memory, this API will allocate some heap memory for internal usage 79 * - ESP_ERR_INVALID_STATE: Paddr is mapped already, this API will return corresponding vaddr_start of the previously mapped block. 80 * Only to-be-mapped paddr block is totally enclosed by a previously mapped block will lead to this error. (Identical scenario will behave similarly) 81 * new_block_start new_block_end 82 * |-------- New Block --------| 83 * |--------------- Block ---------------| 84 * block_start block_end 85 * 86 */ 87 esp_err_t esp_mmu_map(esp_paddr_t paddr_start, size_t size, mmu_target_t target, mmu_mem_caps_t caps, int flags, void **out_ptr); 88 89 /** 90 * @brief Unmap a previously mapped virtual memory block 91 * 92 * @note This API does not guarantee thread safety 93 * 94 * @param[in] ptr Start address of the virtual memory 95 * 96 * @return 97 * - ESP_OK 98 * - ESP_ERR_INVALID_ARG: Null pointer 99 * - ESP_ERR_NOT_FOUND: Vaddr is not in external memory, or it's not mapped yet 100 */ 101 esp_err_t esp_mmu_unmap(void *ptr); 102 103 /** 104 * @brief Get largest consecutive free external virtual memory block size, with given capabilities and given physical target 105 * 106 * @param[in] caps Bitwise OR of MMU_MEM_CAP_* flags indicating the memory block 107 * @param[in] target Physical memory target you're going to map to, see `mmu_target_t`. 108 * @param[out] out_len Largest free block length, in bytes. 109 * 110 * @return 111 * - ESP_OK 112 * - ESP_ERR_INVALID_ARG: Invalid arguments, could be null pointer 113 */ 114 esp_err_t esp_mmu_map_get_max_consecutive_free_block_size(mmu_mem_caps_t caps, mmu_target_t target, size_t *out_len); 115 116 /** 117 * Dump all the previously mapped blocks 118 * 119 * @note This API shall not be called from an ISR. 120 * @note This API does not guarantee thread safety 121 * 122 * @param stream stream to print information to; use stdout or stderr to print 123 * to the console; use fmemopen/open_memstream to print to a 124 * string buffer. 125 * @return 126 * - ESP_OK 127 */ 128 esp_err_t esp_mmu_map_dump_mapped_blocks(FILE* stream); 129 130 /** 131 * @brief Convert virtual address to physical address 132 * 133 * @param[in] vaddr Virtual address 134 * @param[out] out_paddr Physical address 135 * @param[out] out_target Physical memory target, see `mmu_target_t` 136 * 137 * @return 138 * - ESP_OK 139 * - ESP_ERR_INVALID_ARG: Null pointer, or vaddr is not within external memory 140 * - ESP_ERR_NOT_FOUND: Vaddr is not mapped yet 141 */ 142 esp_err_t esp_mmu_vaddr_to_paddr(void *vaddr, esp_paddr_t *out_paddr, mmu_target_t *out_target); 143 144 /** 145 * @brief Convert physical address to virtual address 146 * 147 * @param[in] paddr Physical address 148 * @param[in] target Physical memory target, see `mmu_target_t` 149 * @param[in] type Virtual address type, could be either instruction or data 150 * @param[out] out_vaddr Virtual address 151 * 152 * @return 153 * - ESP_OK 154 * - ESP_ERR_INVALID_ARG: Null pointer 155 * - ESP_ERR_NOT_FOUND: Paddr is not mapped yet 156 */ 157 esp_err_t esp_mmu_paddr_to_vaddr(esp_paddr_t paddr, mmu_target_t target, mmu_vaddr_t type, void **out_vaddr); 158 159 /** 160 * @brief If the physical address is mapped, this API will provide the capabilities of the virtual address where the physical address is mapped to. 161 * 162 * @note: Only return value is ESP_OK(which means physically address is successfully mapped), then caps you get make sense. 163 * @note This API only check one page (see CONFIG_MMU_PAGE_SIZE), starting from the `paddr` 164 * 165 * @param[in] paddr Physical address 166 * @param[out] out_caps Bitwise OR of MMU_MEM_CAP_* flags indicating the capabilities of a virtual address where the physical address is mapped to. 167 * @return 168 * - ESP_OK: Physical address successfully mapped. 169 * - ESP_ERR_INVALID_ARG: Null pointer 170 * - ESP_ERR_NOT_FOUND: Physical address is not mapped successfully. 171 */ 172 esp_err_t esp_mmu_paddr_find_caps(const esp_paddr_t paddr, mmu_mem_caps_t *out_caps); 173 174 #ifdef __cplusplus 175 } 176 #endif 177