1 /******************************************************************************
2 * @file cachel1_armv7.h
3 * @brief CMSIS Level 1 Cache API for Armv7-M and later
6 ******************************************************************************/
8 * Copyright (c) 2020-2021 Arm Limited. All rights reserved.
10 * SPDX-License-Identifier: Apache-2.0
12 * Licensed under the Apache License, Version 2.0 (the License); you may
13 * not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
25 #if defined ( __ICCARM__ )
26 #pragma system_include /* treat file as system include file for MISRA check */
27 #elif defined (__clang__)
28 #pragma clang system_header /* treat file as system include file */
31 #ifndef ARM_CACHEL1_ARMV7_H
32 #define ARM_CACHEL1_ARMV7_H
35 \ingroup CMSIS_Core_FunctionInterface
36 \defgroup CMSIS_Core_CacheFunctions Cache Functions
37 \brief Functions that configure Instruction and Data cache.
41 /* Cache Size ID Register Macros */
42 #define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
43 #define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos )
45 #ifndef __SCB_DCACHE_LINE_SIZE
46 #define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
49 #ifndef __SCB_ICACHE_LINE_SIZE
50 #define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
55 \details Turns on I-Cache
57 __STATIC_FORCEINLINE void SCB_EnableICache (void)
59 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
60 if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */
64 SCB->ICIALLU = 0UL; /* invalidate I-Cache */
67 SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */
75 \brief Disable I-Cache
76 \details Turns off I-Cache
78 __STATIC_FORCEINLINE void SCB_DisableICache (void)
80 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
83 SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */
84 SCB->ICIALLU = 0UL; /* invalidate I-Cache */
92 \brief Invalidate I-Cache
93 \details Invalidates I-Cache
95 __STATIC_FORCEINLINE void SCB_InvalidateICache (void)
97 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
108 \brief I-Cache Invalidate by address
109 \details Invalidates I-Cache for the given address.
110 I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
111 I-Cache memory blocks which are part of given address + given size are invalidated.
112 \param[in] addr address
113 \param[in] isize size of memory block (in number of bytes)
115 __STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (volatile void *addr, int32_t isize)
117 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
119 int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U));
120 uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */;
125 SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
126 op_addr += __SCB_ICACHE_LINE_SIZE;
127 op_size -= __SCB_ICACHE_LINE_SIZE;
128 } while ( op_size > 0 );
138 \brief Enable D-Cache
139 \details Turns on D-Cache
141 __STATIC_FORCEINLINE void SCB_EnableDCache (void)
143 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
148 if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */
150 SCB->CSSELR = 0U; /* select Level 1 data cache */
153 ccsidr = SCB->CCSIDR;
155 /* invalidate D-Cache */
156 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
158 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
160 SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
161 ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
162 #if defined ( __CC_ARM )
163 __schedule_barrier();
165 } while (ways-- != 0U);
166 } while(sets-- != 0U);
169 SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
178 \brief Disable D-Cache
179 \details Turns off D-Cache
181 __STATIC_FORCEINLINE void SCB_DisableDCache (void)
183 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
188 SCB->CSSELR = 0U; /* select Level 1 data cache */
191 SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
194 ccsidr = SCB->CCSIDR;
196 /* clean & invalidate D-Cache */
197 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
199 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
201 SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
202 ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
203 #if defined ( __CC_ARM )
204 __schedule_barrier();
206 } while (ways-- != 0U);
207 } while(sets-- != 0U);
216 \brief Invalidate D-Cache
217 \details Invalidates D-Cache
219 __STATIC_FORCEINLINE void SCB_InvalidateDCache (void)
221 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
226 SCB->CSSELR = 0U; /* select Level 1 data cache */
229 ccsidr = SCB->CCSIDR;
231 /* invalidate D-Cache */
232 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
234 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
236 SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
237 ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
238 #if defined ( __CC_ARM )
239 __schedule_barrier();
241 } while (ways-- != 0U);
242 } while(sets-- != 0U);
252 \details Cleans D-Cache
254 __STATIC_FORCEINLINE void SCB_CleanDCache (void)
256 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
261 SCB->CSSELR = 0U; /* select Level 1 data cache */
264 ccsidr = SCB->CCSIDR;
267 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
269 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
271 SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) |
272 ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) );
273 #if defined ( __CC_ARM )
274 __schedule_barrier();
276 } while (ways-- != 0U);
277 } while(sets-- != 0U);
286 \brief Clean & Invalidate D-Cache
287 \details Cleans and Invalidates D-Cache
289 __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void)
291 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
296 SCB->CSSELR = 0U; /* select Level 1 data cache */
299 ccsidr = SCB->CCSIDR;
301 /* clean & invalidate D-Cache */
302 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
304 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
306 SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
307 ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
308 #if defined ( __CC_ARM )
309 __schedule_barrier();
311 } while (ways-- != 0U);
312 } while(sets-- != 0U);
321 \brief D-Cache Invalidate by address
322 \details Invalidates D-Cache for the given address.
323 D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
324 D-Cache memory blocks which are part of given address + given size are invalidated.
325 \param[in] addr address
326 \param[in] dsize size of memory block (in number of bytes)
328 __STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (volatile void *addr, int32_t dsize)
330 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
332 int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
333 uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
338 SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
339 op_addr += __SCB_DCACHE_LINE_SIZE;
340 op_size -= __SCB_DCACHE_LINE_SIZE;
341 } while ( op_size > 0 );
351 \brief D-Cache Clean by address
352 \details Cleans D-Cache for the given address
353 D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity.
354 D-Cache memory blocks which are part of given address + given size are cleaned.
355 \param[in] addr address
356 \param[in] dsize size of memory block (in number of bytes)
358 __STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (volatile void *addr, int32_t dsize)
360 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
362 int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
363 uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
368 SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
369 op_addr += __SCB_DCACHE_LINE_SIZE;
370 op_size -= __SCB_DCACHE_LINE_SIZE;
371 } while ( op_size > 0 );
381 \brief D-Cache Clean and Invalidate by address
382 \details Cleans and invalidates D_Cache for the given address
383 D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity.
384 D-Cache memory blocks which are part of given address + given size are cleaned and invalidated.
385 \param[in] addr address (aligned to 32-byte boundary)
386 \param[in] dsize size of memory block (in number of bytes)
388 __STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (volatile void *addr, int32_t dsize)
390 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
392 int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
393 uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
398 SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
399 op_addr += __SCB_DCACHE_LINE_SIZE;
400 op_size -= __SCB_DCACHE_LINE_SIZE;
401 } while ( op_size > 0 );
409 /*@} end of CMSIS_Core_CacheFunctions */
411 #endif /* ARM_CACHEL1_ARMV7_H */