xiuos/Ubiquitous/XiZi_AIoT/services/drivers/rk-3568/ethernet/hal_cache.c

1095 lines
25 KiB
C

/* 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"
#include "hal_def.h"
/** @defgroup CACHE_Exported_Definition_Group1 Basic Definition
* @{
*/
/***************************** MACRO Definition ******************************/
#ifdef HAL_CACHE_DECODED_ADDR_BASE
#define DECODED_ADDR(x) (x + HAL_CACHE_DECODED_ADDR_BASE)
#else
#define DECODED_ADDR(x) (x)
#endif
/***************************** 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);
}
#elif defined(__RISC_V)
static inline unsigned long HAL_SYS_EnterCriticalSection(void)
{
unsigned long flags;
__asm volatile ("csrrci %0, mstatus, 8"
: "=&r" (flags)
:
: "memory");
return flags;
}
static inline void HAL_SYS_ExitCriticalSection(unsigned long flags)
{
__asm volatile ("csrw mstatus, %0"
:
: "r" (flags)
: "memory");
}
#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)
#if 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
#elif defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
SCB_EnableICache();
#endif
#endif /* HAL_ICACHE_MODULE_ENABLED */
return HAL_OK;
}
/**
* @brief disable icache.
* @return HAL_OK if success.
*/
HAL_Status HAL_ICACHE_Disable(void)
{
#if defined(HAL_ICACHE_MODULE_ENABLED)
#if 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
#elif defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
SCB_DisableICache();
#endif
#endif /* HAL_ICACHE_MODULE_ENABLED */
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)
#if 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
#elif defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
SCB_InvalidateICache();
#endif
#endif /* HAL_ICACHE_MODULE_ENABLED */
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)
#if 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);
address = DECODED_ADDR(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
#elif defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
SCB_InvalidateICache_by_Addr((void *)address, (int32_t)sizeByte);
#endif
#endif /* HAL_ICACHE_MODULE_ENABLED */
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)
#if 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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_EnableDCache();
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
return HAL_OK;
}
/**
* @brief disable dcache.
* @return HAL_OK if success.
*/
HAL_Status HAL_DCACHE_Disable(void)
{
#if defined(HAL_DCACHE_MODULE_ENABLED)
#if 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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_DisableDCache();
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
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)
#if 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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_InvalidateDCache();
#elif defined(__CORTEX_A)
L1C_InvalidateDCacheAll();
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
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)
#if 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;
}
address = DECODED_ADDR(address);
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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_InvalidateDCache_by_Addr((void *)address, (int32_t)sizeByte);
#elif defined(__CORTEX_A)
uint32_t start, stop, addr;
if (sizeByte == 0) {
return HAL_OK;
}
start = address;
stop = start + sizeByte;
if (start & (CACHE_LINE_SIZE - 1)) {
addr = start & ~(CACHE_LINE_SIZE - 1);
L1C_CleanInvalidateDCacheMVA((void *)addr);
start = addr + CACHE_LINE_SIZE;
}
if (stop & (CACHE_LINE_SIZE - 1)) {
addr = stop & ~(CACHE_LINE_SIZE - 1);
L1C_CleanInvalidateDCacheMVA((void *)addr);
stop = addr;
}
for (addr = start; addr < stop; addr += CACHE_LINE_SIZE) {
L1C_InvalidateDCacheMVA((void *)addr);
}
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
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)
#if 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;
}
address = DECODED_ADDR(address);
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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_CleanDCache_by_Addr((void *)address, (int32_t)sizeByte);
#elif defined(__CORTEX_A)
uint32_t start, stop, addr;
if (sizeByte == 0) {
return HAL_OK;
}
start = address & ~(CACHE_LINE_SIZE - 1);
stop = (address + sizeByte) & ~(CACHE_LINE_SIZE - 1);
for (addr = start; addr <= stop; addr += CACHE_LINE_SIZE) {
L1C_CleanDCacheMVA((void *)addr);
}
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
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)
#if 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;
}
address = DECODED_ADDR(address);
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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_CleanInvalidateDCache_by_Addr((void *)address, (int32_t)sizeByte);
#elif defined(__CORTEX_A)
uint32_t start, stop, addr;
if (sizeByte == 0) {
return HAL_OK;
}
start = address & ~(CACHE_LINE_SIZE - 1);
stop = (address + sizeByte) & ~(CACHE_LINE_SIZE - 1);
for (addr = start; addr <= stop; addr += CACHE_LINE_SIZE) {
L1C_CleanInvalidateDCacheMVA((void *)addr);
}
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
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)
#if 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
#elif defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
SCB_CleanInvalidateDCache();
#elif defined(__CORTEX_A)
L1C_CleanInvalidateDCacheAll();
#endif
#endif /* HAL_DCACHE_MODULE_ENABLED */
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;
}
/** @} */
/** @} */
/** @} */