refactor(hal): extract cache && mmu HAL into esp_hal_cache

This commit is contained in:
morris
2026-09-16 21:40:16 +08:00
parent e492079576
commit 193fca5b95
111 changed files with 226 additions and 285 deletions
-185
View File
@@ -1,185 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "soc/soc_caps.h"
#include "hal/cache_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Cache hal config
*/
typedef struct {
uint8_t core_nums; ///< CPU core numbers
uint32_t l2_cache_size; ///< L2 cache size
uint32_t l2_cache_line_size; ///< L2 cache line size
} cache_hal_config_t;
/**
* Cache init and cache hal context init
*
* @param config Cache hal config
*/
void cache_hal_init(const cache_hal_config_t *config);
/**
* @brief Disable Cache
*
* Disable the ICache or DCache or both, of a certain level or all levels.
* All the items in the corresponding Cache(s) will be invalideated.
* Next request to these items will trigger a transaction to the physical memory
*
* @note If the autoload feature is enabled, this API will return until the ICache autoload is disabled.
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*/
void cache_hal_disable(uint32_t cache_level, cache_type_t type);
/**
* @brief Enable Cache
*
* Enable the ICache or DCache or both, of a certain level or all levels.
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*/
void cache_hal_enable(uint32_t cache_level, cache_type_t type);
/**
* @brief Suspend Cache
*
* Suspend the ICache or DCache or both, of a certain level or all levels.
* This API suspends the CPU access to cache for a while, without invalidation.
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*/
void cache_hal_suspend(uint32_t cache_level, cache_type_t type);
/**
* @brief Resume Cache
*
* Resume the ICache or DCache or both, of a certain level or all levels.
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*/
void cache_hal_resume(uint32_t cache_level, cache_type_t type);
/**
* @brief Check if corresponding cache is enabled or not
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*
* @return true: enabled; false: disabled
*/
bool cache_hal_is_cache_enabled(uint32_t cache_level, cache_type_t type);
/**
* @brief Invalidate Cache supported addr
*
* Invalidate a Cache item for either ICache or DCache.
*
* @param vaddr Start address of the region to be invalidated
* @param size Size of the region to be invalidated
*
* @return True for valid address. No operation if invalid
*/
bool cache_hal_invalidate_addr(uint32_t vaddr, uint32_t size);
#if SOC_CACHE_WRITEBACK_SUPPORTED
/**
* @brief Writeback Cache supported addr
*
* Writeback the DCache item to external memory
*
* @param vaddr Start address of the region to writeback
* @param size Size of the region to writeback
*
* @return True for valid address. No operation if invalid
*/
bool cache_hal_writeback_addr(uint32_t vaddr, uint32_t size);
#endif //#if SOC_CACHE_WRITEBACK_SUPPORTED
#if SOC_CACHE_FREEZE_SUPPORTED
/**
* @brief Freeze Cache
*
* Freeze cache, CPU access to cache will be suspended, until the cache is unfrozen.
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*/
void cache_hal_freeze(uint32_t cache_level, cache_type_t type);
/**
* @brief Unfreeze cache
*
* Unfreeze cache, CPU access to cache will be restored
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*/
void cache_hal_unfreeze(uint32_t cache_level, cache_type_t type);
#endif //#if SOC_CACHE_FREEZE_SUPPORTED
/**
* @brief Get cache line size, in bytes
*
* @param cache_level Level of the Cache(s)
* @param type see `cache_type_t`
*
* @return cache line size, in bytes. 0 stands for no such cache in this type or level
*/
uint32_t cache_hal_get_cache_line_size(uint32_t cache_level, cache_type_t type);
/**
* @brief Start cache preload for a region (manual preload)
*
* Preloads the given address range into cache, this can improve
* performance when the region will be read soon.
*
* @param cache_level Level of the cache (e.g. CACHE_LL_LEVEL_EXT_MEM)
* @param type CACHE_TYPE_DATA, CACHE_TYPE_INSTRUCTION, or CACHE_TYPE_ALL
* @param vaddr Start virtual address of the region to preload
* @param size Size in bytes. Should be cache-line aligned; if not,
* the actual preloaded length is rounded down to cache-line boundary.
* @param order preload order
*/
void cache_hal_preload(uint32_t cache_level, cache_type_t type, uint32_t vaddr, uint32_t size, cache_preload_order_t order);
/**
* @brief Wait until cache preload started by cache_hal_preload() is done
*
* @param cache_level Level of the cache (must match the level used in cache_hal_preload)
* @param type CACHE_TYPE_DATA, CACHE_TYPE_INSTRUCTION, or CACHE_TYPE_ALL
*/
void cache_hal_preload_wait_done(uint32_t cache_level, cache_type_t type);
/**
* @brief Get Cache level and the ID of the vaddr
*
* @param vaddr_start virtual address start
* @param len vaddr length
* @param out_level cache level
* @param out_id cache id
*
* @return true for valid, false for invalid addr or null pointer
*/
bool cache_hal_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32_t len, uint32_t *out_level, uint32_t *out_id);
#ifdef __cplusplus
}
#endif
-38
View File
@@ -1,38 +0,0 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "hal/cache_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_CACHE_CNT_SUPPORTED
/**
* @brief Description of one cache profile counter unit
*
* A unit is one set of counters observing one traffic stream, e.g. the
* instruction fetches of core 0 into the L1 cache.
*/
typedef struct {
const char *name; /*!< Short human-readable name */
uint8_t level; /*!< Cache level (1 or 2) */
cache_profile_traffic_t traffic; /*!< Kind of traffic observed */
int8_t core_id; /*!< Originating core, -1 if unknown/mixed */
uint32_t counter_reg[CACHE_PROFILE_COUNTER_MAX]; /*!< Counter registers; 0 if the unit
does not have that counter */
} cache_profile_counter_unit_t;
extern const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM];
#endif
#ifdef __cplusplus
}
#endif
-69
View File
@@ -1,69 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_bit_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Kind of traffic observed by a cache profile counter unit
*/
typedef enum {
CACHE_PROFILE_TRAFFIC_INST, /*!< Instruction fetches */
CACHE_PROFILE_TRAFFIC_DATA, /*!< Data accesses */
CACHE_PROFILE_TRAFFIC_UNIFIED, /*!< Mixed/unknown (unified request bus) */
} cache_profile_traffic_t;
/**
* @brief One of the counters of a cache profile counter unit
*/
typedef enum {
CACHE_PROFILE_COUNTER_HIT, /*!< Completed accesses ("hit" counter) */
CACHE_PROFILE_COUNTER_MISS, /*!< Miss stall events ("miss" counter) */
CACHE_PROFILE_COUNTER_CONFLICT, /*!< Requester conflicts */
CACHE_PROFILE_COUNTER_NXTLVL_RD, /*!< Line fills from the next level */
CACHE_PROFILE_COUNTER_NXTLVL_WR, /*!< Write-backs to the next level */
CACHE_PROFILE_COUNTER_MAX,
} cache_profile_counter_t;
typedef enum {
CACHE_TYPE_DATA,
CACHE_TYPE_INSTRUCTION,
CACHE_TYPE_ALL //This means both ICache and DCache will be used. On some chips, I/D are controlled by a shared Cache. Also use this enum under this condition. See `SOC_SHARED_IDCACHE_SUPPORTED`.
} cache_type_t;
/**
* @brief Ibuses and Dbuses.
*
* @note
* These enumurations are abstract concepts. Virtual address reside in one of these buses.
* Therefore, use `cache_ll_l1_get_bus(bus_id, vaddr_start, len)` to convert your vaddr into buses first
*/
typedef enum {
CACHE_BUS_IBUS0 = BIT(0),
CACHE_BUS_IBUS1 = BIT(1),
CACHE_BUS_IBUS2 = BIT(2),
CACHE_BUS_DBUS0 = BIT(3),
CACHE_BUS_DBUS1 = BIT(4),
CACHE_BUS_DBUS2 = BIT(5),
} cache_bus_mask_t;
/**
* @brief Preload order
*/
typedef enum {
CACHE_PRELOAD_ORDER_ASCENDING,
CACHE_PRELOAD_ORDER_DESCENDING,
} cache_preload_order_t;
#ifdef __cplusplus
}
#endif
-187
View File
@@ -1,187 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <esp_types.h>
#include "soc/soc_caps.h"
#include "hal/mmu_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MMU hal config
*/
typedef struct {
uint8_t core_nums; ///< CPU core numbers
uint32_t mmu_page_size; ///< MMU page size
} mmu_hal_config_t;
/**
* MMU Hal layer initialisation
*
* @param config MMU hal config
*/
void mmu_hal_init(const mmu_hal_config_t *config);
/**
* MMU Hal layer context initialisation
*
* @param config MMU hal config
*/
void mmu_hal_ctx_init(const mmu_hal_config_t *config);
/**
* Unmap all the MMU table. After this all external memory vaddr are not available
*/
void mmu_hal_unmap_all(void);
/**
* Helper functions to convert the MMU page numbers into bytes. e.g.:
* - When MMU page size is 16KB, page_num = 2 will be converted into 32KB
* - When MMU page size is 32KB, page_num = 2 will be converted into 64KB
*
* @param mmu_id MMU ID
* @param page_num page numbers
*
* @return
* length in byte
*/
uint32_t mmu_hal_pages_to_bytes(uint32_t mmu_id, uint32_t page_num);
/**
* Helper functions to convert bytes into MMU page numbers. e.g.:
* - When MMU page size is 16KB, bytes = 64KB will be converted into 4 pages
* - When MMU page size is 32KB, bytes = 64KB will be converted into 2 pages
*
* @param mmu_id MMU ID
* @param bytes length in byte
*
* @return
* length in CONFIG_MMU_PAGE_SIZE
*/
uint32_t mmu_hal_bytes_to_pages(uint32_t mmu_id, uint32_t bytes);
/**
* To map a virtual address block to a physical memory block
*
* @param mmu_id MMU ID
* @param mem_type physical memory type, see `mmu_target_t`
* @param vaddr start virtual address to be mapped
* @param paddr start physical address to be mapped
* @param len length to be mapped, in bytes
* @param[out] out_len actual mapped length
*
* @note vaddr and paddr should be aligned with the mmu page size, see CONFIG_MMU_PAGE_SIZE
*/
void mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr, uint32_t paddr, uint32_t len, uint32_t *out_len);
#if SOC_PSRAM_ENCRYPTION_PAGE_CONFIGURABLE
/**
* Map a PSRAM physical range to virtual memory without setting the encryption
* SENSITIVE bit on each MMU entry. Used only for the explicitly carved-out
* unencrypted PSRAM region (see CONFIG_SPIRAM_ENC_EXEMPT).
*
* @param vaddr start virtual address (MMU-page-aligned)
* @param paddr start physical address (MMU-page-aligned)
* @param len length in bytes
*/
void mmu_hal_map_region_no_enc(uint32_t vaddr, uint32_t paddr, uint32_t len);
#endif
/**
* To unmap a virtual address block that is mapped to a physical memory block previously
*
* @param[in] mmu_id MMU ID
* @param[in] vaddr start virtual address
* @param[in] len length to be unmapped, in bytes
*/
void mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len);
/**
* Convert virtual address to physical address
*
* @param mmu_id MMU ID
* @param vaddr virtual address
* @param[out] out_paddr physical address
* @param[out] out_target Indicating the vaddr/paddr is mapped on which target, see `mmu_target_t`
*
* @return
* - true: virtual address is valid
* - false: virtual address isn't valid
*/
bool mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_paddr, mmu_target_t *out_target);
/**
* Convert physical address to virtual address
*
* @note This function can only find the first match virtual address.
* However it is possible that a physical address is mapped to multiple virtual addresses.
*
* @param mmu_id MMU ID
* @param paddr physical address
* @param target physical memory target, see `mmu_target_t`
* @param type virtual address type, could be instruction or data
* @param[out] out_vaddr virtual address
*
* @return
* - true: found a matched vaddr
* - false: not found a matched vaddr
*/
bool mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target, mmu_vaddr_t type, uint32_t *out_vaddr);
/**
* Check if the vaddr region is valid
*
* @param mmu_id MMU ID
* @param vaddr_start start of the virtual address
* @param len length, in bytes
* @param type virtual address type, could be instruction type or data type. See `mmu_vaddr_t`
*
* @return
* True for valid
*/
bool mmu_hal_check_valid_ext_vaddr_region(uint32_t mmu_id, uint32_t vaddr_start, uint32_t len, mmu_vaddr_t type);
/**
* Check if the paddr region is valid
*
* @param mmu_id MMU ID
* @param paddr_start start of the physical address
* @param len length, in bytes
*
* @return
* True for valid
*/
bool mmu_hal_check_valid_paddr_region(uint32_t mmu_id, uint32_t paddr_start, uint32_t len);
#if SOC_MMU_PER_EXT_MEM_TARGET
/**
* Get MMU ID from MMU target
*
* @param target MMU target
*
* @return
* MMU ID
*/
uint32_t mmu_hal_get_id_from_target(mmu_target_t target);
/**
* Get MMU ID from vaddr
*
* @param vaddr Virtual address
*
* @return
* MMU ID
*/
uint32_t mmu_hal_get_id_from_vaddr(uint32_t vaddr);
#endif
#ifdef __cplusplus
}
#endif
-63
View File
@@ -1,63 +0,0 @@
/*
* SPDX-FileCopyrightText: 2010-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_bit_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
MMU_MEM_CAP_EXEC = BIT(0),
MMU_MEM_CAP_READ = BIT(1),
MMU_MEM_CAP_WRITE = BIT(2),
MMU_MEM_CAP_32BIT = BIT(3),
MMU_MEM_CAP_8BIT = BIT(4),
} mmu_mem_caps_t;
/**
* MMU Page size
*/
typedef enum {
MMU_PAGE_8KB = 0x2000,
MMU_PAGE_SIZE_MIN = MMU_PAGE_8KB,
MMU_PAGE_16KB = 0x4000,
MMU_PAGE_32KB = 0x8000,
MMU_PAGE_64KB = 0x10000,
MMU_PAGE_128KB = 0x20000,
MMU_PAGE_256KB = 0x40000,
MMU_PAGE_SIZE_MAX = MMU_PAGE_256KB,
} mmu_page_size_t;
/**
* MMU virtual address flags type
*/
typedef enum {
MMU_VADDR_DATA = BIT(0),
MMU_VADDR_INSTRUCTION = BIT(1),
} mmu_vaddr_t;
/**
* External physical memory
*/
typedef enum {
MMU_TARGET_FLASH0 = BIT(0),
MMU_TARGET_PSRAM0 = BIT(1),
} mmu_target_t;
/**
* MMU table id
*/
typedef enum {
MMU_TABLE_CORE0,
MMU_TABLE_CORE1,
} mmu_table_id_t;
#ifdef __cplusplus
}
#endif