{IDF_TARGET_NAME} Memory Management Unit (MMU) is relatively simple. It can do memory address translation between physical memory addresses and virtual memory addresses. So CPU can access physical memories via virtual addresses. There are multiple types of virtual memory addresses, which have different capabilities.
ESP-IDF provides a memory mapping driver that manages the relation between these physical memory addresses and virtual memory addresses, so as to achieve some features such as reading from SPI flash via a pointer.
Memory mapping driver is actually a capabilities-based virtual memory address allocator that allows applications to make virtual memory address allocations for different purposes. In the following chapters, we call this driver ``esp_mmap`` driver.
-:cpp:enumerator:`MMU_MEM_CAP_EXEC`: This capability indicates that the virtual memory address has the execute permission. Note this permission scope is within the MMU hardware.
-:cpp:enumerator:`MMU_MEM_CAP_READ`: This capability indicates that the virtual memory address has the read permission. Note this permission scope is within the MMU hardware.
-:cpp:enumerator:`MMU_MEM_CAP_WRITE`: This capability indicates that the virtual memory address has the write permission. Note this permission scope is within the MMU hardware.
-:cpp:enumerator:`MMU_MEM_CAP_32BIT`: This capability indicates that the virtual memory address allows for 32 bits or multiples of 32 bits access.
-:cpp:enumerator:`MMU_MEM_CAP_8BIT`: This capability indicates that the virtual memory address allows for 8 bits or multiples of 8 bits access.
8 MB external memory addresses (from 0x40400000 to 0x40C00000) which have the :cpp:enumerator:`MMU_MEM_CAP_EXEC` and :cpp:enumerator:`MMU_MEM_CAP_READ` capabilities are not available for users to allocate, due to hardware limitations.
4 MB external memory addresses (from 0x40400000 to 0x40800000) which have the :cpp:enumerator:`MMU_MEM_CAP_EXEC` and :cpp:enumerator:`MMU_MEM_CAP_READ` capabilities are not avaiable for users to allocate, due to hardware limitations.
You can call :cpp:func:`esp_mmu_map_get_max_consecutive_free_block_size` to know the largest consecutive mappable block size with certain capabilities.
Memory Management Drivers
=========================
Driver Concept
--------------
Terminology
^^^^^^^^^^^
The virtual memory pool is made up with one or multiple virtual memory regions, see below figure:
- Dynamical mapping is done by calling ``esp_mmap`` driver API :cpp:func:`esp_mmu_map`. This API maps the given physical memory block to a virtual memory block which is allocated by the ``esp_mmap`` driver.
You can call :cpp:func:`esp_mmu_map` to do a dynamical mapping. This API can allocate a certain size of virtual memory block according to the virtual memory capabilities you selected, then map this virtual memory block to the physical memory block as you requested. The ``esp_mmap`` driver supports mapping to one or more types of physical memory, so you should specify the physical memory target when mapping.
* If it is the enclosed scenario, this API will return an :c:macro:`ESP_ERR_INVALID_STATE`. The ``out_ptr`` will be assigned to the start virtual memory address of the previously mapped one which encloses the to-be-mapped one.
* If it is the identical scenario, this API will behaves exactly the same as the enclosed scenario.
* If it is the overlapped scenario, this API will by default return an :c:macro:`ESP_ERR_INVALID_ARG`. This means, ``esp_mmap`` driver by default does not allow mapping a physical memory address to multiple virtual memory addresses.
Specially, you can use :c:macro:`ESP_MMU_MMAP_FLAG_PADDR_SHARED`. This flag stands for one-to-multiple mapping between a physical address and multiple virtual addresses:
You can call :cpp:func:`esp_mmu_unmap` to unmap a previously mapped memory block. This API returns an :c:macro:`ESP_ERR_NOT_FOUND` if you are trying to unmap a virtual memory block that is not mapped to any physical memory block yet.
SPI flash can be accessed by SPI1 (ESP-IDF ``esp_flash`` driver APIs), or by pointers. ESP-IDF ``esp_flash`` driver APIs have already considered the memory synchronization, so users do not need to worry about this.
PSRAM can also be accessed by EDMA. Data desynchronization may happen because hardware does not guarantee the data consistency under such condition. You should call :cpp:func:`esp_cache_msync` to synchronize the Cache and the PSRAM.