Browse Source

stmhal/rtc: LSx oscillator is only initialized upon initial power up.

Initial power up also includes VBAT.

If LSE is configured but fails to start, LSI is used until next full power
cycle.  Also handles STM32F7xx variant.
pull/1595/head
T S 9 years ago
committed by Damien George
parent
commit
8f7ff854b0
  1. 94
      stmhal/rtc.c

94
stmhal/rtc.c

@ -160,9 +160,14 @@ void rtc_init(void) {
STATIC void RTC_CalendarConfig(void); STATIC void RTC_CalendarConfig(void);
#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE
STATIC bool rtc_use_lse = true;
#else
STATIC bool rtc_use_lse = false;
#endif
void rtc_init(void) { void rtc_init(void) {
RTCHandle.Instance = RTC; RTCHandle.Instance = RTC;
RTC_DateTypeDef date;
/* Configure RTC prescaler and RTC data registers */ /* Configure RTC prescaler and RTC data registers */
/* RTC configured as follow: /* RTC configured as follow:
@ -179,49 +184,62 @@ void rtc_init(void) {
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
// if LTE enabled & ready --> no need to (re-)init RTC
if ((RCC->BDCR & (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) == (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) { if ((RCC->BDCR & (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) == (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) {
// LSE is enabled & ready --> no need to (re-)init RTC
// remove Backup Domain write protection // remove Backup Domain write protection
#if defined(MCU_SERIES_F7) HAL_PWR_EnableBkUpAccess();
PWR->CR1 |= PWR_CR1_DBP;
#else
PWR->CR |= PWR_CR_DBP;
#endif
// Clear source Reset Flag // Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS(); __HAL_RCC_CLEAR_RESET_FLAGS();
// provide some status information // provide some status information
rtc_info |= 0x40000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8; rtc_info |= 0x40000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
return; return;
} else if ((RCC->BDCR & RCC_BDCR_RTCSEL) == RCC_BDCR_RTCSEL_1) {
// LSI is already active
// remove Backup Domain write protection
HAL_PWR_EnableBkUpAccess();
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
RCC->CSR |= 1;
// provide some status information
rtc_info |= 0x80000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
return;
} }
mp_uint_t tick = HAL_GetTick(); mp_uint_t tick = HAL_GetTick();
if (HAL_RTC_Init(&RTCHandle) != HAL_OK) { if (HAL_RTC_Init(&RTCHandle) != HAL_OK) {
// init error if (rtc_use_lse) {
rtc_info = 0xffff; // indicate error // fall back to LSI...
return; rtc_use_lse = false;
PWR->CR |= PWR_CR_DBP;
RTCHandle.State = HAL_RTC_STATE_RESET;
if (HAL_RTC_Init(&RTCHandle) != HAL_OK) {
rtc_info = 0x0100ffff; // indicate error
return;
}
} else {
// init error
rtc_info = 0xffff; // indicate error
return;
}
} }
// record how long it took for the RTC to start up // record how long it took for the RTC to start up
rtc_info = HAL_GetTick() - tick; rtc_info = HAL_GetTick() - tick;
HAL_RTC_GetDate(&RTCHandle, &date, FORMAT_BIN); // fresh reset; configure RTC Calendar
if (date.Year == 0 && date.Month ==0 && date.Date == 0) { RTC_CalendarConfig();
// fresh reset; configure RTC Calendar
RTC_CalendarConfig(); if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) {
} else { // power on reset occurred
// RTC was previously set, so leave it alone rtc_info |= 0x10000;
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { }
// power on reset occurred if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) {
rtc_info |= 0x10000; // external reset occurred
} rtc_info |= 0x20000;
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) {
// external reset occurred
rtc_info |= 0x20000;
}
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
} }
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
} }
STATIC void RTC_CalendarConfig(void) { STATIC void RTC_CalendarConfig(void) {
@ -275,24 +293,24 @@ void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) {
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE if (rtc_use_lse) {
RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF; RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
#else } else {
RCC_OscInitStruct.LSEState = RCC_LSE_OFF; RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.LSIState = RCC_LSI_ON;
#endif }
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
//Error_Handler(); //Error_Handler();
return; return;
} }
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE if (rtc_use_lse) {
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
#else } else {
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
#endif }
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
//Error_Handler(); //Error_Handler();
return; return;

Loading…
Cancel
Save