Пример #1
0
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified parameters in the
  *         RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit: pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(I2S and RTC clocks).
  *         
  * @note   A caution to be taken when HAL_RCCEx_PeriphCLKConfig() is used to select RTC clock selection, in this case 
  *         the Reset of Backup domain will be applied in order to modify the RTC Clock source as consequence all backup 
  *        domain (RTC and RCC_BDCR register expect BKPSRAM) will be reset
  *              
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
  uint32_t tickstart = 0;
  uint32_t tmpreg1 = 0;
    
  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
  
  /*---------------------------- I2S configuration ---------------------------*/
  if(((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_I2S) == (RCC_PERIPHCLK_I2S))|| \
     (PeriphClkInit->PeriphClockSelection == RCC_PERIPHCLK_PLLI2S))
  {
    /* check for Parameters */
    assert_param(IS_RCC_PLLI2SR_VALUE(PeriphClkInit->PLLI2S.PLLI2SR));
    assert_param(IS_RCC_PLLI2SN_VALUE(PeriphClkInit->PLLI2S.PLLI2SN));
      
    /* Disable the PLLI2S */
    __HAL_RCC_PLLI2S_DISABLE();
    /* Get tick */
    tickstart = HAL_GetTick();
    /* Wait till PLLI2S is disabled */
    while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  != RESET)
    {
      if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
      {
        /* return in case of Timeout detected */
        return HAL_TIMEOUT;
      } 
    }
    /* Configure the PLLI2S division factors */
    /* PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) * (PLLI2SN/PLLM) */
    /* I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
    __HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SN , PeriphClkInit->PLLI2S.PLLI2SR);
    
    /* Enable the PLLI2S */
    __HAL_RCC_PLLI2S_ENABLE();
    /* Get tick */
    tickstart = HAL_GetTick();
    /* Wait till PLLI2S is ready */
    while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY)  == RESET)
    {
      if((HAL_GetTick() - tickstart ) > PLLI2S_TIMEOUT_VALUE)
      {
        /* return in case of Timeout detected */
        return HAL_TIMEOUT;
      }
    }
  }
  /*--------------------------------------------------------------------------*/
  
  /*----------------------------- RTC configuration --------------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))
  {    
    /* Enable Power Clock*/
    __HAL_RCC_PWR_CLK_ENABLE();
    
    /* Enable write access to Backup domain */
    PWR->CR |= PWR_CR_DBP;
    
    /* Get tick */
    tickstart = HAL_GetTick();
    
    while((PWR->CR & PWR_CR_DBP) == RESET)
    {
      if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
      {
        return HAL_TIMEOUT;
      }      
    }
    /* Reset the Backup domain only if the RTC Clock source selection is modified */
    if((RCC->BDCR & RCC_BDCR_RTCSEL) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))
    {
      /* Store the content of BDCR register before the reset of Backup Domain */
      tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
      /* RTC Clock selection can be changed only if the Backup Domain is reset */
      __HAL_RCC_BACKUPRESET_FORCE();
      __HAL_RCC_BACKUPRESET_RELEASE();
      /* Restore the Content of BDCR register */
      RCC->BDCR = tmpreg1;
      /* Wait for LSERDY if LSE was enabled */
      if(HAL_IS_BIT_SET(tmpreg1, RCC_BDCR_LSERDY))
      {
        /* Get tick */
        tickstart = HAL_GetTick();
        
        /* Wait till LSE is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
        {
          if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
  }
  /*--------------------------------------------------------------------------*/

  return HAL_OK;
}
/**
  * @brief  Returns the peripheral clock frequency
  * @note   Returns 0 if peripheral clock is unknown
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg @ref RCC_PERIPHCLK_RTC  RTC peripheral clock
  *            @arg @ref RCC_PERIPHCLK_LCD  LCD peripheral clock (depends on devices)
  * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
    uint32_t temp_reg = 0, clkprediv = 0, frequency = 0;
    uint32_t srcclk = 0;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));

    switch (PeriphClk)
    {
    case RCC_PERIPHCLK_RTC:
#if defined(LCD)
    case RCC_PERIPHCLK_LCD:
#endif /* LCD */
    {
        /* Get RCC CSR configuration ------------------------------------------------------*/
        temp_reg = RCC->CSR;

        /* Get the current RTC source */
        srcclk = __HAL_RCC_GET_RTC_SOURCE();

        /* Check if LSE is ready if RTC clock selection is LSE */
        if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSERDY)))
        {
            frequency = LSE_VALUE;
        }
        /* Check if LSI is ready if RTC clock selection is LSI */
        else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSIRDY)))
        {
            frequency = LSI_VALUE;
        }
        /* Check if HSE is ready and if RTC clock selection is HSE */
        else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIVX) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)))
        {
            /* Get the current HSE clock divider */
            clkprediv = __HAL_RCC_GET_RTC_HSE_PRESCALER();

            switch (clkprediv)
            {
            case RCC_RTC_HSE_DIV_16:  /* HSE DIV16 has been selected */
            {
                frequency = HSE_VALUE / 16;
                break;
            }
            case RCC_RTC_HSE_DIV_8:   /* HSE DIV8 has been selected  */
            {
                frequency = HSE_VALUE / 8;
                break;
            }
            case RCC_RTC_HSE_DIV_4:   /* HSE DIV4 has been selected  */
            {
                frequency = HSE_VALUE / 4;
                break;
            }
            default:                  /* HSE DIV2 has been selected  */
            {
                frequency = HSE_VALUE / 2;
                break;
            }
            }
        }
        /* Clock not enabled for RTC */
        else
        {
            frequency = 0;
        }
        break;
    }
    default:
    {
        break;
    }
    }
    return(frequency);
}
/**
  * @brief  Returns the peripheral clock frequency
  * @note   Returns 0 if peripheral clock is unknown
  * @param  PeriphClk Peripheral clock identifier
  *         This parameter can be one of the following values:
  *            @arg @ref RCC_PERIPHCLK_RTC  RTC peripheral clock
  *            @arg @ref RCC_PERIPHCLK_LCD  LCD peripheral clock (depends on devices)
  * @retval Frequency in Hz (0: means that no available frequency for the peripheral)
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
  uint32_t temp_reg = 0, frequency = 0;
  uint32_t srcclk = 0;

  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
  
  switch (PeriphClk)
  {
  case RCC_PERIPHCLK_RTC:
#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
  case RCC_PERIPHCLK_LCD:
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */
    {
      /* Get RCC CSR configuration ------------------------------------------------------*/
      temp_reg = RCC->CSR;

      /* Get the current RTC source */
      srcclk = __HAL_RCC_GET_RTC_SOURCE();

      /* Check if LSE is ready if RTC clock selection is LSE */
      if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSERDY)))
      {
        frequency = LSE_VALUE;
      }
      /* Check if LSI is ready if RTC clock selection is LSI */
      else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSIRDY)))
      {
        frequency = LSI_VALUE;
      }
      /* Check if HSE is ready */
      else if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
      {
        switch (READ_BIT(RCC->CR, RCC_CR_RTCPRE))
        {
          case RCC_CR_RTCPRE:     /* HSE DIV16 has been selected */
          {
            frequency = HSE_VALUE / 16;
            break;
          }
          case RCC_CR_RTCPRE_1:   /* HSE DIV8 has been selected */
          {
            frequency = HSE_VALUE / 8;
            break;
          }
          case RCC_CR_RTCPRE_0:   /* HSE DIV4 has been selected */
          {
            frequency = HSE_VALUE / 4;
            break;
          }
          default:
          {
            frequency = HSE_VALUE / 2;
            break;
          }
        }
      }
      /* Clock not enabled for RTC*/
      else
      {
        frequency = 0;
      }
      break;
    }
  default: 
    {
      break;
    }
  }
  return(frequency);
}
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
  * @retval HAL status
  * @note   If HAL_ERROR returned, first switch-OFF HSE clock oscillator with @ref HAL_RCC_OscConfig()
  *         to possibly update HSE divider.
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
    uint32_t tickstart = 0;
    uint32_t temp_reg = 0;

    /* Check the parameters */
    assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

    /*------------------------------- RTC/LCD Configuration ------------------------*/
    if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
#if defined(LCD)
            || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
#endif /* LCD */
       )
    {
        /* check for RTC Parameters used to output RTCCLK */
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
        {
            assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
        }

#if defined(LCD)
        if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
        {
            assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
        }
#endif /* LCD */

        /* As soon as function is called to change RTC clock source, activation of the
           power domain is done. */
        /* Enable Power Clock*/
        __HAL_RCC_PWR_CLK_ENABLE();

        /* Enable write access to Backup domain */
        SET_BIT(PWR->CR, PWR_CR_DBP);

        /* Wait for Backup domain Write protection disable */
        tickstart = HAL_GetTick();

        while((PWR->CR & PWR_CR_DBP) == RESET)
        {
            if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
            {
                return HAL_TIMEOUT;
            }
        }

        /* Check if user wants to change HSE RTC prescaler whereas HSE is enabled */
        temp_reg = (RCC->CR & RCC_CR_RTCPRE);
        if ((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CR_RTCPRE))
#if defined (LCD)
                || (temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CR_RTCPRE))
#endif /* LCD */
           )
        {   /* Check HSE State */
            if (((PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL) == RCC_CSR_RTCSEL_HSE) && HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
            {
                /* To update HSE divider, first switch-OFF HSE clock oscillator*/
                return HAL_ERROR;
            }
        }

        /* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
        temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);

        if((temp_reg != 0x00000000U) && (((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
                                          && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
#if defined(LCD)
                                         || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
                                             && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
#endif /* LCD */
                                        ))
        {
            /* Store the content of CSR register before the reset of Backup Domain */
            temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));

            /* RTC Clock selection can be changed only if the Backup Domain is reset */
            __HAL_RCC_BACKUPRESET_FORCE();
            __HAL_RCC_BACKUPRESET_RELEASE();

            /* Restore the Content of CSR register */
            RCC->CSR = temp_reg;

            /* Wait for LSERDY if LSE was enabled */
            if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSERDY))
            {
                /* Get Start Tick */
                tickstart = HAL_GetTick();

                /* Wait till LSE is ready */
                while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
                {
                    if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
                    {
                        return HAL_TIMEOUT;
                    }
                }
            }

        }
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }

    return HAL_OK;
}
/**
  * @brief  Initializes the RCC extended peripherals clocks according to the specified
  *         parameters in the RCC_PeriphCLKInitTypeDef.
  * @param  PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
  *         contains the configuration information for the Extended Peripherals clocks(RTC/LCD clock).
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
  uint32_t tickstart = 0;
  uint32_t temp_reg = 0;
  
  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
  
  /*------------------------------- RTC/LCD Configuration ------------------------*/ 
  if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) 
#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
      || (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */
    )
  {
    /* check for RTC Parameters used to output RTCCLK */
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
    {
      assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
    }

#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD)
    {
      assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->LCDClockSelection));
    }
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */

    /* Enable Power Clock*/
    __HAL_RCC_PWR_CLK_ENABLE();
    
    /* Enable write access to Backup domain */
    SET_BIT(PWR->CR, PWR_CR_DBP);
    
    /* Wait for Backup domain Write protection disable */
    tickstart = HAL_GetTick();
    
    while((PWR->CR & PWR_CR_DBP) == RESET)
    {
      if((HAL_GetTick() - tickstart ) > RCC_DBP_TIMEOUT_VALUE)
      {
        return HAL_TIMEOUT;
      }
    }
    
    /* Reset the Backup domain only if the RTC Clock source selection is modified */ 
    temp_reg = (RCC->CSR & RCC_CSR_RTCSEL);
    
    if(((temp_reg != (PeriphClkInit->RTCClockSelection & RCC_CSR_RTCSEL)) \
      && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
#if defined(STM32L100xB) || defined(STM32L100xBA) || defined(STM32L100xC)\
 || defined(STM32L152xB) || defined(STM32L152xBA) || defined(STM32L152xC)\
 || defined(STM32L162xC) || defined(STM32L152xCA) || defined(STM32L152xD)\
 || defined(STM32L162xCA) || defined(STM32L162xD) || defined(STM32L152xE) || defined(STM32L152xDX)\
 || defined(STM32L162xE) || defined(STM32L162xDX)
      || ((temp_reg != (PeriphClkInit->LCDClockSelection & RCC_CSR_RTCSEL)) \
       && (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LCD) == RCC_PERIPHCLK_LCD))
#endif /* STM32L100xB || STM32L152xBA || ... || STM32L152xE || STM32L152xDX || STM32L162xE || STM32L162xDX */
     )
    {
      /* Store the content of CSR register before the reset of Backup Domain */
      temp_reg = (RCC->CSR & ~(RCC_CSR_RTCSEL));
      
      /* RTC Clock selection can be changed only if the Backup Domain is reset */
      __HAL_RCC_BACKUPRESET_FORCE();
      __HAL_RCC_BACKUPRESET_RELEASE();
      
      /* Restore the Content of CSR register */
      RCC->CSR = temp_reg;
      
       /* Wait for LSERDY if LSE was enabled */
      if (HAL_IS_BIT_SET(temp_reg, RCC_CSR_LSERDY))
      {
        /* Get Start Tick */
        tickstart = HAL_GetTick();
        
        /* Wait till LSE is ready */  
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
        {
          if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      
      __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
    }
  }
  
  return HAL_OK;
}