summaryrefslogtreecommitdiff
path: root/bsp/rockchip/common/rk_hal/lib/hal/src/hal_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/rockchip/common/rk_hal/lib/hal/src/hal_cache.c')
-rw-r--r--bsp/rockchip/common/rk_hal/lib/hal/src/hal_cache.c925
1 files changed, 925 insertions, 0 deletions
diff --git a/bsp/rockchip/common/rk_hal/lib/hal/src/hal_cache.c b/bsp/rockchip/common/rk_hal/lib/hal/src/hal_cache.c
new file mode 100644
index 0000000000..3a79922149
--- /dev/null
+++ b/bsp/rockchip/common/rk_hal/lib/hal/src/hal_cache.c
@@ -0,0 +1,925 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
+ */
+
+/** @addtogroup RK_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup CACHE
+ * @{
+ */
+#include "hal_base.h"
+#include "hal_cache.h"
+
+/** @defgroup CACHE_Exported_Definition_Group1 Basic Definition
+ * @{
+ */
+
+/***************************** MACRO Definition ******************************/
+
+/***************************** Structure Definition **************************/
+
+/********************* Private Function Definition ***************************/
+
+#if defined(__CORTEX_M)
+__STATIC_INLINE unsigned long HAL_SYS_EnterCriticalSection(void)
+{
+ unsigned long flags;
+
+ flags = __get_PRIMASK();
+ __disable_irq();
+
+ return flags;
+}
+
+__STATIC_INLINE void HAL_SYS_ExitCriticalSection(unsigned long flags)
+{
+ __set_PRIMASK(flags);
+}
+#else
+__STATIC_INLINE unsigned long HAL_SYS_EnterCriticalSection(void)
+{
+ return 0;
+}
+
+__STATIC_INLINE void HAL_SYS_ExitCriticalSection(unsigned long flags)
+{
+}
+#endif
+
+/** @} */
+/********************* Public Function Definition ****************************/
+/** @defgroup CACHE_Exported_Functions_Group5 Other Functions
+ * @attention these APIs allow direct use in the HAL layer
+ * @{
+ */
+
+/**
+ * @brief translate the cpuAddr to sramAddr
+ * @param cpuAddr: the address mapping to sram, only can be accessed by cpu
+ * @return sramAddr: the real address of sram, it can be accessed by cpu & device
+ */
+uint32_t HAL_CpuAddrToDmaAddr(uint32_t cpuAddr)
+{
+ uint32_t sramAddr = cpuAddr;
+
+#ifdef SRAM_IADDR_TO_DADDR_OFFSET
+
+ if (cpuAddr >= SRAM_IADDR_START
+ && cpuAddr < (SRAM_IADDR_START + SRAM_SIZE)) {
+ sramAddr = cpuAddr + SRAM_IADDR_TO_DADDR_OFFSET;
+ }
+
+#endif
+
+#ifdef XIP_NOR_IADDR_TO_DADDR_OFFSET
+
+ if (cpuAddr >= XIP_NOR_IADDR_START
+ && cpuAddr < (XIP_NOR_IADDR_START + XIP_NOR_SIZE)) {
+ sramAddr = cpuAddr + XIP_NOR_IADDR_TO_DADDR_OFFSET;
+ }
+
+#endif
+
+#ifdef XIP_PSRAM_IADDR_TO_DADDR_OFFSET
+
+ if (cpuAddr >= XIP_PSRAM_IADDR_START
+ && cpuAddr < (XIP_PSRAM_IADDR_START + XIP_PSRAM_SIZE)) {
+ sramAddr = cpuAddr + XIP_PSRAM_IADDR_TO_DADDR_OFFSET;
+ }
+
+#endif
+
+ return sramAddr;
+}
+
+#ifdef MPU
+/**
+ * @brief check mpu is enable.
+ * @return HAL_ENABLE if mpu enable.
+ */
+__STATIC_INLINE HAL_FuncStatus HAL_MPU_IsEnable(void)
+{
+ HAL_FuncStatus ret = HAL_DISABLE;
+
+ if (MPU->CTRL & MPU_CTRL_ENABLE_Msk) {
+ ret = HAL_ENABLE;
+ }
+
+ return ret;
+}
+#endif
+
+/**
+ * @brief enable icache.
+ * @return HAL_OK if success.
+ * @attention The MPU must be configured before cache if you need the function.
+ */
+HAL_Status HAL_ICACHE_Enable(void)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t status;
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ /* config icache: mpu disable, stb disable, write through, hot buffer enable,
+ prefetch enable */
+ ICACHE->CACHE_CTRL |=
+ (ICACHE_CACHE_CTRL_CACHE_EN_MASK | ICACHE_CACHE_CTRL_CACHE_WT_EN_MASK);
+ ICACHE->CACHE_CTRL &= (~ICACHE_CACHE_CTRL_CACHE_STB_EN_MASK);
+
+ /* if mpu has been enable, we will enable cache mpu function */
+#ifdef MPU
+ if (HAL_MPU_IsEnable()) {
+ ICACHE->CACHE_CTRL |= ICACHE_CACHE_CTRL_CACHE_MPU_MODE_MASK;
+ }
+#endif
+
+ do {
+ status =
+ ICACHE->CACHE_STATUS & ICACHE_CACHE_STATUS_CACHE_INIT_FINISH_MASK;
+ } while (status == 0);
+
+ ICACHE->CACHE_CTRL &= ~ICACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief disable icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_Disable(void)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_CTRL |= ICACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief invalidate all of the icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_Invalidate(void)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t status = 0;
+ unsigned long flags;
+
+ if ((uint32_t)DCACHE == (uint32_t)ICACHE) {
+ if (DCACHE->CACHE_CTRL & DCACHE_CACHE_CTRL_CACHE_WT_EN_MASK) {
+ return HAL_OK;
+ } else {
+ return HAL_INVAL;
+ }
+ }
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_MAINTAIN[0] =
+ CACHE_M_INVALID_ALL | ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+
+ do {
+ status = ICACHE->CACHE_MAINTAIN[0] &
+ ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+ } while (status);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief invalidate the specified region of the icache.
+ * @param address: the start address of specified region which you want invalidate.
+ * @param sizeByte: the length in bytes of invalidate range.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_InvalidateByRange(uint32_t address,
+ uint32_t sizeByte)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t value = 0;
+ uint32_t offset = 0;
+ uint32_t status = 0;
+ unsigned long flags;
+
+ if (sizeByte == 0) {
+ return HAL_OK;
+ }
+
+ address = HAL_CpuAddrToDmaAddr(address);
+
+ offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
+ value = (address & ICACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
+ CACHE_M_INVALID | ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_MAINTAIN[1] = offset;
+ ICACHE->CACHE_MAINTAIN[0] = value;
+
+ do {
+ status = ICACHE->CACHE_MAINTAIN[0] &
+ ICACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+ } while (status);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief enable performance measurement unit of icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_EnablePMU(void)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_CTRL |= ICACHE_CACHE_CTRL_CACHE_PMU_EN_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief disable performance measurement unit of icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_DisablePMU(void)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_CTRL &= (~ICACHE_CACHE_CTRL_CACHE_PMU_EN_MASK);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief get current state of performance measurement unit in icache.
+ * @param stat: return the current state if success.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_GetPMU(struct CACHE_PMU_CNT *stat)
+{
+#if defined(HAL_ICACHE_MODULE_ENABLED) && defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ HAL_ASSERT(stat != NULL);
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ stat->rdNum = ICACHE->PMU_RD_NUM_CNT;
+ stat->wrNum = ICACHE->PMU_WR_NUM_CNT;
+ stat->sramRdHit = ICACHE->PMU_SRAM_RD_HIT_CNT;
+ stat->hbRdHit = ICACHE->PMU_HB_RD_HIT_CNT;
+ stat->stbRdHit = ICACHE->PMU_STB_RD_HIT_CNT;
+ stat->rdHit = ICACHE->PMU_RD_HIT_CNT;
+ stat->wrHit = ICACHE->PMU_WR_HIT_CNT;
+ stat->rdMissPenalty = ICACHE->PMU_RD_MISS_PENALTY_CNT;
+ stat->wrMissPenalty = ICACHE->PMU_WR_MISS_PENALTY_CNT;
+ stat->rdLat = ICACHE->PMU_RD_LAT_CNT;
+ stat->wrLat = ICACHE->PMU_WR_LAT_CNT;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the interrupt of icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_EnableInt(void)
+{
+#if defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_INT_EN |= ICACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the interrupt of icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_DisableInt(void)
+{
+#if defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_INT_EN &= ~ICACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the interrupt status of icache.
+ * @return HAL_TRUE if ahb error occur.
+ */
+HAL_Check HAL_ICACHE_GetInt(void)
+{
+ uint32_t status = 0;
+
+#if defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+
+ status = ICACHE->CACHE_INT_ST & ICACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
+
+#endif
+
+#endif
+
+ return status ? HAL_TRUE : HAL_FALSE;
+}
+
+/**
+ * @brief Get the ahb bus error address of icache.
+ * @return ahb buss error address if success.
+ * @attention The return value is only valid if you get a ahb error from CACHE_INT_ST
+ */
+uint32_t HAL_ICACHE_GetErrAddr(void)
+{
+ uint32_t address = -1;
+
+#if defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+
+ address = ICACHE->CACHE_ERR_HADDR;
+
+#endif
+
+#endif
+
+ return address;
+}
+
+/**
+ * @brief Clear the interrupt status of icache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_ICACHE_ClearInt(void)
+{
+#if defined(ICACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ ICACHE->CACHE_INT_ST |= ICACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief enable dcache.
+ * @return HAL_OK if success.
+ * @attention The MPU must be configured before cache if you need the feature.
+ * @attention Dynamically disable and enable dcache is not allowed.
+ */
+HAL_Status HAL_DCACHE_Enable(void)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t status;
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ /* stb enable, stb_entry=7, stb_timeout enable, write back, prefetch enable */
+ DCACHE->CACHE_CTRL |=
+ DCACHE_CACHE_CTRL_CACHE_EN_MASK
+ | (7U << DCACHE_CACHE_CTRL_CACHE_ENTRY_THRESH_SHIFT)
+ | DCACHE_CACHE_CTRL_STB_TIMEOUT_EN_MASK;
+ DCACHE->STB_TIMEOUT_CTRL = 1;
+
+ /* if mpu has been enable, we will enable cache mpu function */
+#ifdef MPU
+ if (HAL_MPU_IsEnable()) {
+ DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_MPU_MODE_MASK;
+ }
+#endif
+
+ do {
+ status =
+ DCACHE->CACHE_STATUS & DCACHE_CACHE_STATUS_CACHE_INIT_FINISH_MASK;
+ } while (status == 0);
+
+ DCACHE->CACHE_CTRL &= ~DCACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief disable dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_Disable(void)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_BYPASS_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief invalidate all of the dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_Invalidate(void)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t status = 0;
+ unsigned long flags;
+
+ if ((uint32_t)DCACHE == (uint32_t)ICACHE) {
+ if (DCACHE->CACHE_CTRL & DCACHE_CACHE_CTRL_CACHE_WT_EN_MASK) {
+ return HAL_OK;
+ } else {
+ return HAL_INVAL;
+ }
+ }
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_MAINTAIN[0] =
+ CACHE_M_INVALID_ALL | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+
+ do {
+ status = DCACHE->CACHE_MAINTAIN[0] &
+ DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+ } while (status);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief invalidate the specified region of the dcache.
+ * @param address: the start address of specified region which you want invalidate.
+ * @param sizeByte: the length in bytes of invalidate range.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_InvalidateByRange(uint32_t address,
+ uint32_t sizeByte)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t value = 0;
+ uint32_t offset = 0;
+ uint32_t status = 0;
+ unsigned long flags;
+
+ if (sizeByte == 0) {
+ return HAL_OK;
+ }
+
+ offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
+ value = (address & DCACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
+ CACHE_M_INVALID | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_MAINTAIN[1] = offset;
+ DCACHE->CACHE_MAINTAIN[0] = value;
+
+ do {
+ status = DCACHE->CACHE_MAINTAIN[0] &
+ DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+ } while (status);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief clean the specified region of the dcache, it will flush the dirty cache in
+ * the specified region.
+ * @param address: the start address of specified region which you want invalidate.
+ * @param sizeByte: the length in bytes of invalidate range.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_CleanByRange(uint32_t address,
+ uint32_t sizeByte)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t value = 0;
+ uint32_t offset = 0;
+ uint32_t status = 0;
+ unsigned long flags;
+
+ if (sizeByte == 0) {
+ return HAL_OK;
+ }
+
+ offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
+ value = (address & DCACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
+ CACHE_M_CLEAN | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_MAINTAIN[1] = offset;
+ DCACHE->CACHE_MAINTAIN[0] = value;
+
+ do {
+ status = DCACHE->CACHE_MAINTAIN[0] &
+ DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+ } while (status);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief clean and invalidate the specified region of the dcache, it will flush the dirty
+ * cache in the specified region, and set the cache line to invalid state.
+ * @param address: the start address of specified region which you want invalidate.
+ * @param sizeByte: the length in bytes of invalidate range.
+ * @return HAL_OK if success.
+ */
+HAL_Status
+HAL_DCACHE_CleanInvalidateByRange(uint32_t address, uint32_t sizeByte)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t value = 0;
+ uint32_t offset = 0;
+ uint32_t status = 0;
+ unsigned long flags;
+
+ if (sizeByte == 0) {
+ return HAL_OK;
+ }
+
+ offset = ((address & (CACHE_LINE_SIZE - 1)) + sizeByte - 1) >> CACHE_LINE_SHIFT;
+ value = (address & DCACHE_CACHE_MAINTAIN0_CACHE_M_ADDR_MASK) |
+ CACHE_M_CLEAN_INVALID | DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_MAINTAIN[1] = offset;
+ DCACHE->CACHE_MAINTAIN[0] = value;
+
+ do {
+ status = DCACHE->CACHE_MAINTAIN[0] &
+ DCACHE_CACHE_MAINTAIN0_CACHE_M_VALID_MASK;
+ } while (status);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief clean and invalidate all of the dcache, the dirty cache line will be flush
+ * to external memory, and all of the cache line will be set invalid.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_CleanInvalidate(void)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ uint32_t status = 0;
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_FLUSH_MASK;
+
+ do {
+ status =
+ DCACHE->CACHE_STATUS & DCACHE_CACHE_STATUS_CACHE_FLUSH_DONE_MASK;
+ } while (!status);
+
+ DCACHE->CACHE_CTRL &= ~DCACHE_CACHE_CTRL_CACHE_FLUSH_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief enable performance measurement unit of dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_EnablePMU(void)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_CTRL |= DCACHE_CACHE_CTRL_CACHE_PMU_EN_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief disable performance measurement unit of dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_DisablePMU(void)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_CTRL &= (~DCACHE_CACHE_CTRL_CACHE_PMU_EN_MASK);
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief get current state of performance measurement unit in icache.
+ * @param stat: return the current state if success.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_GetPMU(struct CACHE_PMU_CNT *stat)
+{
+#if defined(HAL_DCACHE_MODULE_ENABLED) && defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ HAL_ASSERT(stat != NULL);
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ stat->rdNum = DCACHE->PMU_RD_NUM_CNT;
+ stat->wrNum = DCACHE->PMU_WR_NUM_CNT;
+ stat->sramRdHit = DCACHE->PMU_SRAM_RD_HIT_CNT;
+ stat->hbRdHit = DCACHE->PMU_HB_RD_HIT_CNT;
+ stat->stbRdHit = DCACHE->PMU_STB_RD_HIT_CNT;
+ stat->rdHit = DCACHE->PMU_RD_HIT_CNT;
+ stat->wrHit = DCACHE->PMU_WR_HIT_CNT;
+ stat->rdMissPenalty = DCACHE->PMU_RD_MISS_PENALTY_CNT;
+ stat->wrMissPenalty = DCACHE->PMU_WR_MISS_PENALTY_CNT;
+ stat->rdLat = DCACHE->PMU_RD_LAT_CNT;
+ stat->wrLat = DCACHE->PMU_WR_LAT_CNT;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the interrupt of dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_EnableInt(void)
+{
+#if defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_INT_EN |= DCACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the interrupt of dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_DisableInt(void)
+{
+#if defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_INT_EN &= ~DCACHE_CACHE_INT_EN_ERR_RECORD_EN_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the interrupt status of dcache.
+ * @return HAL_TRUE if ahb error occur.
+ */
+HAL_Check HAL_DCACHE_GetInt(void)
+{
+ uint32_t status = 0;
+
+#if defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+
+ status = DCACHE->CACHE_INT_ST & DCACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
+
+#endif
+
+#endif
+
+ return status ? HAL_TRUE : HAL_FALSE;
+}
+
+/**
+ * @brief Clear the interrupt status of dcache.
+ * @return HAL_OK if success.
+ */
+HAL_Status HAL_DCACHE_ClearInt(void)
+{
+#if defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+ unsigned long flags;
+
+ flags = HAL_SYS_EnterCriticalSection();
+
+ DCACHE->CACHE_INT_ST |= DCACHE_CACHE_INT_ST_AHB_ERROR_STATUS_MASK;
+
+ HAL_SYS_ExitCriticalSection(flags);
+#endif
+
+#endif
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the ahb bus error address of dcache.
+ * @return ahb buss error address if success.
+ * @attention The return value is only valid if you get a ahb error from CACHE_INT_ST
+ */
+uint32_t HAL_DCACHE_GetErrAddr(void)
+{
+ uint32_t address = -1;
+
+#if defined(DCACHE)
+
+#if defined(CACHE_REVISION) && (CACHE_REVISION == 0x00000100U)
+
+ address = DCACHE->CACHE_ERR_HADDR;
+
+#endif
+
+#endif
+
+ return address;
+}
+
+/** @} */
+
+/** @} */
+
+/** @} */