diff --git a/src/modm/board/disco_f303vc/board.hpp b/src/modm/board/disco_f303vc/board.hpp index b472676416..cd083cff90 100644 --- a/src/modm/board/disco_f303vc/board.hpp +++ b/src/modm/board/disco_f303vc/board.hpp @@ -35,6 +35,7 @@ using namespace modm::literals; /// supplied by the on-board st-link struct SystemClock { + static constexpr uint32_t Hse = 8_MHz; static constexpr uint32_t Frequency = 72_MHz; static constexpr uint32_t Ahb = Frequency; static constexpr uint32_t Apb1 = Frequency / 2; @@ -89,13 +90,12 @@ struct SystemClock static constexpr uint32_t Usb = Ahb / 1.5; static constexpr uint32_t Iwdg = Rcc::LsiFrequency; - static constexpr uint32_t Rtc = Rcc::LsiFrequency; + static constexpr uint32_t Rtc = Hse / 32; static bool inline enable() { - Rcc::enableLowSpeedInternalClock(); - Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::Lsi); + Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::ExternalClock); Rcc::enableExternalClock(); // 8MHz const Rcc::PllFactors pllFactors{ diff --git a/src/modm/board/disco_f401vc/board.hpp b/src/modm/board/disco_f401vc/board.hpp index e0e788e227..f9e2e56c3e 100644 --- a/src/modm/board/disco_f401vc/board.hpp +++ b/src/modm/board/disco_f401vc/board.hpp @@ -36,6 +36,7 @@ using namespace modm::literals; /// STM32F401 running at 168MHz generated from the external 8MHz crystal struct SystemClock { + static constexpr uint32_t Hse = 8_MHz; static constexpr uint32_t Frequency = 84_MHz; static constexpr uint32_t Ahb = Frequency; static constexpr uint32_t Apb1 = Frequency / 4; @@ -72,15 +73,14 @@ struct SystemClock static constexpr uint32_t Usb = 48_MHz; static constexpr uint32_t Iwdg = Rcc::LsiFrequency; - static constexpr uint32_t Rtc = Rcc::LsiFrequency; + static constexpr uint32_t Rtc = Hse / 25; static bool inline enable() { - Rcc::enableLowSpeedInternalClock(); - Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::Lsi); - Rcc::enableExternalCrystal(); // 8MHz + Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::ExternalClock, 25); + const Rcc::PllFactors pllFactors{ .pllM = 4, // 8MHz / M=4 -> 2MHz .pllN = 168, // 2MHz * N=168 -> 336MHz diff --git a/src/modm/board/disco_f407vg/board.hpp b/src/modm/board/disco_f407vg/board.hpp index e57db9071c..bffbd71f4c 100644 --- a/src/modm/board/disco_f407vg/board.hpp +++ b/src/modm/board/disco_f407vg/board.hpp @@ -34,6 +34,7 @@ using namespace modm::literals; /// STM32F407 running at 168MHz generated from the external 8MHz crystal struct SystemClock { + static constexpr uint32_t Hse = 8_MHz; static constexpr uint32_t Frequency = 168_MHz; static constexpr uint32_t Ahb = Frequency; static constexpr uint32_t Apb1 = Frequency / 4; @@ -83,15 +84,14 @@ struct SystemClock static constexpr uint32_t Usb = 48_MHz; static constexpr uint32_t Iwdg = Rcc::LsiFrequency; - static constexpr uint32_t Rtc = Rcc::LsiFrequency; + static constexpr uint32_t Rtc = Hse / 25; static bool inline enable() { - Rcc::enableLowSpeedInternalClock(); - Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::Lsi); - Rcc::enableExternalCrystal(); // 8MHz + Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::ExternalClock, 25); + const Rcc::PllFactors pllFactors{ .pllM = 4, // 8MHz / M=4 -> 2MHz .pllN = 168, // 2MHz * N=168 -> 336MHz diff --git a/src/modm/board/disco_f411ve/board.hpp b/src/modm/board/disco_f411ve/board.hpp index 341828cd6d..bbd36cc475 100644 --- a/src/modm/board/disco_f411ve/board.hpp +++ b/src/modm/board/disco_f411ve/board.hpp @@ -29,6 +29,7 @@ using namespace modm::literals; /// STM32F411 running at 96MHz generated from the external 8MHz crystal struct SystemClock { + static constexpr uint32_t Hse = 8_MHz; static constexpr uint32_t Frequency = 96_MHz; static constexpr uint32_t Ahb = Frequency; static constexpr uint32_t Apb1 = Frequency / 2; @@ -68,15 +69,14 @@ struct SystemClock static constexpr uint32_t Usb = 48_MHz; static constexpr uint32_t Iwdg = Rcc::LsiFrequency; - static constexpr uint32_t Rtc = Rcc::LsiFrequency; + static constexpr uint32_t Rtc = Hse / 25; static bool inline enable() { - Rcc::enableLowSpeedInternalClock(); - Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::Lsi); - Rcc::enableExternalCrystal(); // 8MHz + Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::ExternalClock, 25); + const Rcc::PllFactors pllFactors{ .pllM = 7, // 8MHz / M=7 -> ~1.14MHz .pllN = 336, // 1.14MHz * N=336 -> 384MHz diff --git a/src/modm/board/disco_f429zi/board.hpp b/src/modm/board/disco_f429zi/board.hpp index b10e7a9f00..c0645aba71 100644 --- a/src/modm/board/disco_f429zi/board.hpp +++ b/src/modm/board/disco_f429zi/board.hpp @@ -32,6 +32,7 @@ using namespace modm::literals; /// STM32F429 running at 168MHz from the external 8MHz crystal struct SystemClock { + static constexpr uint32_t Hse = 8_MHz; static constexpr uint32_t Frequency = 168_MHz; static constexpr uint32_t Apb1 = Frequency / 4; static constexpr uint32_t Apb2 = Frequency / 2; @@ -80,15 +81,14 @@ struct SystemClock static constexpr uint32_t Usb = 48_MHz; static constexpr uint32_t Iwdg = Rcc::LsiFrequency; - static constexpr uint32_t Rtc = Rcc::LsiFrequency; + static constexpr uint32_t Rtc = Hse / 25; static bool inline enable() { - Rcc::enableLowSpeedInternalClock(); - Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::Lsi); - Rcc::enableExternalCrystal(); // 8 MHz + Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::ExternalClock, 25); + const Rcc::PllFactors pllFactors{ .pllM = 4, // 8MHz / M -> 2MHz .pllN = 168, // 2MHz * N -> 336MHz diff --git a/src/modm/board/stm32f030f4p6_demo/board.hpp b/src/modm/board/stm32f030f4p6_demo/board.hpp index 2b35dfb184..2d915646c9 100644 --- a/src/modm/board/stm32f030f4p6_demo/board.hpp +++ b/src/modm/board/stm32f030f4p6_demo/board.hpp @@ -31,6 +31,7 @@ using namespace modm::literals; /// STM32F030 running at 48MHz generated from the external 8MHz crystal struct SystemClock { + static constexpr uint32_t Hse = 8_MHz; static constexpr uint32_t Frequency = 48_MHz; static constexpr uint32_t Ahb = Frequency; static constexpr uint32_t Apb = Frequency; @@ -52,15 +53,13 @@ struct SystemClock static constexpr uint32_t Timer16 = Apb; static constexpr uint32_t Timer17 = Apb; static constexpr uint32_t Iwdg = Rcc::LsiFrequency; - static constexpr uint32_t Rtc = Rcc::LsiFrequency; + static constexpr uint32_t Rtc = Hse / 32; static bool inline enable() { - Rcc::enableLowSpeedInternalClock(); - Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::Lsi); - Rcc::enableExternalCrystal(); // 8MHz + Rcc::enableRealTimeClock(Rcc::RealTimeClockSource::ExternalClock); // external clock / 1 * 6 = 48MHz const Rcc::PllFactors pllFactors{ diff --git a/src/modm/platform/clock/stm32/module.lb b/src/modm/platform/clock/stm32/module.lb index c426d22ac7..ec56e8d6f9 100644 --- a/src/modm/platform/clock/stm32/module.lb +++ b/src/modm/platform/clock/stm32/module.lb @@ -89,6 +89,10 @@ def build(env): (target["family"] == "l4" and target["name"][0] in ["p", "q", "r", "s"]) properties["pllsai_p_usb"] = (target["family"] == "f7") or \ ((target["family"] == "f4") and target["name"] in ["46", "69", "79"]) + properties["rtcpre"] = target.family in ["f2", "f4", "f7", "h7", "l0", "l1"] + properties["cfgr_rtc"] = "CR" if target.family in ["l0", "l1"] else \ + ("CFGR1" if target.family in ["h5"] else "CFGR") + if target.family in ["h7"]: if target.name in ["a3", "b0", "b3"]: diff --git a/src/modm/platform/clock/stm32/rcc.hpp.in b/src/modm/platform/clock/stm32/rcc.hpp.in index ff30e3893b..6c99b45e9d 100644 --- a/src/modm/platform/clock/stm32/rcc.hpp.in +++ b/src/modm/platform/clock/stm32/rcc.hpp.in @@ -204,6 +204,16 @@ public: LowSpeedExternalClock = Lse, LowSpeedExternalCrystal = Lse }; +%% if target.family in ["l0", "l1"] + enum class + RealTimeClockHsePrescaler : uint8_t + { + Div2 = 0, + Div4 = 1, + Div8 = 2, + Div16 = 3, + }; +%% endif enum class WatchdogClockSource : uint32_t @@ -788,8 +798,11 @@ public: enableSystemClock(SystemClockSource src, uint32_t waitCycles = 2048); static inline bool - enableRealTimeClock(RealTimeClockSource src) + enableRealTimeClock(RealTimeClockSource src{% if rtcpre %}, {% if target.family in ["l0", "l1"] %}RealTimeClockHsePrescaler hseDiv = RealTimeClockHsePrescaler::Div16{% else %}uint8_t hseDiv = 0xff{% endif %}{% endif %}) { +%% if rtcpre + RCC->{{cfgr_rtc}} = (RCC->{{cfgr_rtc}} & ~RCC_{{cfgr_rtc}}_RTCPRE_Msk) | ((uint8_t(hseDiv) << RCC_{{cfgr_rtc}}_RTCPRE_Pos) & RCC_{{cfgr_rtc}}_RTCPRE_Msk); +%% endif RCC->{{bdcr}} = (RCC->{{bdcr}} & ~RCC_{{bdcr}}_RTCSEL) | RCC_{{bdcr}}_RTCEN | uint32_t(src); return true; } diff --git a/src/modm/platform/rtc/stm32/rtc_impl.hpp.in b/src/modm/platform/rtc/stm32/rtc_impl.hpp.in index 28c915bb6e..78905df39e 100644 --- a/src/modm/platform/rtc/stm32/rtc_impl.hpp.in +++ b/src/modm/platform/rtc/stm32/rtc_impl.hpp.in @@ -54,6 +54,12 @@ Rtc::initialize(bool forced) case 320: t2ms = [](uint32_t ticks) -> uint32_t { return ((c_prediv_s - ticks) * 25u) >> 3; }; break; // 37kHz: prediv_a=74, prediv_s=500 -> 1000/500 = 2 case 500: t2ms = [](uint32_t ticks) -> uint32_t { return (c_prediv_s - ticks) << 1; }; break; + // 250kHz: prediv_a=125, prediv_s=2000 -> 1000/2000 = 1 >> 1 + case 2000: t2ms = [](uint32_t ticks) -> uint32_t { return (c_prediv_s - ticks) >> 1; }; break; + // 320kHz: prediv_a=125, prediv_s=2560 -> 1000/2560 = 25 >> 6 + case 2560: t2ms = [](uint32_t ticks) -> uint32_t { return ((c_prediv_s - ticks) * 25u) >> 6; }; break; + // 1MHz: prediv_a=125, prediv_s=8000 -> 1000/8000 = 1 >> 3 + case 8000: t2ms = [](uint32_t ticks) -> uint32_t { return (c_prediv_s - ticks) >> 3; }; break; // Otherwise just do the division default: t2ms = [](uint32_t ticks) -> uint32_t { return ((c_prediv_s - ticks) * 1000u) / (c_prediv_s + 1); }; break; }