1 /**
2   ******************************************************************************
3   * @file    stm32wbaxx_hal_cortex.c
4   * @author  MCD Application Team
5   * @brief   CORTEX HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the CORTEX:
8   *           + Initialization and Configuration functions
9   *           + Peripheral Control functions
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2022 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file
17   * in the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21   @verbatim
22   ==============================================================================
23                         ##### How to use this driver #####
24   ==============================================================================
25 
26     [..]
27     *** How to configure Interrupts using CORTEX HAL driver ***
28     ===========================================================
29     [..]
30     This section provides functions allowing to configure the NVIC interrupts (IRQ).
31     The Cortex-M33 exceptions are managed by CMSIS functions.
32 
33     (#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping() function.
34     (#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority().
35     (#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ().
36 
37      -@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ pre-emption is no more possible.
38          The pending IRQ priority will be managed only by the sub priority.
39 
40      -@- IRQ priority order (sorted by highest to lowest priority):
41         (+@) Lowest pre-emption priority
42         (+@) Lowest sub priority
43         (+@) Lowest hardware priority (IRQ number)
44 
45     [..]
46     *** How to configure SysTick using CORTEX HAL driver ***
47     ========================================================
48     [..]
49     Setup SysTick Timer for time base.
50 
51    (+) The HAL_SYSTICK_Config() function calls the SysTick_Config() function which
52        is a CMSIS function that:
53         (++) Configures the SysTick Reload register with value passed as function parameter.
54         (++) Configures the SysTick IRQ priority to the lowest value (0x0F).
55         (++) Resets the SysTick Counter register.
56         (++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK).
57         (++) Enables the SysTick Interrupt.
58         (++) Starts the SysTick Counter.
59 
60    (+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro
61        __HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
62        HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined
63        inside the stm32wbaxx_hal_cortex.h file.
64 
65    (+) You can change the SysTick IRQ priority by calling the
66        HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function
67        call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function.
68 
69    (+) To adjust the SysTick time base, use the following formula:
70 
71        Reload Value = SysTick Counter Clock (Hz) x  Desired Time base (s)
72        (++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function
73        (++) Reload Value should not exceed 0xFFFFFF
74 
75   @endverbatim
76   ******************************************************************************
77 
78   The table below gives the allowed values of the pre-emption priority and subpriority according
79   to the Priority Grouping configuration performed by HAL_NVIC_SetPriorityGrouping() function.
80 
81     ==========================================================================================================================
82       NVIC_PriorityGroup   | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority  |       Description
83     ==========================================================================================================================
84      NVIC_PRIORITYGROUP_0  |                0                  |            0-15             | 0 bit for pre-emption priority
85                            |                                   |                             | 4 bits for subpriority
86     --------------------------------------------------------------------------------------------------------------------------
87      NVIC_PRIORITYGROUP_1  |                0-1                |            0-7              | 1 bit for pre-emption priority
88                            |                                   |                             | 3 bits for subpriority
89     --------------------------------------------------------------------------------------------------------------------------
90      NVIC_PRIORITYGROUP_2  |                0-3                |            0-3              | 2 bits for pre-emption priority
91                            |                                   |                             | 2 bits for subpriority
92     --------------------------------------------------------------------------------------------------------------------------
93      NVIC_PRIORITYGROUP_3  |                0-7                |            0-1              | 3 bits for pre-emption priority
94                            |                                   |                             | 1 bit for subpriority
95     --------------------------------------------------------------------------------------------------------------------------
96      NVIC_PRIORITYGROUP_4  |                0-15               |            0                | 4 bits for pre-emption priority
97                            |                                   |                             | 0 bit for subpriority
98     ==========================================================================================================================
99 
100   ******************************************************************************
101   */
102 
103 /* Includes ------------------------------------------------------------------*/
104 #include "stm32wbaxx_hal.h"
105 
106 /** @addtogroup STM32WBAxx_HAL_Driver
107   * @{
108   */
109 
110 /** @addtogroup CORTEX
111   * @{
112   */
113 
114 #ifdef HAL_CORTEX_MODULE_ENABLED
115 
116 /* Private types -------------------------------------------------------------*/
117 /* Private variables ---------------------------------------------------------*/
118 /* Private constants ---------------------------------------------------------*/
119 /* Private macros ------------------------------------------------------------*/
120 /* Private functions ---------------------------------------------------------*/
121 static void MPU_ConfigRegion(MPU_Type *MPUx, MPU_Region_InitTypeDef *MPU_RegionInit);
122 static void MPU_ConfigMemoryAttributes(MPU_Type *MPUx, MPU_Attributes_InitTypeDef *MPU_AttributesInit);
123 /* Exported functions --------------------------------------------------------*/
124 
125 /** @addtogroup CORTEX_Exported_Functions
126   * @{
127   */
128 
129 
130 /** @addtogroup CORTEX_Exported_Functions_Group1
131   *  @brief    Initialization and Configuration functions
132   *
133 @verbatim
134   ==============================================================================
135               ##### Initialization and Configuration functions #####
136   ==============================================================================
137     [..]
138       This section provides the CORTEX HAL driver functions allowing to configure Interrupts
139       SysTick functionalities
140 
141 @endverbatim
142   * @{
143   */
144 
145 
146 /**
147   * @brief  Set the priority grouping field (pre-emption priority and subpriority)
148   *         using the required unlock sequence.
149   * @param  PriorityGroup: The priority grouping bits length.
150   *         This parameter can be one of the following values:
151   *         @arg NVIC_PRIORITYGROUP_0: 0 bit  for pre-emption priority,
152   *                                    4 bits for subpriority
153   *         @arg NVIC_PRIORITYGROUP_1: 1 bit  for pre-emption priority,
154   *                                    3 bits for subpriority
155   *         @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
156   *                                    2 bits for subpriority
157   *         @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
158   *                                    1 bit  for subpriority
159   *         @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
160   *                                    0 bit  for subpriority
161   * @note   When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
162   *         The pending IRQ priority will be managed only by the subpriority.
163   * @retval None
164   */
HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)165 void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
166 {
167   /* Check the parameters */
168   assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
169 
170   /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
171   NVIC_SetPriorityGrouping(PriorityGroup);
172 }
173 
174 /**
175   * @brief  Set the priority of an interrupt.
176   * @param  IRQn: External interrupt number.
177   *         This parameter can be an enumerator of IRQn_Type enumeration
178   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
179   * @param  PreemptPriority: The pre-emption priority for the IRQn channel.
180   *         This parameter can be a value between 0 and 15
181   *         A lower priority value indicates a higher priority
182   * @param  SubPriority: the subpriority level for the IRQ channel.
183   *         This parameter can be a value between 0 and 15
184   *         A lower priority value indicates a higher priority.
185   * @retval None
186   */
HAL_NVIC_SetPriority(IRQn_Type IRQn,uint32_t PreemptPriority,uint32_t SubPriority)187 void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
188 {
189   uint32_t prioritygroup;
190 
191   /* Check the parameters */
192   assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
193   assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
194 
195   prioritygroup = NVIC_GetPriorityGrouping();
196 
197   NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
198 }
199 
200 /**
201   * @brief  Enable a device specific interrupt in the NVIC interrupt controller.
202   * @note   To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
203   *         function should be called before.
204   * @param  IRQn External interrupt number.
205   *         This parameter can be an enumerator of IRQn_Type enumeration
206   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
207   * @retval None
208   */
HAL_NVIC_EnableIRQ(IRQn_Type IRQn)209 void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
210 {
211   /* Check the parameters */
212   assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
213 
214   /* Enable interrupt */
215   NVIC_EnableIRQ(IRQn);
216 }
217 
218 /**
219   * @brief  Disable a device specific interrupt in the NVIC interrupt controller.
220   * @param  IRQn External interrupt number.
221   *         This parameter can be an enumerator of IRQn_Type enumeration
222   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
223   * @retval None
224   */
HAL_NVIC_DisableIRQ(IRQn_Type IRQn)225 void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
226 {
227   /* Check the parameters */
228   assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
229 
230   /* Disable interrupt */
231   NVIC_DisableIRQ(IRQn);
232 }
233 
234 /**
235   * @brief  Initiate a system reset request to reset the MCU.
236   * @retval None
237   */
HAL_NVIC_SystemReset(void)238 void HAL_NVIC_SystemReset(void)
239 {
240   /* System Reset */
241   NVIC_SystemReset();
242 }
243 
244 /**
245   * @brief  Initialize the System Timer with interrupt enabled and start the System Tick Timer (SysTick):
246   *         Counter is in free running mode to generate periodic interrupts.
247   * @param  TicksNumb: Specifies the ticks Number of ticks between two interrupts.
248   * @retval status:  - 0  Function succeeded.
249   *                  - 1  Function failed.
250   */
HAL_SYSTICK_Config(uint32_t TicksNumb)251 uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
252 {
253   return SysTick_Config(TicksNumb);
254 }
255 /**
256   * @}
257   */
258 
259 /** @addtogroup CORTEX_Exported_Functions_Group2
260   *  @brief   Cortex control functions
261   *
262 @verbatim
263   ==============================================================================
264                       ##### Peripheral Control functions #####
265   ==============================================================================
266     [..]
267       This subsection provides a set of functions allowing to control the CORTEX
268       (NVIC, SYSTICK, MPU) functionalities.
269 
270 
271 @endverbatim
272   * @{
273   */
274 
275 /**
276   * @brief  Get the priority grouping field from the NVIC Interrupt Controller.
277   * @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field)
278   */
HAL_NVIC_GetPriorityGrouping(void)279 uint32_t HAL_NVIC_GetPriorityGrouping(void)
280 {
281   /* Get the PRIGROUP[10:8] field value */
282   return NVIC_GetPriorityGrouping();
283 }
284 
285 /**
286   * @brief  Get the priority of an interrupt.
287   * @param  IRQn: External interrupt number.
288   *         This parameter can be an enumerator of IRQn_Type enumeration
289   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
290   * @param   PriorityGroup: the priority grouping bits length.
291   *         This parameter can be one of the following values:
292   *           @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority,
293   *                                      4 bits for subpriority
294   *           @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority,
295   *                                      3 bits for subpriority
296   *           @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
297   *                                      2 bits for subpriority
298   *           @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
299   *                                      1 bit for subpriority
300   *           @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
301   *                                      0 bit for subpriority
302   * @param  pPreemptPriority: Pointer on the Preemptive priority value (starting from 0).
303   * @param  pSubPriority: Pointer on the Subpriority value (starting from 0).
304   * @retval None
305   */
HAL_NVIC_GetPriority(IRQn_Type IRQn,uint32_t PriorityGroup,uint32_t * pPreemptPriority,uint32_t * pSubPriority)306 void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority)
307 {
308   /* Check the parameters */
309   assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
310   /* Get priority for Cortex-M system or device specific interrupts */
311   NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority);
312 }
313 
314 /**
315   * @brief  Set Pending bit of an external interrupt.
316   * @param  IRQn External interrupt number
317   *         This parameter can be an enumerator of IRQn_Type enumeration
318   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
319   * @retval None
320   */
HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)321 void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)
322 {
323   /* Set interrupt pending */
324   NVIC_SetPendingIRQ(IRQn);
325 }
326 
327 /**
328   * @brief  Get Pending Interrupt (read the pending register in the NVIC
329   *         and return the pending bit for the specified interrupt).
330   * @param  IRQn External interrupt number.
331   *          This parameter can be an enumerator of IRQn_Type enumeration
332   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
333   * @retval status: - 0  Interrupt status is not pending.
334   *                 - 1  Interrupt status is pending.
335   */
HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)336 uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)
337 {
338   /* Return 1 if pending else 0 */
339   return NVIC_GetPendingIRQ(IRQn);
340 }
341 
342 /**
343   * @brief  Clear the pending bit of an external interrupt.
344   * @param  IRQn External interrupt number.
345   *         This parameter can be an enumerator of IRQn_Type enumeration
346   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
347   * @retval None
348   */
HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)349 void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
350 {
351   /* Clear pending interrupt */
352   NVIC_ClearPendingIRQ(IRQn);
353 }
354 
355 /**
356   * @brief Get active interrupt (read the active register in NVIC and return the active bit).
357   * @param IRQn External interrupt number
358   *         This parameter can be an enumerator of IRQn_Type enumeration
359   *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32wbaxxxx.h))
360   * @retval status: - 0  Interrupt status is not pending.
361   *                 - 1  Interrupt status is pending.
362   */
HAL_NVIC_GetActive(IRQn_Type IRQn)363 uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
364 {
365   /* Return 1 if active else 0 */
366   return NVIC_GetActive(IRQn);
367 }
368 
369 /**
370   * @brief  Configure the SysTick clock source.
371   * @param  CLKSource: specifies the SysTick clock source.
372   *          This parameter can be one of the following values:
373   *             @arg SYSTICK_CLKSOURCE_LSI: LSI clock selected as SysTick clock source.
374   *             @arg SYSTICK_CLKSOURCE_LSE: LSE clock selected as SysTick clock source.
375   *             @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source.
376   *             @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source.
377   * @retval None
378   */
HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)379 void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
380 {
381   /* Check the parameters */
382   assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));
383   switch (CLKSource)
384   {
385     /* Select HCLK as Systick clock source */
386     case SYSTICK_CLKSOURCE_HCLK:
387       SET_BIT(SysTick->CTRL, SysTick_CTRL_CLKSOURCE_Msk);
388       break;
389     /* Select HCLK_DIV8 as Systick clock source */
390     case SYSTICK_CLKSOURCE_HCLK_DIV8:
391       CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_CLKSOURCE_Msk);
392       MODIFY_REG(RCC->CCIPR1, RCC_CCIPR1_SYSTICKSEL, (0x00000000U));
393       break;
394     /* Select LSI as Systick clock source */
395     case SYSTICK_CLKSOURCE_LSI:
396       CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_CLKSOURCE_Msk);
397       MODIFY_REG(RCC->CCIPR1, RCC_CCIPR1_SYSTICKSEL, RCC_CCIPR1_SYSTICKSEL_0);
398       break;
399     /* Select LSE as Systick clock source */
400     case SYSTICK_CLKSOURCE_LSE:
401       CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_CLKSOURCE_Msk);
402       MODIFY_REG(RCC->CCIPR1, RCC_CCIPR1_SYSTICKSEL, RCC_CCIPR1_SYSTICKSEL_1);
403       break;
404     default:
405       /* Nothing to do */
406       break;
407   }
408 }
409 
410 /**
411   * @brief  Handle SYSTICK interrupt request.
412   * @retval None
413   */
HAL_SYSTICK_IRQHandler(void)414 void HAL_SYSTICK_IRQHandler(void)
415 {
416   HAL_SYSTICK_Callback();
417 }
418 
419 /**
420   * @brief  SYSTICK callback.
421   * @retval None
422   */
HAL_SYSTICK_Callback(void)423 __weak void HAL_SYSTICK_Callback(void)
424 {
425   /* NOTE : This function should not be modified, when the callback is needed,
426             the HAL_SYSTICK_Callback could be implemented in the user file
427    */
428 }
429 
430 #if (__MPU_PRESENT == 1)
431 
432 /**
433   * @brief  Enable the MPU.
434   * @param  MPU_Control: Specifies the control mode of the MPU during hard fault,
435   *          NMI, FAULTMASK and privileged accessto the default memory
436   *          This parameter can be one of the following values:
437   *            @arg MPU_HFNMI_PRIVDEF_NONE
438   *            @arg MPU_HARDFAULT_NMI
439   *            @arg MPU_PRIVILEGED_DEFAULT
440   *            @arg MPU_HFNMI_PRIVDEF
441   * @retval None
442   */
HAL_MPU_Enable(uint32_t MPU_Control)443 void HAL_MPU_Enable(uint32_t MPU_Control)
444 {
445   __DMB(); /* Data Memory Barrier operation to force any outstanding writes to memory before enabling the MPU */
446 
447   /* Enable the MPU */
448   MPU->CTRL   = MPU_Control | MPU_CTRL_ENABLE_Msk;
449 
450   /* Enable fault exceptions */
451   SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
452 
453   /* Follow ARM recommendation with */
454   /* Data Synchronization and Instruction Synchronization Barriers to ensure MPU configuration */
455   __DSB(); /* Ensure that the subsequent instruction is executed only after the write to memory */
456   __ISB(); /* Flush and refill pipeline with updated MPU configuration settings */
457 }
458 
459 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
460 /**
461   * @brief  Enable the non-secure MPU.
462   * @param  MPU_Control: Specifies the control mode of the MPU during hard fault,
463   *          NMI, FAULTMASK and privileged accessto the default memory
464   *          This parameter can be one of the following values:
465   *            @arg MPU_HFNMI_PRIVDEF_NONE
466   *            @arg MPU_HARDFAULT_NMI
467   *            @arg MPU_PRIVILEGED_DEFAULT
468   *            @arg MPU_HFNMI_PRIVDEF
469   * @retval None
470   */
HAL_MPU_Enable_NS(uint32_t MPU_Control)471 void HAL_MPU_Enable_NS(uint32_t MPU_Control)
472 {
473   __DMB(); /* Data Memory Barrier operation to force any outstanding writes to memory before enabling the MPU */
474 
475   /* Enable the MPU */
476   MPU_NS->CTRL   = MPU_Control | MPU_CTRL_ENABLE_Msk;
477 
478   /* Enable fault exceptions */
479   SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
480 
481   /* Follow ARM recommendation with */
482   /* Data Synchronization and Instruction Synchronization Barriers to ensure MPU configuration */
483   __DSB(); /* Ensure that the subsequent instruction is executed only after the write to memory */
484   __ISB(); /* Flush and refill pipeline with updated MPU configuration settings */
485 }
486 #endif /* __ARM_FEATURE_CMSE */
487 
488 /**
489   * @brief  Disable the MPU.
490   * @retval None
491   */
HAL_MPU_Disable(void)492 void HAL_MPU_Disable(void)
493 {
494   __DMB(); /* Force any outstanding transfers to complete before disabling MPU */
495 
496   /* Disable fault exceptions */
497   SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
498 
499   /* Disable the MPU */
500   MPU->CTRL  &= ~MPU_CTRL_ENABLE_Msk;
501 
502   /* Follow ARM recommendation with */
503   /* Data Synchronization and Instruction Synchronization Barriers to ensure MPU configuration */
504   __DSB(); /* Ensure that the subsequent instruction is executed only after the write to memory */
505   __ISB(); /* Flush and refill pipeline with updated MPU configuration settings */
506 }
507 
508 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
HAL_MPU_Disable_NS(void)509 void HAL_MPU_Disable_NS(void)
510 {
511   __DMB(); /* Force any outstanding transfers to complete before disabling MPU */
512 
513   /* Disable fault exceptions */
514   SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
515 
516   /* Disable the MPU */
517   MPU_NS->CTRL  &= ~MPU_CTRL_ENABLE_Msk;
518 
519   /* Follow ARM recommendation with */
520   /* Data Synchronization and Instruction Synchronization Barriers to ensure MPU configuration */
521   __DSB(); /* Ensure that the subsequent instruction is executed only after the write to memory */
522   __ISB(); /* Flush and refill pipeline with updated MPU configuration settings */
523 }
524 #endif /* __ARM_FEATURE_CMSE */
525 /**
526   * @brief  Initialize and configure the Region and the memory to be protected.
527   * @param  MPU_RegionInit: Pointer to a MPU_Region_InitTypeDef structure that contains
528   *                the initialization and configuration information.
529   * @retval None
530   */
HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef * MPU_RegionInit)531 void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_RegionInit)
532 {
533   MPU_ConfigRegion(MPU, MPU_RegionInit);
534 }
535 
536 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
537 /**
538   * @brief  Initialize and configure the Region and the memory to be protected for non-secure MPU.
539   * @param  MPU_RegionInit: Pointer to a MPU_Region_InitTypeDef structure that contains
540   *                the initialization and configuration information.
541   * @retval None
542   */
HAL_MPU_ConfigRegion_NS(MPU_Region_InitTypeDef * MPU_RegionInit)543 void HAL_MPU_ConfigRegion_NS(MPU_Region_InitTypeDef *MPU_RegionInit)
544 {
545   MPU_ConfigRegion(MPU_NS, MPU_RegionInit);
546 }
547 #endif /* __ARM_FEATURE_CMSE */
548 
MPU_ConfigRegion(MPU_Type * MPUx,MPU_Region_InitTypeDef * MPU_RegionInit)549 static void MPU_ConfigRegion(MPU_Type *MPUx, MPU_Region_InitTypeDef *MPU_RegionInit)
550 {
551   /* Check the parameters */
552   assert_param(IS_MPU_REGION_NUMBER(MPU_RegionInit->Number));
553   assert_param(IS_MPU_REGION_ENABLE(MPU_RegionInit->Enable));
554 
555   /* Follow ARM recommendation with Data Memory Barrier prior to MPU configuration */
556   __DMB();
557 
558   /* Set the Region number */
559   MPUx->RNR = MPU_RegionInit->Number;
560 
561   if (MPU_RegionInit->Enable != MPU_REGION_DISABLE)
562   {
563     /* Check the parameters */
564     assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_RegionInit->DisableExec));
565     assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_RegionInit->AccessPermission));
566     assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_RegionInit->IsShareable));
567 
568     MPUx->RBAR = (((uint32_t)MPU_RegionInit->BaseAddress               & 0xFFFFFFE0U)  |
569                   ((uint32_t)MPU_RegionInit->IsShareable           << MPU_RBAR_SH_Pos)  |
570                   ((uint32_t)MPU_RegionInit->AccessPermission      << MPU_RBAR_AP_Pos)  |
571                   ((uint32_t)MPU_RegionInit->DisableExec           << MPU_RBAR_XN_Pos));
572 
573     MPUx->RLAR = (((uint32_t)MPU_RegionInit->LimitAddress                    & 0xFFFFFFE0U) |
574                   ((uint32_t)MPU_RegionInit->AttributesIndex       << MPU_RLAR_AttrIndx_Pos) |
575                   ((uint32_t)MPU_RegionInit->Enable                << MPU_RLAR_EN_Pos));
576   }
577   else
578   {
579     MPUx->RBAR = 0U;
580     MPUx->RLAR = 0U;
581   }
582 }
583 /**
584   * @brief  Initialize and configure the memory attributes.
585   * @param  MPU_AttributesInit: Pointer to a MPU_Attributes_InitTypeDef structure that contains
586   *                the initialization and configuration information.
587   * @retval None
588   */
HAL_MPU_ConfigMemoryAttributes(MPU_Attributes_InitTypeDef * MPU_AttributesInit)589 void HAL_MPU_ConfigMemoryAttributes(MPU_Attributes_InitTypeDef *MPU_AttributesInit)
590 {
591   MPU_ConfigMemoryAttributes(MPU, MPU_AttributesInit);
592 }
593 
594 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
595 /**
596   * @brief  Initialize and configure the memory attributes for non-secure MPU.
597   * @param  MPU_AttributesInit: Pointer to a MPU_Attributes_InitTypeDef structure that contains
598   *                the initialization and configuration information.
599   * @retval None
600   */
HAL_MPU_ConfigMemoryAttributes_NS(MPU_Attributes_InitTypeDef * MPU_AttributesInit)601 void HAL_MPU_ConfigMemoryAttributes_NS(MPU_Attributes_InitTypeDef *MPU_AttributesInit)
602 {
603   MPU_ConfigMemoryAttributes(MPU_NS, MPU_AttributesInit);
604 }
605 #endif /* __ARM_FEATURE_CMSE */
606 
MPU_ConfigMemoryAttributes(MPU_Type * MPUx,MPU_Attributes_InitTypeDef * MPU_AttributesInit)607 static void MPU_ConfigMemoryAttributes(MPU_Type *MPUx, MPU_Attributes_InitTypeDef *MPU_AttributesInit)
608 {
609   __IO uint32_t *mair;
610   uint32_t      attr_values;
611   uint32_t      attr_number;
612 
613   /* Check the parameters */
614   assert_param(IS_MPU_ATTRIBUTES_NUMBER(MPU_AttributesInit->Number));
615   /* No need to check Attributes value as all 0x0..0xFF possible */
616 
617   /* Follow ARM recommendation with Data Memory Barrier prior to MPUx configuration */
618   __DMB();
619 
620   if (MPU_AttributesInit->Number < MPU_ATTRIBUTES_NUMBER4)
621   {
622     /* Program MPU_MAIR0 */
623     mair = &(MPUx->MAIR0);
624     attr_number = MPU_AttributesInit->Number;
625   }
626   else
627   {
628     /* Program MPU_MAIR1 */
629     mair = &(MPUx->MAIR1);
630     attr_number = (uint32_t)MPU_AttributesInit->Number - 4U;
631   }
632 
633   attr_values = *(mair);
634   attr_values &=  ~(0xFFU << (attr_number * 8U));
635   *(mair) = attr_values | ((uint32_t)MPU_AttributesInit->Attributes << (attr_number * 8U));
636 }
637 
638 #endif /* __MPU_PRESENT */
639 
640 /**
641   * @}
642   */
643 
644 /**
645   * @}
646   */
647 
648 #endif /* HAL_CORTEX_MODULE_ENABLED */
649 /**
650   * @}
651   */
652 
653 /**
654   * @}
655   */
656