1 /*
2  * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include "sdkconfig.h"
10 
11 #if !CONFIG_IDF_TARGET_ESP32
12 #error esp_himem is only supported on ESP32
13 #else
14 
15 #include <stddef.h>
16 #include "esp_err.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 //Opaque pointers as handles for ram/range data
23 typedef struct esp_himem_ramdata_t *esp_himem_handle_t;
24 typedef struct esp_himem_rangedata_t *esp_himem_rangehandle_t;
25 
26 //ESP32 MMU block size
27 #define ESP_HIMEM_BLKSZ (0x8000)
28 
29 #define ESP_HIMEM_MAPFLAG_RO 1 /*!< Indicates that a mapping will only be read from. Note that this is unused for now. */
30 
31 /**
32  * @brief Allocate a block in high memory
33  *
34  * @param size Size of the to-be-allocated block, in bytes. Note that this needs to be
35  *             a multiple of the external RAM mmu block size (32K).
36  * @param[out] handle_out Handle to be returned
37  * @returns - ESP_OK if succesful
38  *          - ESP_ERR_NO_MEM if out of memory
39  *          - ESP_ERR_INVALID_SIZE if size is not a multiple of 32K
40  */
41 esp_err_t esp_himem_alloc(size_t size, esp_himem_handle_t *handle_out);
42 
43 
44 /**
45  * @brief Allocate a memory region to map blocks into
46  *
47  * This allocates a contiguous CPU memory region that can be used to map blocks
48  * of physical memory into.
49  *
50  * @param size Size of the range to be allocated. Note this needs to be a multiple of
51  *             the external RAM mmu block size (32K).
52  * @param[out] handle_out Handle to be returned
53  * @returns - ESP_OK if succesful
54  *          - ESP_ERR_NO_MEM if out of memory or address space
55  *          - ESP_ERR_INVALID_SIZE if size is not a multiple of 32K
56  */
57 esp_err_t esp_himem_alloc_map_range(size_t size, esp_himem_rangehandle_t *handle_out);
58 
59 /**
60  * @brief Map a block of high memory into the CPUs address space
61  *
62  * This effectively makes the block available for read/write operations.
63  *
64  * @note The region to be mapped needs to have offsets and sizes that are aligned to the
65  *       SPI RAM MMU block size (32K)
66  *
67  * @param handle Handle to the block of memory, as given by esp_himem_alloc
68  * @param range Range handle to map the memory in
69  * @param ram_offset Offset into the block of physical memory of the block to map
70  * @param range_offset Offset into the address range where the block will be mapped
71  * @param len Length of region to map
72  * @param flags One of ESP_HIMEM_MAPFLAG_*
73  * @param[out] out_ptr Pointer to variable to store resulting memory pointer in
74  * @returns - ESP_OK if the memory could be mapped
75  *          - ESP_ERR_INVALID_ARG if offset, range or len aren't MMU-block-aligned (32K)
76  *          - ESP_ERR_INVALID_SIZE if the offsets/lengths don't fit in the allocated memory or range
77  *          - ESP_ERR_INVALID_STATE if a block in the selected ram offset/length is already mapped, or
78  *                                  if a block in the selected range offset/length already has a mapping.
79  */
80 esp_err_t esp_himem_map(esp_himem_handle_t handle, esp_himem_rangehandle_t range, size_t ram_offset, size_t range_offset, size_t len, int flags, void **out_ptr);
81 
82 
83 /**
84  * @brief Free a block of physical memory
85  *
86  * This clears out the associated handle making the memory available for re-allocation again.
87  * This will only succeed if none of the memory blocks currently have a mapping.
88  *
89  * @param handle Handle to the block of memory, as given by esp_himem_alloc
90  * @returns - ESP_OK if the memory is succesfully freed
91  *          - ESP_ERR_INVALID_ARG if the handle still is (partially) mapped
92  */
93 esp_err_t esp_himem_free(esp_himem_handle_t handle);
94 
95 
96 
97 /**
98  * @brief Free a mapping range
99  *
100  * This clears out the associated handle making the range available for re-allocation again.
101  * This will only succeed if none of the range blocks currently are used for a mapping.
102  *
103  * @param handle Handle to the range block, as given by esp_himem_alloc_map_range
104  * @returns - ESP_OK if the memory is succesfully freed
105  *          - ESP_ERR_INVALID_ARG if the handle still is (partially) mapped to
106  */
107 esp_err_t esp_himem_free_map_range(esp_himem_rangehandle_t handle);
108 
109 
110 /**
111  * @brief Unmap a region
112  *
113  * @param range Range handle
114  * @param ptr Pointer returned by esp_himem_map
115  * @param len Length of the block to be unmapped. Must be aligned to the SPI RAM MMU blocksize (32K)
116  * @returns - ESP_OK if the memory is succesfully unmapped,
117  *          - ESP_ERR_INVALID_ARG if ptr or len are invalid.
118  */
119 esp_err_t esp_himem_unmap(esp_himem_rangehandle_t range, void *ptr, size_t len);
120 
121 
122 /**
123  * @brief Get total amount of memory under control of himem API
124  *
125  * @returns Amount of memory, in bytes
126  */
127 size_t esp_himem_get_phys_size(void);
128 
129 /**
130  * @brief Get free amount of memory under control of himem API
131  *
132  * @returns Amount of free memory, in bytes
133  */
134 size_t esp_himem_get_free_size(void);
135 
136 
137 /**
138  * @brief Get amount of SPI memory address space needed for bankswitching
139  *
140  * @note This is also weakly defined in esp32/spiram.c and returns 0 there, so
141  *       if no other function in this file is used, no memory is reserved.
142  *
143  * @returns Amount of reserved area, in bytes
144  */
145 size_t esp_himem_reserved_area_size(void);
146 
147 
148 #ifdef __cplusplus
149 }
150 #endif
151 
152 #endif // !CONFIG_IDF_TARGET_ESP32
153