RTEMS 6.1-rc6
Loading...
Searching...
No Matches
cachel1_armv7.h
Go to the documentation of this file.
1/******************************************************************************
2 * @file cachel1_armv7.h
3 * @brief CMSIS Level 1 Cache API for Armv7-M and later
4 * @version V1.0.3
5 * @date 17. March 2023
6 ******************************************************************************/
7/*
8 * Copyright (c) 2020-2021 Arm Limited. All rights reserved.
9 *
10 * SPDX-License-Identifier: Apache-2.0
11 *
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
15 *
16 * www.apache.org/licenses/LICENSE-2.0
17 *
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.
23 */
24
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 */
29#endif
30
31#ifndef ARM_CACHEL1_ARMV7_H
32#define ARM_CACHEL1_ARMV7_H
33
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 )
44
45#ifndef __SCB_DCACHE_LINE_SIZE
46#define __SCB_DCACHE_LINE_SIZE 32U
47#endif
48
49#ifndef __SCB_ICACHE_LINE_SIZE
50#define __SCB_ICACHE_LINE_SIZE 32U
51#endif
52
57__STATIC_FORCEINLINE void SCB_EnableICache (void)
58{
59 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
60 if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */
61
62 __DSB();
63 __ISB();
64 SCB->ICIALLU = 0UL; /* invalidate I-Cache */
65 __DSB();
66 __ISB();
67 SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */
68 __DSB();
69 __ISB();
70 #endif
71}
72
73
78__STATIC_FORCEINLINE void SCB_DisableICache (void)
79{
80 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
81 __DSB();
82 __ISB();
83 SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */
84 SCB->ICIALLU = 0UL; /* invalidate I-Cache */
85 __DSB();
86 __ISB();
87 #endif
88}
89
90
95__STATIC_FORCEINLINE void SCB_InvalidateICache (void)
96{
97 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
98 __DSB();
99 __ISB();
100 SCB->ICIALLU = 0UL;
101 __DSB();
102 __ISB();
103 #endif
104}
105
106
115__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (volatile void *addr, int32_t isize)
116{
117 #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
118 if ( isize > 0 ) {
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) */;
121
122 __DSB();
123
124 do {
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 );
129
130 __DSB();
131 __ISB();
132 }
133 #endif
134}
135
136
141__STATIC_FORCEINLINE void SCB_EnableDCache (void)
142{
143 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
144 uint32_t ccsidr;
145 uint32_t sets;
146 uint32_t ways;
147
148 if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */
149
150 SCB->CSSELR = 0U; /* select Level 1 data cache */
151 __DSB();
152
153 ccsidr = SCB->CCSIDR;
154
155 /* invalidate D-Cache */
156 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
157 do {
158 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
159 do {
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();
164 #endif
165 } while (ways-- != 0U);
166 } while(sets-- != 0U);
167 __DSB();
168
169 SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
170
171 __DSB();
172 __ISB();
173 #endif
174}
175
176
181__STATIC_FORCEINLINE void SCB_DisableDCache (void)
182{
183 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
184 struct {
185 uint32_t ccsidr;
186 uint32_t sets;
187 uint32_t ways;
188 } locals
189 #if ((defined(__GNUC__) || defined(__clang__)) && !defined(__OPTIMIZE__))
190 __ALIGNED(__SCB_DCACHE_LINE_SIZE)
191 #endif
192 ;
193
194 SCB->CSSELR = 0U; /* select Level 1 data cache */
195 __DSB();
196
197 SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
198 __DSB();
199
200 #if !defined(__OPTIMIZE__)
201 /*
202 * For the endless loop issue with no optimization builds.
203 * More details, see https://github.com/ARM-software/CMSIS_5/issues/620
204 *
205 * The issue only happens when local variables are in stack. If
206 * local variables are saved in general purpose register, then the function
207 * is OK.
208 *
209 * When local variables are in stack, after disabling the cache, flush the
210 * local variables cache line for data consistency.
211 */
212 /* Clean and invalidate the local variable cache. */
213 #if defined(__ICCARM__)
214 /* As we can't align the stack to the cache line size, invalidate each of the variables */
215 SCB->DCCIMVAC = (uint32_t)&locals.sets;
216 SCB->DCCIMVAC = (uint32_t)&locals.ways;
217 SCB->DCCIMVAC = (uint32_t)&locals.ccsidr;
218 #else
219 SCB->DCCIMVAC = (uint32_t)&locals;
220 #endif
221 __DSB();
222 __ISB();
223 #endif
224
225 locals.ccsidr = SCB->CCSIDR;
226 /* clean & invalidate D-Cache */
227 locals.sets = (uint32_t)(CCSIDR_SETS(locals.ccsidr));
228 do {
229 locals.ways = (uint32_t)(CCSIDR_WAYS(locals.ccsidr));
230 do {
231 SCB->DCCISW = (((locals.sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
232 ((locals.ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) );
233 #if defined ( __CC_ARM )
234 __schedule_barrier();
235 #endif
236 } while (locals.ways-- != 0U);
237 } while(locals.sets-- != 0U);
238
239 __DSB();
240 __ISB();
241 #endif
242}
243
244
249__STATIC_FORCEINLINE void SCB_InvalidateDCache (void)
250{
251 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
252 uint32_t ccsidr;
253 uint32_t sets;
254 uint32_t ways;
255
256 SCB->CSSELR = 0U; /* select Level 1 data cache */
257 __DSB();
258
259 ccsidr = SCB->CCSIDR;
260
261 /* invalidate D-Cache */
262 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
263 do {
264 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
265 do {
266 SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |
267 ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) );
268 #if defined ( __CC_ARM )
269 __schedule_barrier();
270 #endif
271 } while (ways-- != 0U);
272 } while(sets-- != 0U);
273
274 __DSB();
275 __ISB();
276 #endif
277}
278
279
284__STATIC_FORCEINLINE void SCB_CleanDCache (void)
285{
286 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
287 uint32_t ccsidr;
288 uint32_t sets;
289 uint32_t ways;
290
291 SCB->CSSELR = 0U; /* select Level 1 data cache */
292 __DSB();
293
294 ccsidr = SCB->CCSIDR;
295
296 /* clean D-Cache */
297 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
298 do {
299 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
300 do {
301 SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) |
302 ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) );
303 #if defined ( __CC_ARM )
304 __schedule_barrier();
305 #endif
306 } while (ways-- != 0U);
307 } while(sets-- != 0U);
308
309 __DSB();
310 __ISB();
311 #endif
312}
313
314
319__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void)
320{
321 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
322 uint32_t ccsidr;
323 uint32_t sets;
324 uint32_t ways;
325
326 SCB->CSSELR = 0U; /* select Level 1 data cache */
327 __DSB();
328
329 ccsidr = SCB->CCSIDR;
330
331 /* clean & invalidate D-Cache */
332 sets = (uint32_t)(CCSIDR_SETS(ccsidr));
333 do {
334 ways = (uint32_t)(CCSIDR_WAYS(ccsidr));
335 do {
336 SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |
338 #if defined ( __CC_ARM )
339 __schedule_barrier();
340 #endif
341 } while (ways-- != 0U);
342 } while(sets-- != 0U);
343
344 __DSB();
345 __ISB();
346 #endif
347}
348
349
358__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (volatile void *addr, int32_t dsize)
359{
360 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
361 if ( dsize > 0 ) {
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) */;
364
365 __DSB();
366
367 do {
368 SCB->DCIMVAC = 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 );
372
373 __DSB();
374 __ISB();
375 }
376 #endif
377}
378
379
388__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (volatile void *addr, int32_t dsize)
389{
390 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
391 if ( dsize > 0 ) {
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) */;
394
395 __DSB();
396
397 do {
398 SCB->DCCMVAC = 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 );
402
403 __DSB();
404 __ISB();
405 }
406 #endif
407}
408
409
418__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (volatile void *addr, int32_t dsize)
419{
420 #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
421 if ( dsize > 0 ) {
422 int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
423 uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
424
425 __DSB();
426
427 do {
428 SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
429 op_addr += __SCB_DCACHE_LINE_SIZE;
430 op_size -= __SCB_DCACHE_LINE_SIZE;
431 } while ( op_size > 0 );
432
433 __DSB();
434 __ISB();
435 }
436 #endif
437}
438
441#endif /* ARM_CACHEL1_ARMV7_H */
__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr(volatile void *addr, int32_t dsize)
D-Cache Invalidate by address.
Definition: cachel1_armv7.h:358
__STATIC_FORCEINLINE void SCB_EnableDCache(void)
Enable D-Cache.
Definition: cachel1_armv7.h:141
__STATIC_FORCEINLINE void SCB_DisableICache(void)
Disable I-Cache.
Definition: cachel1_armv7.h:78
__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache(void)
Clean & Invalidate D-Cache.
Definition: cachel1_armv7.h:319
__STATIC_FORCEINLINE void SCB_InvalidateICache(void)
Invalidate I-Cache.
Definition: cachel1_armv7.h:95
__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr(volatile void *addr, int32_t dsize)
D-Cache Clean and Invalidate by address.
Definition: cachel1_armv7.h:418
#define __SCB_DCACHE_LINE_SIZE
Definition: cachel1_armv7.h:46
__STATIC_FORCEINLINE void SCB_EnableICache(void)
Enable I-Cache.
Definition: cachel1_armv7.h:57
__STATIC_FORCEINLINE void SCB_InvalidateDCache(void)
Invalidate D-Cache.
Definition: cachel1_armv7.h:249
__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr(volatile void *addr, int32_t dsize)
D-Cache Clean by address.
Definition: cachel1_armv7.h:388
#define __SCB_ICACHE_LINE_SIZE
Definition: cachel1_armv7.h:50
__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr(volatile void *addr, int32_t isize)
I-Cache Invalidate by address.
Definition: cachel1_armv7.h:115
__STATIC_FORCEINLINE void SCB_CleanDCache(void)
Clean D-Cache.
Definition: cachel1_armv7.h:284
__STATIC_FORCEINLINE void SCB_DisableDCache(void)
Disable D-Cache.
Definition: cachel1_armv7.h:181
__STATIC_FORCEINLINE void __DSB(void)
Data Synchronization Barrier.
Definition: cmsis_gcc.h:286
__STATIC_FORCEINLINE void __ISB(void)
Instruction Synchronization Barrier.
Definition: cmsis_gcc.h:275
#define SCB_DCCISW_SET_Pos
Definition: core_cm7.h:851
#define SCB_CCR_DC_Msk
Definition: core_cm7.h:618
#define SCB_DCCSW_SET_Msk
Definition: core_cm7.h:845
#define SCB_DCCSW_WAY_Pos
Definition: core_cm7.h:841
#define SCB_DCCSW_WAY_Msk
Definition: core_cm7.h:842
#define SCB_DCISW_WAY_Pos
Definition: core_cm7.h:834
#define SCB_DCCISW_WAY_Pos
Definition: core_cm7.h:848
#define SCB_DCISW_SET_Msk
Definition: core_cm7.h:838
#define SCB_DCISW_WAY_Msk
Definition: core_cm7.h:835
#define SCB_DCCSW_SET_Pos
Definition: core_cm7.h:844
#define SCB_DCISW_SET_Pos
Definition: core_cm7.h:837
#define SCB_DCCISW_SET_Msk
Definition: core_cm7.h:852
#define SCB_DCCISW_WAY_Msk
Definition: core_cm7.h:849
#define SCB_CCR_IC_Msk
Definition: core_cm7.h:615
#define SCB
Definition: core_cm4.h:1572