mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
refactor(hal): extract cache && mmu HAL into esp_hal_cache
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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
|
||||
Reference in New Issue
Block a user