1 /**
2   ******************************************************************************
3   * @file    stm32n6xx_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) 2023 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 "stm32n6xx_hal.h"
70 
71 /** @addtogroup STM32N6xx_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