1 /**
2 ******************************************************************************
3 * @file stm32h7rsxx_hal_icache.c
4 * @author MCD Application Team
5 * @brief ICACHE HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the Instruction Cache (ICACHE).
8 * + Initialization and Configuration
9 * + Invalidate functions
10 * + Monitoring management
11 * + Memory address remap management
12 ******************************************************************************
13 * @attention
14 *
15 * Copyright (c) 2022 STMicroelectronics.
16 * All rights reserved.
17 *
18 * This software is licensed under terms that can be found in the LICENSE file
19 * in the root directory of this software component.
20 * If no LICENSE file comes with this software, it is provided AS-IS.
21 *
22 ******************************************************************************
23 @verbatim
24 ==============================================================================
25 ##### ICACHE main features #####
26 ==============================================================================
27 [..]
28 The Texture Cache (ICACHE) is introduced on AXI read-only texture port of
29 the GPU2D to improve performance when reading texture data from internal and
30 external memories.
31
32 ===============================================================================
33 ##### How to use this driver #####
34 ===============================================================================
35 [..]
36 The ICACHE HAL driver can be used as follows:
37
38 (#) Optionally configure the Instruction Cache mode with
39 HAL_ICACHE_ConfigAssociativityMode() if the default configuration
40 does not suit the application requirements.
41
42 (#) Enable and disable the Instruction Cache with respectively
43 HAL_ICACHE_Enable() and HAL_ICACHE_Disable().
44 Use HAL_ICACHE_IsEnabled() to get the Instruction Cache status.
45 To ensure a deterministic cache behavior after power on, system reset or after
46 a call to @ref HAL_ICACHE_Disable(), the application must call
47 @ref HAL_ICACHE_WaitForInvalidateComplete(). Indeed on power on, system reset
48 or cache disable, an automatic cache invalidation procedure is launched and the
49 cache is bypassed until the operation completes.
50
51 (#) Initiate the cache maintenance invalidation procedure with either
52 HAL_ICACHE_Invalidate() (blocking mode) or HAL_ICACHE_Invalidate_IT()
53 (interrupt mode). When interrupt mode is used, the callback function
54 HAL_ICACHE_InvalidateCompleteCallback() is called when the invalidate
55 procedure is complete. The function HAL_ICACHE_WaitForInvalidateComplete()
56 may be called to wait for the end of the invalidate procedure automatically
57 initiated when disabling the Instruction Cache with HAL_ICACHE_Disable().
58 The cache operation is bypassed during the invalidation procedure.
59
60 (#) Use the performance monitoring counters for Hit and Miss with the following
61 functions: HAL_ICACHE_Monitor_Start(), HAL_ICACHE_Monitor_Stop(),
62 HAL_ICACHE_Monitor_Reset(), HAL_ICACHE_Monitor_GetHitValue() and
63 HAL_ICACHE_Monitor_GetMissValue()
64
65 @endverbatim
66 */
67
68 /* Includes ------------------------------------------------------------------*/
69 #include "stm32h7rsxx_hal.h"
70
71 /** @addtogroup STM32H7RSxx_HAL_Driver
72 * @{
73 */
74
75 /** @defgroup ICACHE ICACHE
76 * @brief HAL ICACHE module driver
77 * @{
78 */
79 #if defined(ICACHE) && defined (HAL_ICACHE_MODULE_ENABLED)
80
81 /* Private typedef -----------------------------------------------------------*/
82 /* Private constants ---------------------------------------------------------*/
83 /** @addtogroup ICACHE_Private_Constants ICACHE Private Constants
84 * @{
85 */
86 #define ICACHE_INVALIDATE_TIMEOUT_VALUE 1U /* 1ms */
87 #define ICACHE_DISABLE_TIMEOUT_VALUE 1U /* 1ms */
88
89 /**
90 * @}
91 */
92
93 /* Private macros ------------------------------------------------------------*/
94 /** @defgroup ICACHE_Private_Macros ICACHE Private Macros
95 * @{
96 */
97
98 #define IS_ICACHE_ASSOCIATIVITY_MODE(__MODE__) (((__MODE__) == ICACHE_1WAY) || \
99 ((__MODE__) == ICACHE_4WAYS))
100
101 #define IS_ICACHE_MONITOR_TYPE(__TYPE__) (((__TYPE__) == ICACHE_MONITOR_HIT_MISS) || \
102 ((__TYPE__) == ICACHE_MONITOR_HIT) || \
103 ((__TYPE__) == ICACHE_MONITOR_MISS))
104
105 /**
106 * @}
107 */
108
109 /* Private variables ---------------------------------------------------------*/
110 /* Private function prototypes -----------------------------------------------*/
111
112 /* Exported functions --------------------------------------------------------*/
113
114 /** @defgroup ICACHE_Exported_Functions ICACHE Exported Functions
115 * @{
116 */
117
118 /** @defgroup ICACHE_Exported_Functions_Group1 Initialization and control functions
119 * @brief Initialization and control functions
120 *
121 @verbatim
122 ==============================================================================
123 ##### Initialization and control functions #####
124 ==============================================================================
125 [..]
126 This section provides functions allowing to initialize and control the
127 Instruction Cache (mode, invalidate procedure, performance counters).
128 @endverbatim
129 * @{
130 */
131
132 /**
133 * @brief Configure the Instruction Cache cache associativity mode selection.
134 * @param AssociativityMode Associativity mode selection
135 * This parameter can be one of the following values:
136 * @arg ICACHE_1WAY 1-way cache (direct mapped cache)
137 * @arg ICACHE_4WAYS 4-ways set associative cache (default)
138 * @retval HAL status (HAL_OK/HAL_ERROR)
139 */
HAL_ICACHE_ConfigAssociativityMode(uint32_t AssociativityMode)140 HAL_StatusTypeDef HAL_ICACHE_ConfigAssociativityMode(uint32_t AssociativityMode)
141 {
142 HAL_StatusTypeDef status = HAL_OK;
143
144 /* Check the parameters */
145 assert_param(IS_ICACHE_ASSOCIATIVITY_MODE(AssociativityMode));
146
147 /* Check cache is not enabled */
148 if (READ_BIT(ICACHE->CR, ICACHE_CR_EN) != 0U)
149 {
150 status = HAL_ERROR;
151 }
152 else
153 {
154 MODIFY_REG(ICACHE->CR, ICACHE_CR_WAYSEL, AssociativityMode);
155 }
156
157 return status;
158 }
159
160 /**
161 * @brief DeInitialize the Instruction Cache.
162 * @retval HAL status (HAL_OK)
163 */
HAL_ICACHE_DeInit(void)164 HAL_StatusTypeDef HAL_ICACHE_DeInit(void)
165 {
166 /* Reset interrupt enable value */
167 WRITE_REG(ICACHE->IER, 0U);
168
169 /* Clear any pending flags */
170 WRITE_REG(ICACHE->FCR, ICACHE_FCR_CBSYENDF | ICACHE_FCR_CERRF);
171
172 /* Disable cache then set default associative mode value */
173 CLEAR_BIT(ICACHE->CR, ICACHE_CR_EN);
174 WRITE_REG(ICACHE->CR, ICACHE_CR_WAYSEL);
175
176 /* Stop monitor and reset monitor values */
177 CLEAR_BIT(ICACHE->CR, ICACHE_MONITOR_HIT_MISS);
178 SET_BIT(ICACHE->CR, (ICACHE_MONITOR_HIT_MISS << 2U));
179 CLEAR_BIT(ICACHE->CR, (ICACHE_MONITOR_HIT_MISS << 2U));
180
181
182 return HAL_OK;
183 }
184
185 /**
186 * @brief Enable the Instruction Cache.
187 * @note This function always returns HAL_OK even if there is any ongoing
188 * cache operation. The Instruction Cache is bypassed until the
189 * cache operation completes.
190 * @retval HAL status (HAL_OK)
191 */
HAL_ICACHE_Enable(void)192 HAL_StatusTypeDef HAL_ICACHE_Enable(void)
193 {
194 SET_BIT(ICACHE->CR, ICACHE_CR_EN);
195
196 return HAL_OK;
197 }
198
199 /**
200 * @brief Disable the Instruction Cache.
201 * @note This function waits for the cache being disabled but
202 * not for the end of the automatic cache invalidation procedure.
203 * @retval HAL status (HAL_OK/HAL_TIMEOUT)
204 */
HAL_ICACHE_Disable(void)205 HAL_StatusTypeDef HAL_ICACHE_Disable(void)
206 {
207 HAL_StatusTypeDef status = HAL_OK;
208 uint32_t tickstart;
209
210 /* Make sure BSYENDF is reset before to disable the instruction cache */
211 /* as it automatically starts a cache invalidation procedure */
212 WRITE_REG(ICACHE->FCR, ICACHE_FCR_CBSYENDF);
213
214 CLEAR_BIT(ICACHE->CR, ICACHE_CR_EN);
215
216 /* Get tick */
217 tickstart = HAL_GetTick();
218
219 /* Wait for instruction cache being disabled */
220 while (READ_BIT(ICACHE->CR, ICACHE_CR_EN) != 0U)
221 {
222 if ((HAL_GetTick() - tickstart) > ICACHE_DISABLE_TIMEOUT_VALUE)
223 {
224 /* New check to avoid false timeout detection in case of preemption */
225 if (READ_BIT(ICACHE->CR, ICACHE_CR_EN) != 0U)
226 {
227 status = HAL_TIMEOUT;
228 break;
229 }
230 }
231 }
232
233 return status;
234 }
235
236 /**
237 * @brief Check whether the Instruction Cache is enabled or not.
238 * @retval Status (0: disabled, 1: enabled)
239 */
HAL_ICACHE_IsEnabled(void)240 uint32_t HAL_ICACHE_IsEnabled(void)
241 {
242 return ((READ_BIT(ICACHE->CR, ICACHE_CR_EN) != 0U) ? 1UL : 0UL);
243 }
244
245 /**
246 * @brief Invalidate the Instruction Cache.
247 * @note This function waits for the end of cache invalidation procedure
248 * and clears the associated BSYENDF flag.
249 * @retval HAL status (HAL_OK/HAL_ERROR/HAL_TIMEOUT)
250 */
HAL_ICACHE_Invalidate(void)251 HAL_StatusTypeDef HAL_ICACHE_Invalidate(void)
252 {
253 HAL_StatusTypeDef status;
254
255 /* Check if no ongoing operation */
256 if (READ_BIT(ICACHE->SR, ICACHE_SR_BUSYF) == 0U)
257 {
258 /* Launch cache invalidation */
259 SET_BIT(ICACHE->CR, ICACHE_CR_CACHEINV);
260 }
261
262 status = HAL_ICACHE_WaitForInvalidateComplete();
263
264 return status;
265 }
266
267 /**
268 * @brief Invalidate the Instruction Cache with interrupt.
269 * @note This function launches cache invalidation and returns.
270 * User application shall resort to interrupt generation to check
271 * the end of the cache invalidation with the BSYENDF flag and the
272 * HAL_ICACHE_InvalidateCompleteCallback() callback.
273 * @retval HAL status (HAL_OK/HAL_ERROR)
274 */
HAL_ICACHE_Invalidate_IT(void)275 HAL_StatusTypeDef HAL_ICACHE_Invalidate_IT(void)
276 {
277 HAL_StatusTypeDef status = HAL_OK;
278
279 /* Check no ongoing operation */
280 if (READ_BIT(ICACHE->SR, ICACHE_SR_BUSYF) != 0U)
281 {
282 status = HAL_ERROR;
283 }
284 else
285 {
286 /* Make sure BSYENDF is reset before to start cache invalidation */
287 WRITE_REG(ICACHE->FCR, ICACHE_FCR_CBSYENDF);
288
289 /* Enable end of cache invalidation interrupt */
290 SET_BIT(ICACHE->IER, ICACHE_IER_BSYENDIE);
291
292 /* Launch cache invalidation */
293 SET_BIT(ICACHE->CR, ICACHE_CR_CACHEINV);
294 }
295
296 return status;
297 }
298
299 /**
300 * @brief Wait for the end of the Instruction Cache invalidate procedure.
301 * @note This function checks and clears the BSYENDF flag when set.
302 * @retval HAL status (HAL_OK/HAL_TIMEOUT)
303 */
HAL_ICACHE_WaitForInvalidateComplete(void)304 HAL_StatusTypeDef HAL_ICACHE_WaitForInvalidateComplete(void)
305 {
306 HAL_StatusTypeDef status = HAL_OK;
307 uint32_t tickstart;
308
309 /* Check if ongoing invalidation operation */
310 if (READ_BIT(ICACHE->SR, ICACHE_SR_BUSYF) != 0U)
311 {
312 /* Get tick */
313 tickstart = HAL_GetTick();
314
315 /* Wait for end of cache invalidation */
316 while (READ_BIT(ICACHE->SR, ICACHE_SR_BSYENDF) == 0U)
317 {
318 if ((HAL_GetTick() - tickstart) > ICACHE_INVALIDATE_TIMEOUT_VALUE)
319 {
320 /* New check to avoid false timeout detection in case of preemption */
321 if (READ_BIT(ICACHE->SR, ICACHE_SR_BSYENDF) == 0U)
322 {
323 status = HAL_TIMEOUT;
324 break;
325 }
326 }
327 }
328 }
329
330 /* Clear BSYENDF */
331 WRITE_REG(ICACHE->FCR, ICACHE_FCR_CBSYENDF);
332
333 return status;
334 }
335
336
337 /**
338 * @brief Start the Instruction Cache performance monitoring.
339 * @param MonitorType Monitoring type
340 * This parameter can be one of the following values:
341 * @arg ICACHE_MONITOR_HIT_MISS Hit & Miss monitoring
342 * @arg ICACHE_MONITOR_HIT Hit monitoring
343 * @arg ICACHE_MONITOR_MISS Miss monitoring
344 * @retval HAL status (HAL_OK)
345 */
HAL_ICACHE_Monitor_Start(uint32_t MonitorType)346 HAL_StatusTypeDef HAL_ICACHE_Monitor_Start(uint32_t MonitorType)
347 {
348 /* Check the parameters */
349 assert_param(IS_ICACHE_MONITOR_TYPE(MonitorType));
350
351 SET_BIT(ICACHE->CR, MonitorType);
352
353 return HAL_OK;
354 }
355
356 /**
357 * @brief Stop the Instruction Cache performance monitoring.
358 * @note Stopping the monitoring does not reset the values.
359 * @param MonitorType Monitoring type
360 * This parameter can be one of the following values:
361 * @arg ICACHE_MONITOR_HIT_MISS Hit & Miss monitoring
362 * @arg ICACHE_MONITOR_HIT Hit monitoring
363 * @arg ICACHE_MONITOR_MISS Miss monitoring
364 * @retval HAL status (HAL_OK)
365 */
HAL_ICACHE_Monitor_Stop(uint32_t MonitorType)366 HAL_StatusTypeDef HAL_ICACHE_Monitor_Stop(uint32_t MonitorType)
367 {
368 /* Check the parameters */
369 assert_param(IS_ICACHE_MONITOR_TYPE(MonitorType));
370
371 CLEAR_BIT(ICACHE->CR, MonitorType);
372
373 return HAL_OK;
374 }
375
376 /**
377 * @brief Reset the Instruction Cache performance monitoring values.
378 * @param MonitorType Monitoring type
379 * This parameter can be one of the following values:
380 * @arg ICACHE_MONITOR_HIT_MISS Hit & Miss monitoring
381 * @arg ICACHE_MONITOR_HIT Hit monitoring
382 * @arg ICACHE_MONITOR_MISS Miss monitoring
383 * @retval HAL status (HAL_OK)
384 */
HAL_ICACHE_Monitor_Reset(uint32_t MonitorType)385 HAL_StatusTypeDef HAL_ICACHE_Monitor_Reset(uint32_t MonitorType)
386 {
387 /* Check the parameters */
388 assert_param(IS_ICACHE_MONITOR_TYPE(MonitorType));
389
390 /* Force/Release reset */
391 SET_BIT(ICACHE->CR, (MonitorType << 2U));
392 CLEAR_BIT(ICACHE->CR, (MonitorType << 2U));
393
394 return HAL_OK;
395 }
396
397 /**
398 * @brief Get the Instruction Cache performance Hit monitoring value.
399 * @note Upon reaching the 32-bit maximum value, monitor does not wrap.
400 * @retval Hit monitoring value
401 */
HAL_ICACHE_Monitor_GetHitValue(void)402 uint32_t HAL_ICACHE_Monitor_GetHitValue(void)
403 {
404 return (ICACHE->HMONR);
405 }
406
407 /**
408 * @brief Get the Instruction Cache performance Miss monitoring value.
409 * @note Upon reaching the 32-bit maximum value, monitor does not wrap.
410 * @retval Miss monitoring value
411 */
HAL_ICACHE_Monitor_GetMissValue(void)412 uint32_t HAL_ICACHE_Monitor_GetMissValue(void)
413 {
414 return (ICACHE->MMONR);
415 }
416
417 /**
418 * @}
419 */
420
421 /** @defgroup ICACHE_Exported_Functions_Group2 IRQ and callback functions
422 * @brief IRQ and callback functions
423 *
424 @verbatim
425 ==============================================================================
426 ##### IRQ and callback functions #####
427 ==============================================================================
428 [..]
429 This section provides functions allowing to handle ICACHE global interrupt
430 and the associated callback functions.
431 @endverbatim
432 * @{
433 */
434
435 /**
436 * @brief Handle the Instruction Cache interrupt request.
437 * @note This function should be called under the ICACHE_IRQHandler().
438 * @note This function respectively disables the interrupt and clears the
439 * flag of any pending flag before calling the associated user callback.
440 * @retval None
441 */
HAL_ICACHE_IRQHandler(void)442 void HAL_ICACHE_IRQHandler(void)
443 {
444 /* Get current interrupt flags and interrupt sources value */
445 uint32_t itflags = READ_REG(ICACHE->SR);
446 uint32_t itsources = READ_REG(ICACHE->IER);
447
448 /* Check Instruction cache Error interrupt flag */
449 if (((itflags & itsources) & ICACHE_FLAG_ERROR) != 0U)
450 {
451 /* Disable error interrupt */
452 CLEAR_BIT(ICACHE->IER, ICACHE_IER_ERRIE);
453
454 /* Clear ERR pending flag */
455 WRITE_REG(ICACHE->FCR, ICACHE_FCR_CERRF);
456
457 /* Instruction cache error interrupt user callback */
458 HAL_ICACHE_ErrorCallback();
459 }
460
461 /* Check Instruction cache BusyEnd interrupt flag */
462 if (((itflags & itsources) & ICACHE_FLAG_BUSYEND) != 0U)
463 {
464 /* Disable end of cache invalidation interrupt */
465 CLEAR_BIT(ICACHE->IER, ICACHE_IER_BSYENDIE);
466
467 /* Clear BSYENDF pending flag */
468 WRITE_REG(ICACHE->FCR, ICACHE_FCR_CBSYENDF);
469
470 /* Instruction cache busyend interrupt user callback */
471 HAL_ICACHE_InvalidateCompleteCallback();
472 }
473 }
474
475 /**
476 * @brief Cache invalidation complete callback.
477 */
HAL_ICACHE_InvalidateCompleteCallback(void)478 __weak void HAL_ICACHE_InvalidateCompleteCallback(void)
479 {
480 /* NOTE : This function should not be modified, when the callback is needed,
481 the HAL_ICACHE_InvalidateCompleteCallback() should be implemented in the user file
482 */
483 }
484
485 /**
486 * @brief Error callback.
487 */
HAL_ICACHE_ErrorCallback(void)488 __weak void HAL_ICACHE_ErrorCallback(void)
489 {
490 /* NOTE : This function should not be modified, when the callback is needed,
491 the HAL_ICACHE_ErrorCallback() should be implemented in the user file
492 */
493 }
494
495 /**
496 * @}
497 */
498
499
500 /**
501 * @}
502 */
503
504 #endif /* ICACHE && HAL_ICACHE_MODULE_ENABLED */
505
506 /**
507 * @}
508 */
509
510 /**
511 * @}
512 */
513