1 /*
2 * Copyright (c) 2019 - 2020, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef NRF_CACHE_H__
33 #define NRF_CACHE_H__
34
35 #include <nrfx.h>
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40
41 /**
42 * @defgroup nrf_cache_hal CACHE HAL
43 * @{
44 * @ingroup nrf_cache
45 * @brief The hardware access layer for managing the CACHE peripheral.
46 */
47
48 /** @brief Cache regions. */
49 typedef enum
50 {
51 NRF_CACHE_REGION_FLASH = 0, ///< Cache region related to Flash access.
52 NRF_CACHE_REGION_XIP = 1, ///< Cache region related to XIP access.
53 } nrf_cache_region_t;
54
55 /**
56 * @brief Function for enabling the CACHE peripheral.
57 *
58 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
59 */
60 NRF_STATIC_INLINE void nrf_cache_enable(NRF_CACHE_Type * p_reg);
61
62 /**
63 * @brief Function for disabling the CACHE peripheral.
64 *
65 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
66 */
67 NRF_STATIC_INLINE void nrf_cache_disable(NRF_CACHE_Type * p_reg);
68
69 /**
70 * @brief Function for invalidating the cache content.
71 *
72 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
73 */
74 NRF_STATIC_INLINE void nrf_cache_invalidate(NRF_CACHE_Type * p_reg);
75
76 /**
77 * @brief Function for erasing the cache content.
78 *
79 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
80 */
81 NRF_STATIC_INLINE void nrf_cache_erase(NRF_CACHE_Type * p_reg);
82
83 /**
84 * @brief Function for checking the status of @ref nrf_cache_erase().
85 *
86 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
87 *
88 * @retval true Erase is finished.
89 * @retval false Erase is not complete or has not started.
90 */
91 NRF_STATIC_INLINE bool nrf_cache_erase_status_check(NRF_CACHE_Type const * p_reg);
92
93 /**
94 * @brief Function for clearing the status of the cache erase.
95 *
96 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
97 */
98 NRF_STATIC_INLINE void nrf_cache_erase_status_clear(NRF_CACHE_Type * p_reg);
99
100 /**
101 * @brief Function for setting the cache profiling.
102 *
103 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
104 * @param[in] enable True if cache profiling is to be enabled, false otherwise.
105 */
106 NRF_STATIC_INLINE void nrf_cache_profiling_set(NRF_CACHE_Type * p_reg, bool enable);
107
108 /**
109 * @brief Function for clearing the cache profiling counters.
110 *
111 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
112 */
113 NRF_STATIC_INLINE void nrf_cache_profiling_counters_clear(NRF_CACHE_Type * p_reg);
114
115 /**
116 * @brief Function for getting the number of cache hits for instruction fetch from the specified
117 * cache region.
118 *
119 * @note Separate counters are used for flash region and XIP region.
120 * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
121 *
122 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
123 * @param[in] region Cache region.
124 *
125 * @return Number of instruction fetch cache hits.
126 */
127 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_hit_counter_get(NRF_CACHE_Type const * p_reg,
128 nrf_cache_region_t region);
129
130 /**
131 * @brief Function for getting the number of cache misses for instruction fetch from the specified
132 * cache region.
133 *
134 * @note Separate counters are used for flash region and XIP region.
135 * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
136 *
137 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
138 * @param[in] region Cache region.
139 *
140 * @return Number of instruction fetch cache misses.
141 */
142 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_miss_counter_get(NRF_CACHE_Type const * p_reg,
143 nrf_cache_region_t region);
144
145 /**
146 * @brief Function for getting the number of cache hits for data fetch from the specified
147 * cache region.
148 *
149 * @note Separate counters are used for flash region and XIP region.
150 * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
151 *
152 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
153 * @param[in] region Cache region.
154 *
155 * @return Number of data fetch cache hits.
156 */
157 NRF_STATIC_INLINE uint32_t nrf_cache_data_hit_counter_get(NRF_CACHE_Type const * p_reg,
158 nrf_cache_region_t region);
159
160 /**
161 * @brief Function for getting the number of cache misses for data fetch from the specified
162 * cache region.
163 *
164 * @note Separate counters are used for flash region and XIP region.
165 * @note Cache profiling must be enabled first. See @ref nrf_cache_profiling_set.
166 *
167 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
168 * @param[in] region Cache region.
169 *
170 * @return Number of data fetch cache misses.
171 */
172 NRF_STATIC_INLINE uint32_t nrf_cache_data_miss_counter_get(NRF_CACHE_Type const * p_reg,
173 nrf_cache_region_t region);
174
175 /**
176 * @brief Function for setting the cache RAM mode.
177 *
178 * When configured in the RAM mode, the accesses to internal or external flash will not be cached.
179 * In this mode, the cache data contents can be used as the read/write RAM.
180 * Only the data content of the cache is available as RAM.
181 *
182 * @note -Enabling the RAM mode causes the RAM to be cleared.
183 * @note -Disabling the RAM mode causes the cache to be invalidated.
184 *
185 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
186 * @param[in] enable True if the cache RAM mode is to be enabled, false otherwise.
187 */
188 NRF_STATIC_INLINE void nrf_cache_ram_mode_set(NRF_CACHE_Type * p_reg, bool enable);
189
190 /**
191 * @brief Function for blocking the cache content access.
192 *
193 * To unlock the cache content access, a reset has to be performed.
194 *
195 * @note Blocking is ignored in the RAM mode.
196 *
197 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
198 */
199 NRF_STATIC_INLINE void nrf_cache_read_lock_enable(NRF_CACHE_Type * p_reg);
200
201 /**
202 * @brief Function for blocking the cache content updates.
203 *
204 * Blocking of updates prevents updating of cache content on cache misses,
205 * but the peripheral will continue to check for instruction/data fetches
206 * in the content already present in the cache.
207 *
208 * @note Blocking is ignored in the RAM mode.
209 *
210 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
211 * @param[in] enable True if cache content update lock is to be enabled, false otherwise.
212 */
213 NRF_STATIC_INLINE void nrf_cache_update_lock_set(NRF_CACHE_Type * p_reg, bool enable);
214
215 /**
216 * @brief Function for getting the cache data word.
217 *
218 * @note When operating in the RAM mode, the cache data is accessible as a general purpose RAM.
219 *
220 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
221 * @param[in] set Set that contains the data to get.
222 * @param[in] way Way that contains the data to get.
223 * @param[in] word Data word index to get.
224 *
225 * @return 32-bit data word.
226 */
227 NRF_STATIC_INLINE uint32_t nrf_cache_data_get(NRF_CACHEDATA_Type const * p_reg,
228 uint32_t set,
229 uint8_t way,
230 uint8_t word);
231
232 /**
233 * @brief Function for getting the tag associated with the specified set and way.
234 *
235 * The tag is used to check if an entry in the cache matches the address that is being fetched.
236 *
237 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
238 * @param[in] set Set that contains the tag to get.
239 * @param[in] way Way that contains the tag to get.
240 *
241 * @return Tag value.
242 */
243 NRF_STATIC_INLINE uint32_t nrf_cache_tag_get(NRF_CACHEINFO_Type const * p_reg,
244 uint32_t set,
245 uint8_t way);
246
247 /**
248 * @brief Function for checking the validity of a cache line associated with the specified set and way.
249 *
250 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
251 * @param[in] set Set that contains the cache line to check.
252 * @param[in] way Way that contains the cache line to check.
253 *
254 * @retval true Cache line is valid.
255 * @retval false Cache line is invalid.
256 */
257 NRF_STATIC_INLINE bool nrf_cache_line_validity_check(NRF_CACHEINFO_Type const * p_reg,
258 uint32_t set,
259 uint8_t way);
260
261 /**
262 * @brief Function for getting the most recently used way in the specified set.
263 *
264 * The most recently used way is updated on each fetch from the cache and is used for the cache replacement policy.
265 *
266 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
267 * @param[in] set Specified set.
268 *
269 * @return The most recently used way in the specified set.
270 */
271 NRF_STATIC_INLINE uint8_t nrf_cache_mru_get(NRF_CACHEINFO_Type const * p_reg, uint32_t set);
272
273 #ifndef NRF_DECLARE_ONLY
274
nrf_cache_enable(NRF_CACHE_Type * p_reg)275 NRF_STATIC_INLINE void nrf_cache_enable(NRF_CACHE_Type * p_reg)
276 {
277 p_reg->ENABLE = CACHE_ENABLE_ENABLE_Enabled;
278 }
279
nrf_cache_disable(NRF_CACHE_Type * p_reg)280 NRF_STATIC_INLINE void nrf_cache_disable(NRF_CACHE_Type * p_reg)
281 {
282 p_reg->ENABLE = CACHE_ENABLE_ENABLE_Disabled;
283 }
284
nrf_cache_invalidate(NRF_CACHE_Type * p_reg)285 NRF_STATIC_INLINE void nrf_cache_invalidate(NRF_CACHE_Type * p_reg)
286 {
287 p_reg->INVALIDATE = CACHE_INVALIDATE_INVALIDATE_Invalidate;
288 }
289
nrf_cache_erase(NRF_CACHE_Type * p_reg)290 NRF_STATIC_INLINE void nrf_cache_erase(NRF_CACHE_Type * p_reg)
291 {
292 p_reg->ERASE = CACHE_ERASE_ERASE_Erase;
293 }
294
nrf_cache_erase_status_check(NRF_CACHE_Type const * p_reg)295 NRF_STATIC_INLINE bool nrf_cache_erase_status_check(NRF_CACHE_Type const * p_reg)
296 {
297 return (bool)(p_reg->ERASESTATUS & CACHE_ERASESTATUS_ERASESTATUS_Msk);
298 }
299
nrf_cache_erase_status_clear(NRF_CACHE_Type * p_reg)300 NRF_STATIC_INLINE void nrf_cache_erase_status_clear(NRF_CACHE_Type * p_reg)
301 {
302 p_reg->ERASESTATUS = 0;
303 }
304
nrf_cache_profiling_set(NRF_CACHE_Type * p_reg,bool enable)305 NRF_STATIC_INLINE void nrf_cache_profiling_set(NRF_CACHE_Type * p_reg, bool enable)
306 {
307 p_reg->PROFILINGENABLE =
308 (enable ? CACHE_PROFILINGENABLE_ENABLE_Enable : CACHE_PROFILINGENABLE_ENABLE_Disable);
309 }
310
nrf_cache_profiling_counters_clear(NRF_CACHE_Type * p_reg)311 NRF_STATIC_INLINE void nrf_cache_profiling_counters_clear(NRF_CACHE_Type * p_reg)
312 {
313 p_reg->PROFILINGCLEAR = (CACHE_PROFILINGCLEAR_CLEAR_Clear << CACHE_PROFILINGCLEAR_CLEAR_Pos);
314 }
315
nrf_cache_instruction_hit_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)316 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_hit_counter_get(NRF_CACHE_Type const * p_reg,
317 nrf_cache_region_t region)
318 {
319 return p_reg->PROFILING[region].IHIT;
320 }
321
nrf_cache_instruction_miss_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)322 NRF_STATIC_INLINE uint32_t nrf_cache_instruction_miss_counter_get(NRF_CACHE_Type const * p_reg,
323 nrf_cache_region_t region)
324 {
325 return p_reg->PROFILING[region].IMISS;
326 }
327
nrf_cache_data_hit_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)328 NRF_STATIC_INLINE uint32_t nrf_cache_data_hit_counter_get(NRF_CACHE_Type const * p_reg,
329 nrf_cache_region_t region)
330 {
331 return p_reg->PROFILING[region].DHIT;
332 }
333
nrf_cache_data_miss_counter_get(NRF_CACHE_Type const * p_reg,nrf_cache_region_t region)334 NRF_STATIC_INLINE uint32_t nrf_cache_data_miss_counter_get(NRF_CACHE_Type const * p_reg,
335 nrf_cache_region_t region)
336 {
337 return p_reg->PROFILING[region].DMISS;
338 }
339
nrf_cache_ram_mode_set(NRF_CACHE_Type * p_reg,bool enable)340 NRF_STATIC_INLINE void nrf_cache_ram_mode_set(NRF_CACHE_Type * p_reg, bool enable)
341 {
342 p_reg->MODE = (enable ? CACHE_MODE_MODE_Ram : CACHE_MODE_MODE_Cache);
343 }
344
nrf_cache_read_lock_enable(NRF_CACHE_Type * p_reg)345 NRF_STATIC_INLINE void nrf_cache_read_lock_enable(NRF_CACHE_Type * p_reg)
346 {
347 p_reg->DEBUGLOCK = CACHE_DEBUGLOCK_DEBUGLOCK_Locked;
348 }
349
nrf_cache_update_lock_set(NRF_CACHE_Type * p_reg,bool enable)350 NRF_STATIC_INLINE void nrf_cache_update_lock_set(NRF_CACHE_Type * p_reg, bool enable)
351 {
352 p_reg->WRITELOCK =
353 (enable ? CACHE_WRITELOCK_WRITELOCK_Locked : CACHE_WRITELOCK_WRITELOCK_Unlocked);
354 }
355
nrf_cache_data_get(NRF_CACHEDATA_Type const * p_reg,uint32_t set,uint8_t way,uint8_t word)356 NRF_STATIC_INLINE uint32_t nrf_cache_data_get(NRF_CACHEDATA_Type const * p_reg,
357 uint32_t set,
358 uint8_t way,
359 uint8_t word)
360 {
361 volatile CACHEDATA_SET_WAY_Type const * reg = &p_reg->SET[set].WAY[way];
362 switch (word)
363 {
364 case 0: return reg->DATA0;
365 case 1: return reg->DATA1;
366 case 2: return reg->DATA2;
367 case 3: return reg->DATA3;
368 default:
369 NRFX_ASSERT(false);
370 return 0;
371 }
372 }
373
nrf_cache_tag_get(NRF_CACHEINFO_Type const * p_reg,uint32_t set,uint8_t way)374 NRF_STATIC_INLINE uint32_t nrf_cache_tag_get(NRF_CACHEINFO_Type const * p_reg,
375 uint32_t set,
376 uint8_t way)
377 {
378 return (p_reg->SET[set].WAY[way] & CACHEINFO_SET_WAY_TAG_Msk);
379 }
380
nrf_cache_line_validity_check(NRF_CACHEINFO_Type const * p_reg,uint32_t set,uint8_t way)381 NRF_STATIC_INLINE bool nrf_cache_line_validity_check(NRF_CACHEINFO_Type const * p_reg,
382 uint32_t set,
383 uint8_t way)
384 {
385 return (bool)(p_reg->SET[set].WAY[way] & CACHEINFO_SET_WAY_V_Msk);
386 }
387
nrf_cache_mru_get(NRF_CACHEINFO_Type const * p_reg,uint32_t set)388 NRF_STATIC_INLINE uint8_t nrf_cache_mru_get(NRF_CACHEINFO_Type const * p_reg, uint32_t set)
389 {
390 return ((p_reg->SET[set].WAY[0] & CACHEINFO_SET_WAY_MRU_Msk) >> CACHEINFO_SET_WAY_MRU_Pos);
391 }
392
393 #endif // NRF_DECLARE_ONLY
394
395 /** @} */
396
397 #ifdef __cplusplus
398 }
399 #endif
400
401 #endif // NRF_CACHE_H__
402