Example #1
0
/**
 * @brief   Initialize RTC.
 *
 * @notapi
 */
void rtc_lld_init(void){

  /* RSF bit must be cleared by software after an APB1 reset or an APB1 clock
     stop. Otherwise its value will not be actual. */
  RTC->CRL &= ~RTC_CRL_RSF;

  /* Required because access to PRL.*/
  rtc_lld_apb1_sync();

  /* All interrupts initially disabled.*/
  rtc_lld_wait_write();
  RTC->CRH = 0;

  /* Callback initially disabled.*/
  RTCD1.callback = NULL;

  /* IRQ vector permanently assigned to this driver.*/
  nvicEnableVector(RTC_IRQn, CORTEX_PRIORITY_MASK(STM32_RTC_IRQ_PRIORITY));
}
/**
 * @brief   Enable access to registers and initialize RTC if BKP domain
 *          was previously reseted.
 * @note:   Cold start time of LSE oscillator on STM32 platform 
 *          takes about 3 seconds.
 *
 * @notapi
 */
void rtc_lld_init(void){
  uint32_t preload;

  rccEnableBKPInterface(FALSE);

  /* Enables access to BKP registers.*/
  PWR->CR |= PWR_CR_DBP;

  /* If the RTC is not enabled then performs a reset of the backup domain.*/
  if (!(RCC->BDCR & RCC_BDCR_RTCEN)) {
    RCC->BDCR = RCC_BDCR_BDRST;
    RCC->BDCR = 0;
  }

#if STM32_RTC == STM32_RTC_LSE
  if (!(RCC->BDCR & RCC_BDCR_LSEON)) {
    RCC->BDCR |= RCC_BDCR_LSEON;
    while (!(RCC->BDCR & RCC_BDCR_LSERDY))
      ;
  }
  preload = STM32_LSECLK - 1;
#elif STM32_RTC == STM32_RTC_LSI
  /* TODO: Move the LSI clock initialization in the HAL low level driver.*/
  RCC->CSR |= RCC_CSR_LSION;
  while (!(RCC->CSR & RCC_CSR_LSIRDY))
    ;
  /* According to errata sheet we must wait additional 100 uS for
     stabilization.
     TODO: Change this code, software loops are not reliable.*/
  uint32_t tmo = (STM32_SYSCLK / 1000000) * 100;
  while (tmo--)
    ;
  preload = STM32_LSICLK - 1;
#elif STM32_RTC == STM32_RTC_HSE
  preload = (STM32_HSICLK / 128) - 1;
#endif

  /* Selects clock source (previously enabled and stabilized).*/
  RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | STM32_RTC;

  /* RTC enabled regardless its previous status.*/
  RCC->BDCR |= RCC_BDCR_RTCEN;

  /* Ensure that RTC_CNT and RTC_DIV contain actual values after enabling
     clocking on APB1, because these values only update when APB1
     functioning.*/
  RTC->CRL = 0;
  while (!(RTC->CRL & RTC_CRL_RSF))
    ;

  /* Write preload register only if its value differs.*/
  if (preload != ((((uint32_t)(RTC->PRLH)) << 16) + (uint32_t)RTC->PRLL)) {

    rtc_lld_wait_write();

    /* Enters configuration mode and writes PRLx registers then leaves the
       configuration mode.*/
    RTC->CRL |= RTC_CRL_CNF;
    RTC->PRLH = (uint16_t)(preload >> 16);
    RTC->PRLL = (uint16_t)(preload & 0xFFFF);
    RTC->CRL &= ~RTC_CRL_CNF;
  }