|
- /******************************************************************************
- * @file cachel1_armv7.h
- * @brief CMSIS Level 1 Cache API for Armv7-M and later
- * @version V1.0.0
- * @date 03. March 2020
- ******************************************************************************/
- /*
- * Copyright (c) 2020 Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
- #elif defined (__clang__)
- #pragma clang system_header /* treat file as system include file */
- #endif
-
- #ifndef ARM_CACHEL1_ARMV7_H
- #define ARM_CACHEL1_ARMV7_H
-
- /**
- \ingroup CMSIS_Core_FunctionInterface
- \defgroup CMSIS_Core_CacheFunctions Cache Functions
- \brief Functions that configure Instruction and Data cache.
- @{
- */
-
- /* Cache Size ID Register Macros */
- #define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
- #define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos )
-
- #ifndef __SCB_DCACHE_LINE_SIZE
- #define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
- #endif
-
- #ifndef __SCB_ICACHE_LINE_SIZE
- #define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
- #endif
-
- /**
- \brief Enable I-Cache
- \details Turns on I-Cache
- */
- __STATIC_FORCEINLINE void SCB_EnableICache (void)
- {
- #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
- if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */
-
- __DSB();
- __ISB();
- SCB->ICIALLU = 0UL; /* invalidate I-Cache */
- __DSB();
- __ISB();
- SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief Disable I-Cache
- \details Turns off I-Cache
- */
- __STATIC_FORCEINLINE void SCB_DisableICache (void)
- {
- #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
- __DSB();
- __ISB();
- SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */
- SCB->ICIALLU = 0UL; /* invalidate I-Cache */
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief Invalidate I-Cache
- \details Invalidates I-Cache
- */
- __STATIC_FORCEINLINE void SCB_InvalidateICache (void)
- {
- #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
- __DSB();
- __ISB();
- SCB->ICIALLU = 0UL;
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief I-Cache Invalidate by address
- \details Invalidates I-Cache for the given address.
- I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
- I-Cache memory blocks which are part of given address + given size are invalidated.
- \param[in] addr address
- \param[in] isize size of memory block (in number of bytes)
- */
- __STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (void *addr, int32_t isize)
- {
- #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
- if ( isize > 0 ) {
- int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U));
- uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */;
-
- __DSB();
-
- do {
- SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
- op_addr += __SCB_ICACHE_LINE_SIZE;
- op_size -= __SCB_ICACHE_LINE_SIZE;
- } while ( op_size > 0 );
-
- __DSB();
- __ISB();
- }
- #endif
- }
-
-
- /**
- \brief Enable D-Cache
- \details Turns on D-Cache
- */
- __STATIC_FORCEINLINE void SCB_EnableDCache (void)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- uint32_t ccsidr;
- uint32_t sets;
- uint32_t ways;
-
- if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */
-
- SCB->CSSELR = 0U; /* select Level 1 data cache */
- __DSB();
-
- ccsidr = SCB->CCSIDR;
-
- /* invalidate D-Cache */
- sets = (uint32_t)(CCSIDR_SETS(ccsidr));
- do {
- ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
- do {
- SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
- ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
- #if defined ( __CC_ARM )
- __schedule_barrier();
- #endif
- } while (ways-- != 0U);
- } while(sets-- != 0U);
- __DSB();
-
- SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
-
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief Disable D-Cache
- \details Turns off D-Cache
- */
- __STATIC_FORCEINLINE void SCB_DisableDCache (void)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- uint32_t ccsidr;
- uint32_t sets;
- uint32_t ways;
-
- SCB->CSSELR = 0U; /* select Level 1 data cache */
- __DSB();
-
- SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
- __DSB();
-
- ccsidr = SCB->CCSIDR;
-
- /* clean & invalidate D-Cache */
- sets = (uint32_t)(CCSIDR_SETS(ccsidr));
- do {
- ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
- do {
- SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
- ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
- #if defined ( __CC_ARM )
- __schedule_barrier();
- #endif
- } while (ways-- != 0U);
- } while(sets-- != 0U);
-
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief Invalidate D-Cache
- \details Invalidates D-Cache
- */
- __STATIC_FORCEINLINE void SCB_InvalidateDCache (void)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- uint32_t ccsidr;
- uint32_t sets;
- uint32_t ways;
-
- SCB->CSSELR = 0U; /* select Level 1 data cache */
- __DSB();
-
- ccsidr = SCB->CCSIDR;
-
- /* invalidate D-Cache */
- sets = (uint32_t)(CCSIDR_SETS(ccsidr));
- do {
- ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
- do {
- SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
- ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
- #if defined ( __CC_ARM )
- __schedule_barrier();
- #endif
- } while (ways-- != 0U);
- } while(sets-- != 0U);
-
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief Clean D-Cache
- \details Cleans D-Cache
- */
- __STATIC_FORCEINLINE void SCB_CleanDCache (void)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- uint32_t ccsidr;
- uint32_t sets;
- uint32_t ways;
-
- SCB->CSSELR = 0U; /* select Level 1 data cache */
- __DSB();
-
- ccsidr = SCB->CCSIDR;
-
- /* clean D-Cache */
- sets = (uint32_t)(CCSIDR_SETS(ccsidr));
- do {
- ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
- do {
- SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) |
- ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) );
- #if defined ( __CC_ARM )
- __schedule_barrier();
- #endif
- } while (ways-- != 0U);
- } while(sets-- != 0U);
-
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief Clean & Invalidate D-Cache
- \details Cleans and Invalidates D-Cache
- */
- __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- uint32_t ccsidr;
- uint32_t sets;
- uint32_t ways;
-
- SCB->CSSELR = 0U; /* select Level 1 data cache */
- __DSB();
-
- ccsidr = SCB->CCSIDR;
-
- /* clean & invalidate D-Cache */
- sets = (uint32_t)(CCSIDR_SETS(ccsidr));
- do {
- ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
- do {
- SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
- ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
- #if defined ( __CC_ARM )
- __schedule_barrier();
- #endif
- } while (ways-- != 0U);
- } while(sets-- != 0U);
-
- __DSB();
- __ISB();
- #endif
- }
-
-
- /**
- \brief D-Cache Invalidate by address
- \details Invalidates D-Cache for the given address.
- D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
- D-Cache memory blocks which are part of given address + given size are invalidated.
- \param[in] addr address
- \param[in] dsize size of memory block (in number of bytes)
- */
- __STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- if ( dsize > 0 ) {
- int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
- uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
-
- __DSB();
-
- do {
- SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
- op_addr += __SCB_DCACHE_LINE_SIZE;
- op_size -= __SCB_DCACHE_LINE_SIZE;
- } while ( op_size > 0 );
-
- __DSB();
- __ISB();
- }
- #endif
- }
-
-
- /**
- \brief D-Cache Clean by address
- \details Cleans D-Cache for the given address
- D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity.
- D-Cache memory blocks which are part of given address + given size are cleaned.
- \param[in] addr address
- \param[in] dsize size of memory block (in number of bytes)
- */
- __STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- if ( dsize > 0 ) {
- int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
- uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
-
- __DSB();
-
- do {
- SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
- op_addr += __SCB_DCACHE_LINE_SIZE;
- op_size -= __SCB_DCACHE_LINE_SIZE;
- } while ( op_size > 0 );
-
- __DSB();
- __ISB();
- }
- #endif
- }
-
-
- /**
- \brief D-Cache Clean and Invalidate by address
- \details Cleans and invalidates D_Cache for the given address
- D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity.
- D-Cache memory blocks which are part of given address + given size are cleaned and invalidated.
- \param[in] addr address (aligned to 32-byte boundary)
- \param[in] dsize size of memory block (in number of bytes)
- */
- __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
- {
- #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
- if ( dsize > 0 ) {
- int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
- uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
-
- __DSB();
-
- do {
- SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
- op_addr += __SCB_DCACHE_LINE_SIZE;
- op_size -= __SCB_DCACHE_LINE_SIZE;
- } while ( op_size > 0 );
-
- __DSB();
- __ISB();
- }
- #endif
- }
-
- /*@} end of CMSIS_Core_CacheFunctions */
-
- #endif /* ARM_CACHEL1_ARMV7_H */
|