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); 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
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();
} }
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) { 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;