Skip to content

Commit 14e9793

Browse files
kwagyemandpgeorge
authored andcommitted
stm32/boards: Use LSI-matched RTC prescalers on Arduino boards.
The Arduino Giga, Nicla Vision, Opta and Portenta H7 have an accurate external 32768Hz oscillator (a SiT1532, +-20ppm) on OSC32_IN, but their stock Arduino MCUboot bootloader is built with Mbed's lse_available disabled and reinitialises the RTC onto the LSI at every hard reset when it finds any other clock source selected -- and the backup-domain reset that requires wipes the calendar. Verified on a Nicla Vision: with the RTC switched to LSE bypass (which does start and keep +-0ppm time while running), every machine.reset() and deep-sleep wake came back on the LSI with the calendar reset to the bootloader's 2021-01-01 epoch. So these boards run the RTC from the LSI, but the prescalers divided by 32768, making the RTC about 2.3% slow -- over half an hour per day, far beyond what rtc.calibration() can correct. Set the LSI prescalers to divide by the LSI's nominal 32000 instead, and drop the MICROPY_HW_RCC_RTC_CLKSOURCE override so the runtime prescaler selection sees whichever source the bootloader provides: boards updated to an LSE-enabled bootloader get the SiT1532 with 32768Hz prescalers automatically, everything else stays on the corrected LSI. Tested on an Arduino Nicla Vision (stock bootloader): -684ppm over 240s measurements against the HSE-derived SysTick (previously -22300ppm measured over two hours against NTP), time preserved through machine.deepsleep(20000) and machine.reset(), and the microsecond subsecond fields still exact (32000/64 = 500). Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
1 parent 89d350e commit 14e9793

4 files changed

Lines changed: 40 additions & 16 deletions

File tree

ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ void GIGA_board_low_power(int mode);
9797
// Peripheral clock sources
9898
#define MICROPY_HW_RCC_HSI48_STATE (RCC_HSI48_ON)
9999
#define MICROPY_HW_RCC_USB_CLKSOURCE (RCC_USBCLKSOURCE_HSI48)
100-
#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSI)
101100
#define MICROPY_HW_RCC_FMC_CLKSOURCE (RCC_FMCCLKSOURCE_PLL2)
102101
#define MICROPY_HW_RCC_RNG_CLKSOURCE (RCC_RNGCLKSOURCE_HSI48)
103102
#define MICROPY_HW_RCC_ADC_CLKSOURCE (RCC_ADCCLKSOURCE_PLL3)
@@ -116,9 +115,16 @@ void GIGA_board_low_power(int mode);
116115
#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_OPEN)
117116
#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_OPEN)
118117

119-
// There is an external 32kHz oscillator
120-
#define RTC_ASYNCH_PREDIV (0)
121-
#define RTC_SYNCH_PREDIV (0x7fff)
118+
// There is an accurate external 32kHz oscillator (a SiT1532 on OSC32_IN), but the
119+
// stock Arduino MCUboot bootloader is built with Mbed's lse_available=false and
120+
// reinitialises the RTC onto the LSI (wiping the calendar) at every hard reset if it
121+
// finds any other clock source selected. So the RTC is left running from the LSI,
122+
// with prescalers for its nominal 32kHz; the LSE (and its 32768Hz prescalers) is
123+
// picked up automatically on boards whose bootloader has been updated to enable it.
124+
#define RTC_ASYNCH_PREDIV_LSE (0)
125+
#define RTC_SYNCH_PREDIV_LSE (0x7fff)
126+
#define RTC_ASYNCH_PREDIV_LSI (0)
127+
#define RTC_SYNCH_PREDIV_LSI (31999)
122128
#define MICROPY_HW_RTC_USE_BYPASS (0)
123129
#define MICROPY_HW_RTC_USE_US (1)
124130
#define MICROPY_HW_RTC_USE_CALOUT (1)

ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ void NICLAV_board_osc_enable(int enable);
100100
// Peripheral clock sources
101101
#define MICROPY_HW_RCC_HSI48_STATE (RCC_HSI48_ON)
102102
#define MICROPY_HW_RCC_USB_CLKSOURCE (RCC_USBCLKSOURCE_HSI48)
103-
#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSI)
104103
#define MICROPY_HW_RCC_FMC_CLKSOURCE (RCC_FMCCLKSOURCE_PLL2)
105104
#define MICROPY_HW_RCC_RNG_CLKSOURCE (RCC_RNGCLKSOURCE_HSI48)
106105
#define MICROPY_HW_RCC_ADC_CLKSOURCE (RCC_ADCCLKSOURCE_PLL3)
@@ -120,9 +119,16 @@ void NICLAV_board_osc_enable(int enable);
120119
#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_CLOSE)
121120
#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_CLOSE)
122121

123-
// There is an external 32kHz oscillator
124-
#define RTC_ASYNCH_PREDIV (0)
125-
#define RTC_SYNCH_PREDIV (0x7fff)
122+
// There is an accurate external 32kHz oscillator (a SiT1532 on OSC32_IN), but the
123+
// stock Arduino MCUboot bootloader is built with Mbed's lse_available=false and
124+
// reinitialises the RTC onto the LSI (wiping the calendar) at every hard reset if it
125+
// finds any other clock source selected. So the RTC is left running from the LSI,
126+
// with prescalers for its nominal 32kHz; the LSE (and its 32768Hz prescalers) is
127+
// picked up automatically on boards whose bootloader has been updated to enable it.
128+
#define RTC_ASYNCH_PREDIV_LSE (0)
129+
#define RTC_SYNCH_PREDIV_LSE (0x7fff)
130+
#define RTC_ASYNCH_PREDIV_LSI (0)
131+
#define RTC_SYNCH_PREDIV_LSI (31999)
126132
#define MICROPY_HW_RTC_USE_BYPASS (1)
127133
#define MICROPY_HW_RTC_USE_US (1)
128134
#define MICROPY_HW_RTC_USE_CALOUT (1)

ports/stm32/boards/ARDUINO_OPTA/mpconfigboard.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ void OPTA_board_osc_enable(int enable);
9191
// Peripheral clock sources
9292
#define MICROPY_HW_RCC_HSI48_STATE (RCC_HSI48_ON)
9393
#define MICROPY_HW_RCC_USB_CLKSOURCE (RCC_USBCLKSOURCE_HSI48)
94-
#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSI)
9594
#define MICROPY_HW_RCC_FMC_CLKSOURCE (RCC_FMCCLKSOURCE_PLL2)
9695
#define MICROPY_HW_RCC_RNG_CLKSOURCE (RCC_RNGCLKSOURCE_HSI48)
9796
#define MICROPY_HW_RCC_ADC_CLKSOURCE (RCC_ADCCLKSOURCE_PLL3)
@@ -110,9 +109,16 @@ void OPTA_board_osc_enable(int enable);
110109
#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_OPEN)
111110
#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_OPEN)
112111

113-
// There is an external 32kHz oscillator
114-
#define RTC_ASYNCH_PREDIV (0)
115-
#define RTC_SYNCH_PREDIV (0x7fff)
112+
// There is an accurate external 32kHz oscillator (a SiT1532 on OSC32_IN), but the
113+
// stock Arduino MCUboot bootloader is built with Mbed's lse_available=false and
114+
// reinitialises the RTC onto the LSI (wiping the calendar) at every hard reset if it
115+
// finds any other clock source selected. So the RTC is left running from the LSI,
116+
// with prescalers for its nominal 32kHz; the LSE (and its 32768Hz prescalers) is
117+
// picked up automatically on boards whose bootloader has been updated to enable it.
118+
#define RTC_ASYNCH_PREDIV_LSE (0)
119+
#define RTC_SYNCH_PREDIV_LSE (0x7fff)
120+
#define RTC_ASYNCH_PREDIV_LSI (0)
121+
#define RTC_SYNCH_PREDIV_LSI (31999)
116122
#define MICROPY_HW_RTC_USE_BYPASS (1)
117123
#define MICROPY_HW_RTC_USE_US (1)
118124
#define MICROPY_HW_RTC_USE_CALOUT (1)

ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ void PORTENTA_board_osc_enable(int enable);
9999
// Peripheral clock sources
100100
#define MICROPY_HW_RCC_HSI48_STATE (RCC_HSI48_ON)
101101
#define MICROPY_HW_RCC_USB_CLKSOURCE (RCC_USBCLKSOURCE_HSI48)
102-
#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSI)
103102
#define MICROPY_HW_RCC_FMC_CLKSOURCE (RCC_FMCCLKSOURCE_PLL2)
104103
#define MICROPY_HW_RCC_RNG_CLKSOURCE (RCC_RNGCLKSOURCE_HSI48)
105104
#define MICROPY_HW_RCC_ADC_CLKSOURCE (RCC_ADCCLKSOURCE_PLL3)
@@ -118,9 +117,16 @@ void PORTENTA_board_osc_enable(int enable);
118117
#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_OPEN)
119118
#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_OPEN)
120119

121-
// There is an external 32kHz oscillator
122-
#define RTC_ASYNCH_PREDIV (0)
123-
#define RTC_SYNCH_PREDIV (0x7fff)
120+
// There is an accurate external 32kHz oscillator (a SiT1532 on OSC32_IN), but the
121+
// stock Arduino MCUboot bootloader is built with Mbed's lse_available=false and
122+
// reinitialises the RTC onto the LSI (wiping the calendar) at every hard reset if it
123+
// finds any other clock source selected. So the RTC is left running from the LSI,
124+
// with prescalers for its nominal 32kHz; the LSE (and its 32768Hz prescalers) is
125+
// picked up automatically on boards whose bootloader has been updated to enable it.
126+
#define RTC_ASYNCH_PREDIV_LSE (0)
127+
#define RTC_SYNCH_PREDIV_LSE (0x7fff)
128+
#define RTC_ASYNCH_PREDIV_LSI (0)
129+
#define RTC_SYNCH_PREDIV_LSI (31999)
124130
#define MICROPY_HW_RTC_USE_BYPASS (1)
125131
#define MICROPY_HW_RTC_USE_US (1)
126132
#define MICROPY_HW_RTC_USE_CALOUT (1)

0 commit comments

Comments
 (0)