Subversion Repositories EngineBay2

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/**
2
  ******************************************************************************
3
  * @file    stm32l1xx_hal_rcc_ex.c
4
  * @author  MCD Application Team
5
  * @brief   Extended RCC HAL module driver.
28 mjames 6
  *          This file provides firmware functions to manage the following
2 mjames 7
  *          functionalities RCC extension peripheral:
8
  *           + Extended Peripheral Control functions
9
  *
10
  ******************************************************************************
11
  * @attention
12
  *
28 mjames 13
  * <h2><center>&copy; Copyright(c) 2017 STMicroelectronics.
14
  * All rights reserved.</center></h2>
2 mjames 15
  *
28 mjames 16
  * This software component is licensed by ST under BSD 3-Clause license,
17
  * the "License"; You may not use this file except in compliance with the
18
  * License. You may obtain a copy of the License at:
19
  *                        opensource.org/licenses/BSD-3-Clause
2 mjames 20
  *
28 mjames 21
  ******************************************************************************
22
  */
2 mjames 23
 
24
/* Includes ------------------------------------------------------------------*/
25
#include "stm32l1xx_hal.h"
26
 
27
/** @addtogroup STM32L1xx_HAL_Driver
28
  * @{
29
  */
30
 
31
#ifdef HAL_RCC_MODULE_ENABLED
32
 
33
/** @defgroup RCCEx RCCEx
34
  * @brief RCC Extension HAL module driver
35
  * @{
36
  */
37
 
38
/* Private typedef -----------------------------------------------------------*/
39
/* Private define ------------------------------------------------------------*/
40
/** @defgroup RCCEx_Private_Constants RCCEx Private Constants
41
  * @{
42
  */
43
/**
44
  * @}
45
  */
28 mjames 46
 
2 mjames 47
/* Private macro -------------------------------------------------------------*/
48
/** @defgroup RCCEx_Private_Macros RCCEx Private Macros
49
  * @{
50
  */
51
/**
52
  * @}
53
  */
54
 
55
/* Private variables ---------------------------------------------------------*/
56
/* Private function prototypes -----------------------------------------------*/
57
/* Private functions ---------------------------------------------------------*/
58
 
59
/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
60
  * @{
61
  */
62
 
28 mjames 63
/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
64
 *  @brief  Extended Peripheral Control functions
2 mjames 65
 *
28 mjames 66
@verbatim
2 mjames 67
 ===============================================================================
68
                ##### Extended Peripheral Control functions  #####
28 mjames 69
 ===============================================================================
2 mjames 70
    [..]
28 mjames 71
    This subsection provides a set of functions allowing to control the RCC Clocks
2 mjames 72
    frequencies.
28 mjames 73
    [..]
2 mjames 74
    (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
28 mjames 75
        select the RTC clock source; in this case the Backup domain will be reset in
76
        order to modify the RTC Clock source, as consequence RTC registers (including
2 mjames 77
        the backup registers) are set to their reset values.
28 mjames 78
 
2 mjames 79
@endverbatim
80
  * @{
81
  */
82
 
83
/**
84
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
85
  *         parameters in the RCC_PeriphCLKInitTypeDef.
86
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
87
  *         contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
88
  * @retval HAL status
89
  * @note   If HAL_ERROR returned, first switch-OFF HSE clock oscillator with @ref HAL_RCC_OscConfig()
90
  *         to possibly update HSE divider.
91
  */
92
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
93
{
28 mjames 94
  uint32_t tickstart;
95
  uint32_t temp_reg;
96
 
2 mjames 97
  /* Check the parameters */
98
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
28 mjames 99
 
100
  /*------------------------------- RTC/LCD Configuration ------------------------*/
101
  if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
2 mjames 102
#if defined(LCD)
103
   || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
104
#endif /* LCD */
105
     )
106
  {
107
    /* check for RTC Parameters used to output RTCCLK */
108
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
109
    {
110
      assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
111
    }
112
 
113
#if defined(LCD)
114
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
115
    {
116
      assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
117
    }
118
#endif /* LCD */
119
 
120
    FlagStatus       pwrclkchanged = RESET;
121
 
28 mjames 122
    /* As soon as function is called to change RTC clock source, activation of the
2 mjames 123
       power domain is done. */
124
    /* Requires to enable write access to Backup Domain of necessary */
125
    if(__HAL_RCC_PWR_IS_CLK_DISABLED())
126
    {
127
      __HAL_RCC_PWR_CLK_ENABLE();
128
      pwrclkchanged = SET;
129
    }
28 mjames 130
 
2 mjames 131
    if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
132
    {
133
      /* Enable write access to Backup domain */
134
      SET_BIT(PWR->CR, PWR_CR_DBP);
28 mjames 135
 
2 mjames 136
      /* Wait for Backup domain Write protection disable */
137
      tickstart = HAL_GetTick();
138
 
139
      while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
140
      {
141
        if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
142
        {
143
          return HAL_TIMEOUT;
144
        }
145
      }
146
    }
147
 
28 mjames 148
    /* Check if user wants to change HSE RTC prescaler whereas HSE is enabled */
2 mjames 149
    temp_reg = (RCC->CR & RCC_CR_RTCPRE);
150
    if ((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CR_RTCPRE))
151
#if defined (LCD)
152
     || (temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CR_RTCPRE))
153
#endif /* LCD */
154
       )
155
    { /* Check HSE State */
28 mjames 156
      if ((PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL) == RCC_CSR_RTCSEL_HSE)
2 mjames 157
      {
28 mjames 158
        if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
159
        {
160
          /* To update HSE divider, first switch-OFF HSE clock oscillator*/
161
          return HAL_ERROR;
162
        }
2 mjames 163
      }
164
    }
28 mjames 165
 
166
    /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
2 mjames 167
    temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);
28 mjames 168
 
2 mjames 169
    if((temp_reg != 0x00000000U) && (((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
170
      && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
171
#if defined(LCD)
172
      || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
173
       && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
174
#endif /* LCD */
175
     ))
176
    {
177
      /* Store the content of CSR register before the reset of Backup Domain */
178
      temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));
28 mjames 179
 
2 mjames 180
      /* RTC Clock selection can be changed only if the Backup Domain is reset */
181
      __HAL_RCC_BACKUPRESET_FORCE();
182
      __HAL_RCC_BACKUPRESET_RELEASE();
28 mjames 183
 
2 mjames 184
      /* Restore the Content of CSR register */
185
      RCC->CSR = temp_reg;
28 mjames 186
 
2 mjames 187
       /* Wait for LSERDY if LSE was enabled */
188
      if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSEON))
189
      {
190
        /* Get Start Tick */
191
        tickstart = HAL_GetTick();
28 mjames 192
 
193
        /* Wait till LSE is ready */
194
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == 0U)
2 mjames 195
        {
196
          if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
197
          {
198
            return HAL_TIMEOUT;
199
          }
200
        }
201
      }
202
    }
203
    __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
204
 
205
    /* Require to disable power clock if necessary */
206
    if(pwrclkchanged == SET)
207
    {
208
      __HAL_RCC_PWR_CLK_DISABLE();
209
    }
210
  }
28 mjames 211
 
2 mjames 212
  return HAL_OK;
213
}
214
 
215
/**
216
  * @brief  Get the PeriphClkInit according to the internal RCC configuration registers.
28 mjames 217
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
2 mjames 218
  *         returns the configuration information for the Extended Peripherals clocks(RTC/LCD clocks).
219
  * @retval None
220
  */
221
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
222
{
28 mjames 223
  uint32_t srcclk;
224
 
2 mjames 225
  /* Set all possible values for the extended clock type parameter------------*/
226
  PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_RTC;
28 mjames 227
#if defined(LCD)
2 mjames 228
  PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_LCD;
229
#endif /* LCD */
230
 
231
  /* Get the RTC/LCD configuration -----------------------------------------------*/
232
  srcclk = __HAL_RCC_GET_RTC_SOURCE();
233
  if (srcclk != RCC_RTCCLKSOURCE_HSE_DIV2)
234
  {
235
    /* Source clock is LSE or LSI*/
236
    PeriphClkInit->RTCClockSelection = srcclk;
237
  }
238
  else
239
  {
240
    /* Source clock is HSE. Need to get the prescaler value*/
241
    PeriphClkInit->RTCClockSelection = srcclk | (READ_BIT(RCC->CR, RCC_CR_RTCPRE));
242
  }
243
#if defined(LCD)
244
  PeriphClkInit->LCDClockSelection = PeriphClkInit->RTCClockSelection;
245
#endif /* LCD */
246
}
247
 
248
/**
249
  * @brief  Return the peripheral clock frequency
250
  * @note   Return 0 if peripheral clock is unknown
251
  * @param  PeriphClk Peripheral clock identifier
252
  *         This parameter can be one of the following values:
253
  *            @arg @ref RCC_PERIPHCLK_RTC      RTC peripheral clock
254
  *            @arg @ref RCC_PERIPHCLK_LCD      LCD peripheral clock (*)
255
  * @note   (*) means that this peripheral is not present on all the devices
256
  * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
257
  */
258
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
259
{
28 mjames 260
  uint32_t frequency = 0;
261
  uint32_t srcclk;
2 mjames 262
 
263
  /* Check the parameters */
264
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
28 mjames 265
 
2 mjames 266
  switch (PeriphClk)
267
  {
268
  case RCC_PERIPHCLK_RTC:
269
#if defined(LCD)
270
  case RCC_PERIPHCLK_LCD:
271
#endif /* LCD */
272
    {
273
      /* Get the current RTC source */
274
      srcclk = __HAL_RCC_GET_RTC_SOURCE();
275
 
276
      /* Check if LSE is ready if RTC clock selection is LSE */
28 mjames 277
      if (srcclk == RCC_RTCCLKSOURCE_LSE)
2 mjames 278
      {
28 mjames 279
        if (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSERDY))
280
        {
281
          frequency = LSE_VALUE;
282
        }
2 mjames 283
      }
284
      /* Check if LSI is ready if RTC clock selection is LSI */
28 mjames 285
      else if (srcclk == RCC_RTCCLKSOURCE_LSI)
2 mjames 286
      {
28 mjames 287
        if (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))
288
        {
289
          frequency = LSI_VALUE;
290
        }
2 mjames 291
      }
292
      /* Check if HSE is ready and if RTC clock selection is HSE */
28 mjames 293
      else if (srcclk == RCC_RTCCLKSOURCE_HSE_DIVX)
2 mjames 294
      {
28 mjames 295
        if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
2 mjames 296
        {
28 mjames 297
          /* Get the current HSE clock divider */
298
          switch (__HAL_RCC_GET_RTC_HSE_PRESCALER())
2 mjames 299
          {
28 mjames 300
            case RCC_RTC_HSE_DIV_16:  /* HSE DIV16 has been selected */
301
            {
302
              frequency = HSE_VALUE / 16U;
303
              break;
304
            }
305
            case RCC_RTC_HSE_DIV_8:   /* HSE DIV8 has been selected  */
306
            {
307
              frequency = HSE_VALUE / 8U;
308
              break;
309
            }
310
            case RCC_RTC_HSE_DIV_4:   /* HSE DIV4 has been selected  */
311
            {
312
              frequency = HSE_VALUE / 4U;
313
              break;
314
            }
315
            default:                  /* HSE DIV2 has been selected  */
316
            {
317
              frequency = HSE_VALUE / 2U;
318
              break;
319
            }
2 mjames 320
          }
321
        }
322
      }
323
      else
324
      {
28 mjames 325
        /* No clock source, frequency default init at 0 */
2 mjames 326
      }
327
      break;
328
    }
28 mjames 329
 
330
  default:
331
    break;
2 mjames 332
  }
28 mjames 333
 
2 mjames 334
  return(frequency);
335
}
336
 
337
#if defined(RCC_LSECSS_SUPPORT)
338
/**
339
  * @brief  Enables the LSE Clock Security System.
340
  * @note   If a failure is detected on the external 32 kHz oscillator, the LSE clock is no longer supplied
341
  *         to the RTC but no hardware action is made to the registers.
342
  *         In Standby mode a wakeup is generated. In other modes an interrupt can be sent to wakeup
343
  *         the software (see Section 5.3.4: Clock interrupt register (RCC_CIR) on page 104).
344
  *         The software MUST then disable the LSECSSON bit, stop the defective 32 kHz oscillator
345
  *         (disabling LSEON), and can change the RTC clock source (no clock or LSI or HSE, with
28 mjames 346
  *         RTCSEL), or take any required action to secure the application.
2 mjames 347
  * @note   LSE CSS available only for high density and medium+ devices
348
  * @retval None
349
  */
350
void HAL_RCCEx_EnableLSECSS(void)
351
{
352
  *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)ENABLE;
353
}
354
 
355
/**
356
  * @brief  Disables the LSE Clock Security System.
28 mjames 357
  * @note   Once enabled this bit cannot be disabled, except after an LSE failure detection
2 mjames 358
  *         (LSECSSD=1). In that case the software MUST disable the LSECSSON bit.
359
  *         Reset by power on reset and RTC software reset (RTCRST bit).
360
  * @note   LSE CSS available only for high density and medium+ devices
361
  * @retval None
362
  */
363
void HAL_RCCEx_DisableLSECSS(void)
364
{
365
  /* Disable LSE CSS */
366
  *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)DISABLE;
367
 
368
  /* Disable LSE CSS IT */
369
  __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
370
}
371
 
372
/**
373
  * @brief  Enable the LSE Clock Security System IT & corresponding EXTI line.
374
  * @note   LSE Clock Security System IT is mapped on RTC EXTI line 19
375
  * @retval None
376
  */
377
void HAL_RCCEx_EnableLSECSS_IT(void)
378
{
379
  /* Enable LSE CSS */
380
  *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)ENABLE;
381
 
382
  /* Enable LSE CSS IT */
383
  __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
28 mjames 384
 
2 mjames 385
  /* Enable IT on EXTI Line 19 */
386
  __HAL_RCC_LSECSS_EXTI_ENABLE_IT();
387
  __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
388
}
389
 
390
/**
391
  * @brief Handle the RCC LSE Clock Security System interrupt request.
392
  * @retval None
393
  */
394
void HAL_RCCEx_LSECSS_IRQHandler(void)
395
{
396
  /* Check RCC LSE CSSF flag  */
397
  if(__HAL_RCC_GET_IT(RCC_IT_LSECSS))
398
  {
399
    /* RCC LSE Clock Security System interrupt user callback */
400
    HAL_RCCEx_LSECSS_Callback();
401
 
402
    /* Clear RCC LSE CSS pending bit */
403
    __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
404
  }
28 mjames 405
}
2 mjames 406
 
407
/**
408
  * @brief  RCCEx LSE Clock Security System interrupt callback.
409
  * @retval none
410
  */
411
__weak void HAL_RCCEx_LSECSS_Callback(void)
412
{
413
  /* NOTE : This function should not be modified, when the callback is needed,
414
            the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file
415
   */
416
}
417
#endif /* RCC_LSECSS_SUPPORT */
28 mjames 418
 
2 mjames 419
/**
420
  * @}
421
  */
422
 
423
/**
424
  * @}
425
  */
426
 
427
/**
428
  * @}
429
  */
430
 
431
/**
432
  * @}
433
  */
434
 
435
#endif /* HAL_RCC_MODULE_ENABLED */
436
/**
437
  * @}
438
  */
439
 
440
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/