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.
This commit is contained in:
T S 2015-11-01 14:31:44 +01:00 committed by Damien George
parent 8bfa11b138
commit 8f7ff854b0
1 changed files with 56 additions and 38 deletions

View File

@ -160,9 +160,14 @@ void rtc_init(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) {
RTCHandle.Instance = RTC;
RTC_DateTypeDef date;
/* Configure RTC prescaler and RTC data registers */
/* RTC configured as follow:
@ -179,49 +184,62 @@ void rtc_init(void) {
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
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)) {
// LSE is enabled & ready --> no need to (re-)init RTC
// remove Backup Domain write protection
#if defined(MCU_SERIES_F7)
PWR->CR1 |= PWR_CR1_DBP;
#else
PWR->CR |= PWR_CR_DBP;
#endif
HAL_PWR_EnableBkUpAccess();
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
// provide some status information
rtc_info |= 0x40000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
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();
if (HAL_RTC_Init(&RTCHandle) != HAL_OK) {
// init error
rtc_info = 0xffff; // indicate error
return;
if (rtc_use_lse) {
// fall back to LSI...
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
rtc_info = HAL_GetTick() - tick;
HAL_RTC_GetDate(&RTCHandle, &date, FORMAT_BIN);
if (date.Year == 0 && date.Month ==0 && date.Date == 0) {
// fresh reset; configure RTC Calendar
RTC_CalendarConfig();
} else {
// RTC was previously set, so leave it alone
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) {
// power on reset occurred
rtc_info |= 0x10000;
}
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) {
// external reset occurred
rtc_info |= 0x20000;
}
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
// fresh reset; configure RTC Calendar
RTC_CalendarConfig();
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) {
// power on reset occurred
rtc_info |= 0x10000;
}
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET) {
// external reset occurred
rtc_info |= 0x20000;
}
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
}
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.PLL.PLLState = RCC_PLL_NONE;
#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
#else
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
#endif
if (rtc_use_lse) {
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
} else {
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
}
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
//Error_Handler();
return;
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
#else
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
#endif
if (rtc_use_lse) {
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
} else {
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
}
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
//Error_Handler();
return;