summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stmhal/boards/PYBV10/mpconfigboard.h3
-rw-r--r--stmhal/diskio.c1
-rw-r--r--stmhal/main.c2
-rw-r--r--stmhal/modmachine.c23
-rw-r--r--stmhal/modutime.c2
-rw-r--r--stmhal/rtc.c415
-rw-r--r--stmhal/rtc.h3
-rw-r--r--stmhal/system_stm32.c77
8 files changed, 358 insertions, 168 deletions
diff --git a/stmhal/boards/PYBV10/mpconfigboard.h b/stmhal/boards/PYBV10/mpconfigboard.h
index 7aa980498..fece73330 100644
--- a/stmhal/boards/PYBV10/mpconfigboard.h
+++ b/stmhal/boards/PYBV10/mpconfigboard.h
@@ -22,9 +22,12 @@
#define MICROPY_HW_CLK_PLLN (336)
#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2)
#define MICROPY_HW_CLK_PLLQ (7)
+#define MICROPY_HW_CLK_LAST_FREQ (1)
// The pyboard has a 32kHz crystal for the RTC
#define MICROPY_HW_RTC_USE_LSE (1)
+#define MICROPY_HW_RTC_USE_US (0)
+#define MICROPY_HW_RTC_USE_CALOUT (1)
// UART config
#define MICROPY_HW_UART1_NAME "XB"
diff --git a/stmhal/diskio.c b/stmhal/diskio.c
index a15dce1aa..8c8c8ee15 100644
--- a/stmhal/diskio.c
+++ b/stmhal/diskio.c
@@ -279,6 +279,7 @@ DWORD get_fattime (
void
)
{
+ rtc_init_finalise();
RTC_TimeTypeDef time;
RTC_DateTypeDef date;
HAL_RTC_GetTime(&RTCHandle, &time, FORMAT_BIN);
diff --git a/stmhal/main.c b/stmhal/main.c
index f6d6ada70..ffbd6cfa9 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -422,7 +422,7 @@ soft_reset:
#if MICROPY_HW_ENABLE_RTC
if (first_soft_reset) {
- rtc_init();
+ rtc_init_start();
}
#endif
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index c495573fb..25977e789 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -39,6 +39,7 @@
#include "pin.h"
#include "timer.h"
#include "usb.h"
+#include "rtc.h"
#include "i2c.h"
#include "spi.h"
@@ -281,6 +282,9 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
} else {
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
}
+ uint32_t h = RCC_ClkInitStruct.AHBCLKDivider >> 4;
+ uint32_t b1 = RCC_ClkInitStruct.APB1CLKDivider >> 10;
+ uint32_t b2 = RCC_ClkInitStruct.APB2CLKDivider >> 10;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
goto fail;
}
@@ -312,6 +316,23 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
// re-init TIM3 for USB CDC rate
timer_tim3_init();
+ #if defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ
+ #if defined(MCU_SERIES_F7)
+ #define FREQ_BKP BKP31R
+ #else
+ #define FREQ_BKP BKP19R
+ #endif
+ // qqqqqqqq pppppppp nnnnnnnn nnmmmmmm
+ // qqqqQQQQ ppppppPP nNNNNNNN NNMMMMMM
+ // 222111HH HHQQQQPP nNNNNNNN NNMMMMMM
+ p = (p / 2) - 1;
+ RTC->FREQ_BKP = m
+ | (n << 6) | (p << 16) | (q << 18)
+ | (h << 22)
+ | (b1 << 26)
+ | (b2 << 29);
+ #endif
+
return mp_const_none;
fail:;
@@ -349,6 +370,8 @@ STATIC mp_obj_t machine_sleep(void) {
MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
STATIC mp_obj_t machine_deepsleep(void) {
+ rtc_init_finalise();
+
#if defined(MCU_SERIES_F7)
printf("machine.deepsleep not supported yet\n");
#else
diff --git a/stmhal/modutime.c b/stmhal/modutime.c
index 889229558..8502e0fd6 100644
--- a/stmhal/modutime.c
+++ b/stmhal/modutime.c
@@ -57,6 +57,7 @@ STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0 || args[0] == mp_const_none) {
// get current date and time
// note: need to call get time then get date to correctly access the registers
+ rtc_init_finalise();
RTC_DateTypeDef date;
RTC_TimeTypeDef time;
HAL_RTC_GetTime(&RTCHandle, &time, FORMAT_BIN);
@@ -119,6 +120,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
STATIC mp_obj_t time_time(void) {
// get date and time
// note: need to call get time then get date to correctly access the registers
+ rtc_init_finalise();
RTC_DateTypeDef date;
RTC_TimeTypeDef time;
HAL_RTC_GetTime(&RTCHandle, &time, FORMAT_BIN);
diff --git a/stmhal/rtc.c b/stmhal/rtc.c
index 561548ee4..8fdb11250 100644
--- a/stmhal/rtc.c
+++ b/stmhal/rtc.c
@@ -31,6 +31,7 @@
#include "py/runtime.h"
#include "rtc.h"
#include "irq.h"
+#include "mphalport.h"
/// \moduleref pyb
/// \class RTC - real time clock
@@ -52,112 +53,18 @@ static mp_uint_t rtc_info;
// Note: LSI is around (32KHz), these dividers should work either way
// ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)
+// modify RTC_ASYNCH_PREDIV & RTC_SYNCH_PREDIV in board/<BN>/mpconfigport.h to change sub-second ticks
+// default is 3906.25 µs, min is ~30.52 µs (will increas Ivbat by ~500nA)
+#ifndef RTC_ASYNCH_PREDIV
#define RTC_ASYNCH_PREDIV (0x7f)
+#endif
+#ifndef RTC_SYNCH_PREDIV
#define RTC_SYNCH_PREDIV (0x00ff)
-
-#if 0
-#define RTC_INFO_USE_EXISTING (0)
-#define RTC_INFO_USE_LSE (1)
-#define RTC_INFO_USE_LSI (3)
-
-void rtc_init(void) {
- // Enable the PWR clock
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
-
- // Allow access to RTC
- PWR_BackupAccessCmd(ENABLE);
-
- if (RTC_ReadBackupRegister(RTC_BKP_DR0) == 0x32F2) {
- // RTC still alive, so don't re-init it
- // wait for RTC APB register synchronisation
- RTC_WaitForSynchro();
- rtc_info = RTC_INFO_USE_EXISTING;
- return;
- }
-
- uint32_t timeout = 10000000;
-
- // Enable the PWR clock
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
-
- // Allow access to RTC
- PWR_BackupAccessCmd(ENABLE);
-
- // Enable the LSE OSC
- RCC_LSEConfig(RCC_LSE_ON);
-
- // Wait till LSE is ready
- mp_uint_t sys_tick = sys_tick_counter;
- while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) && (--timeout > 0)) {
- }
-
- // record how long it took for the RTC to start up
- rtc_info = (sys_tick_counter - sys_tick) << 2;
-
- // If LSE timed out, use LSI instead
- if (timeout == 0) {
- // Disable the LSE OSC
- RCC_LSEConfig(RCC_LSE_OFF);
-
- // Enable the LSI OSC
- RCC_LSICmd(ENABLE);
-
- // Wait till LSI is ready
- while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {
- }
-
- // Use LSI as the RTC Clock Source
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
-
- // record that we are using the LSI
- rtc_info |= RTC_INFO_USE_LSI;
- } else {
- // Use LSE as the RTC Clock Source
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
-
- // record that we are using the LSE
- rtc_info |= RTC_INFO_USE_LSE;
- }
-
- // Note: LSI is around (32KHz), these dividers should work either way
- // ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)
- uint32_t uwSynchPrediv = 0xFF;
- uint32_t uwAsynchPrediv = 0x7F;
-
- // Enable the RTC Clock
- RCC_RTCCLKCmd(ENABLE);
-
- // Wait for RTC APB registers synchronisation
- RTC_WaitForSynchro();
-
- // Configure the RTC data register and RTC prescaler
- RTC_InitTypeDef RTC_InitStructure;
- RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;
- RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;
- RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
- RTC_Init(&RTC_InitStructure);
-
- // Set the date (BCD)
- RTC_DateTypeDef RTC_DateStructure;
- RTC_DateStructure.RTC_Year = 0x13;
- RTC_DateStructure.RTC_Month = RTC_Month_October;
- RTC_DateStructure.RTC_Date = 0x26;
- RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Saturday;
- RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
-
- // Set the time (BCD)
- RTC_TimeTypeDef RTC_TimeStructure;
- RTC_TimeStructure.RTC_H12 = RTC_H12_AM;
- RTC_TimeStructure.RTC_Hours = 0x01;
- RTC_TimeStructure.RTC_Minutes = 0x53;
- RTC_TimeStructure.RTC_Seconds = 0x00;
- RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);
-
- // Indicator for the RTC configuration
- RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
-}
#endif
+STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc);
+STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse);
+STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc);
STATIC void RTC_CalendarConfig(void);
#if defined(MICROPY_HW_RTC_USE_LSE) && MICROPY_HW_RTC_USE_LSE
@@ -165,8 +72,40 @@ STATIC bool rtc_use_lse = true;
#else
STATIC bool rtc_use_lse = false;
#endif
+STATIC uint32_t rtc_startup_tick;
+STATIC bool rtc_need_init_finalise = false;
-void rtc_init(void) {
+// check if LSE exists
+// not well tested, should probably be removed
+STATIC bool lse_magic(void) {
+#if 0
+ uint32_t mode_in = GPIOC->MODER & 0x3fffffff;
+ uint32_t mode_out = mode_in | 0x40000000;
+ GPIOC->MODER = mode_out;
+ GPIOC->OTYPER &= 0x7fff;
+ GPIOC->BSRRH = 0x8000;
+ GPIOC->OSPEEDR &= 0x3fffffff;
+ GPIOC->PUPDR &= 0x3fffffff;
+ int i = 0xff0;
+ __IO int d = 0;
+ uint32_t tc = 0;
+ __IO uint32_t j;
+ while (i) {
+ GPIOC->MODER = mode_out;
+ GPIOC->MODER = mode_in;
+ for (j = 0; j < d; j++) ;
+ i--;
+ if ((GPIOC->IDR & 0x8000) == 0) {
+ tc++;
+ }
+ }
+ return (tc < 0xff0)?true:false;
+#else
+ return false;
+#endif
+}
+
+void rtc_init_start(void) {
RTCHandle.Instance = RTC;
/* Configure RTC prescaler and RTC data registers */
@@ -184,6 +123,7 @@ void rtc_init(void) {
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
+ rtc_need_init_finalise = false;
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
@@ -193,8 +133,8 @@ void rtc_init(void) {
// 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
+ } else if (((RCC->BDCR & RCC_BDCR_RTCSEL) == RCC_BDCR_RTCSEL_1) && ((RCC->CSR & 3) == 3)) {
+ // LSI configured & enabled & ready --> no need to (re-)init RTC
// remove Backup Domain write protection
HAL_PWR_EnableBkUpAccess();
// Clear source Reset Flag
@@ -204,16 +144,33 @@ void rtc_init(void) {
rtc_info |= 0x80000 | (RCC->BDCR & 7) | (RCC->CSR & 3) << 8;
return;
}
+ rtc_startup_tick = HAL_GetTick();
+ rtc_info = 0x3f000000 | (rtc_startup_tick & 0xffffff);
+ if (rtc_use_lse) {
+ if (lse_magic()) {
+ // don't even try LSE
+ rtc_use_lse = false;
+ rtc_info &= ~0x01000000;
+ }
+ }
+ PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse);
+}
- mp_uint_t tick = HAL_GetTick();
+void rtc_init_finalise() {
+ if (!rtc_need_init_finalise) {
+ return;
+ }
- if (HAL_RTC_Init(&RTCHandle) != HAL_OK) {
+ rtc_info = 0x20000000 | (rtc_use_lse << 28);
+ if (PYB_RTC_Init(&RTCHandle) != HAL_OK) {
if (rtc_use_lse) {
// fall back to LSI...
rtc_use_lse = false;
+ rtc_startup_tick = HAL_GetTick();
+ PYB_RTC_MspInit_Kick(&RTCHandle, rtc_use_lse);
HAL_PWR_EnableBkUpAccess();
RTCHandle.State = HAL_RTC_STATE_RESET;
- if (HAL_RTC_Init(&RTCHandle) != HAL_OK) {
+ if (PYB_RTC_Init(&RTCHandle) != HAL_OK) {
rtc_info = 0x0100ffff; // indicate error
return;
}
@@ -225,11 +182,10 @@ void rtc_init(void) {
}
// record how long it took for the RTC to start up
- rtc_info = HAL_GetTick() - tick;
+ rtc_info |= (HAL_GetTick() - rtc_startup_tick) & 0xffff;
// fresh reset; configure RTC Calendar
RTC_CalendarConfig();
-
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) {
// power on reset occurred
rtc_info |= 0x10000;
@@ -240,46 +196,118 @@ void rtc_init(void) {
}
// Clear source Reset Flag
__HAL_RCC_CLEAR_RESET_FLAGS();
+ rtc_need_init_finalise = false;
}
-STATIC void RTC_CalendarConfig(void) {
- // set the date to 1st Jan 2014
- RTC_DateTypeDef date;
- date.Year = 14;
- date.Month = 1;
- date.Date = 1;
- date.WeekDay = RTC_WEEKDAY_WEDNESDAY;
-
- if(HAL_RTC_SetDate(&RTCHandle, &date, FORMAT_BIN) != HAL_OK) {
- // init error
- return;
+STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) {
+ /*------------------------------ LSI Configuration -------------------------*/
+ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) {
+ // Check the LSI State
+ if (RCC_OscInitStruct->LSIState != RCC_LSI_OFF) {
+ // Enable the Internal Low Speed oscillator (LSI).
+ __HAL_RCC_LSI_ENABLE();
+ } else {
+ // Disable the Internal Low Speed oscillator (LSI).
+ __HAL_RCC_LSI_DISABLE();
+ }
}
- // set the time to 00:00:00
- RTC_TimeTypeDef time;
- time.Hours = 0;
- time.Minutes = 0;
- time.Seconds = 0;
- time.TimeFormat = RTC_HOURFORMAT12_AM;
- time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
- time.StoreOperation = RTC_STOREOPERATION_RESET;
+ /*------------------------------ LSE Configuration -------------------------*/
+ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) {
+ // Enable Power Clock
+ __PWR_CLK_ENABLE();
+ HAL_PWR_EnableBkUpAccess();
+ uint32_t tickstart = HAL_GetTick();
+
+ #if defined(MCU_SERIES_F7)
+ //__HAL_RCC_PWR_CLK_ENABLE();
+ // Enable write access to Backup domain
+ //PWR->CR1 |= PWR_CR1_DBP;
+ // Wait for Backup domain Write protection disable
+ while ((PWR->CR1 & PWR_CR1_DBP) == RESET) {
+ if (HAL_GetTick() - tickstart > RCC_DBP_TIMEOUT_VALUE) {
+ return HAL_TIMEOUT;
+ }
+ }
+ #else
+ // Enable write access to Backup domain
+ //PWR->CR |= PWR_CR_DBP;
+ // Wait for Backup domain Write protection disable
+ while ((PWR->CR & PWR_CR_DBP) == RESET) {
+ if (HAL_GetTick() - tickstart > DBP_TIMEOUT_VALUE) {
+ return HAL_TIMEOUT;
+ }
+ }
+ #endif
- if (HAL_RTC_SetTime(&RTCHandle, &time, FORMAT_BIN) != HAL_OK) {
- // init error
- return;
+ // Set the new LSE configuration
+ __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
}
+
+ return HAL_OK;
}
-/*
- Note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
- the RTC clock source; in this case the Backup domain will be reset in
- order to modify the RTC Clock source, as consequence RTC registers (including
- the backup registers) and RCC_BDCR register are set to their reset values.
-*/
-void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
+STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) {
+ // Check the RTC peripheral state
+ if (hrtc == NULL) {
+ return HAL_ERROR;
+ }
+ if (hrtc->State == HAL_RTC_STATE_RESET) {
+ // Allocate lock resource and initialize it
+ hrtc->Lock = HAL_UNLOCKED;
+ // Initialize RTC MSP
+ if (PYB_RTC_MspInit_Finalise(hrtc) != HAL_OK) {
+ return HAL_ERROR;
+ }
+ }
+
+ // Set RTC state
+ hrtc->State = HAL_RTC_STATE_BUSY;
+
+ // Disable the write protection for RTC registers
+ __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
+
+ // Set Initialization mode
+ if (RTC_EnterInitMode(hrtc) != HAL_OK) {
+ // Enable the write protection for RTC registers
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ // Set RTC state
+ hrtc->State = HAL_RTC_STATE_ERROR;
+
+ return HAL_ERROR;
+ } else {
+ // Clear RTC_CR FMT, OSEL and POL Bits
+ hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL));
+ // Set RTC_CR register
+ hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity);
+
+ // Configure the RTC PRER
+ hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv);
+ hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16);
+
+ // Exit Initialization mode
+ hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT;
+
+ #if defined(MCU_SERIES_F7)
+ hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMTYPE;
+ hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType);
+ #else
+ hrtc->Instance->TAFCR &= (uint32_t)~RTC_TAFCR_ALARMOUTTYPE;
+ hrtc->Instance->TAFCR |= (uint32_t)(hrtc->Init.OutPutType);
+ #endif
+
+ // Enable the write protection for RTC registers
+ __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
+
+ // Set RTC state
+ hrtc->State = HAL_RTC_STATE_READY;
+
+ return HAL_OK;
+ }
+}
+STATIC void PYB_RTC_MspInit_Kick(RTC_HandleTypeDef *hrtc, bool rtc_use_lse) {
/* To change the source clock of the RTC feature (LSE, LSI), You have to:
- Enable the power clock using __PWR_CLK_ENABLE()
- Enable write access using HAL_PWR_EnableBkUpAccess() function before to
@@ -291,6 +319,7 @@ void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) {
// RTC clock source uses LSE (external crystal) only if relevant
// configuration variable is set. Otherwise it uses LSI (internal osc).
+ RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (rtc_use_lse) {
@@ -300,11 +329,36 @@ void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) {
RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
}
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
- //Error_Handler();
- return;
+ PYB_RCC_OscConfig(&RCC_OscInitStruct);
+
+ // now ramp up osc. in background and flag calendear init needed
+ rtc_need_init_finalise = true;
+}
+
+#define PYB_LSE_TIMEOUT_VALUE 1000 // ST docs spec 2000 ms LSE startup, seems to be too pessimistic
+#define PYB_LSI_TIMEOUT_VALUE 500 // this is way too pessimistic, typ. < 1ms
+
+STATIC HAL_StatusTypeDef PYB_RTC_MspInit_Finalise(RTC_HandleTypeDef *hrtc) {
+ // we already had a kick so now wait for the corresponding ready state...
+ if (rtc_use_lse) {
+ // we now have to wait for LSE ready or timeout
+ uint32_t tickstart = rtc_startup_tick;
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET) {
+ if ((HAL_GetTick() - tickstart ) > PYB_LSE_TIMEOUT_VALUE) {
+ return HAL_TIMEOUT;
+ }
+ }
+ } else {
+ // we now have to wait for LSI ready or timeout
+ uint32_t tickstart = rtc_startup_tick;
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET) {
+ if ((HAL_GetTick() - tickstart ) > PYB_LSI_TIMEOUT_VALUE) {
+ return HAL_TIMEOUT;
+ }
+ }
}
+ RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
if (rtc_use_lse) {
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
@@ -313,15 +367,40 @@ void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) {
}
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
//Error_Handler();
- return;
+ return HAL_ERROR;
}
// enable RTC peripheral clock
__HAL_RCC_RTC_ENABLE();
+ return HAL_OK;
}
-void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc) {
- __HAL_RCC_RTC_DISABLE();
+STATIC void RTC_CalendarConfig(void) {
+ // set the date to 1st Jan 2015
+ RTC_DateTypeDef date;
+ date.Year = 15;
+ date.Month = 1;
+ date.Date = 1;
+ date.WeekDay = RTC_WEEKDAY_THURSDAY;
+
+ if(HAL_RTC_SetDate(&RTCHandle, &date, FORMAT_BIN) != HAL_OK) {
+ // init error
+ return;
+ }
+
+ // set the time to 00:00:00
+ RTC_TimeTypeDef time;
+ time.Hours = 0;
+ time.Minutes = 0;
+ time.Seconds = 0;
+ time.TimeFormat = RTC_HOURFORMAT12_AM;
+ time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
+ time.StoreOperation = RTC_STOREOPERATION_RESET;
+
+ if (HAL_RTC_SetTime(&RTCHandle, &time, FORMAT_BIN) != HAL_OK) {
+ // init error
+ return;
+ }
}
/******************************************************************************/
@@ -369,7 +448,25 @@ MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_info_obj, pyb_rtc_info);
/// `weekday` is 1-7 for Monday through Sunday.
///
/// `subseconds` counts down from 255 to 0
+
+#define MEG_DIV_64 (1000000 / 64)
+#define MEG_DIV_SCALE ((RTC_SYNCH_PREDIV + 1) / 64)
+
+#if defined(MICROPY_HW_RTC_USE_US) && MICROPY_HW_RTC_USE_US
+uint32_t rtc_subsec_to_us(uint32_t ss) {
+ return ((RTC_SYNCH_PREDIV - ss) * MEG_DIV_64) / MEG_DIV_SCALE;
+}
+
+uint32_t rtc_us_to_subsec(uint32_t us) {
+ return RTC_SYNCH_PREDIV - (us * MEG_DIV_SCALE / MEG_DIV_64);
+}
+#else
+#define rtc_us_to_subsec
+#define rtc_subsec_to_us
+#endif
+
mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
+ rtc_init_finalise();
if (n_args == 1) {
// get date and time
// note: need to call get time then get date to correctly access the registers
@@ -385,7 +482,7 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
mp_obj_new_int(time.Hours),
mp_obj_new_int(time.Minutes),
mp_obj_new_int(time.Seconds),
- mp_obj_new_int(time.SubSeconds),
+ mp_obj_new_int(rtc_subsec_to_us(time.SubSeconds)),
};
return mp_obj_new_tuple(8, tuple);
} else {
@@ -404,7 +501,7 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
time.Hours = mp_obj_get_int(items[4]);
time.Minutes = mp_obj_get_int(items[5]);
time.Seconds = mp_obj_get_int(items[6]);
- time.SubSeconds = mp_obj_get_int(items[7]);
+ time.SubSeconds = rtc_us_to_subsec(mp_obj_get_int(items[7]));
time.TimeFormat = RTC_HOURFORMAT12_AM;
time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
time.StoreOperation = RTC_STOREOPERATION_SET;
@@ -429,6 +526,8 @@ mp_obj_t pyb_rtc_wakeup(mp_uint_t n_args, const mp_obj_t *args) {
// wucksel=0b110 is 1Hz clock with 0x10000 added to wut
// so a 1 second wakeup could be wut=2047, wucksel=0b000, or wut=4095, wucksel=0b001, etc
+ rtc_init_finalise();
+
// disable wakeup IRQ while we configure it
HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
@@ -539,13 +638,31 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_wakeup_obj, 2, 4, pyb_rtc_wakeup);
// When an integer argument is provided, check that it falls in the range [-511 to 512]
// and set the calibration value; otherwise return calibration value
mp_obj_t pyb_rtc_calibration(mp_uint_t n_args, const mp_obj_t *args) {
+ rtc_init_finalise();
mp_int_t cal;
if (n_args == 2) {
cal = mp_obj_get_int(args[1]);
mp_uint_t cal_p, cal_m;
if (cal < -511 || cal > 512) {
+#if defined(MICROPY_HW_RTC_USE_CALOUT) && MICROPY_HW_RTC_USE_CALOUT
+ if ((cal & 0xfffe) == 0x0ffe) {
+ // turn on/off X18 (PC13) 512Hz output
+ // Note:
+ // Output will stay active even in VBAT mode (and inrease current)
+ if (cal & 1) {
+ HAL_RTCEx_SetCalibrationOutPut(&RTCHandle, RTC_CALIBOUTPUT_512HZ);
+ } else {
+ HAL_RTCEx_DeactivateCalibrationOutPut(&RTCHandle);
+ }
+ return mp_obj_new_int(cal & 1);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+ "calibration value out of range"));
+ }
+#else
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"calibration value out of range"));
+#endif
}
if (cal > 0) {
cal_p = RTC_SMOOTHCALIB_PLUSPULSES_SET;
diff --git a/stmhal/rtc.h b/stmhal/rtc.h
index 6aacd653c..c8f215c05 100644
--- a/stmhal/rtc.h
+++ b/stmhal/rtc.h
@@ -27,4 +27,5 @@
extern RTC_HandleTypeDef RTCHandle;
extern const mp_obj_type_t pyb_rtc_type;
-void rtc_init(void);
+void rtc_init_start(void);
+void rtc_init_finalise(void);
diff --git a/stmhal/system_stm32.c b/stmhal/system_stm32.c
index 22c917adc..e286a1572 100644
--- a/stmhal/system_stm32.c
+++ b/stmhal/system_stm32.c
@@ -269,15 +269,66 @@ void SystemClock_Config(void)
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
- /* Enable HSE Oscillator and activate PLL with HSE as source */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM;
- RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN;
- RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP;
- RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ;
+ /* Enable HSE Oscillator and activate PLL with HSE as source */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
+ clocks dividers */
+ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+
+#if defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ
+ #if defined(MCU_SERIES_F7)
+ #define FREQ_BKP BKP31R
+ #else
+ #define FREQ_BKP BKP19R
+ #endif
+ uint32_t m = RTC->FREQ_BKP;
+ uint32_t n;
+ uint32_t p;
+ uint32_t q;
+
+ // 222111HH HHQQQQPP nNNNNNNN NNMMMMMM
+ uint32_t h = (m >> 22) & 0xf;
+ uint32_t b1 = (m >> 26) & 0x7;
+ uint32_t b2 = (m >> 29) & 0x7;
+ q = (m >> 18) & 0xf;
+ p = (((m >> 16) & 0x03)+1)*2;
+ n = (m >> 6) & 0x3ff;
+ m &= 0x3f;
+ if ((q < 2) || (q > 15) || (p > 8) || (p < 2) || (n < 192) || (n >= 433) || (m < 2)) {
+ m = MICROPY_HW_CLK_PLLM;
+ n = MICROPY_HW_CLK_PLLN;
+ p = MICROPY_HW_CLK_PLLP;
+ q = MICROPY_HW_CLK_PLLQ;
+ h = RCC_SYSCLK_DIV1;
+ b1 = RCC_HCLK_DIV4;
+ b2 = RCC_HCLK_DIV2;
+ } else {
+ h <<= 4;
+ b1 <<= 10;
+ b2 <<= 10;
+ }
+ RCC_OscInitStruct.PLL.PLLM = m; //MICROPY_HW_CLK_PLLM;
+ RCC_OscInitStruct.PLL.PLLN = n; //MICROPY_HW_CLK_PLLN;
+ RCC_OscInitStruct.PLL.PLLP = p; //MICROPY_HW_CLK_PLLP;
+ RCC_OscInitStruct.PLL.PLLQ = q; //MICROPY_HW_CLK_PLLQ;
+
+ RCC_ClkInitStruct.AHBCLKDivider = h; //RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = b1; //RCC_HCLK_DIV4;
+ RCC_ClkInitStruct.APB2CLKDivider = b2; //RCC_HCLK_DIV2;
+#else
+ RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM;
+ RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN;
+ RCC_OscInitStruct.PLL.PLLP = MICROPY_HW_CLK_PLLP;
+ RCC_OscInitStruct.PLL.PLLQ = MICROPY_HW_CLK_PLLQ;
+
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
+#endif
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
__fatal_error("HAL_RCC_OscConfig");
@@ -291,14 +342,6 @@ void SystemClock_Config(void)
}
#endif
- /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
- clocks dividers */
- RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
-
#if !defined(MICROPY_HW_FLASH_LATENCY)
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_5
#endif