1 /**
2   ******************************************************************************
3   * @file    stm32l0xx_hal.c
4   * @author  MCD Application Team
5   * @brief   HAL module driver.
6   *          This is the common part of the HAL initialization
7   *
8   ******************************************************************************
9   * @attention
10   *
11   * Copyright (c) 2016 STMicroelectronics.
12   * All rights reserved.
13   *
14   * This software is licensed under terms that can be found in the LICENSE file
15   * in the root directory of this software component.
16   * If no LICENSE file comes with this software, it is provided AS-IS.
17   *
18   ******************************************************************************
19   @verbatim
20   ==============================================================================
21                      ##### How to use this driver #####
22   ==============================================================================
23     [..]
24     The common HAL driver contains a set of generic and common APIs that can be
25     used by the PPP peripheral drivers and the user to start using the HAL.
26     [..]
27     The HAL contains two APIs categories:
28          (+) Common HAL APIs
29          (+) Services HAL APIs
30 
31   @endverbatim
32   ******************************************************************************
33   */
34 
35 /* Includes ------------------------------------------------------------------*/
36 #include "stm32l0xx_hal.h"
37 
38 /** @addtogroup STM32L0xx_HAL_Driver
39   * @{
40   */
41 
42 #ifdef HAL_MODULE_ENABLED
43 
44 /** @addtogroup HAL
45   * @brief HAL module driver.
46   * @{
47   */
48 
49 /** @addtogroup HAL_Exported_Constants
50   * @{
51   */
52 
53 /** @defgroup HAL_Version HAL Version
54   * @{
55   */
56 
57 /**
58  * @brief STM32L0xx HAL Driver version number
59  */
60 #define __STM32L0xx_HAL_VERSION_MAIN   (0x01U) /*!< [31:24] main version */
61 #define __STM32L0xx_HAL_VERSION_SUB1   (0x0AU) /*!< [23:16] sub1 version */
62 #define __STM32L0xx_HAL_VERSION_SUB2   (0x06U) /*!< [15:8]  sub2 version */
63 #define __STM32L0xx_HAL_VERSION_RC     (0x00U) /*!< [7:0]  release candidate */
64 #define __STM32L0xx_HAL_VERSION         ((__STM32L0xx_HAL_VERSION_MAIN << 24U)\
65                                         |(__STM32L0xx_HAL_VERSION_SUB1 << 16U)\
66                                         |(__STM32L0xx_HAL_VERSION_SUB2 << 8U )\
67                                         |(__STM32L0xx_HAL_VERSION_RC))
68 
69 #define IDCODE_DEVID_MASK    (0x00000FFFU)
70 
71 /**
72   * @}
73   */
74 
75 /**
76   * @}
77   */
78 
79 /* Exported variables --------------------------------------------------------*/
80 /** @addtogroup HAL_Exported_Variables
81   * @{
82   */
83 __IO uint32_t uwTick;
84 uint32_t uwTickPrio   = (1UL << __NVIC_PRIO_BITS); /* Invalid PRIO */
85 HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT;  /* 1KHz */
86 /**
87   * @}
88   */
89 
90 /* Exported functions --------------------------------------------------------*/
91 /** @addtogroup HAL_Exported_Functions
92   * @{
93   */
94 
95 /** @addtogroup HAL_Exported_Functions_Group1
96  *  @brief    Initialization and de-initialization functions
97  *
98 @verbatim
99  ===============================================================================
100               ##### Initialization and de-initialization functions #####
101  ===============================================================================
102    [..]  This section provides functions allowing to:
103       (+) Initialize the Flash interface, the NVIC allocation and initial clock
104           configuration. It initializes the source of time base also when timeout
105           is needed and the backup domain when enabled.
106       (+) De-initialize common part of the HAL.
107       (+) Configure the time base source to have 1ms time base with a dedicated
108           Tick interrupt priority.
109         (++) SysTick timer is used by default as source of time base, but user
110              can eventually implement his proper time base source (a general purpose
111              timer for example or other time source), keeping in mind that Time base
112              duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
113              handled in milliseconds basis.
114         (++) Time base configuration function (HAL_InitTick ()) is called automatically
115              at the beginning of the program after reset by HAL_Init() or at any time
116              when clock is configured, by HAL_RCC_ClockConfig().
117         (++) Source of time base is configured  to generate interrupts at regular
118              time intervals. Care must be taken if HAL_Delay() is called from a
119              peripheral ISR process, the Tick interrupt line must have higher priority
120             (numerically lower) than the peripheral interrupt. Otherwise the caller
121             ISR process will be blocked.
122        (++) functions affecting time base configurations are declared as __weak
123              to make  override possible  in case of other  implementations in user file.
124 
125 @endverbatim
126   * @{
127   */
128 
129 /**
130   * @brief This function configures the Flash prefetch, Flash preread and Buffer cache,
131   *        Configures time base source, NVIC and Low level hardware
132   * @note This function is called at the beginning of program after reset and before
133   *       the clock configuration
134   * @note The time base configuration is based on MSI clock when exiting from Reset.
135   *       Once done, time base tick start incrementing.
136   *        In the default implementation,Systick is used as source of time base.
137   *        the tick variable is incremented each 1ms in its ISR.
138   * @retval HAL status
139   */
HAL_Init(void)140 HAL_StatusTypeDef HAL_Init(void)
141 {
142   HAL_StatusTypeDef  status = HAL_OK;
143 
144   /* Configure Buffer cache, Flash prefetch,  Flash preread */
145 #if (BUFFER_CACHE_DISABLE != 0)
146   __HAL_FLASH_BUFFER_CACHE_DISABLE();
147 #endif /* BUFFER_CACHE_DISABLE */
148 
149 #if (PREREAD_ENABLE != 0)
150   __HAL_FLASH_PREREAD_BUFFER_ENABLE();
151 #endif /* PREREAD_ENABLE */
152 
153 #if (PREFETCH_ENABLE != 0)
154   __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
155 #endif /* PREFETCH_ENABLE */
156 
157   /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
158   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
159   {
160     status = HAL_ERROR;
161   }
162   else
163   {
164     /* Init the low level hardware */
165     HAL_MspInit();
166   }
167 
168   /* Return function status */
169   return status;
170 }
171 
172 /**
173   * @brief This function de-initializes common part of the HAL and stops the source
174   *        of time base.
175   * @note This function is optional.
176   * @retval HAL status
177   */
HAL_DeInit(void)178 HAL_StatusTypeDef HAL_DeInit(void)
179 {
180   /* Reset of all peripherals */
181   __HAL_RCC_APB1_FORCE_RESET();
182   __HAL_RCC_APB1_RELEASE_RESET();
183 
184   __HAL_RCC_APB2_FORCE_RESET();
185   __HAL_RCC_APB2_RELEASE_RESET();
186 
187   __HAL_RCC_AHB_FORCE_RESET();
188   __HAL_RCC_AHB_RELEASE_RESET();
189 
190   __HAL_RCC_IOP_FORCE_RESET();
191   __HAL_RCC_IOP_RELEASE_RESET();
192 
193   /* De-Init the low level hardware */
194   HAL_MspDeInit();
195 
196   /* Return function status */
197   return HAL_OK;
198 }
199 
200 /**
201   * @brief  Initializes the MSP.
202   * @retval None
203   */
HAL_MspInit(void)204 __weak void HAL_MspInit(void)
205 {
206   /* NOTE : This function should not be modified, when the callback is needed,
207             the HAL_MspInit could be implemented in the user file
208    */
209 }
210 
211 /**
212   * @brief  DeInitializes the MSP.
213   * @retval None
214   */
HAL_MspDeInit(void)215 __weak void HAL_MspDeInit(void)
216 {
217   /* NOTE : This function should not be modified, when the callback is needed,
218             the HAL_MspDeInit could be implemented in the user file
219    */
220 }
221 
222 /**
223   * @brief This function configures the source of the time base:
224   *        The time source is configured  to have 1ms time base with a dedicated
225   *        Tick interrupt priority.
226   * @note This function is called  automatically at the beginning of program after
227   *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig().
228   * @note In the default implementation, SysTick timer is the source of time base.
229   *       It is used to generate interrupts at regular time intervals.
230   *       Care must be taken if HAL_Delay() is called from a peripheral ISR process,
231   *       The SysTick interrupt must have higher priority (numerically lower)
232   *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
233   *       The function is declared as __weak  to be overwritten  in case of other
234   *       implementation  in user file.
235   * @param TickPriority Tick interrupt priority.
236   * @retval HAL status
237   */
HAL_InitTick(uint32_t TickPriority)238 __weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
239 {
240   /* Configure the SysTick to have interrupt in 1ms time basis*/
241   if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
242   {
243     return HAL_ERROR;
244   }
245 
246   /* Configure the SysTick IRQ priority */
247   if (TickPriority < (1UL << __NVIC_PRIO_BITS))
248   {
249     HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
250     uwTickPrio = TickPriority;
251   }
252   else
253   {
254     return HAL_ERROR;
255   }
256 
257   /* Return function status */
258   return HAL_OK;
259 }
260 
261 /**
262   * @}
263   */
264 
265 /** @addtogroup HAL_Exported_Functions_Group2
266  *  @brief    HAL Control functions
267  *
268 @verbatim
269  ===============================================================================
270                       ##### HAL Control functions #####
271  ===============================================================================
272     [..]  This section provides functions allowing to:
273       (+) Provide a tick value in millisecond
274       (+) Provide a blocking delay in millisecond
275       (+) Suspend the time base source interrupt
276       (+) Resume the time base source interrupt
277       (+) Get the HAL API driver version
278       (+) Get the device identifier
279       (+) Get the device revision identifier
280 
281 @endverbatim
282   * @{
283   */
284 
285 /**
286   * @brief This function is called to increment a global variable "uwTick"
287   *        used as application time base.
288   * @note In the default implementation, this variable is incremented each 1ms
289   *       in SysTick ISR.
290  * @note This function is declared as __weak to be overwritten in case of other
291   *      implementations in user file.
292   * @retval None
293   */
HAL_IncTick(void)294 __weak void HAL_IncTick(void)
295 {
296   uwTick += uwTickFreq;
297 }
298 
299 /**
300   * @brief Provides a tick value in millisecond.
301   * @note This function is declared as __weak to be overwritten in case of other
302   *       implementations in user file.
303   * @retval tick value
304   */
HAL_GetTick(void)305 __weak uint32_t HAL_GetTick(void)
306 {
307   return uwTick;
308 }
309 
310 /**
311   * @brief This function returns a tick priority.
312   * @retval tick priority
313   */
HAL_GetTickPrio(void)314 uint32_t HAL_GetTickPrio(void)
315 {
316   return uwTickPrio;
317 }
318 
319 /**
320   * @brief Set new tick Freq.
321   * @retval Status
322   */
HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)323 HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
324 {
325   HAL_StatusTypeDef status  = HAL_OK;
326   HAL_TickFreqTypeDef prevTickFreq;
327 
328   assert_param(IS_TICKFREQ(Freq));
329 
330   if (uwTickFreq != Freq)
331   {
332     /* Back up uwTickFreq frequency */
333     prevTickFreq = uwTickFreq;
334 
335     /* Update uwTickFreq global variable used by HAL_InitTick() */
336     uwTickFreq = Freq;
337 
338     /* Apply the new tick Freq  */
339     status = HAL_InitTick(uwTickPrio);
340 
341     if (status != HAL_OK)
342     {
343       /* Restore previous tick frequency */
344       uwTickFreq = prevTickFreq;
345     }
346   }
347 
348   return status;
349 }
350 
351 /**
352   * @brief Return tick frequency.
353   * @retval Tick frequency.
354   *         Value of @ref HAL_TickFreqTypeDef.
355   */
HAL_GetTickFreq(void)356 HAL_TickFreqTypeDef HAL_GetTickFreq(void)
357 {
358   return uwTickFreq;
359 }
360 
361 /**
362   * @brief This function provides minimum delay (in milliseconds) based
363   *        on variable incremented.
364   * @note In the default implementation , SysTick timer is the source of time base.
365   *       It is used to generate interrupts at regular time intervals where uwTick
366   *       is incremented.
367   * @note This function is declared as __weak to be overwritten in case of other
368   *       implementations in user file.
369   * @param Delay specifies the delay time length, in milliseconds.
370   * @retval None
371   */
HAL_Delay(uint32_t Delay)372 __weak void HAL_Delay(uint32_t Delay)
373 {
374   uint32_t tickstart = HAL_GetTick();
375   uint32_t wait = Delay;
376 
377   /* Add a freq to guarantee minimum wait */
378   if (wait < HAL_MAX_DELAY)
379   {
380     wait += (uint32_t)(uwTickFreq);
381   }
382 
383   while((HAL_GetTick() - tickstart) < wait)
384   {
385   }
386 }
387 
388 /**
389   * @brief Suspends the Tick increment.
390   * @note In the default implementation , SysTick timer is the source of time base. It is
391   *       used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
392   *       is called, the SysTick interrupt will be disabled and so Tick increment
393   *       is suspended.
394   * @note This function is declared as __weak to be overwritten in case of other
395   *       implementations in user file.
396   * @retval None
397   */
HAL_SuspendTick(void)398 __weak void HAL_SuspendTick(void)
399 {
400   /* Disable SysTick Interrupt */
401   SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
402 }
403 
404 /**
405   * @brief Resumes the Tick increment.
406   * @note In the default implementation , SysTick timer is the source of time base. It is
407   *       used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
408   *       is called, the SysTick interrupt will be enabled and so Tick increment
409   *       is resumed.
410   * @note This function is declared as __weak to be overwritten in case of other
411   *       implementations in user file.
412   * @retval None
413   */
HAL_ResumeTick(void)414 __weak void HAL_ResumeTick(void)
415 {
416   /* Enable SysTick Interrupt */
417   SysTick->CTRL  |= SysTick_CTRL_TICKINT_Msk;
418 }
419 
420 /**
421   * @brief Returns the HAL revision
422   * @retval version: 0xXYZR (8bits for each decimal, R for RC)
423   */
HAL_GetHalVersion(void)424 uint32_t HAL_GetHalVersion(void)
425 {
426   return __STM32L0xx_HAL_VERSION;
427 }
428 
429 /**
430   * @brief Returns the device revision identifier.
431   * @retval Device revision identifier
432   */
HAL_GetREVID(void)433 uint32_t HAL_GetREVID(void)
434 {
435   return((DBGMCU->IDCODE) >> 16U);
436 }
437 
438 /**
439   * @brief  Returns the device identifier.
440   * @retval Device identifier
441   */
HAL_GetDEVID(void)442 uint32_t HAL_GetDEVID(void)
443 {
444    return((DBGMCU->IDCODE) & IDCODE_DEVID_MASK);
445 }
446 
447 /**
448   * @brief  Returns the first word of the unique device identifier (UID based on 96 bits)
449   * @retval Device identifier
450   */
HAL_GetUIDw0(void)451 uint32_t HAL_GetUIDw0(void)
452 {
453   return(READ_REG(*((uint32_t *)UID_BASE)));
454 }
455 
456 /**
457   * @brief  Returns the second word of the unique device identifier (UID based on 96 bits)
458   * @retval Device identifier
459   */
HAL_GetUIDw1(void)460 uint32_t HAL_GetUIDw1(void)
461 {
462   return(READ_REG(*((uint32_t *)(UID_BASE + 0x04U))));
463 }
464 
465 /**
466   * @brief  Returns the third word of the unique device identifier (UID based on 96 bits)
467   * @retval Device identifier
468   */
HAL_GetUIDw2(void)469 uint32_t HAL_GetUIDw2(void)
470 {
471   return(READ_REG(*((uint32_t *)(UID_BASE + 0x14U))));
472 }
473 
474 /**
475   * @}
476   */
477 
478 /** @addtogroup HAL_Exported_Functions_Group2
479  *  @brief    HAL Debug functions
480  *
481 @verbatim
482  ===============================================================================
483                       ##### HAL Debug functions #####
484  ===============================================================================
485     [..]  This section provides functions allowing to:
486       (+) Enable/Disable Debug module during SLEEP mode
487       (+) Enable/Disable Debug module during STOP mode
488       (+) Enable/Disable Debug module during STANDBY mode
489 
490 @endverbatim
491   * @{
492   */
493 
494 /**
495   * @brief  Enables the Debug Module during SLEEP mode
496   * @retval None
497   */
HAL_DBGMCU_EnableDBGSleepMode(void)498 void HAL_DBGMCU_EnableDBGSleepMode(void)
499 {
500   SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
501 }
502 
503 /**
504   * @brief  Disables the Debug Module during SLEEP mode
505   * @retval None
506   */
HAL_DBGMCU_DisableDBGSleepMode(void)507 void HAL_DBGMCU_DisableDBGSleepMode(void)
508 {
509   CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
510 }
511 
512 /**
513   * @brief  Enables the Debug Module during STOP mode
514   * @retval None
515   */
HAL_DBGMCU_EnableDBGStopMode(void)516 void HAL_DBGMCU_EnableDBGStopMode(void)
517 {
518   SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
519 }
520 
521 /**
522   * @brief  Disables the Debug Module during STOP mode
523   * @retval None
524   */
HAL_DBGMCU_DisableDBGStopMode(void)525 void HAL_DBGMCU_DisableDBGStopMode(void)
526 {
527   CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
528 }
529 
530 /**
531   * @brief  Enables the Debug Module during STANDBY mode
532   * @retval None
533   */
HAL_DBGMCU_EnableDBGStandbyMode(void)534 void HAL_DBGMCU_EnableDBGStandbyMode(void)
535 {
536   SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
537 }
538 
539 /**
540   * @brief  Disables the Debug Module during STANDBY mode
541   * @retval None
542   */
HAL_DBGMCU_DisableDBGStandbyMode(void)543 void HAL_DBGMCU_DisableDBGStandbyMode(void)
544 {
545   CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
546 }
547 
548 /**
549   * @brief  Enable low power mode behavior when the MCU is in Debug mode.
550   * @param Periph: specifies the low power mode.
551   *   This parameter can be any combination of the following values:
552   *     @arg DBGMCU_SLEEP: Keep debugger connection during SLEEP mode
553   *     @arg DBGMCU_STOP: Keep debugger connection during STOP mode
554   *     @arg DBGMCU_STANDBY: Keep debugger connection during STANDBY mode
555   * @retval None
556   */
HAL_DBGMCU_DBG_EnableLowPowerConfig(uint32_t Periph)557 void HAL_DBGMCU_DBG_EnableLowPowerConfig(uint32_t Periph)
558 {
559   /* Check the parameters */
560   assert_param(IS_DBGMCU_PERIPH(Periph));
561 
562   DBGMCU->CR |= Periph;
563 
564 }
565 /**
566   * @brief  Disable low power mode behavior when the MCU is in Debug mode.
567   * @param Periph: specifies the low power mode.
568   *   This parameter can be any combination of the following values:
569   *     @arg DBGMCU_SLEEP: Keep debugger connection during SLEEP mode
570   *     @arg DBGMCU_STOP: Keep debugger connection during STOP mode
571   *     @arg DBGMCU_STANDBY: Keep debugger connection during STANDBY mode
572   * @retval None
573   */
HAL_DBGMCU_DBG_DisableLowPowerConfig(uint32_t Periph)574 void HAL_DBGMCU_DBG_DisableLowPowerConfig(uint32_t Periph)
575 {
576   /* Check the parameters */
577   assert_param(IS_DBGMCU_PERIPH(Periph));
578   {
579     DBGMCU->CR &= ~Periph;
580   }
581 }
582 
583 /**
584   * @}
585   */
586 
587 /** @addtogroup HAL_Exported_Functions_Group3
588  *  @brief    HAL SYSCFG configuration functions
589  *
590 @verbatim
591  ===============================================================================
592                       ##### HAL SYSCFG configuration functions #####
593  ===============================================================================
594     [..]  This section provides functions allowing to:
595       (+) Return the boot mode
596       (+) Select the output of internal reference voltage (VREFINT)
597       (+) Lock/Unlock the SYSCFG VREF register values
598 
599 @endverbatim
600   * @{
601   */
602 
603 /**
604   * @brief  Returns the boot mode as configured by user.
605   * @retval The boot mode as configured by user. The returned value can be one
606   *         of the following values:
607   *              - 0x00000000 : Boot is configured in Main Flash memory
608   *              - 0x00000100 : Boot is configured in System Flash memory
609   *              - 0x00000300 : Boot is configured in Embedded SRAM memory
610   */
HAL_SYSCFG_GetBootMode(void)611 uint32_t  HAL_SYSCFG_GetBootMode(void)
612 {
613   return (SYSCFG->CFGR1 & SYSCFG_CFGR1_BOOT_MODE);
614 }
615 
616 /**
617   * @brief Selects the output of internal reference voltage (VREFINT).
618   *        The VREFINT output can be routed to(PB0) or
619   *        (PB1) or both.
620   * @param SYSCFG_Vrefint_OUTPUT: new state of the Vrefint output.
621   *        This parameter can be one of the following values:
622   *     @arg SYSCFG_VREFINT_OUT_NONE
623   *     @arg SYSCFG_VREFINT_OUT_PB0
624   *     @arg SYSCFG_VREFINT_OUT_PB1
625   *     @arg SYSCFG_VREFINT_OUT_PB0_PB1
626   * @retval None
627   */
HAL_SYSCFG_VREFINT_OutputSelect(uint32_t SYSCFG_Vrefint_OUTPUT)628 void HAL_SYSCFG_VREFINT_OutputSelect(uint32_t SYSCFG_Vrefint_OUTPUT)
629 {
630   /* Check the parameters */
631   assert_param(IS_SYSCFG_VREFINT_OUT_SELECT(SYSCFG_Vrefint_OUTPUT));
632 
633   /* Set the output Vrefint pin */
634   SYSCFG->CFGR3 &= ~(SYSCFG_CFGR3_VREF_OUT);
635   SYSCFG->CFGR3 |= (uint32_t)(SYSCFG_Vrefint_OUTPUT);
636 }
637 
638 /**
639   * @brief  Lock the SYSCFG VREF register values
640   * @retval None
641   */
HAL_SYSCFG_Enable_Lock_VREFINT(void)642 void HAL_SYSCFG_Enable_Lock_VREFINT(void)
643 {
644     /* Enable the LOCK by setting REF_LOCK bit in the CFGR3 register */
645     SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_REF_LOCK);
646 }
647 
648 /**
649   * @brief  Unlock the overall SYSCFG VREF register values
650   * @retval None
651   */
HAL_SYSCFG_Disable_Lock_VREFINT(void)652 void HAL_SYSCFG_Disable_Lock_VREFINT(void)
653 {
654     /* Disable the LOCK by setting REF_LOCK bit in the CFGR3 register */
655     CLEAR_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_REF_LOCK);
656 }
657 
658 /**
659   * @}
660   */
661 
662 /**
663   * @}
664   */
665 
666 /**
667   * @}
668   */
669 #endif /* HAL_MODULE_ENABLED */
670 /**
671   * @}
672   */
673 
674 
675