From 442ec380ce4ede22037823aa6ec1179e1bf4907e Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 19 Jun 2023 15:04:52 +0200 Subject: [PATCH 01/23] STM32RTC: syncAlarmTime Get the Alarm given by the parameter In case the Alarm name is ALARM_B, this change will avoid getting the Alarm_A Signed-off-by: Francois Ramu --- src/STM32RTC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 10d8379..0c8bf9d 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -1276,7 +1276,7 @@ void STM32RTC::syncAlarmTime(Alarm name) RTC_GetAlarm(::ALARM_B, &_alarmBDay, &_alarmBHours, &_alarmBMinutes, &_alarmBSeconds, &_alarmBSubSeconds, &p, &match); _alarmBPeriod = (p == HOUR_AM) ? AM : PM; - } + } else #else UNUSED(name); #endif From a703c0f74186a6bcbf2e7cb5224cc52f3ee3d2f9 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 15 Sep 2023 09:32:01 +0200 Subject: [PATCH 02/23] ci(config): limit number of build Signed-off-by: Frederic Pillon --- .github/workflows/Continuous-Integration.yml | 1 - extras/rtc_cores_config.json | 890 ++++++++++++++++--- 2 files changed, 769 insertions(+), 122 deletions(-) diff --git a/.github/workflows/Continuous-Integration.yml b/.github/workflows/Continuous-Integration.yml index fa839df..abee14e 100644 --- a/.github/workflows/Continuous-Integration.yml +++ b/.github/workflows/Continuous-Integration.yml @@ -27,7 +27,6 @@ jobs: id: Compile uses: stm32duino/actions/compile-examples@main with: - board-pattern: ".*NUCLEO.*" custom-config: "./extras/rtc_cores_config.json" # Use the output from the `Compile` step diff --git a/extras/rtc_cores_config.json b/extras/rtc_cores_config.json index 8b3ed50..32a8293 100644 --- a/extras/rtc_cores_config.json +++ b/extras/rtc_cores_config.json @@ -28,175 +28,823 @@ "boards": [ "AFROFLIGHT_F103CB_12M", "BLACKPILL_F103CB", + "BLACKPILL_F401CC", "BLACK_F407VG", - "BLACK_F407ZE", "BLACK_F407ZG", - "BLUEBUTTON_F103R8T", "BLUEBUTTON_F103RCT", - "BLUEPILL_F103C6", "BLUEPILL_F103CB", - "DEMO_F030F4_16M", "DEMO_F030F4_HSI", - "GENERIC_F042C4TX", "GENERIC_F042C4UX", "GENERIC_F042C6TX", "GENERIC_F042K4TX", + "BLACK_F407ZE", + "BLACK_F407ZG", + "BLUEBUTTON_F103R8T", + "BLUEBUTTON_F103RCT", + "BLUEPILL_F103C6", + "BLUEPILL_F103CB", + "DEMO_F030F4_16M", + "DEMO_F030F4_HSI", + "GENERIC_C011D6YX", + "GENERIC_C011F4PX", + "GENERIC_C011F4UX", + "GENERIC_C011F6PX", + "GENERIC_C011F6UX", + "GENERIC_C031C4TX", + "GENERIC_C031C4UX", + "GENERIC_C031C6TX", + "GENERIC_C031F4PX", + "GENERIC_F031C4TX", + "GENERIC_F031E6YX", + "GENERIC_F031F4PX", + "GENERIC_F031G4UX", + "GENERIC_F031K4UX", + "GENERIC_F042C4TX", + "GENERIC_F042C4UX", + "GENERIC_F042C6TX", + "GENERIC_F042F4PX", + "GENERIC_F042G4UX", + "GENERIC_F042K4TX", + "GENERIC_F051C4TX", "GENERIC_F051K6UX", - "GENERIC_F072C8TX", "GENERIC_F072C8UX", "GENERIC_F072CBTX", "GENERIC_F072CBUX", - "GENERIC_F072R8TX", "GENERIC_F072RBHX", "GENERIC_F072RBIX", - "GENERIC_F091RCHX", "GENERIC_F091RCTX", "GENERIC_F091RCYX", - "GENERIC_F100C4TX", "GENERIC_F100C8TX", + "GENERIC_F058R8HX", + "GENERIC_F071C8TX", + "GENERIC_F071C8UX", + "GENERIC_F071CBTX", + "GENERIC_F071CBUX", + "GENERIC_F071V8HX", + "GENERIC_F071V8TX", + "GENERIC_F071VBHX", + "GENERIC_F072C8TX", + "GENERIC_F072C8UX", + "GENERIC_F072CBTX", + "GENERIC_F072CBUX", + "GENERIC_F072R8TX", + "GENERIC_F072RBHX", + "GENERIC_F072RBTX", + "GENERIC_F072V8HX", + "GENERIC_F072V8TX", + "GENERIC_F072VBHX", + "GENERIC_F078CBTX", + "GENERIC_F078CBUX", + "GENERIC_F078RBHX", + "GENERIC_F078VBHX", + "GENERIC_F091CBTX", + "GENERIC_F091CBUX", + "GENERIC_F091CCTX", + "GENERIC_F091RBTX", + "GENERIC_F091RCHX", + "GENERIC_F091RCTX", + "GENERIC_F091VBTX", + "GENERIC_F091VCTX", + "GENERIC_F098CCTX", + "GENERIC_F098RCHX", + "GENERIC_F098RCTX", + "GENERIC_F098VCHX", + "GENERIC_F100C4TX", + "GENERIC_F100C8TX", + "GENERIC_F100R4HX", "GENERIC_F100R8TX", - "GENERIC_F103C4TX", "GENERIC_F103C6UX", "GENERIC_F103C8TX", "GENERIC_F103CBUX", - "GENERIC_F103R4HX", "GENERIC_F103R4TX", "GENERIC_F103R8HX", "GENERIC_F103R8TX", - "GENERIC_F103RCTX", "GENERIC_F103RDTX", "GENERIC_F103RCYX", "GENERIC_F103RDYX", "GENERIC_F103RFTX", - "GENERIC_F103T4UX", "GENERIC_F103T8UX", - "GENERIC_F103V8HX", "GENERIC_F103V8TX", "GENERIC_F103VBHX","GENERIC_F103VBIX", - "GENERIC_F103VCHX", "GENERIC_F103VCTX", "GENERIC_F103VDHX", "GENERIC_F103VDTX", "GENERIC_F103VEHX", + "GENERIC_F100V8TX", + "GENERIC_F100ZCTX", + "GENERIC_F100ZDTX", + "GENERIC_F101C4TX", + "GENERIC_F101R4TX", + "GENERIC_F101T4UX", + "GENERIC_F101V8TX", + "GENERIC_F101ZCTX", + "GENERIC_F101ZDTX", + "GENERIC_F103C4TX", + "GENERIC_F103C6TX", + "GENERIC_F103C8TX", + "GENERIC_F103CBTX", + "GENERIC_F103R4HX", + "GENERIC_F103R4TX", + "GENERIC_F103R8HX", + "GENERIC_F103R8TX", + "GENERIC_F103RCTX", + "GENERIC_F103RCYX", + "GENERIC_F103RDTX", + "GENERIC_F103RDYX", + "GENERIC_F103RFTX", + "GENERIC_F103T4UX", + "GENERIC_F103T8UX", + "GENERIC_F103V8HX", + "GENERIC_F103V8TX", + "GENERIC_F103VBHX", + "GENERIC_F103VBTX", + "GENERIC_F103VCHX", + "GENERIC_F103VCTX", + "GENERIC_F103VDHX", + "GENERIC_F103VDTX", + "GENERIC_F103VEHX", "GENERIC_F103VFTX", - "GENERIC_F103ZCHX", "GENERIC_F103ZCTX", "GENERIC_F103ZDHX", "GENERIC_F103ZDTX", "GENERIC_F103ZEHX", - "GENERIC_F103ZFHX", "GENERIC_F103ZFTX", "GENERIC_F103ZGHX", - "GENERIC_F207ZCTX", "GENERIC_F207ZETX", "GENERIC_F207ZFTX", - "GENERIC_F217ZETX", "GENERIC_F217ZGTX", + "GENERIC_F103ZCHX", + "GENERIC_F103ZCTX", + "GENERIC_F103ZDHX", + "GENERIC_F103ZDTX", + "GENERIC_F103ZEHX", + "GENERIC_F103ZFHX", + "GENERIC_F103ZFTX", + "GENERIC_F103ZGHX", + "GENERIC_F205RBTX", + "GENERIC_F205RCTX", + "GENERIC_F205RETX", + "GENERIC_F205REYX", + "GENERIC_F205RFTX", + "GENERIC_F205RGEX", + "GENERIC_F205RGTX", + "GENERIC_F205RGYX", + "GENERIC_F205VBTX", + "GENERIC_F205VCTX", + "GENERIC_F205VETX", + "GENERIC_F205VFTX", + "GENERIC_F205VGTX", + "GENERIC_F205ZCTX", + "GENERIC_F205ZETX", + "GENERIC_F205ZFTX", + "GENERIC_F205ZGTX", + "GENERIC_F207ICHX", + "GENERIC_F207ICTX", + "GENERIC_F207IEHX", + "GENERIC_F207IETX", + "GENERIC_F207IFHX", + "GENERIC_F207IFTX", + "GENERIC_F207IGHX", + "GENERIC_F207IGTX", + "GENERIC_F207VCTX", + "GENERIC_F207VETX", + "GENERIC_F207VFTX", + "GENERIC_F207VGTX", + "GENERIC_F207ZCTX", + "GENERIC_F207ZETX", + "GENERIC_F207ZFTX", + "GENERIC_F207ZGTX", + "GENERIC_F215RETX", + "GENERIC_F215VETX", + "GENERIC_F215ZETX", + "GENERIC_F217IEHX", + "GENERIC_F217IETX", + "GENERIC_F217IGHX", + "GENERIC_F217VETX", + "GENERIC_F217ZETX", + "GENERIC_F301C6TX", + "GENERIC_F301C8TX", + "GENERIC_F301K6TX", + "GENERIC_F301R6TX", "GENERIC_F302R6TX", + "GENERIC_F303C6TX", + "GENERIC_F303C8TX", "GENERIC_F303CBTX", "GENERIC_F303K6TX", + "GENERIC_F303K8TX", + "GENERIC_F303R6TX", + "GENERIC_F303R8TX", "GENERIC_F303RBTX", "GENERIC_F303RDTX", - "GENERIC_F303VCTX", - "GENERIC_F334K4TX", "GENERIC_F334K6TX", "GENERIC_F334K8TX", - "GENERIC_F401CBUX", "GENERIC_F401CBYX", "GENERIC_F401CCFX", "GENERIC_F401CCYX", - "GENERIC_F401CDUX", "GENERIC_F401CDYX", "GENERIC_F401CEUX", "GENERIC_F401CEYX", - "GENERIC_F401RBTX", "GENERIC_F401RCTX", "GENERIC_F401RDTX", - "GENERIC_F401VBTX", "GENERIC_F401VCTX", "GENERIC_F401VDTX", + "GENERIC_F303VBTX", + "GENERIC_F318C8TX", + "GENERIC_F334C4TX", + "GENERIC_F334C6TX", + "GENERIC_F334K4TX", + "GENERIC_F334K6TX", + "GENERIC_F334R6TX", + "GENERIC_F378RCTX", + "GENERIC_F378VCHX", + "GENERIC_F401CBUX", + "GENERIC_F401CBYX", + "GENERIC_F401CCUX", + "GENERIC_F401CCYX", + "GENERIC_F401CDUX", + "GENERIC_F401CDYX", + "GENERIC_F401CEUX", + "GENERIC_F401CEYX", + "GENERIC_F401RBTX", + "GENERIC_F401RCTX", + "GENERIC_F401RDTX", + "GENERIC_F401VBTX", + "GENERIC_F401VCTX", + "GENERIC_F401VDTX", + "GENERIC_F405RGTX", "GENERIC_F407VETX", + "GENERIC_F407VGTX", + "GENERIC_F407ZETX", "GENERIC_F407ZGTX", - "GENERIC_F410C8TX", "GENERIC_F410C8UX", - "GENERIC_F410R8IX", "GENERIC_F410R8TX", "GENERIC_F410RBIX", - "GENERIC_F411CCUX", "GENERIC_F411CCYX", "GENERIC_F411CEYX", + "GENERIC_F410C8TX", + "GENERIC_F410C8UX", + "GENERIC_F410R8IX", + "GENERIC_F410R8TX", + "GENERIC_F410RBIX", + "GENERIC_F410T8YX", + "GENERIC_F411CCUX", + "GENERIC_F411CCYX", + "GENERIC_F411CEUX", "GENERIC_F411RCTX", - "GENERIC_F412CGUX", - "GENERIC_F412REYX", "GENERIC_F412REYXP", - "GENERIC_F412RGTX", "GENERIC_F412RGYX", "GENERIC_F412RGYXP", + "GENERIC_F412CEUX", + "GENERIC_F412RETX", + "GENERIC_F412REYX", + "GENERIC_F412REYXP", + "GENERIC_F412RGTX", + "GENERIC_F412RGYX", + "GENERIC_F412ZEJX", + "GENERIC_F412ZETX", + "GENERIC_F412ZGJX", + "GENERIC_F413CGUX", "GENERIC_F413CHUX", + "GENERIC_F413RGTX", "GENERIC_F413RHTX", - "GENERIC_F413ZGJX", "GENERIC_F413ZGTX", "GENERIC_F413ZHJX", - "GENERIC_F415RGTX", - "GENERIC_F417VETX", "GENERIC_F417VGTX", - "GENERIC_F417ZETX", "GENERIC_F417ZGTX", - "GENERIC_F423CHUX", - "GENERIC_F423RHTX", - "GENERIC_F423ZHJX", "GENERIC_F423ZHTX", - "GENERIC_F427ZGTX", "GENERIC_F427ZITX", - "GENERIC_F429ZETX", "GENERIC_F429ZGTX", "GENERIC_F429ZGYX", "GENERIC_F429ZIYX", - "GENERIC_F437ZGTX", "GENERIC_F437ZITX", - "GENERIC_F439ZGTX", "GENERIC_F439ZGYX", "GENERIC_F439ZITX", "GENERIC_F439ZIYX", + "GENERIC_F413ZGJX", + "GENERIC_F413ZGTX", + "GENERIC_F413ZHJX", + "GENERIC_F413ZHTX", + "GENERIC_F417VETX", + "GENERIC_F417ZETX", + "GENERIC_F423ZHJX", + "GENERIC_F427ZGTX", + "GENERIC_F427ZITX", + "GENERIC_F429ZETX", + "GENERIC_F429ZGTX", + "GENERIC_F429ZGYX", + "GENERIC_F429ZITX", + "GENERIC_F429ZIYX", + "GENERIC_F437ZGTX", + "GENERIC_F437ZITX", + "GENERIC_F439ZGTX", + "GENERIC_F439ZGYX", + "GENERIC_F439ZITX", "GENERIC_F446RCTX", - "GENERIC_F446VETX", - "GENERIC_F745ZETX", "GENERIC_F745ZGTX", - "GENERIC_F746BETX", "GENERIC_F746BGTX", "GENERIC_F746NEHX", - "GENERIC_F746ZETX", "GENERIC_F746ZEYX", "GENERIC_F746ZGYX", + "GENERIC_F446VCTX", + "GENERIC_F446ZCHX", + "GENERIC_F446ZCJX", + "GENERIC_F446ZCTX", + "GENERIC_F446ZEHX", + "GENERIC_F446ZEJX", + "GENERIC_F722RCTX", + "GENERIC_F722RETX", + "GENERIC_F722ZCTX", + "GENERIC_F722ZETX", + "GENERIC_F730R8TX", + "GENERIC_F745ZETX", + "GENERIC_F745ZGTX", + "GENERIC_F746BETX", + "GENERIC_F746BGTX", + "GENERIC_F746NEHX", + "GENERIC_F746NGHX", + "GENERIC_F746ZETX", + "GENERIC_F746ZEYX", + "GENERIC_F746ZGTX", + "GENERIC_F746ZGYX", "GENERIC_F750N8HX", "GENERIC_F750Z8TX", - "GENERIC_F756BGTX", "GENERIC_F756NGHX", - "GENERIC_F756ZGTX", "GENERIC_F756ZGYX", - "GENERIC_F765VGHX", "GENERIC_F765VIHX", "GENERIC_F765VITX", - "GENERIC_F767VGHX", "GENERIC_F767VGTX", "GENERIC_F767VIHX", "GENERIC_F767VITX", - "GENERIC_F765ZGTX", "GENERIC_F765ZITX", + "GENERIC_F756BGTX", + "GENERIC_F756ZGTX", + "GENERIC_F765IGKX", + "GENERIC_F765IGTX", + "GENERIC_F765IIKX", + "GENERIC_F765IITX", + "GENERIC_F765VGHX", + "GENERIC_F765VGTX", + "GENERIC_F765VIHX", + "GENERIC_F765VITX", + "GENERIC_F765ZGTX", + "GENERIC_F765ZITX", + "GENERIC_F767IGKX", + "GENERIC_F767IGTX", + "GENERIC_F767IIKX", + "GENERIC_F767IITX", + "GENERIC_F767VGHX", + "GENERIC_F767VGTX", + "GENERIC_F767VIHX", + "GENERIC_F767VITX", "GENERIC_F767ZGTX", - "GENERIC_F777VIHX", "GENERIC_F777VITX", - "GENERIC_F777ZITX", + "GENERIC_F767ZITX", + "GENERIC_F777IIKX", + "GENERIC_F777VIHX", + "GENERIC_G030C6TX", "GENERIC_G030K6TX", - "GENERIC_G031J4MX", "GENERIC_G031J6MX", - "GENERIC_G031K4TX", "GENERIC_G031K4UX", "GENERIC_G031K6TX", "GENERIC_G031K6UX", "GENERIC_G031K8TX", "GENERIC_G031K8UX", - "GENERIC_G041K6TX", "GENERIC_G041K6UX", "GENERIC_G041K8UX", - "GENERIC_G071R6TX", "GENERIC_G071R8TX", "GENERIC_G071RBIX", "GENERIC_G071RBTX", "GENERIC_G081RBIX", - "GENERIC_G0B1RBTX", "GENERIC_G0B1RCTX", "GENERIC_G0C1RCTX", "GENERIC_G0C1RETX", - "GENERIC_G431K6TX", "GENERIC_G431K6UX", "GENERIC_G431K8TX", "GENERIC_G431K8UX", "GENERIC_G431KBTX", "GENERIC_G431KBUX", + "GENERIC_G031C4TX", + "GENERIC_G031C4UX", + "GENERIC_G031C6TX", + "GENERIC_G031C6UX", + "GENERIC_G031C8TX", + "GENERIC_G031C8UX", + "GENERIC_G031F4PX", + "GENERIC_G031F6PX", + "GENERIC_G031F8PX", + "GENERIC_G031G4UX", + "GENERIC_G031G6UX", + "GENERIC_G031G8UX", + "GENERIC_G031J4MX", + "GENERIC_G031J6MX", + "GENERIC_G031K4TX", + "GENERIC_G031K4UX", + "GENERIC_G031K6TX", + "GENERIC_G031K6UX", + "GENERIC_G031K8TX", + "GENERIC_G031K8UX", + "GENERIC_G031Y8YX", + "GENERIC_G041C6TX", + "GENERIC_G041C6UX", + "GENERIC_G041C8TX", + "GENERIC_G041F6PX", + "GENERIC_G041F8PX", + "GENERIC_G041G6UX", + "GENERIC_G041K6TX", + "GENERIC_G041K6UX", + "GENERIC_G041K8TX", + "GENERIC_G050C6TX", + "GENERIC_G050K6TX", + "GENERIC_G051C6TX", + "GENERIC_G051C6UX", + "GENERIC_G051C8TX", + "GENERIC_G051C8UX", + "GENERIC_G051F6PX", + "GENERIC_G051F8PX", + "GENERIC_G051F8YX", + "GENERIC_G051G6UX", + "GENERIC_G051G8UX", + "GENERIC_G051K6TX", + "GENERIC_G051K6UX", + "GENERIC_G051K8TX", + "GENERIC_G051K8UX", + "GENERIC_G061C6TX", + "GENERIC_G061C6UX", + "GENERIC_G061C8TX", + "GENERIC_G061F6PX", + "GENERIC_G061F8PX", + "GENERIC_G061G6UX", + "GENERIC_G061K6TX", + "GENERIC_G061K6UX", + "GENERIC_G061K8TX", + "GENERIC_G071C6TX", + "GENERIC_G071C6UX", + "GENERIC_G071C8TX", + "GENERIC_G071C8UX", + "GENERIC_G071CBTX", + "GENERIC_G071CBUX", + "GENERIC_G071EBYX", + "GENERIC_G071G6UX", + "GENERIC_G071G8UX", + "GENERIC_G071G8UXN", + "GENERIC_G071GBUX", + "GENERIC_G071GBUXN", + "GENERIC_G071K6TX", + "GENERIC_G071K6UX", + "GENERIC_G071K8TX", + "GENERIC_G071K8UX", + "GENERIC_G071KBTX", + "GENERIC_G071KBUX", + "GENERIC_G071R6TX", + "GENERIC_G071R8TX", + "GENERIC_G071RBIX", + "GENERIC_G071RBTX", + "GENERIC_G081CBTX", + "GENERIC_G081KBTX", + "GENERIC_G081RBIX", + "GENERIC_G0B1CBTX", + "GENERIC_G0B1CBUX", + "GENERIC_G0B1CCTX", + "GENERIC_G0B1CCUX", + "GENERIC_G0B1CETX", + "GENERIC_G0B1CEUX", + "GENERIC_G0B1KBTX", + "GENERIC_G0B1KBUX", + "GENERIC_G0B1KCTX", + "GENERIC_G0B1KCUX", + "GENERIC_G0B1KETX", + "GENERIC_G0B1KEUX", + "GENERIC_G0B1MBTX", + "GENERIC_G0B1MCTX", + "GENERIC_G0B1METX", + "GENERIC_G0B1NEYX", + "GENERIC_G0B1RBTX", + "GENERIC_G0B1RCTX", + "GENERIC_G0B1RETX", + "GENERIC_G0B1VBIX", + "GENERIC_G0B1VBTX", + "GENERIC_G0B1VCIX", + "GENERIC_G0B1VCTX", + "GENERIC_G0B1VEIX", + "GENERIC_G0B1VETX", + "GENERIC_G0C1CCTX", + "GENERIC_G0C1CCUX", + "GENERIC_G0C1CETX", + "GENERIC_G0C1KCTX", + "GENERIC_G0C1KCUX", + "GENERIC_G0C1KETX", + "GENERIC_G0C1MCTX", + "GENERIC_G0C1RCTX", + "GENERIC_G0C1VCIX", + "GENERIC_G0C1VCTX", + "GENERIC_G0C1VEIX", + "GENERIC_G431C6TX", + "GENERIC_G431C6UX", + "GENERIC_G431C8TX", + "GENERIC_G431C8UX", + "GENERIC_G431CBTX", + "GENERIC_G431CBUX", + "GENERIC_G431K6TX", + "GENERIC_G431K6UX", + "GENERIC_G431K8TX", + "GENERIC_G431K8UX", + "GENERIC_G431KBTX", + "GENERIC_G431KBUX", + "GENERIC_G431M6TX", + "GENERIC_G431M8TX", + "GENERIC_G431MBTX", + "GENERIC_G431R6IX", + "GENERIC_G431R6TX", + "GENERIC_G431R8IX", + "GENERIC_G431R8TX", + "GENERIC_G431RBIX", + "GENERIC_G431RBTX", + "GENERIC_G431V6TX", + "GENERIC_G431V8TX", + "GENERIC_G431VBTX", "GENERIC_G441KBTX", - "GENERIC_G431R6IX", "GENERIC_G431R6TX", "GENERIC_G431R8IX", "GENERIC_G431R8TX", "GENERIC_G431RBIX", "GENERIC_G431RBTX", "GENERIC_G441RBIX", - "GENERIC_G473RBTX", "GENERIC_G473RCTX", "GENERIC_G473RETX", - "GENERIC_G474RBTX", "GENERIC_G474RCTX", "GENERIC_G474RETX", + "GENERIC_G471CCTX", + "GENERIC_G471MCTX", + "GENERIC_G471QCTX", + "GENERIC_G471RCTX", + "GENERIC_G471VCHX", + "GENERIC_G471VCIX", + "GENERIC_G471VCTX", + "GENERIC_G471VEHX", + "GENERIC_G471VEIX", + "GENERIC_G473CBTX", + "GENERIC_G473CCTX", + "GENERIC_G473CETX", + "GENERIC_G473MBTX", + "GENERIC_G473MCTX", + "GENERIC_G473METX", + "GENERIC_G473PBIX", + "GENERIC_G473PCIX", + "GENERIC_G473PEIX", + "GENERIC_G473QBTX", + "GENERIC_G473QCTX", + "GENERIC_G473QETX", + "GENERIC_G473RBTX", + "GENERIC_G473RCTX", + "GENERIC_G473RETX", + "GENERIC_G473VBHX", + "GENERIC_G473VBTX", + "GENERIC_G473VCHX", + "GENERIC_G473VCTX", + "GENERIC_G473VEHX", + "GENERIC_G473VETX", + "GENERIC_G474CBTX", + "GENERIC_G474CCTX", + "GENERIC_G474CETX", + "GENERIC_G474MBTX", + "GENERIC_G474MCTX", + "GENERIC_G474METX", + "GENERIC_G474PBIX", + "GENERIC_G474PCIX", + "GENERIC_G474PEIX", + "GENERIC_G474QBTX", + "GENERIC_G474QCTX", + "GENERIC_G474QETX", + "GENERIC_G474RBTX", + "GENERIC_G474RCTX", + "GENERIC_G474RETX", + "GENERIC_G474VBHX", + "GENERIC_G474VBTX", + "GENERIC_G474VCHX", + "GENERIC_G474VCTX", + "GENERIC_G474VEHX", + "GENERIC_G474VETX", + "GENERIC_G483CETX", + "GENERIC_G483METX", + "GENERIC_G483PEIX", + "GENERIC_G483QETX", "GENERIC_G483RETX", - "GENERIC_H742IGKX", "GENERIC_H742IIKX", "GENERIC_H742IGTX", "GENERIC_H742IITX", - "GENERIC_H742VGHX", "GENERIC_H742VIHX", "GENERIC_H742VGTX", "GENERIC_H742VITX", - "GENERIC_H742ZGTX", "GENERIC_H742ZITX", - "GENERIC_H743VGHX", "GENERIC_H743VIHX", "GENERIC_H743VITX", + "GENERIC_G483VEHX", + "GENERIC_G483VETX", + "GENERIC_G484VEHX", + "GENERIC_G491CCTX", + "GENERIC_G491CETX", + "GENERIC_G491KCUX", + "GENERIC_G491KEUX", + "GENERIC_G491MCSX", + "GENERIC_G491MCTX", + "GENERIC_G491MESX", + "GENERIC_G491METX", + "GENERIC_G491RCIX", + "GENERIC_G491RCTX", + "GENERIC_G491REIX", + "GENERIC_G491RETX", + "GENERIC_G491REYX", + "GENERIC_G491VCTX", + "GENERIC_G491VETX", + "GENERIC_G4A1MESX", + "GENERIC_G4A1REIX", + "GENERIC_G4A1RETX", + "GENERIC_H563ZGTX", + "GENERIC_H723ZETX", + "GENERIC_H723ZGTX", + "GENERIC_H730ZBTX", + "GENERIC_H742IGKX", + "GENERIC_H742IGTX", + "GENERIC_H742IIKX", + "GENERIC_H742IITX", + "GENERIC_H742VGHX", + "GENERIC_H742VGTX", + "GENERIC_H742VIHX", + "GENERIC_H742VITX", + "GENERIC_H742ZGTX", + "GENERIC_H742ZITX", + "GENERIC_H743IGKX", + "GENERIC_H743IGTX", + "GENERIC_H743IIKX", + "GENERIC_H743IITX", + "GENERIC_H743VGHX", + "GENERIC_H743VGTX", + "GENERIC_H743VIHX", + "GENERIC_H743VITX", "GENERIC_H743ZGTX", - "GENERIC_H747AGIX", "GENERIC_H747AIIX", "GENERIC_H747IGTX", "GENERIC_H747IITX", - "GENERIC_H750IBTX", "GENERIC_H750VBTX", "GENERIC_H750ZBTX", - "GENERIC_H753VIHX", "GENERIC_H753VITX", + "GENERIC_H743ZITX", + "GENERIC_H747AGIX", + "GENERIC_H747AIIX", + "GENERIC_H747IGTX", + "GENERIC_H747IITX", + "GENERIC_H750IBKX", + "GENERIC_H750IBTX", + "GENERIC_H750VBTX", + "GENERIC_H750ZBTX", + "GENERIC_H753IIKX", + "GENERIC_H753VIHX", "GENERIC_H753ZITX", - "GENERIC_H757AIIX", "GENERIC_H757IITX", - "GENERIC_H743IGKX", "GENERIC_H743IGTX", "GENERIC_H743IIKX", "GENERIC_H743IITX", "GENERIC_H753IIKX", "GENERIC_H753IITX", - "GENERIC_L010RBTX", + "GENERIC_H757AIIX", + "GENERIC_L010F4PX", + "GENERIC_L010K4TX", + "GENERIC_L011D3PX", + "GENERIC_L011D4PX", + "GENERIC_L011E3YX", + "GENERIC_L011F3PX", + "GENERIC_L011F3UX", + "GENERIC_L011F4PX", + "GENERIC_L011F4UX", + "GENERIC_L011G3UX", + "GENERIC_L011G4UX", + "GENERIC_L011K3TX", + "GENERIC_L011K3UX", + "GENERIC_L011K4TX", + "GENERIC_L011K4UX", + "GENERIC_L031C4TX", + "GENERIC_L031C4UX", + "GENERIC_L031C6TX", + "GENERIC_L031C6UX", + "GENERIC_L031E4YX", + "GENERIC_L031E6YX", + "GENERIC_L031F4PX", + "GENERIC_L031F6PX", + "GENERIC_L031G4UX", + "GENERIC_L031G6UX", "GENERIC_L031K4TX", - "GENERIC_L041K6TX", - "GENERIC_L051C6TX", "GENERIC_L051C6UX", "GENERIC_L051C8UX", - "GENERIC_L052R6TX", "GENERIC_L052R8TX", - "GENERIC_L053R6TX", "GENERIC_L063R8TX", - "GENERIC_L072CZEX", "GENERIC_L072CZYX", + "GENERIC_L031K6TX", + "GENERIC_L041C4TX", + "GENERIC_L041C6TX", + "GENERIC_L051C6TX", + "GENERIC_L051C6UX", + "GENERIC_L051C8TX", + "GENERIC_L052C6TX", + "GENERIC_L052C6UX", + "GENERIC_L052C8TX", + "GENERIC_L052C8UX", + "GENERIC_L052K6TX", + "GENERIC_L052K8TX", + "GENERIC_L052R6HX", + "GENERIC_L052R6TX", + "GENERIC_L052R8HX", + "GENERIC_L052R8TX", + "GENERIC_L052T6YX", + "GENERIC_L052T8YX", + "GENERIC_L053C6TX", + "GENERIC_L053C6UX", + "GENERIC_L053C8TX", + "GENERIC_L053C8UX", + "GENERIC_L053R6HX", + "GENERIC_L053R6TX", + "GENERIC_L053R8TX", + "GENERIC_L062C8UX", + "GENERIC_L063C8TX", + "GENERIC_L072CBTX", + "GENERIC_L072CBUX", + "GENERIC_L072CBYX", + "GENERIC_L072CZEX", + "GENERIC_L072CZTX", + "GENERIC_L072CZUX", + "GENERIC_L072CZYX", + "GENERIC_L072KBTX", + "GENERIC_L072KBUX", "GENERIC_L072KZTX", - "GENERIC_L072RBTX", "GENERIC_L072RZTX", + "GENERIC_L072KZUX", + "GENERIC_L072RBHX", + "GENERIC_L072RBIX", + "GENERIC_L072RBTX", + "GENERIC_L072RZHX", + "GENERIC_L072RZIX", + "GENERIC_L072RZTX", + "GENERIC_L072V8IX", + "GENERIC_L072V8TX", + "GENERIC_L072VBIX", + "GENERIC_L072VBTX", + "GENERIC_L072VZIX", + "GENERIC_L072VZTX", + "GENERIC_L073CBTX", + "GENERIC_L073CBUX", + "GENERIC_L073CZTX", + "GENERIC_L073CZUX", "GENERIC_L073CZYX", + "GENERIC_L073RBHX", "GENERIC_L073RBTX", - "GENERIC_L082CZYX", - "GENERIC_L082KBTX", "GENERIC_L082KZTX", - "GENERIC_L083RBTX", "GENERIC_L083RZTX", - "GENERIC_L100C6UX", "GENERIC_L100C6UXA", - "GENERIC_L151C6TX", "GENERIC_L151C6TXA", "GENERIC_L151C6UX", "GENERIC_L151C6UXA", "GENERIC_L151C8TX", "GENERIC_L151C8TXA", - "GENERIC_L151C8UX", "GENERIC_L151C8UXA", "GENERIC_L151CBTX", "GENERIC_L151CBUX", "GENERIC_L151CBUXA", - "GENERIC_L152C6TX", "GENERIC_L152C6TXA", "GENERIC_L152C6UX", "GENERIC_L152C6UXA", "GENERIC_L152C8TX", "GENERIC_L152C8TXA", - "GENERIC_L152C8UX", "GENERIC_L152C8UXA", "GENERIC_L152CBTX", "GENERIC_L152CBTXA", "GENERIC_L152CBUX", "GENERIC_L152CBUXA", - "GENERIC_L151RETX", "GENERIC_L162RETX", - "GENERIC_L412K8TX", "GENERIC_L412K8UX", "GENERIC_L412KBUX", - "GENERIC_L422KBTX", "GENERIC_L422KBUX", + "GENERIC_L073RZHX", + "GENERIC_L073RZIX", + "GENERIC_L073RZTX", + "GENERIC_L073V8IX", + "GENERIC_L073V8TX", + "GENERIC_L073VBIX", + "GENERIC_L073VBTX", + "GENERIC_L073VZIX", + "GENERIC_L073VZTX", + "GENERIC_L082CZUX", + "GENERIC_L082KBTX", + "GENERIC_L082KBUX", + "GENERIC_L083CBTX", + "GENERIC_L083CZTX", + "GENERIC_L083RBHX", + "GENERIC_L083RBTX", + "GENERIC_L083V8IX", + "GENERIC_L083VBIX", + "GENERIC_L083VBTX", + "GENERIC_L083VZIX", + "GENERIC_L083VZTX", + "GENERIC_L100C6UX", + "GENERIC_L100C6UXA", + "GENERIC_L151C6TX", + "GENERIC_L151C6TXA", + "GENERIC_L151C6UX", + "GENERIC_L151C6UXA", + "GENERIC_L151C8TX", + "GENERIC_L151C8TXA", + "GENERIC_L151C8UX", + "GENERIC_L151C8UXA", + "GENERIC_L151CBTX", + "GENERIC_L151CBTXA", + "GENERIC_L151CBUX", + "GENERIC_L151CBUXA", + "GENERIC_L151RETX", + "GENERIC_L151ZDTX", + "GENERIC_L152C6TX", + "GENERIC_L152C6TXA", + "GENERIC_L152C6UX", + "GENERIC_L152C6UXA", + "GENERIC_L152C8TX", + "GENERIC_L152C8TXA", + "GENERIC_L152C8UX", + "GENERIC_L152C8UXA", + "GENERIC_L152CBTX", + "GENERIC_L152CBTXA", + "GENERIC_L152CBUX", + "GENERIC_L152RETX", + "GENERIC_L152ZDTX", + "GENERIC_L412K8TX", + "GENERIC_L412K8UX", + "GENERIC_L412KBTX", + "GENERIC_L412KBUX", + "GENERIC_L422KBTX", + "GENERIC_L431RBIX", + "GENERIC_L431RBTX", + "GENERIC_L431RBYX", + "GENERIC_L431RCIX", + "GENERIC_L431RCTX", "GENERIC_L432KBUX", - "GENERIC_L433CBTX", "GENERIC_L433CCTX", "GENERIC_L433CBUX", - "GENERIC_L442KCUX", - "GENERIC_L443CCTX", "GENERIC_L443CCUX", - "GENERIC_L452RCIX", "GENERIC_L452RCTX", "GENERIC_L452RCYX", "GENERIC_L452REIX", "GENERIC_L452REYX", - "GENERIC_L462REIX", "GENERIC_L462RETX", "GENERIC_L462REYX", - "GENERIC_L475RCTX", "GENERIC_L475RETX", "GENERIC_L475RGTX", - "GENERIC_L476RCTX", "GENERIC_L476RETX", - "GENERIC_L486RGTX", - "GENERIC_L475VCTX", "GENERIC_L475VGTX", - "GENERIC_L476VCTX", "GENERIC_L476VETX", "GENERIC_L476VGTX", - "GENERIC_L486VGTX", + "GENERIC_L432KCUX", + "GENERIC_L433CBTX", + "GENERIC_L433CBUX", + "GENERIC_L433CCTX", + "GENERIC_L433CCUX", + "GENERIC_L433RBIX", + "GENERIC_L433RBTX", + "GENERIC_L433RBYX", + "GENERIC_L433RCIX", + "GENERIC_L433RCTX", + "GENERIC_L433RCYX", + "GENERIC_L443CCTX", + "GENERIC_L443RCIX", + "GENERIC_L443RCTX", + "GENERIC_L452RCIX", + "GENERIC_L452RCTX", + "GENERIC_L452RCYX", + "GENERIC_L452REIX", + "GENERIC_L452RETX", + "GENERIC_L452REYX", + "GENERIC_L452REYXP", + "GENERIC_L462REIX", + "GENERIC_L462RETX", + "GENERIC_L475RCTX", + "GENERIC_L475RETX", + "GENERIC_L475RGTX", + "GENERIC_L475VCTX", + "GENERIC_L475VETX", + "GENERIC_L475VGTX", + "GENERIC_L476RCTX", + "GENERIC_L476RETX", + "GENERIC_L476RGTX", + "GENERIC_L476VCTX", + "GENERIC_L476VETX", + "GENERIC_L476VGTX", "GENERIC_L496ZETX", - "GENERIC_L4A6ZGTX", - "GENERIC_L4A6ZGTXP", - "GENERIC_L4R5VGTX", "GENERIC_L4R5VITX", + "GENERIC_L496ZGTX", + "GENERIC_L496ZGTXP", + "GENERIC_L4R5VGTX", + "GENERIC_L4R5VITX", + "GENERIC_L4R5ZGTX", "GENERIC_L4R5ZGYX", + "GENERIC_L4R5ZITX", + "GENERIC_L4R5ZIYX", "GENERIC_L4R7VITX", - "GENERIC_L4S7VITX", - "GENERIC_L4R5ZGTX", "GENERIC_L4R5ZITX", "GENERIC_L4R7ZITX", - "GENERIC_L4R9ZGJX", "GENERIC_L4R9ZGYX", "GENERIC_L4R9ZIYX", + "GENERIC_L4R9ZGJX", + "GENERIC_L4R9ZGYX", + "GENERIC_L4R9ZIJX", + "GENERIC_L4R9ZIYX", + "GENERIC_L4S5VITX", + "GENERIC_L4S5ZITX", "GENERIC_L4S5ZIYX", - "GENERIC_L4S7ZITX", - "GENERIC_L4S9ZIJX", "GENERIC_L4S9ZIYX", "GENERIC_L552ZCTXQ", - "GENERIC_L562ZETXQ", - "GENERIC_U575AGIXQ", "GENERIC_U575AIIXQ", "GENERIC_U575ZGTXQ", "GENERIC_U585ZETXQ", - "GENERIC_WB55CCUX", "GENERIC_WB55CGUX", - "GENERIC_WB55RCVX", "GENERIC_WB55REVX", + "GENERIC_L552ZETXQ", + "GENERIC_MP153AACX", + "GENERIC_MP153CACX", + "GENERIC_MP153DACX", + "GENERIC_MP153FACX", + "GENERIC_MP157AACX", + "GENERIC_MP157CACX", + "GENERIC_MP157DACX", + "GENERIC_U575AGIXQ", + "GENERIC_U575AIIXQ", + "GENERIC_U575ZGTXQ", + "GENERIC_U575ZITXQ", + "GENERIC_WB35CCUXA", + "GENERIC_WB35CEUXA", + "GENERIC_WB55CCUX", + "GENERIC_WB55CEUX", + "GENERIC_WB55RCVX", + "GENERIC_WB55REVX", "GENERIC_WL54CCUX", - "GENERIC_WL54JCIX", "GENERIC_WLE4J8IX", "GENERIC_WLE4JBIX", - "GENERIC_WLE4C8UX", "GENERIC_WLE4CBUX", "GENERIC_WLE4CCUX", + "GENERIC_WL54JCIX", + "GENERIC_WL55CCUX", + "GENERIC_WL55JCIX", + "GENERIC_WLE4C8UX", + "GENERIC_WLE4CBUX", + "GENERIC_WLE4CCUX", + "GENERIC_WLE4J8IX", + "GENERIC_WLE4JBIX", "GENERIC_WLE4JCIX", - "GENERIC_WLE5C8UX", "GENERIC_WLE5CBUX", "GENERIC_WLE5CCUX", - "GENERIC_WLE5J8IX", "GENERIC_WLE5JBIX", "GENERIC_WLE5JCIX", + "GENERIC_WLE5C8UX", + "GENERIC_WLE5CBUX", + "GENERIC_WLE5J8IX", + "GENERIC_WLE5JBIX", "NUCLEO_H743ZI", "NUCLEO_L496ZG", "NUCLEO_L4R5ZI", - "PYBSTICK26_DUINO", "PYBSTICK26_LITE", "PYBSTICK26_STD", + "PYBSTICK26_DUINO", + "PYBSTICK26_LITE", + "PYBSTICK26_STD", "RAK811_TRACKERA" ] - } , + }, { - "pattern": "RTC_Seconds", - "applicable": false, - "boards": [ "NUCLEO_C031C6", "NUCLEO_F030R8", "NUCLEO_F031K6", "NUCLEO_F042K6"] + "pattern": "^[^F][^1].*", + "applicable": true, + "boards": [ + "NUCLEO_C031C6", + "NUCLEO_F091RC", + "NUCLEO_F103RB", + "NUCLEO_F207ZG", + "NUCLEO_F303RE", + "NUCLEO_F429ZI", + "NUCLEO_F767ZI", + "NUCLEO_G071RB", + "NUCLEO_G0B1RE", + "NUCLEO_G474RE", + "NUCLEO_H563ZI", + "NUCLEO_H743ZI2", + "NUCLEO_L073RZ", + "NUCLEO_L152RE", + "NUCLEO_L452REP", + "NUCLEO_L4R5ZI_P", + "NUCLEO_L552ZE_Q", + "NUCLEO_U575ZI_Q", + "NUCLEO_WB15CC", + "NUCLEO_WL55JC1" + ] }, { "pattern": "F1RTCDateRetention", "applicable": true, "boards": [ "NUCLEO_F103RB"] + }, + { + "pattern": "RTC_Seconds", + "applicable": false, + "boards": [ + "NUCLEO_C031C6" + ] } ] } From 2d11284fa65025b38a1427adc3913b1ecbfdd2b2 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 8 Sep 2023 14:24:44 +0200 Subject: [PATCH 03/23] fix: code syntax for better readability Signed-off-by: Frederic Pillon --- src/rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtc.c b/src/rtc.c index 903ca7c..795bdd8 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -390,7 +390,7 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #else if (!LL_RTC_IsActiveFlag_INITS(RtcHandle.Instance) || reset) { // RTC needs initialization - RtcHandle.Init.HourFormat = format == HOUR_FORMAT_12 ? RTC_HOURFORMAT_12 : RTC_HOURFORMAT_24; + RtcHandle.Init.HourFormat = (format == HOUR_FORMAT_12) ? RTC_HOURFORMAT_12 : RTC_HOURFORMAT_24; RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; From 9acf6f7aed3e9987fa881ededfb2cd178883c8a8 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 12 Sep 2023 18:37:58 +0200 Subject: [PATCH 04/23] fix: init RtcHandle.instance else this prevent isConfigured(void) to return correct value. Signed-off-by: Frederic Pillon --- src/rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtc.c b/src/rtc.c index 795bdd8..2cd5440 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -56,7 +56,7 @@ extern "C" { /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ -static RTC_HandleTypeDef RtcHandle = {0}; +static RTC_HandleTypeDef RtcHandle = {.Instance = RTC}; static voidCallbackPtr RTCUserCallback = NULL; static void *callbackUserData = NULL; #ifdef RTC_ALARM_B From 9d07ee5d5865488788aa32c2c2dd658fa4cda9f6 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 9 May 2023 14:41:30 +0200 Subject: [PATCH 05/23] fix: harden prediv management vs clock config prediv was not properly computed and some misalignment's could occur depending of the RTC state at init. Signed-off-by: Frederic Pillon --- README.md | 4 +- src/STM32RTC.cpp | 50 +++------ src/STM32RTC.h | 15 ++- src/rtc.c | 284 ++++++++++++++++++++++++----------------------- src/rtc.h | 12 +- 5 files changed, 174 insertions(+), 191 deletions(-) diff --git a/README.md b/README.md index dc9fdd6..7dd0ffd 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ _RTC clock source_ * **`void setClockSource(Source_Clock source)`** : this function must be called before `begin()`. _RTC Asynchronous and Synchronous prescaler_ -* **`void getPrediv(int8_t *predivA, int16_t *predivS)`** : get (a)synchronous prescaler values if set else computed ones for the current clock source. -* **`void setPrediv(int8_t predivA, int16_t predivS)`** : set (a)synchronous prescaler values. This function must be called before `begin()`. Use -1 to reset value and use computed ones. Those values have to match the following conditions: **_1Hz = RTC CLK source / ((predivA + 1) * (predivS + 1))_** +* **`void getPrediv(uint32_t *predivA, uint32_t *predivS)`** : get (a)synchronous prescaler values if set else computed ones for the current clock source. +* **`void setPrediv(uint32_t predivA, uint32_t predivS)`** : set (a)synchronous prescaler values. This function must be called before `begin()`. Use `(PREDIVA_MAX + 1)` and `(PREDIVS_MAX +1)` to reset value and use computed ones. Those values have to match the following conditions: **_1Hz = RTC CLK source / ((predivA + 1) * (predivS + 1))_** _SubSeconds management_ * **`uint32_t getSubSeconds(void)`** diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 0c8bf9d..daf028c 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -103,7 +103,7 @@ void STM32RTC::begin(bool resetTime, Hour_Format format) */ void STM32RTC::end(void) { - RTC_DeInit(); + RTC_DeInit(true); _timeSet = false; } @@ -131,60 +131,38 @@ void STM32RTC::setClockSource(Source_Clock source) } } -#if defined(STM32F1xx) -/** - * @brief get user asynchronous prescaler value for the current clock source. - * @param predivA: pointer to the current Asynchronous prescaler value - * @param dummy : not used (kept for compatibility reason) - * @retval None - */ -void STM32RTC::getPrediv(uint32_t *predivA, int16_t *dummy) -{ - UNUSED(dummy); - RTC_getPrediv(predivA); -} -#else /** * @brief get user (a)synchronous prescaler values if set else computed * ones for the current clock source. * @param predivA: pointer to the current Asynchronous prescaler value - * @param predivS: pointer to the current Synchronous prescaler value + * @param predivS: pointer to the current Synchronous prescaler value, + * not used for STM32F1xx series. * @retval None */ -void STM32RTC::getPrediv(int8_t *predivA, int16_t *predivS) +void STM32RTC::getPrediv(uint32_t *predivA, uint32_t *predivS) { - if ((predivA != nullptr) && (predivS != nullptr)) { + if ((predivA != nullptr) +#if !defined(STM32F1xx) + && (predivS != nullptr) +#endif /* STM32F1xx */ + ) { RTC_getPrediv(predivA, predivS); } } -#endif /* STM32F1xx */ -#if defined(STM32F1xx) -/** - * @brief set user asynchronous prescalers value. - * @note This method must be called before begin(). - * @param predivA: Asynchronous prescaler value. Reset value: RTC_AUTO_1_SECOND - * @param dummy : not used (kept for compatibility reason) - * @retval None - */ -void STM32RTC::setPrediv(uint32_t predivA, int16_t dummy) -{ - UNUSED(dummy); - RTC_setPrediv(predivA); -} -#else /** * @brief set user (a)synchronous prescalers value. * @note This method must be called before begin(). - * @param predivA: Asynchronous prescaler value. Reset value: -1 - * @param predivS: Synchronous prescaler value. Reset value: -1 + * @param predivA: Asynchronous prescaler value. + * @note Reset value: RTC_AUTO_1_SECOND for STM32F1xx series, else (PREDIVA_MAX + 1) + * @param predivS: Synchronous prescaler value. + * @note Reset value: (PREDIVS_MAX + 1), not used for STM32F1xx series. * @retval None */ -void STM32RTC::setPrediv(int8_t predivA, int16_t predivS) +void STM32RTC::setPrediv(uint32_t predivA, uint32_t predivS) { RTC_setPrediv(predivA, predivS); } -#endif /* STM32F1xx */ /** * @brief enable the RTC alarm. diff --git a/src/STM32RTC.h b/src/STM32RTC.h index b8be12b..e89cea8 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -212,13 +212,9 @@ class STM32RTC { void setAlarmEpoch(time_t ts, Alarm_Match match, Alarm name); void setAlarmEpoch(time_t ts, Alarm_Match match = MATCH_DHHMMSS, uint32_t subSeconds = 0, Alarm name = ALARM_A); -#if defined(STM32F1xx) - void getPrediv(uint32_t *predivA, int16_t *dummy = nullptr); - void setPrediv(uint32_t predivA, int16_t dummy = 0); -#else - void getPrediv(int8_t *predivA, int16_t *predivS); - void setPrediv(int8_t predivA, int16_t predivS); -#endif /* STM32F1xx */ + void getPrediv(uint32_t *predivA, uint32_t *predivS); + void setPrediv(uint32_t predivA, uint32_t predivS); + bool isConfigured(void) { return RTC_IsConfigured(); @@ -232,7 +228,10 @@ class STM32RTC { friend class STM32LowPower; private: - STM32RTC(void): _clockSource(LSI_CLOCK) {} + STM32RTC(void): _clockSource(LSI_CLOCK) + { + setClockSource(_clockSource); + } static bool _timeSet; diff --git a/src/rtc.c b/src/rtc.c index 2cd5440..2e78997 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -66,14 +66,16 @@ static void *callbackUserDataB = NULL; static voidCallbackPtr RTCSecondsIrqCallback = NULL; static sourceClock_t clkSrc = LSI_CLOCK; +static uint32_t clkVal = LSI_VALUE; static uint8_t HSEDiv = 0; #if !defined(STM32F1xx) /* predividers values */ static uint8_t predivSync_bits = 0xFF; -static int8_t predivAsync = -1; -static int16_t predivSync = -1; +static uint32_t predivAsync = (PREDIVA_MAX + 1); +static uint32_t predivSync = (PREDIVS_MAX + 1); #else -static uint32_t prediv = RTC_AUTO_1_SECOND; +/* Default, let HAL calculate the prescaler*/ +static uint32_t predivAsync = RTC_AUTO_1_SECOND; #endif /* !STM32F1xx */ static hourFormat_t initFormat = HOUR_FORMAT_12; @@ -81,7 +83,7 @@ static hourFormat_t initFormat = HOUR_FORMAT_12; /* Private function prototypes -----------------------------------------------*/ static void RTC_initClock(sourceClock_t source); #if !defined(STM32F1xx) -static void RTC_computePrediv(int8_t *asynch, int16_t *synch); +static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch); #endif /* !STM32F1xx */ static inline int _log2(int x) @@ -98,15 +100,54 @@ static inline int _log2(int x) */ void RTC_SetClockSource(sourceClock_t source) { - switch (source) { - case LSI_CLOCK: - case LSE_CLOCK: - case HSE_CLOCK: - clkSrc = source; - break; - default: - clkSrc = LSI_CLOCK; - break; + clkSrc = source; + if (source == LSE_CLOCK) { + clkVal = LSE_VALUE; + } else if (source == HSE_CLOCK) { + /* HSE division factor for RTC clock must be define to ensure that + * the clock supplied to the RTC is less than or equal to 1 MHz + */ +#if defined(STM32F1xx) + /* HSE max is 16 MHZ divided by 128 --> 125 KHz */ + HSEDiv = 128; +#elif defined(RCC_RTCCLKSOURCE_HSE_DIV32) && !defined(RCC_RTCCLKSOURCE_HSE_DIV31) + HSEDiv = 32; +#elif !defined(RCC_RTCCLKSOURCE_HSE_DIV31) + if ((HSE_VALUE / 2) <= HSE_RTC_MAX) { + HSEDiv = 2; + } else if ((HSE_VALUE / 4) <= HSE_RTC_MAX) { + HSEDiv = 4; + } else if ((HSE_VALUE / 8) <= HSE_RTC_MAX) { + HSEDiv = 8; + } else if ((HSE_VALUE / 16) <= HSE_RTC_MAX) { + HSEDiv = 16; + } +#elif defined(RCC_RTCCLKSOURCE_HSE_DIV31) + /* Not defined for STM32F2xx */ +#ifndef RCC_RTCCLKSOURCE_HSE_DIVX +#define RCC_RTCCLKSOURCE_HSE_DIVX 0x00000300U +#endif /* RCC_RTCCLKSOURCE_HSE_DIVX */ +#if defined(RCC_RTCCLKSOURCE_HSE_DIV63) +#define HSEDIV_MAX 64 +#else +#define HSEDIV_MAX 32 +#endif + for (HSEDiv = 2; HSEDiv < HSEDIV_MAX; HSEDiv++) { + if ((HSE_VALUE / HSEDiv) <= HSE_RTC_MAX) { + break; + } + } +#else +#error "Could not define HSE div" +#endif /* STM32F1xx */ + if ((HSE_VALUE / HSEDiv) > HSE_RTC_MAX) { + Error_Handler(); + } + clkVal = HSE_VALUE / HSEDiv; + } else if (source == LSI_CLOCK) { + clkVal = LSI_VALUE; + } else { + Error_Handler(); } } @@ -123,7 +164,7 @@ void RTC_SetClockSource(sourceClock_t source) static void RTC_initClock(sourceClock_t source) { RCC_PeriphCLKInitTypeDef PeriphClkInit; - + RTC_SetClockSource(source); if (source == LSE_CLOCK) { /* Enable the clock if not already set by user */ enableClock(LSE_CLOCK); @@ -133,7 +174,6 @@ static void RTC_initClock(sourceClock_t source) if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } - clkSrc = LSE_CLOCK; } else if (source == HSE_CLOCK) { /* Enable the clock if not already set by user */ enableClock(HSE_CLOCK); @@ -145,23 +185,17 @@ static void RTC_initClock(sourceClock_t source) #if defined(STM32F1xx) /* HSE max is 16 MHZ divided by 128 --> 125 KHz */ PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV128; - HSEDiv = 128; #elif defined(RCC_RTCCLKSOURCE_HSE_DIV32) && !defined(RCC_RTCCLKSOURCE_HSE_DIV31) PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32; - HSEDiv = 32; #elif !defined(RCC_RTCCLKSOURCE_HSE_DIV31) if ((HSE_VALUE / 2) <= HSE_RTC_MAX) { PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV2; - HSEDiv = 2; } else if ((HSE_VALUE / 4) <= HSE_RTC_MAX) { PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV4; - HSEDiv = 4; } else if ((HSE_VALUE / 8) <= HSE_RTC_MAX) { PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV8; - HSEDiv = 8; } else if ((HSE_VALUE / 16) <= HSE_RTC_MAX) { PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV16; - HSEDiv = 16; } #elif defined(RCC_RTCCLKSOURCE_HSE_DIV31) /* Not defined for STM32F2xx */ @@ -169,29 +203,17 @@ static void RTC_initClock(sourceClock_t source) #define RCC_RTCCLKSOURCE_HSE_DIVX 0x00000300U #endif /* RCC_RTCCLKSOURCE_HSE_DIVX */ #if defined(RCC_RTCCLKSOURCE_HSE_DIV63) -#define HSEDIV_MAX 64 #define HSESHIFT 12 #else -#define HSEDIV_MAX 32 #define HSESHIFT 16 #endif - for (HSEDiv = 2; HSEDiv < HSEDIV_MAX; HSEDiv++) { - if ((HSE_VALUE / HSEDiv) <= HSE_RTC_MAX) { - PeriphClkInit.RTCClockSelection = (HSEDiv << HSESHIFT) | RCC_RTCCLKSOURCE_HSE_DIVX; - break; - } - } + PeriphClkInit.RTCClockSelection = (HSEDiv << HSESHIFT) | RCC_RTCCLKSOURCE_HSE_DIVX; #else #error "Could not define RTCClockSelection" #endif /* STM32F1xx */ - if ((HSE_VALUE / HSEDiv) > HSE_RTC_MAX) { - Error_Handler(); - } - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } - clkSrc = HSE_CLOCK; } else if (source == LSI_CLOCK) { /* Enable the clock if not already set by user */ enableClock(LSI_CLOCK); @@ -201,78 +223,72 @@ static void RTC_initClock(sourceClock_t source) if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } - clkSrc = LSI_CLOCK; } else { Error_Handler(); } } -#if defined(STM32F1xx) -/** - * @brief set user asynchronous prescaler value. - * @note use RTC_AUTO_1_SECOND to reset value - * @param asynch: asynchronous prescaler value in range 0 - PREDIVA_MAX - * @retval None - */ -void RTC_setPrediv(uint32_t asynch) -{ - /* set the prescaler for a stm32F1 (value is hold by one param) */ - prediv = asynch; - LL_RTC_SetAsynchPrescaler(RTC, asynch); -} -#else /** * @brief set user (a)synchronous prescaler values. - * @note use -1 to reset value and use computed ones * @param asynch: asynchronous prescaler value in range 0 - PREDIVA_MAX + * @note Reset value: RTC_AUTO_1_SECOND for STM32F1xx series, else (PREDIVA_MAX + 1) * @param synch: synchronous prescaler value in range 0 - PREDIVS_MAX + * @note Reset value: (PREDIVS_MAX + 1), not used for STM32F1xx series. * @retval None */ -void RTC_setPrediv(int8_t asynch, int16_t synch) +void RTC_setPrediv(uint32_t asynch, uint32_t synch) { - if ((asynch >= -1) && ((uint32_t)asynch <= PREDIVA_MAX) && \ - (synch >= -1) && ((uint32_t)synch <= PREDIVS_MAX)) { +#if defined(STM32F1xx) + UNUSED(synch); + /* set the prescaler for a stm32F1 (value is hold by one param) */ + predivAsync = asynch; + if (!IS_RTC_ASYNCH_PREDIV(predivAsync)) { + predivAsync = RTC_AUTO_1_SECOND; + } + LL_RTC_SetAsynchPrescaler(RTC, predivAsync); +#else + if ((asynch <= PREDIVA_MAX) && (synch <= PREDIVS_MAX)) { predivAsync = asynch; predivSync = synch; } else { RTC_computePrediv(&predivAsync, &predivSync); } predivSync_bits = (uint8_t)_log2(predivSync) + 1; -} #endif /* STM32F1xx */ - -#if defined(STM32F1xx) -/** - * @brief get user asynchronous prescaler value for the current clock source. - * @param asynch: pointer where return asynchronous prescaler value. - * @retval None - */ -void RTC_getPrediv(uint32_t *asynch) -{ - /* get the prescaler for a stm32F1 (value is hold by one param) */ - prediv = LL_RTC_GetDivider(RTC); - *asynch = prediv; } -#else + + /** * @brief get user (a)synchronous prescaler values if set else computed ones * for the current clock source. * @param asynch: pointer where return asynchronous prescaler value. - * @param synch: pointer where return synchronous prescaler value. + * @param synch: pointer where return synchronous prescaler value, + * not used for STM32F1xx series. * @retval None */ -void RTC_getPrediv(int8_t *asynch, int16_t *synch) +void RTC_getPrediv(uint32_t *asynch, uint32_t *synch) { - if ((predivAsync == -1) || (predivSync == -1)) { - RTC_computePrediv(&predivAsync, &predivSync); +#if defined(STM32F1xx) + UNUSED(synch); + /* get the prescaler for a stm32F1 (value is hold by one param) */ + predivAsync = LL_RTC_GetDivider(RTC); + *asynch = predivAsync; +#else + if ((!IS_RTC_SYNCH_PREDIV(predivSync)) || (!IS_RTC_ASYNCH_PREDIV(predivAsync))) { + if (!LL_RTC_IsActiveFlag_INITS(RtcHandle.Instance)) { + RTC_computePrediv(&predivAsync, &predivSync); + } else { + predivAsync = LL_RTC_GetAsynchPrescaler(RtcHandle.Instance); + predivSync = LL_RTC_GetSynchPrescaler(RtcHandle.Instance); + } } if ((asynch != NULL) && (synch != NULL)) { *asynch = predivAsync; *synch = predivSync; } predivSync_bits = (uint8_t)_log2(predivSync) + 1; -} #endif /* STM32F1xx */ +} #if !defined(STM32F1xx) /** @@ -282,49 +298,39 @@ void RTC_getPrediv(int8_t *asynch, int16_t *synch) * @param synch: pointer where return synchronous prescaler value. * @retval None */ -static void RTC_computePrediv(int8_t *asynch, int16_t *synch) +static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch) { uint32_t predivS = PREDIVS_MAX + 1; - uint32_t clk = 0; + *asynch = PREDIVA_MAX + 1; /* Get user predividers if manually configured */ if ((asynch == NULL) || (synch == NULL)) { return; } - /* Get clock frequency */ - if (clkSrc == LSE_CLOCK) { - clk = LSE_VALUE; - } else if (clkSrc == LSI_CLOCK) { - clk = LSI_VALUE; - } else if (clkSrc == HSE_CLOCK) { - clk = HSE_VALUE / HSEDiv; - } else { - Error_Handler(); - } - /* Find (a)synchronous prescalers to obtain the 1Hz calendar clock */ - for (*asynch = PREDIVA_MAX; *asynch >= 0; (*asynch)--) { - predivS = (clk / (*asynch + 1)) - 1; + do { + (*asynch)--; + predivS = (clkVal / (*asynch + 1)) - 1; - if (((predivS + 1) * (*asynch + 1)) == clk) { + if (((predivS + 1) * (*asynch + 1)) == clkVal) { break; } - } + } while (*asynch != 0); /* * Can't find a 1Hz, so give priority to RTC power consumption * by choosing the higher possible value for predivA */ - if ((predivS > PREDIVS_MAX) || (*asynch < 0)) { + if ((!IS_RTC_SYNCH_PREDIV(predivS)) || (!IS_RTC_ASYNCH_PREDIV(*asynch))) { *asynch = PREDIVA_MAX; - predivS = (clk / (*asynch + 1)) - 1; + predivS = (clkVal / (*asynch + 1)) - 1; } - if (predivS > PREDIVS_MAX) { + if (!IS_RTC_SYNCH_PREDIV(predivS)) { Error_Handler(); } - *synch = (int16_t)predivS; + *synch = predivS; } #endif /* !STM32F1xx */ @@ -352,15 +358,26 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) uint32_t alarmBSubseconds = 0; bool isAlarmBSet = false; #endif -#if defined(STM32F1xx) - uint32_t asynch; -#else - int8_t asynch; - int16_t sync; -#endif initFormat = format; + + /* Ensure all RtcHandle properly set */ RtcHandle.Instance = RTC; +#if defined(STM32F1xx) + RtcHandle.Init.AsynchPrediv = predivAsync; + RtcHandle.Init.OutPut = RTC_OUTPUTSOURCE_NONE; +#else + RtcHandle.Init.HourFormat = (format == HOUR_FORMAT_12) ? RTC_HOURFORMAT_12 : RTC_HOURFORMAT_24; + RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; + RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; + RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; +#if defined(RTC_OUTPUT_PULLUP_NONE) + RtcHandle.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE; +#endif +#if defined(RTC_OUTPUT_REMAP_NONE) + RtcHandle.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE; +#endif /* RTC_OUTPUT_REMAP_NONE */ +#endif /* STM32F1xx */ /* Ensure backup domain is enabled before we init the RTC so we can use the backup registers for date retention on stm32f1xx boards */ enableBackupDomain(); @@ -384,29 +401,15 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) BackupDate |= getBackupRegister(RTC_BKP_DATE + 1) & 0xFFFF; if ((BackupDate == 0) || reset) { // RTC needs initialization - /* Let HAL calculate the prescaler */ - RtcHandle.Init.AsynchPrediv = prediv; - RtcHandle.Init.OutPut = RTC_OUTPUTSOURCE_NONE; + // Init RTC clock + RTC_initClock(source); #else if (!LL_RTC_IsActiveFlag_INITS(RtcHandle.Instance) || reset) { // RTC needs initialization - RtcHandle.Init.HourFormat = (format == HOUR_FORMAT_12) ? RTC_HOURFORMAT_12 : RTC_HOURFORMAT_24; - RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; - RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; - RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; -#if defined(RTC_OUTPUT_PULLUP_NONE) - RtcHandle.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE; -#endif -#if defined(RTC_OUTPUT_REMAP_NONE) - RtcHandle.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE; -#endif /* RTC_OUTPUT_REMAP_NONE */ -#if defined(RTC_BINARY_NONE) - RtcHandle.Init.BinMode = RTC_BINARY_NONE; -#endif - RTC_getPrediv((int8_t *) & (RtcHandle.Init.AsynchPrediv), (int16_t *) & (RtcHandle.Init.SynchPrediv)); -#endif // STM32F1xx // Init RTC clock RTC_initClock(source); + RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); +#endif // STM32F1xx HAL_RTC_Init(&RtcHandle); // Default: saturday 1st of January 2001 @@ -443,14 +446,15 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) if (source != oldRtcClockSource) { // RTC is already initialized, but RTC clock source is changed // In case of RTC source clock change, Backup Domain is reset by RTC_initClock() - // Save current config before call to RTC_initClock() + // Save current config before reinit RTC_GetDate(&years, &month, &days, &weekDay); RTC_GetTime(&hours, &minutes, &seconds, &subSeconds, &period); + // As clock source changed, force update prediv with user or computef ones #if defined(STM32F1xx) - RTC_getPrediv(&asynch); + RTC_setPrediv(predivAsync, 0); #else - RTC_getPrediv(&asynch, &sync); -#endif // STM32F1xx + RTC_setPrediv(predivAsync, predivSync); +#endif if (isAlarmASet) { RTC_GetAlarm(ALARM_A, &alarmDay, &alarmHours, &alarmMinutes, &alarmSeconds, &alarmSubseconds, &alarmPeriod, &alarmMask); } @@ -459,17 +463,18 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) RTC_GetAlarm(ALARM_B, &alarmBDay, &alarmBHours, &alarmBMinutes, &alarmBSeconds, &alarmBSubseconds, &alarmBPeriod, &alarmBMask); } #endif + RTC_DeInit(false); // Init RTC clock RTC_initClock(source); - +#if defined(STM32F1xx) + RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), NULL); +#else + RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); +#endif + HAL_RTC_Init(&RtcHandle); // Restore config RTC_SetTime(hours, minutes, seconds, subSeconds, period); RTC_SetDate(years, month, days, weekDay); -#if defined(STM32F1xx) - RTC_setPrediv(asynch); -#else - RTC_setPrediv(asynch, sync); -#endif // STM32F1xx if (isAlarmASet) { RTC_StartAlarm(ALARM_A, alarmDay, alarmHours, alarmMinutes, alarmSeconds, alarmSubseconds, alarmPeriod, alarmMask); } @@ -480,9 +485,14 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #endif } else { // RTC is already initialized, and RTC stays on the same clock source - // Init RTC clock RTC_initClock(source); + // This initialize variables: predivAsync, predivSync and predivSync_bits +#if defined(STM32F1xx) + RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), NULL); +#else + RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); +#endif #if defined(STM32F1xx) memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4); /* Update date automatically by calling HAL_RTC_GetDate */ @@ -490,9 +500,6 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) /* and fill the new RTC Date value */ RTC_SetDate(RtcHandle.DateToUpdate.Year, RtcHandle.DateToUpdate.Month, RtcHandle.DateToUpdate.Date, RtcHandle.DateToUpdate.WeekDay); -#else - // This initialize variables: predivAsync, predivSync and predivSync_bits - RTC_getPrediv(NULL, NULL); #endif // STM32F1xx } } @@ -507,18 +514,21 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) /** * @brief RTC deinitialization. Stop the RTC. + * @param reset_cb: reset user callback * @retval None */ -void RTC_DeInit(void) +void RTC_DeInit(bool reset_cb) { HAL_RTC_DeInit(&RtcHandle); - RTCUserCallback = NULL; - callbackUserData = NULL; + if (reset_cb) { + RTCUserCallback = NULL; + callbackUserData = NULL; #ifdef RTC_ALARM_B - RTCUserCallbackB = NULL; - callbackUserDataB = NULL; + RTCUserCallbackB = NULL; + callbackUserDataB = NULL; #endif - RTCSecondsIrqCallback = NULL; + RTCSecondsIrqCallback = NULL; + } } /** diff --git a/src/rtc.h b/src/rtc.h index bad868b..4e384d3 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -113,6 +113,7 @@ typedef void(*voidCallbackPtr)(void *); #else /* for stm32F1 the MAX value is combining PREDIV low & high registers */ #define PREDIVA_MAX 0xFFFFFU +#define PREDIVS_MAX 0xFFFFFFFFU /* Unused for STM32F1xx series */ #endif /* !STM32F1xx */ #if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32H5xx) || \ @@ -165,16 +166,11 @@ typedef void(*voidCallbackPtr)(void *); /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ void RTC_SetClockSource(sourceClock_t source); -#if defined(STM32F1xx) -void RTC_getPrediv(uint32_t *asynch); -void RTC_setPrediv(uint32_t asynch); -#else -void RTC_getPrediv(int8_t *asynch, int16_t *synch); -void RTC_setPrediv(int8_t asynch, int16_t synch); -#endif /* STM32F1xx */ +void RTC_getPrediv(uint32_t *asynch, uint32_t *synch); +void RTC_setPrediv(uint32_t asynch, uint32_t synch); bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset); -void RTC_DeInit(void); +void RTC_DeInit(bool reset_cb); bool RTC_IsConfigured(void); void RTC_SetTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period); From 23a1d03ad2d43c4baa019ec6d93684412394032a Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Wed, 13 Sep 2023 10:57:56 +0200 Subject: [PATCH 06/23] chore: set clock source and (a)synchronous prescalers together (a)synchronous prescalers values depend on the RTC clock source. Signed-off-by: Frederic Pillon --- README.md | 2 +- src/STM32RTC.cpp | 15 ++++++++++----- src/STM32RTC.h | 7 +++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7dd0ffd..6340ce2 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ _RTC hours mode (12 or 24)_ _RTC clock source_ * **`Source_Clock getClockSource(void)`** : get current clock source. -* **`void setClockSource(Source_Clock source)`** : this function must be called before `begin()`. +* **`void setClockSource(Source_Clock source, uint32_t predivA, uint32_t predivS)`** : set the clock source (`LSI_CLOCK`, `LSE_CLOCK` or `HSE_CLOCK`) and (a)synchronous prescaler values. This function must be called before `begin()`. Use `(PREDIVA_MAX + 1)` and `(PREDIVS_MAX +1)` to reset value and use computed ones. Those values have to match the following conditions: **_1Hz = RTC CLK source / ((predivA + 1) * (predivS + 1))_** _RTC Asynchronous and Synchronous prescaler_ * **`void getPrediv(uint32_t *predivA, uint32_t *predivS)`** : get (a)synchronous prescaler values if set else computed ones for the current clock source. diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index daf028c..5a0f4ef 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -117,18 +117,23 @@ STM32RTC::Source_Clock STM32RTC::getClockSource(void) } /** - * @brief set the RTC clock source. By default LSI clock is selected. This - * method must be called before begin(). + * @brief set the RTC clock source and user (a)synchronous prescalers values. + * @note By default LSI clock is selected. This method must be called before begin(). * @param source: clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK + * @param predivA: Asynchronous prescaler value. + * @note Reset value: RTC_AUTO_1_SECOND for STM32F1xx series, else (PREDIVA_MAX + 1) + * @param predivS: Synchronous prescaler value. + * @note Reset value: (PREDIVS_MAX + 1), not used for STM32F1xx series. * @retval None */ -void STM32RTC::setClockSource(Source_Clock source) +void STM32RTC::setClockSource(Source_Clock source, uint32_t predivA, uint32_t predivS) { if (IS_CLOCK_SOURCE(source)) { _clockSource = source; RTC_SetClockSource((_clockSource == LSE_CLOCK) ? ::LSE_CLOCK : (_clockSource == HSE_CLOCK) ? ::HSE_CLOCK : ::LSI_CLOCK); } + RTC_setPrediv(predivA, predivS); } /** @@ -151,7 +156,7 @@ void STM32RTC::getPrediv(uint32_t *predivA, uint32_t *predivS) } /** - * @brief set user (a)synchronous prescalers value. + * @brief set user (a)synchronous prescalers values. * @note This method must be called before begin(). * @param predivA: Asynchronous prescaler value. * @note Reset value: RTC_AUTO_1_SECOND for STM32F1xx series, else (PREDIVA_MAX + 1) @@ -161,7 +166,7 @@ void STM32RTC::getPrediv(uint32_t *predivA, uint32_t *predivS) */ void STM32RTC::setPrediv(uint32_t predivA, uint32_t predivS) { - RTC_setPrediv(predivA, predivS); + setClockSource(_clockSource, predivA, predivS); } /** diff --git a/src/STM32RTC.h b/src/STM32RTC.h index e89cea8..d6e6799 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -126,7 +126,9 @@ class STM32RTC { void end(void); Source_Clock getClockSource(void); - void setClockSource(Source_Clock source); + void setClockSource(Source_Clock source, uint32_t predivA = (PREDIVA_MAX + 1), uint32_t predivS = (PREDIVS_MAX + 1)); + void getPrediv(uint32_t *predivA, uint32_t *predivS); + void setPrediv(uint32_t predivA, uint32_t predivS); void enableAlarm(Alarm_Match match, Alarm name = ALARM_A); void disableAlarm(Alarm name = ALARM_A); @@ -212,9 +214,6 @@ class STM32RTC { void setAlarmEpoch(time_t ts, Alarm_Match match, Alarm name); void setAlarmEpoch(time_t ts, Alarm_Match match = MATCH_DHHMMSS, uint32_t subSeconds = 0, Alarm name = ALARM_A); - void getPrediv(uint32_t *predivA, uint32_t *predivS); - void setPrediv(uint32_t predivA, uint32_t predivS); - bool isConfigured(void) { return RTC_IsConfigured(); From 3a29b0eabeace5a4fc5331f63e5af4b934484ce0 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 8 Sep 2023 14:25:41 +0200 Subject: [PATCH 07/23] feat: add a parameter to set binary mode This is valid when the RTC_BINARY_MIX mode exists in the RTC (bitfield in the RTC ICSR register) Set the RTC mode through a setBinaryMode function to be called before begin. Signed-off-by: Francois Ramu Co-authored-by: Frederic Pillon --- src/STM32RTC.cpp | 21 ++++++++++++++++++++ src/STM32RTC.h | 12 +++++++++++- src/rtc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++--- src/rtc.h | 8 +++++++- 4 files changed, 87 insertions(+), 5 deletions(-) diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 5a0f4ef..4e8e58d 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -63,6 +63,7 @@ void STM32RTC::begin(bool resetTime, Hour_Format format) _format = format; reinit = RTC_init((format == HOUR_12) ? HOUR_FORMAT_12 : HOUR_FORMAT_24, + (_mode == MODE_MIX) ? ::MODE_BINARY_MIX : ((_mode == MODE_BIN) ? ::MODE_BINARY_ONLY : ::MODE_BINARY_NONE), (_clockSource == LSE_CLOCK) ? ::LSE_CLOCK : (_clockSource == HSE_CLOCK) ? ::HSE_CLOCK : ::LSI_CLOCK , resetTime); @@ -136,6 +137,26 @@ void STM32RTC::setClockSource(Source_Clock source, uint32_t predivA, uint32_t pr RTC_setPrediv(predivA, predivS); } +/** + * @brief get the Binary Mode. + * @retval mode: MODE_BCD, MODE_BIN or MODE_MIX + */ +STM32RTC::Binary_Mode STM32RTC::getBinaryMode(void) +{ + return _mode; +} + +/** + * @brief set the Binary Mode. By default MODE_BCD is selected. This + * method must be called before begin(). + * @param mode: the RTC mode: MODE_BCD, MODE_BIN or MODE_MIX + * @retval None + */ +void STM32RTC::setBinaryMode(Binary_Mode mode) +{ + _mode = mode; +} + /** * @brief get user (a)synchronous prescaler values if set else computed * ones for the current clock source. diff --git a/src/STM32RTC.h b/src/STM32RTC.h index d6e6799..f0e065b 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -85,6 +85,12 @@ class STM32RTC { PM = HOUR_PM }; + enum Binary_Mode : uint8_t { + MODE_BCD = MODE_BINARY_NONE, /* not used */ + MODE_BIN = MODE_BINARY_ONLY, + MODE_MIX = MODE_BINARY_MIX + }; + enum Alarm_Match : uint8_t { MATCH_OFF = OFF_MSK, // Never MATCH_SS = SS_MSK, // Every Minute @@ -130,6 +136,9 @@ class STM32RTC { void getPrediv(uint32_t *predivA, uint32_t *predivS); void setPrediv(uint32_t predivA, uint32_t predivS); + Binary_Mode getBinaryMode(void); + void setBinaryMode(Binary_Mode mode); + void enableAlarm(Alarm_Match match, Alarm name = ALARM_A); void disableAlarm(Alarm name = ALARM_A); @@ -227,7 +236,7 @@ class STM32RTC { friend class STM32LowPower; private: - STM32RTC(void): _clockSource(LSI_CLOCK) + STM32RTC(void): _mode(MODE_BCD), _clockSource(LSI_CLOCK) { setClockSource(_clockSource); } @@ -235,6 +244,7 @@ class STM32RTC { static bool _timeSet; Hour_Format _format; + Binary_Mode _mode; AM_PM _hoursPeriod; uint8_t _hours; uint8_t _minutes; diff --git a/src/rtc.c b/src/rtc.c index 2e78997..8e86ae6 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -79,12 +79,16 @@ static uint32_t predivAsync = RTC_AUTO_1_SECOND; #endif /* !STM32F1xx */ static hourFormat_t initFormat = HOUR_FORMAT_12; +static binaryMode_t initMode = MODE_BINARY_NONE; /* Private function prototypes -----------------------------------------------*/ static void RTC_initClock(sourceClock_t source); #if !defined(STM32F1xx) static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch); #endif /* !STM32F1xx */ +#if defined(RTC_BINARY_NONE) +static void RTC_BinaryConf(binaryMode_t mode); +#endif static inline int _log2(int x) { @@ -334,17 +338,49 @@ static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch) } #endif /* !STM32F1xx */ +#if defined(RTC_BINARY_NONE) +static void RTC_BinaryConf(binaryMode_t mode) +{ + RtcHandle.Init.BinMode = (mode == MODE_BINARY_MIX) ? RTC_BINARY_MIX : ((mode == MODE_BINARY_ONLY) ? RTC_BINARY_ONLY : RTC_BINARY_NONE); + if (RtcHandle.Init.BinMode == RTC_BINARY_MIX) { + /* Configure the 1s BCD calendar increment */ + + uint32_t inc = 1 / (1.0 / ((float)clkVal / (float)(predivAsync + 1.0))); + if (inc <= 256) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_0; + } else if (inc < (256 << 1)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_1; + } else if (inc < (256 << 2)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_2; + } else if (inc < (256 << 3)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_3; + } else if (inc < (256 << 4)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_4; + } else if (inc < (256 << 5)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_5; + } else if (inc < (256 << 6)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_6; + } else if (inc < (256 << 7)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_7; + } else { + Error_Handler(); + } + } +} +#endif /* RTC_BINARY_NONE */ + /** * @brief RTC Initialization * This function configures the RTC time and calendar. By default, the * RTC is set to the 1st January 2001 * Note: year 2000 is invalid as it is the hardware reset value and doesn't raise INITS flag * @param format: enable the RTC in 12 or 24 hours mode + * @param mode: enable the RTC in BCD or Mix or Binary mode * @param source: RTC clock source: LSE, LSI or HSE * @param reset: force RTC reset, even if previously configured * @retval True if RTC is reinitialized, else false */ -bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) +bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool reset) { bool reinit = false; hourAM_PM_t period = HOUR_AM, alarmPeriod = HOUR_AM; @@ -360,7 +396,7 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #endif initFormat = format; - + initMode = mode; /* Ensure all RtcHandle properly set */ RtcHandle.Instance = RTC; #if defined(STM32F1xx) @@ -409,7 +445,10 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) // Init RTC clock RTC_initClock(source); RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); -#endif // STM32F1xx +#if defined(RTC_BINARY_NONE) + RTC_BinaryConf(mode); +#endif /* RTC_BINARY_NONE */ +#endif // STM32F1xx HAL_RTC_Init(&RtcHandle); // Default: saturday 1st of January 2001 @@ -471,6 +510,9 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #else RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); #endif +#if defined(RTC_BINARY_NONE) + RTC_BinaryConf(mode); +#endif /* RTC_BINARY_NONE */ HAL_RTC_Init(&RtcHandle); // Restore config RTC_SetTime(hours, minutes, seconds, subSeconds, period); @@ -493,6 +535,9 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #else RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); #endif +#if defined(RTC_BINARY_NONE) + RTC_BinaryConf(mode); +#endif /* RTC_BINARY_NONE */ #if defined(STM32F1xx) memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4); /* Update date automatically by calling HAL_RTC_GetDate */ diff --git a/src/rtc.h b/src/rtc.h index 4e384d3..72070d2 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -55,6 +55,12 @@ typedef enum { HOUR_FORMAT_24 } hourFormat_t; +typedef enum { + MODE_BINARY_NONE, /* BCD only */ + MODE_BINARY_ONLY, + MODE_BINARY_MIX +} binaryMode_t; + typedef enum { HOUR_AM, HOUR_PM @@ -169,7 +175,7 @@ void RTC_SetClockSource(sourceClock_t source); void RTC_getPrediv(uint32_t *asynch, uint32_t *synch); void RTC_setPrediv(uint32_t asynch, uint32_t synch); -bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset); +bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool reset); void RTC_DeInit(bool reset_cb); bool RTC_IsConfigured(void); From 475be89d5e81f947c55c143d0fb1dad32f95ff19 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 15 Sep 2023 14:20:54 +0200 Subject: [PATCH 08/23] fix(example): enable alarm(s) if neeed Formatted with Arduino astyle. Signed-off-by: Frederic Pillon --- examples/RTCReset/RTCReset.ino | 51 ++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/examples/RTCReset/RTCReset.ino b/examples/RTCReset/RTCReset.ino index ef55302..f05ea6e 100644 --- a/examples/RTCReset/RTCReset.ino +++ b/examples/RTCReset/RTCReset.ino @@ -36,9 +36,9 @@ typedef struct { bool alarm_a; } cb_data_t; -static cb_data_t atime = { 2222, true}; +static cb_data_t atime = { 2222, true }; #ifdef RTC_ALARM_B -static cb_data_t btime = { 3333, false}; +static cb_data_t btime = { 3333, false }; #endif static byte seconds = 0; static byte minutes = 0; @@ -64,7 +64,7 @@ static uint8_t conv2d(const char* p) { } // sample input: date = "Dec 26 2009", time = "12:34:56" -void initDateTime (void) { +void initDateTime(void) { Serial.printf("Build date & time %s, %s\n", mydate, mytime); year = conv2d(mydate + 9); @@ -89,15 +89,15 @@ void initDateTime (void) { seconds = conv2d(mytime + 6); } -void setup() -{ +void setup() { pinMode(USER_BTN, INPUT_PULLUP); int32_t default_state = digitalRead(USER_BTN); - - Serial.begin(9600); - while (!Serial); + Serial.begin(115200); + while (!Serial) + ; // Wait user input to start - while (digitalRead(USER_BTN) == default_state); + while (digitalRead(USER_BTN) == default_state) + ; // Convenient function to init date and time variables initDateTime(); @@ -110,7 +110,7 @@ void setup() #ifdef RTC_ALARM_B rtc.attachInterrupt(alarmMatch, &btime, STM32RTC::ALARM_B); #endif - rtc.begin(); // Initialize RTC 24H format + rtc.begin(); // Initialize RTC 24H format if (!rtc.isTimeSet()) { Serial.printf("RTC time not set\n Set it.\n"); // Set the time @@ -129,6 +129,10 @@ void setup() } else { // RTC already initialized time_t epoc, alarm_epoc; + rtc.getTime(&hours, &minutes, &seconds, &subSeconds, &period); + year = rtc.getYear(); + month = rtc.getMonth(); + day = rtc.getDay(); if (rtc.isAlarmEnabled()) { rtc.enableAlarm(rtc.MATCH_DHHMMSS); alarm_epoc = rtc.getAlarmEpoch(); @@ -156,16 +160,28 @@ void setup() #endif Serial.printf("RTC time already set\n"); } - Serial.printf("Alarm A enable status: %s\n", (rtc.isAlarmEnabled(STM32RTC::ALARM_A)) ? "True" : "False"); + // For STM32F1xx series, alarm is always disabled after a reset. + bool alarmA = rtc.isAlarmEnabled(STM32RTC::ALARM_A); + Serial.printf("Alarm A enable status: %s\n", (alarmA) ? "True" : "False"); + if (!alarmA) { + rtc.setAlarmDay(day); + rtc.setAlarmTime(hours, minutes, seconds + 5, 567); + rtc.enableAlarm(rtc.MATCH_DHHMMSS); + } #ifdef RTC_ALARM_B - Serial.printf("Alarm B enable status: %s\n", (rtc.isAlarmEnabled(STM32RTC::ALARM_B)) ? "True" : "False"); + bool alarmB = rtc.isAlarmEnabled(STM32RTC::ALARM_B); + Serial.printf("Alarm B enable status: %s\n", (alarmB) ? "True" : "False"); + if (!alarmB) { + rtc.setAlarmDay(day, STM32RTC::ALARM_B); + rtc.setAlarmTime(hours, minutes, seconds + 5, 567, STM32RTC::ALARM_B); + rtc.enableAlarm(rtc.MATCH_DHHMMSS, STM32RTC::ALARM_B); + } #else Serial.println("Alarm B not available."); #endif } -void loop() -{ +void loop() { rtc.getTime(&hours, &minutes, &seconds, &subSeconds, &period); // Print current date & time Serial.printf("\n%02d/%02d/%02d %02d:%02d:%02d.%03d\n", rtc.getDay(), rtc.getMonth(), rtc.getYear(), hours, minutes, seconds, subSeconds); @@ -177,13 +193,12 @@ void loop() delay(1000); } -void alarmMatch(void *data) -{ +void alarmMatch(void* data) { time_t epoc; uint32_t epoc_ms; uint32_t sec = 0; uint32_t _millis = 1000; - cb_data_t cbdata = {.next = 1000, .alarm_a = true}; + cb_data_t cbdata = { .next = 1000, .alarm_a = true }; if (data != NULL) { cbdata.next = ((cb_data_t*)data)->next; cbdata.alarm_a = ((cb_data_t*)data)->alarm_a; @@ -204,7 +219,7 @@ void alarmMatch(void *data) // Update epoch_ms - might need to add a second to epoch epoc_ms += _millis; if (epoc_ms >= 1000) { - sec ++; + sec++; epoc_ms -= 1000; } #endif From 344114d9157d8a6e837426f7a65e0966f1a4f9e5 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 21 Sep 2023 15:24:21 +0200 Subject: [PATCH 09/23] fix: add missing else Signed-off-by: Frederic Pillon --- src/STM32RTC.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 4e8e58d..3397043 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -831,7 +831,7 @@ void STM32RTC::setAlarmSubSeconds(uint32_t subSeconds, Alarm name) #ifdef RTC_ALARM_B if (name == ALARM_B) { _alarmBSubSeconds = subSeconds; - } + } else #else UNUSED(name); #endif @@ -854,7 +854,7 @@ void STM32RTC::setAlarmSeconds(uint8_t seconds, Alarm name) #ifdef RTC_ALARM_B if (name == ALARM_B) { _alarmBSeconds = seconds; - } + } else #else UNUSED(name); #endif @@ -877,7 +877,7 @@ void STM32RTC::setAlarmMinutes(uint8_t minutes, Alarm name) #ifdef RTC_ALARM_B if (name == ALARM_B) { _alarmBMinutes = minutes; - } + } else #else UNUSED(name); #endif From 7714616af9369be81c5b8cb950087d4578a33a51 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 10 May 2023 17:09:25 +0200 Subject: [PATCH 10/23] feat: support binary mode Configure the alarm depending on the MIX mode In case the RTC is running in MIX mode (binary and calendar), the subsecond register is a 32-bit value (and not msec) The Subsecond parameter is expressed in millisecond in RTC_SetTime/GetTime RTC_StartAlarm/GetAlarm Signed-off-by: Francois Ramu --- src/STM32RTC.cpp | 18 ++++++++++- src/STM32RTC.h | 1 + src/rtc.c | 77 +++++++++++++++++++++++++++++++++++++++++++----- src/rtc.h | 4 ++- 4 files changed, 90 insertions(+), 10 deletions(-) diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 3397043..a9b0ef3 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -220,6 +220,21 @@ void STM32RTC::enableAlarm(Alarm_Match match, Alarm name) RTC_StopAlarm(::ALARM_A); } break; + case MATCH_SUBSEC: + /* force _alarmday to 0 to go to the right alarm config in MIX mode */ +#ifdef RTC_ALARM_B + if (name == ALARM_B) { + RTC_StartAlarm(::ALARM_B, 0, 0, 0, 0, + _alarmBSubSeconds, (_alarmBPeriod == AM) ? HOUR_AM : HOUR_PM, + static_cast(31UL)); + } else +#endif + { + RTC_StartAlarm(::ALARM_A, 0, 0, 0, 0, + _alarmSubSeconds, (_alarmPeriod == AM) ? HOUR_AM : HOUR_PM, + static_cast(31UL)); + } + break; case MATCH_YYMMDDHHMMSS://kept for compatibility case MATCH_MMDDHHMMSS: //kept for compatibility case MATCH_DHHMMSS: @@ -615,7 +630,7 @@ uint8_t STM32RTC::getAlarmYear(void) /** * @brief set RTC subseconds. - * @param subseconds: 0-999 + * @param subseconds: 0-999 milliseconds * @retval none */ void STM32RTC::setSubSeconds(uint32_t subSeconds) @@ -1250,6 +1265,7 @@ bool STM32RTC::isAlarmEnabled(Alarm name) void STM32RTC::syncTime(void) { hourAM_PM_t p = HOUR_AM; + RTC_GetTime(&_hours, &_minutes, &_seconds, &_subSeconds, &p); _hoursPeriod = (p == HOUR_AM) ? AM : PM; } diff --git a/src/STM32RTC.h b/src/STM32RTC.h index f0e065b..489ba38 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -93,6 +93,7 @@ class STM32RTC { enum Alarm_Match : uint8_t { MATCH_OFF = OFF_MSK, // Never + MATCH_SUBSEC = SUBSEC_MSK, // Every Subsecond MATCH_SS = SS_MSK, // Every Minute MATCH_MMSS = SS_MSK | MM_MSK, // Every Hour MATCH_HHMMSS = SS_MSK | MM_MSK | HH_MSK, // Every Day diff --git a/src/rtc.c b/src/rtc.c index 8e86ae6..36e4c5e 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -73,6 +73,7 @@ static uint8_t HSEDiv = 0; static uint8_t predivSync_bits = 0xFF; static uint32_t predivAsync = (PREDIVA_MAX + 1); static uint32_t predivSync = (PREDIVS_MAX + 1); +static uint32_t fqce_apre; #else /* Default, let HAL calculate the prescaler*/ static uint32_t predivAsync = RTC_AUTO_1_SECOND; @@ -335,6 +336,8 @@ static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch) Error_Handler(); } *synch = predivS; + + fqce_apre = clkVal / (*asynch + 1); } #endif /* !STM32F1xx */ @@ -597,14 +600,14 @@ bool RTC_IsConfigured(void) * @param hours: 0-12 or 0-23. Depends on the format used. * @param minutes: 0-59 * @param seconds: 0-59 - * @param subSeconds: 0-999 + * @param subSeconds: 0-999 (not used) * @param period: select HOUR_AM or HOUR_PM period in case RTC is set in 12 hours mode. Else ignored. * @retval None */ void RTC_SetTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period) { RTC_TimeTypeDef RTC_TimeStruct; - UNUSED(subSeconds); + UNUSED(subSeconds); /* not used (read-only register) */ /* Ignore time AM PM configuration if in 24 hours format */ if (initFormat == HOUR_FORMAT_24) { period = HOUR_AM; @@ -670,7 +673,16 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s } #if defined(RTC_SSR_SS) if (subSeconds != NULL) { - *subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1); + if (initMode == MODE_BINARY_MIX) { + /* The subsecond is the free-running downcounter, to be converted in milliseconds */ + *subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX) + * 1000) / fqce_apre; /* give one more to compensate the 3.9ms uncertainty */ + *subSeconds = *subSeconds % 1000; /* nb of milliseconds */ + /* predivAsync is 0x7F with LSE clock source */ + } else { + /* the subsecond register value is converted in millisec */ + *subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1); + } } #else UNUSED(subSeconds); @@ -738,7 +750,7 @@ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday) * @param hours: 0-12 or 0-23 depends on the hours mode. * @param minutes: 0-59 * @param seconds: 0-59 - * @param subSeconds: 0-999 + * @param subSeconds: 0-999 milliseconds * @param period: HOUR_AM or HOUR_PM if in 12 hours mode else ignored. * @param mask: configure alarm behavior using alarmMask_t combination. * See AN4579 Table 5 for possible values. @@ -753,11 +765,12 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u period = HOUR_AM; } + /* Use alarm A by default because it is common to all STM32 HAL */ + RTC_AlarmStructure.Alarm = name; + if ((((initFormat == HOUR_FORMAT_24) && IS_RTC_HOUR24(hours)) || IS_RTC_HOUR12(hours)) && IS_RTC_DATE(day) && IS_RTC_MINUTES(minutes) && IS_RTC_SECONDS(seconds)) { /* Set RTC_AlarmStructure with calculated values*/ - /* Use alarm A by default because it is common to all STM32 HAL */ - RTC_AlarmStructure.Alarm = name; RTC_AlarmStructure.AlarmTime.Seconds = seconds; RTC_AlarmStructure.AlarmTime.Minutes = minutes; RTC_AlarmStructure.AlarmTime.Hours = hours; @@ -772,7 +785,12 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u { RTC_AlarmStructure.AlarmSubSecondMask = predivSync_bits << RTC_ALRMASSR_MASKSS_Pos; } - RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000; + if (initMode == MODE_BINARY_MIX) { + /* the subsecond is the millisecond to be converted in a subsecond downcounter value */ + RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - ((subSeconds * fqce_apre) / 1000 + 1); + } else { + RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000; + } } else { RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; } @@ -813,6 +831,41 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u UNUSED(mask); #endif /* !STM32F1xx */ + /* Set RTC_Alarm */ + HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN); + HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO); + HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); +#if defined(RTC_ICSR_BIN) + } else if (RtcHandle.Init.BinMode != RTC_BINARY_NONE) { + /* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */ +#else + } else { +#endif /* RTC_ICSR_BIN */ +#if defined(RTC_SSR_SS) + { +#if defined(RTC_ALRMASSR_SSCLR) + RTC_AlarmStructure.BinaryAutoClr = RTC_ALARMSUBSECONDBIN_AUTOCLR_NO; +#endif /* RTC_ALRMASSR_SSCLR */ + RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_ALL; + +#ifdef RTC_ALARM_B + if (name == ALARM_B) + { + /* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM B */ + RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMBSSR_MASKSS_Pos; + } else +#endif + { + /* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM A */ + RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos; + } + /* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */ + RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * fqce_apre) / 1000; + } + +#else + UNUSED(subSeconds); +#endif /* RTC_SSR_SS */ /* Set RTC_Alarm */ HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN); HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO); @@ -903,7 +956,15 @@ void RTC_GetAlarm(alarm_t name, uint8_t *day, uint8_t *hours, uint8_t *minutes, } #if defined(RTC_SSR_SS) if (subSeconds != NULL) { - *subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1); + if (initMode == MODE_BINARY_MIX) { + /* + * The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR) + * to be converted in milliseconds + */ + *subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre; + } else { + *subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1); + } } #else UNUSED(subSeconds); diff --git a/src/rtc.h b/src/rtc.h index 72070d2..629dc9e 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -76,7 +76,9 @@ typedef enum { /* NOTE: STM32 RTC can't assign a month or a year to an alarm. Those enum are kept for compatibility but are ignored inside enableAlarm(). */ M_MSK = 16, - Y_MSK = 32 + Y_MSK = 32, + SUBSEC_MSK = 48, + ALL_MSK = 0xFF } alarmMask_t; typedef enum { From 699658dbbb24a10d754f887379a05f11e800f7c1 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 13 Jun 2023 14:51:34 +0200 Subject: [PATCH 11/23] chore: provide a way to get the RTC handle Signed-off-by: Frederic Pillon --- README.md | 6 ++++++ src/STM32RTC.h | 6 ++++++ src/rtc.c | 9 +++++++++ src/rtc.h | 1 + 4 files changed, 22 insertions(+) diff --git a/README.md b/README.md index 6340ce2..c913529 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,12 @@ It is possible to use it thanks all alarm API with an extra argument: rtc.enableAlarm(rtc.MATCH_DHHMMSS, STM32RTC::ALARM_B); ``` +### Since STM32RTC version higher than 1.3.7 +_Get the RTC handle_ + +* **`RTC_HandleTypeDef *RTC_GetHandle(void)`** + + Refer to the Arduino RTC documentation for the other functions http://arduino.cc/en/Reference/RTC diff --git a/src/STM32RTC.h b/src/STM32RTC.h index 489ba38..e4a8198 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -132,6 +132,12 @@ class STM32RTC { void end(void); + // Could be used to mix Arduino API and STM32Cube HAL API (ex: DMA). Use at your own risk. + RTC_HandleTypeDef *getHandle(void) + { + return RTC_GetHandle(); + } + Source_Clock getClockSource(void); void setClockSource(Source_Clock source, uint32_t predivA = (PREDIVA_MAX + 1), uint32_t predivS = (PREDIVS_MAX + 1)); void getPrediv(uint32_t *predivA, uint32_t *predivS); diff --git a/src/rtc.c b/src/rtc.c index 36e4c5e..7fd07a2 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -98,6 +98,15 @@ static inline int _log2(int x) /* Exported functions --------------------------------------------------------*/ +/** + * @brief Get pointer to RTC_HandleTypeDef + * @param None + * @retval pointer to RTC_HandleTypeDef + */ +RTC_HandleTypeDef *RTC_GetHandle(void) { + return &RtcHandle; +} + /** * @brief Set RTC clock source * @param source: RTC clock source: LSE, LSI or HSE diff --git a/src/rtc.h b/src/rtc.h index 629dc9e..4983148 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -173,6 +173,7 @@ typedef void(*voidCallbackPtr)(void *); /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ +RTC_HandleTypeDef *RTC_GetHandle(void); void RTC_SetClockSource(sourceClock_t source); void RTC_getPrediv(uint32_t *asynch, uint32_t *synch); void RTC_setPrediv(uint32_t asynch, uint32_t synch); From 88f773384a7d5a60fbdf9353b04ae8732ce7d1a0 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 15 Sep 2023 17:27:02 +0200 Subject: [PATCH 12/23] feat: add the HAL_MSP_Init/DeInit functions Signed-off-by: Frederic Pillon --- src/rtc.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/rtc.c b/src/rtc.c index 7fd07a2..9ee676b 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -98,6 +98,54 @@ static inline int _log2(int x) /* Exported functions --------------------------------------------------------*/ +/* HAL MSP function used for RTC_Init */ +void HAL_RTC_MspInit(RTC_HandleTypeDef *rtcHandle) +{ +#if defined(RTC_SCR_CSSRUF) + if (rtcHandle->Instance == RTC) { + /* In BINARY mode (MIX or ONLY), set the SSR Underflow interrupt */ + if (rtcHandle->Init.BinMode != RTC_BINARY_NONE) { +#if defined(STM32WLxx) + /* Only the STM32WLxx series has a TAMP_STAMP_LSECSS_SSRU_IRQn */ + if (HAL_RTCEx_SetSSRU_IT(rtcHandle) != HAL_OK) { + Error_Handler(); + } + /* Give init value for the RtcFeatures enable */ + rtcHandle->IsEnabled.RtcFeatures = 0; + + /* RTC interrupt Init */ + HAL_NVIC_SetPriority(TAMP_STAMP_LSECSS_SSRU_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); +#else + /* The STM32U5, STM32H5, STM32L4plus have common RTC interrupt and a SSRU flag */ + __HAL_RTC_SSRU_ENABLE_IT(rtcHandle, RTC_IT_SSRU); +#endif /* STM32WLxx */ + } + } +#else /* RTC_SCR_CSSRUF */ + UNUSED(rtcHandle); +#endif /* RTC_SCR_CSSRUF */ + /* RTC_Alarm_IRQn is enabled when enabling Alarm */ +} + +void HAL_RTC_MspDeInit(RTC_HandleTypeDef *rtcHandle) +{ + + if (rtcHandle->Instance == RTC) { + /* Peripheral clock disable */ + __HAL_RCC_RTC_DISABLE(); +#ifdef __HAL_RCC_RTCAPB_CLK_DISABLE + __HAL_RCC_RTCAPB_CLK_DISABLE(); +#endif + /* RTC interrupt Deinit */ +#if defined(STM32WLxx) + /* Only the STM32WLxx series has a TAMP_STAMP_LSECSS_SSRU_IRQn */ + HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); +#endif /* STM32WLxx */ + HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn); + } +} + /** * @brief Get pointer to RTC_HandleTypeDef * @param None From 9e2f974503a0c7d015790bae9254267ee0c39662 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 19 Sep 2023 16:06:32 +0200 Subject: [PATCH 13/23] feat: RTC Time and Alarm configuration in BCD and BIN modes define the Getime and startAlarm function when the RTC is configured in BCD (MODE_BINARY_NONE) or BIN (MODE_BINARY_ONLY). In MODE_BINARY_ONLY, Time and Date are not used, only subsecond Signed-off-by: Francois Ramu --- src/rtc.c | 100 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/src/rtc.c b/src/rtc.c index 9ee676b..2033171 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -151,7 +151,8 @@ void HAL_RTC_MspDeInit(RTC_HandleTypeDef *rtcHandle) * @param None * @retval pointer to RTC_HandleTypeDef */ -RTC_HandleTypeDef *RTC_GetHandle(void) { +RTC_HandleTypeDef *RTC_GetHandle(void) +{ return &RtcHandle; } @@ -707,7 +708,7 @@ void RTC_SetTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSe */ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, hourAM_PM_t *period) { - RTC_TimeTypeDef RTC_TimeStruct; + RTC_TimeTypeDef RTC_TimeStruct = {0}; /* in BIN mode, only the subsecond is used */ if ((hours != NULL) && (minutes != NULL) && (seconds != NULL)) { #if defined(STM32F1xx) @@ -730,15 +731,21 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s } #if defined(RTC_SSR_SS) if (subSeconds != NULL) { + /* + * The subsecond is the free-running downcounter, to be converted in milliseconds. + * Give one more to compensate the fqce_apre uncertainty + */ if (initMode == MODE_BINARY_MIX) { - /* The subsecond is the free-running downcounter, to be converted in milliseconds */ *subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX) - * 1000) / fqce_apre; /* give one more to compensate the 3.9ms uncertainty */ - *subSeconds = *subSeconds % 1000; /* nb of milliseconds */ - /* predivAsync is 0x7F with LSE clock source */ + * 1000) / fqce_apre; + *subSeconds = *subSeconds % 1000; /* nb of milliseconds [0..999] */ + } else if (initMode == MODE_BINARY_ONLY) { + *subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX) + * 1000) / fqce_apre; } else { - /* the subsecond register value is converted in millisec */ - *subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1); + /* the subsecond register value is converted in millisec on 32bit */ + *subSeconds = (((predivSync - RTC_TimeStruct.SubSeconds + 1) & predivSync) + * 1000) / fqce_apre; } } #else @@ -789,7 +796,7 @@ void RTC_SetDate(uint8_t year, uint8_t month, uint8_t day, uint8_t wday) */ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday) { - RTC_DateTypeDef RTC_DateStruct; + RTC_DateTypeDef RTC_DateStruct = {0}; /* in BIN mode, the date is not used */ if ((year != NULL) && (month != NULL) && (day != NULL) && (wday != NULL)) { HAL_RTC_GetDate(&RtcHandle, &RTC_DateStruct, RTC_FORMAT_BIN); @@ -815,6 +822,9 @@ void RTC_GetDate(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *wday) */ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, hourAM_PM_t period, uint8_t mask) { +#if !defined(RTC_SSR_SS) + UNUSED(subSeconds); +#endif RTC_AlarmTypeDef RTC_AlarmStructure; /* Ignore time AM PM configuration if in 24 hours format */ @@ -842,17 +852,19 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u { RTC_AlarmStructure.AlarmSubSecondMask = predivSync_bits << RTC_ALRMASSR_MASKSS_Pos; } - if (initMode == MODE_BINARY_MIX) { + /* + * The subsecond param is a nb of milliseconds to be converted in a subsecond + * downcounter value and to be comapred to the SubSecond register + */ + if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_NONE)) { /* the subsecond is the millisecond to be converted in a subsecond downcounter value */ - RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - ((subSeconds * fqce_apre) / 1000 + 1); + RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000 + 1; } else { - RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000; + RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000 + 1; } } else { RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; } -#else - UNUSED(subSeconds); #endif /* RTC_SSR_SS */ if (period == HOUR_PM) { RTC_AlarmStructure.AlarmTime.TimeFormat = RTC_HOURFORMAT12_PM; @@ -882,7 +894,6 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u } } #else - UNUSED(subSeconds); UNUSED(period); UNUSED(day); UNUSED(mask); @@ -892,42 +903,40 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN); HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO); HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); -#if defined(RTC_ICSR_BIN) - } else if (RtcHandle.Init.BinMode != RTC_BINARY_NONE) { - /* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */ -#else - } else { -#endif /* RTC_ICSR_BIN */ + } #if defined(RTC_SSR_SS) - { + else { + /* SS have to be managed*/ #if defined(RTC_ALRMASSR_SSCLR) - RTC_AlarmStructure.BinaryAutoClr = RTC_ALARMSUBSECONDBIN_AUTOCLR_NO; + RTC_AlarmStructure.BinaryAutoClr = RTC_ALARMSUBSECONDBIN_AUTOCLR_NO; #endif /* RTC_ALRMASSR_SSCLR */ - RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_ALL; - + RTC_AlarmStructure.AlarmMask = RTC_ALARMMASK_ALL; #ifdef RTC_ALARM_B - if (name == ALARM_B) - { - /* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM B */ - RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMBSSR_MASKSS_Pos; - } else + if (name == ALARM_B) { + /* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM B */ + RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMBSSR_MASKSS_Pos; + } else #endif - { - /* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM A */ - RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos; - } + { + /* Expecting RTC_ALARMSUBSECONDBINMASK_NONE for the subsecond mask on ALARM A */ + RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos; + } +#if defined(RTC_ICSR_BIN) + if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) { + /* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */ /* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */ - RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * fqce_apre) / 1000; + RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000; + } else +#endif /* RTC_ICSR_BIN */ + { + RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - subSeconds * (predivSync + 1) / 1000; } - -#else - UNUSED(subSeconds); -#endif /* RTC_SSR_SS */ /* Set RTC_Alarm */ HAL_RTC_SetAlarm_IT(&RtcHandle, &RTC_AlarmStructure, RTC_FORMAT_BIN); HAL_NVIC_SetPriority(RTC_Alarm_IRQn, RTC_IRQ_PRIO, RTC_IRQ_SUBPRIO); HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); } +#endif /* RTC_SSR_SS */ } /** @@ -1013,14 +1022,15 @@ void RTC_GetAlarm(alarm_t name, uint8_t *day, uint8_t *hours, uint8_t *minutes, } #if defined(RTC_SSR_SS) if (subSeconds != NULL) { - if (initMode == MODE_BINARY_MIX) { - /* - * The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR) - * to be converted in milliseconds - */ + /* + * The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR) + * to be converted in milliseconds + */ + if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) { + /* read the ALARM SSR register on SS[14:0] bits --> 0x7FFF */ *subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre; } else { - *subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1); + *subSeconds = (((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & predivSync) * 1000) / (predivSync + 1); } } #else From a1543ea1ae0d624b18921d27aaa5c264937a7876 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 21 Sep 2023 16:22:51 +0200 Subject: [PATCH 14/23] feat: add new API to setAlarmTime with subsecond Add new API to set alarm Time with subseconds which is a nb of milliseconds. Similar to setAlarmSubSeconds. Signed-off-by: Francois Ramu --- README.md | 18 +++++++++++++++++ src/STM32RTC.cpp | 52 +++++++++++++++++++++++++++++++++++++----------- src/STM32RTC.h | 3 ++- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c913529..be001ec 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,24 @@ _Get the RTC handle_ * **`RTC_HandleTypeDef *RTC_GetHandle(void)`** +_binary and mix modes_ + +Some STM32 RTC have a binary mode with 32-bit free-running counter +in addition to their BCD mode for calendar (for example stm32wl55). +Combined with BCD this is the MIX mode. Only using the binary counter is the BIN mode. +Three RTC functional modes are available: + - `STM32RTC::MODE_BCD` + - `STM32RTC::MODE_MIX` + - `STM32RTC::MODE_BIN` + +* **`Binary_Mode getBinaryMode(void);`** +* **`void setBinaryMode(Binary_Mode mode);`** + + +Any API using the Subsecond parameter is expressed in milliseconds +whatever the RTC input clock. This parameter is [0..999] in MIX or BCD mode +and [0..0xFFFFFFFF] in BIN mode. In this configuration, time and date registers +are not used by the RTC. Refer to the Arduino RTC documentation for the other functions http://arduino.cc/en/Reference/RTC diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index a9b0ef3..20ea918 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -154,7 +154,13 @@ STM32RTC::Binary_Mode STM32RTC::getBinaryMode(void) */ void STM32RTC::setBinaryMode(Binary_Mode mode) { +#if defined(RTC_BINARY_NONE) _mode = mode; +#else +#warning "only BCD mode is supported" + UNUSED(mode); + _mode = MODE_BCD; +#endif /* RTC_BINARY_NONE */ } /** @@ -340,7 +346,7 @@ void STM32RTC::standbyMode(void) /** * @brief get RTC subseconds. - * @retval return the current subseconds from the RTC. + * @retval return the current milliseconds from the RTC. */ uint32_t STM32RTC::getSubSeconds(void) { @@ -388,7 +394,7 @@ uint8_t STM32RTC::getHours(AM_PM *period) * @param hours: pointer to the current hours * @param minutes: pointer to the current minutes * @param seconds: pointer to the current seconds - * @param subSeconds: pointer to the current subSeconds + * @param subSeconds: pointer to the current subSeconds (in milliseconds) * @param period: optional (default: nullptr) * pointer to the current hour period set in the RTC: AM or PM * @retval none @@ -835,20 +841,30 @@ void STM32RTC::setDate(uint8_t weekDay, uint8_t day, uint8_t month, uint8_t year /** * @brief set RTC alarm subseconds. - * @param subseconds: 0-999 (in ms) + * @param subseconds: 0-999 (in ms) or 32bit nb of milliseconds in BIN mode * @param name: optional (default: ALARM_A) * ALARM_A or ALARM_B if exists * @retval none */ void STM32RTC::setAlarmSubSeconds(uint32_t subSeconds, Alarm name) { - if (subSeconds < 1000) { +#ifndef RTC_ALARM_B + UNUSED(name); +#endif + if (_mode == MODE_BIN) { +#ifdef RTC_ALARM_B + if (name == ALARM_B) { + _alarmBSubSeconds = subSeconds; + } else +#endif + { + _alarmSubSeconds = subSeconds; + } + } else if (subSeconds < 1000) { #ifdef RTC_ALARM_B if (name == ALARM_B) { _alarmBSubSeconds = subSeconds; } else -#else - UNUSED(name); #endif { _alarmSubSeconds = subSeconds; @@ -931,7 +947,7 @@ void STM32RTC::setAlarmHours(uint8_t hours, AM_PM period, Alarm name) if (_format == HOUR_12) { _alarmBPeriod = period; } - } + } else #else UNUSED(name); #endif @@ -944,6 +960,18 @@ void STM32RTC::setAlarmHours(uint8_t hours, AM_PM period, Alarm name) } } + +/** + * @brief set RTC alarm time. + * @param subSeconds: 0-999 ms or 32bit nb of milliseconds in BIN mode + * @param name: ALARM_A or ALARM_B if exists + * @retval none + */ +void STM32RTC::setAlarmTime(uint32_t subSeconds, Alarm name) +{ + setAlarmTime(0, 0, 0, subSeconds, AM, name); +} + /** * @brief set RTC alarm time. * @param hours: 0-23 @@ -962,7 +990,7 @@ void STM32RTC::setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, Ala * @param hours: 0-23 * @param minutes: 0-59 * @param seconds: 0-59 - * @param subSeconds: 0-999 + * @param subSeconds: 0-999 ms or 32bit nb of milliseconds in BIN mode * @param name: ALARM_A or ALARM_B if exists * @retval none */ @@ -973,10 +1001,10 @@ void STM32RTC::setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uin /** * @brief set RTC alarm time. - * @param hours: 0-23 - * @param minutes: 0-59 - * @param seconds: 0-59 - * @param subSeconds: 0-999 (optional) + * @param hours: 0-23 (not used in BIN mode) + * @param minutes: 0-59 (not used in BIN mode) + * @param seconds: 0-59 (not used in BIN mode) + * @param subSeconds: 0-999 ms (optional) or 32bit nb of milliseconds in BIN mode * @param period: hour format AM or PM (optional) * @param name: optional (default: ALARM_A) * ALARM_A or ALARM_B if exists diff --git a/src/STM32RTC.h b/src/STM32RTC.h index e4a8198..0854727 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -86,7 +86,7 @@ class STM32RTC { }; enum Binary_Mode : uint8_t { - MODE_BCD = MODE_BINARY_NONE, /* not used */ + MODE_BCD = MODE_BINARY_NONE, MODE_BIN = MODE_BINARY_ONLY, MODE_MIX = MODE_BINARY_MIX }; @@ -208,6 +208,7 @@ class STM32RTC { void setAlarmMinutes(uint8_t minutes, Alarm name = ALARM_A); void setAlarmHours(uint8_t hours, Alarm name); void setAlarmHours(uint8_t hours, AM_PM period = AM, Alarm name = ALARM_A); + void setAlarmTime(uint32_t subSeconds, Alarm name = ALARM_A); void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, Alarm name); void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, Alarm name); void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds = 0, AM_PM period = AM, Alarm name = ALARM_A); From 2ae934d619261e829efee44376ad5616b8c0a6be Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 3 Jul 2023 09:35:00 +0200 Subject: [PATCH 15/23] chore(examples): RTC running in MIX or BCD mode with Alarm This examples is configuring the RTC in MIX (binary + calendar) or BCD and sets Alarm A & B (if exists) few ms after the current time. Signed-off-by: Francois Ramu --- examples/mixRTCAlarm/mixRTCAlarm.ino | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 examples/mixRTCAlarm/mixRTCAlarm.ino diff --git a/examples/mixRTCAlarm/mixRTCAlarm.ino b/examples/mixRTCAlarm/mixRTCAlarm.ino new file mode 100644 index 0000000..429181d --- /dev/null +++ b/examples/mixRTCAlarm/mixRTCAlarm.ino @@ -0,0 +1,99 @@ +/* + mode Mix RTC alarm + + This sketch shows how to configure the alarm A & B (if exists) + of the RTC in MIX or BCD (BINARY none) mode + + Creation 12 Dec 2017 + by Wi6Labs + Modified 03 Jul 2020 + by Frederic Pillon for STMicroelectronics + Modified 03 Jul 2023 + by Francois Ramu for STMicroelectronics + + This example code is in the public domain. + + https://github.com/stm32duino/STM32RTC +*/ + +#include + +/* Get the rtc object */ +STM32RTC& rtc = STM32RTC::getInstance(); + +/* Change these values to set the current initial time */ +const byte seconds = 06; +const byte minutes = 22; +const byte hours = 16; + +/* Change these values to set the current initial date */ +const byte day = 25; +const byte month = 6; +const byte year = 23; + +uint32_t timeout; + +void setup() +{ + Serial.begin(115200); + + // Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK. + rtc.setClockSource(STM32RTC::LSE_CLOCK); + + /* Configure the RTC mode : STM32RTC::MODE_MIX or STM32RTC::MODE_BCD */ + rtc.setBinaryMode(STM32RTC::MODE_BCD); + + rtc.begin(true, STM32RTC::HOUR_24); + + rtc.setTime(hours, minutes, seconds); + rtc.setDate(day, month, year); + + /* wait for a while */ + delay(300); + + Serial.printf("Start at %02d:%02d:%02d.%03d\r\n", + rtc.getHours(), rtc.getMinutes(), rtc.getSeconds(), rtc.getSubSeconds()); + + /* Attach the callback function before enabling Interrupt */ + rtc.attachInterrupt(alarmAMatch); + + /* Program the AlarmA in 12 seconds */ + rtc.setAlarmDay(day); + rtc.setAlarmTime(hours, minutes, seconds + 12); + rtc.enableAlarm(rtc.MATCH_DHHMMSS); + Serial.printf("Set Alarm A in 12s (at %02d:%02d:%02d)\r\n", + rtc.getAlarmHours(), rtc.getAlarmMinutes(), rtc.getAlarmSeconds()); + +#ifdef RTC_ALARM_B + /* Program ALARM B in 600ms ms from now (keep timeout < 1000ms) */ + timeout = rtc.getSubSeconds() + 600; + + rtc.attachInterrupt(alarmBMatch, STM32RTC::ALARM_B); + rtc.setAlarmSubSeconds(timeout, STM32RTC::ALARM_B); + rtc.enableAlarm(rtc.MATCH_SUBSEC, STM32RTC::ALARM_B); + Serial.printf("Set Alarm B (in %d ms) at %d ms\r\n", 600, + rtc.getAlarmSubSeconds(STM32RTC::ALARM_B)); +#endif /* RTC_ALARM_B */ +} + +void loop() +{ + /* Just wait for Alarm */ +} + +void alarmAMatch(void *data) +{ + UNUSED(data); + rtc.disableAlarm(STM32RTC::ALARM_A); + Serial.printf("Alarm A Match at %02d:%02d:%02d\r\n", + rtc.getHours(), rtc.getMinutes(), rtc.getSeconds()); +} + +#ifdef RTC_ALARM_B +void alarmBMatch(void *data) +{ + UNUSED(data); + rtc.disableAlarm(STM32RTC::ALARM_B); + Serial.printf("Alarm B Match at %d ms\r\n", rtc.getSubSeconds()); +} +#endif /* RTC_ALARM_B */ From c9d149687bad8db4ec02bed456c8f78fc2bab035 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 21 Sep 2023 09:59:49 +0200 Subject: [PATCH 16/23] chore(examples): RTC running in BINary mode with Alarm This examples is configuring the RTC in BIN mode (binary only) and sets Alarm A & B (if exists) a few ms after the current time. Signed-off-by: Francois Ramu --- .../bin_onlyRTCAlarm/bin_onlyRTCAlarm.ino | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 examples/bin_onlyRTCAlarm/bin_onlyRTCAlarm.ino diff --git a/examples/bin_onlyRTCAlarm/bin_onlyRTCAlarm.ino b/examples/bin_onlyRTCAlarm/bin_onlyRTCAlarm.ino new file mode 100644 index 0000000..e10d869 --- /dev/null +++ b/examples/bin_onlyRTCAlarm/bin_onlyRTCAlarm.ino @@ -0,0 +1,85 @@ +/* + mode BINary only RTC alarm + + This sketch shows how to configure the alarm A & B of the RTC in BIN mode + + Creation 12 Dec 2017 + by Wi6Labs + Modified 03 Jul 2020 + by Frederic Pillon for STMicroelectronics + Modified 03 sept 2023 + by Francois Ramu for STMicroelectronics + + This example code is in the public domain. + + https://github.com/stm32duino/STM32RTC +*/ + +#include + +/* Get the rtc object */ +STM32RTC& rtc = STM32RTC::getInstance(); + +uint32_t timeout; + +void setup() +{ + Serial.begin(115200); + + // Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK. + rtc.setClockSource(STM32RTC::LSE_CLOCK); + + /* Configure the RTC mode */ + rtc.setBinaryMode(STM32RTC::MODE_BIN); + + /* in BIN mode time and Date register are not used, only the subsecond register for milisseconds */ + rtc.begin(true, STM32RTC::HOUR_24); + + /* wait for a while */ + delay(300); + + /* subsecond expressed in milliseconds */ + Serial.printf("Start at %d ms \r\n", rtc.getSubSeconds()); + + /* Attach the callback function before enabling Interrupt */ + rtc.attachInterrupt(alarmAMatch); + + /* Program the AlarmA in 12 seconds */ + rtc.setAlarmTime(0, 0, 0, 12000); + rtc.enableAlarm(rtc.MATCH_SUBSEC); + Serial.printf("Set Alarm A in 12s (at %d ms)\r\n", rtc.getAlarmSubSeconds()); + +#ifdef RTC_ALARM_B + /* Program ALARM B in 600ms ms from now (keep timeout < 1000ms) */ + timeout = rtc.getSubSeconds() + 600; + + rtc.attachInterrupt(alarmBMatch, STM32RTC::ALARM_B); + rtc.setAlarmSubSeconds(timeout, STM32RTC::ALARM_B); + rtc.enableAlarm(rtc.MATCH_SUBSEC, STM32RTC::ALARM_B); + Serial.printf("Set Alarm B (in %d ms) at %d ms\r\n", 600, + rtc.getAlarmSubSeconds(STM32RTC::ALARM_B)); +#endif /* RTC_ALARM_B */ + +} + +void loop() +{ + +} + +void alarmAMatch(void *data) +{ + UNUSED(data); + rtc.disableAlarm(STM32RTC::ALARM_A); + Serial.printf("Alarm A Match at %d ms \r\n", rtc.getSubSeconds()); +} + +#ifdef RTC_ALARM_B +void alarmBMatch(void *data) +{ + UNUSED(data); + rtc.disableAlarm(STM32RTC::ALARM_B); /* Else it will trig again */ + Serial.printf("Alarm B Match at %d ms\r\n", rtc.getSubSeconds()); +} +#endif /* RTC_ALARM_B */ + From e466ec94fc89ec1455253f295616eb27d123e1fa Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Mon, 25 Sep 2023 13:59:23 +0200 Subject: [PATCH 17/23] chore(keywords): add new api and types Signed-off-by: Frederic Pillon --- keywords.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/keywords.txt b/keywords.txt index 5663a9e..0c1af19 100644 --- a/keywords.txt +++ b/keywords.txt @@ -13,6 +13,10 @@ STM32RTC KEYWORD1 ####################################### getInstance KEYWORD2 +getHandle KEYWORD2 + +getBinaryMode KEYWORD2 +setBinaryMode KEYWORD2 getWeekDay KEYWORD2 getDay KEYWORD2 @@ -85,6 +89,7 @@ IS_HOUR_FORMAT KEYWORD2 # Constants (LITERAL1) ####################################### MATCH_OFF LITERAL1 +MATCH_SUBSEC LITERAL1 MATCH_SS LITERAL1 MATCH_MMSS LITERAL1 MATCH_HHMMSS LITERAL1 @@ -100,3 +105,6 @@ LSI_CLOCK LITERAL1 HSE_CLOCK LITERAL1 ALARM_A LITERAL1 ALARM_B LITERAL1 +MODE_BCD LITERAL1 +MODE_BIN LITERAL1 +MODE_MIX LITERAL1 From 3ce53c4e7b0894321c6938d022e1e9e8b7a8d6f2 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 20 Jun 2023 10:57:18 +0200 Subject: [PATCH 18/23] fix calculation of subsecond conversion in MIX or BIN mode Depending on the RTC mode, the SSR subsecond register and AlarmSSR differ when converted to/from a value in milliseconds Correcting the formula in GetTime, GetAlarm/StartAlarm functions. Clarify the use of getEpoch and setAlarmEpoch in BIN only mode. Signed-off-by: Francois Ramu --- README.md | 6 ++++-- src/STM32RTC.cpp | 11 +++++++---- src/rtc.c | 34 ++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index be001ec..fbf5d80 100644 --- a/README.md +++ b/README.md @@ -174,8 +174,10 @@ Three RTC functional modes are available: Any API using the Subsecond parameter is expressed in milliseconds whatever the RTC input clock. This parameter is [0..999] in MIX or BCD mode -and [0..0xFFFFFFFF] in BIN mode. In this configuration, time and date registers -are not used by the RTC. +and [0..0xFFFFFFFF] in BIN mode. In BIN only mode, time and date registers are not used +by the RTC. Thus the getEpoch function is only to be called to get the subsecond [0..0xFFFFFFFF] +(returned time_t is not valid). The setAlarmEpoch only uses the sub-second [0..0xFFFFFFFF] +(time_t value is useless). Refer to the Arduino RTC documentation for the other functions http://arduino.cc/en/Reference/RTC diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 20ea918..1a8eb84 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -1205,10 +1205,13 @@ void STM32RTC::setAlarmEpoch(time_t ts, Alarm_Match match, uint32_t subSeconds, time_t t = ts; struct tm *tmp = gmtime(&t); - setAlarmDay(tmp->tm_mday, name); - setAlarmHours(tmp->tm_hour, name); - setAlarmMinutes(tmp->tm_min, name); - setAlarmSeconds(tmp->tm_sec, name); + /* in BIN only mode, the time_t is not relevant, but only the subSeconds in ms */ + if (_mode != MODE_BIN) { + setAlarmDay(tmp->tm_mday, name); + setAlarmHours(tmp->tm_hour, name); + setAlarmMinutes(tmp->tm_min, name); + setAlarmSeconds(tmp->tm_sec, name); + } setAlarmSubSeconds(subSeconds, name); enableAlarm(match, name); } diff --git a/src/rtc.c b/src/rtc.c index 2033171..f28f68e 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -571,6 +571,10 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool #else RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); #endif + /* + * TODO: RTC is already initialized, but RTC BIN mode is changed + * force the update of the BIN register in the RTC_ICSR + */ #if defined(RTC_BINARY_NONE) RTC_BinaryConf(mode); #endif /* RTC_BINARY_NONE */ @@ -615,6 +619,11 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool HAL_RTCEx_EnableBypassShadow(&RtcHandle); #endif + /* + * NOTE: freezing the RTC during stop mode (lowPower deepSleep) + * could inhibit the alarm interrupt and prevent the system to wakeUp + * from stop mode even if the RTC alarm flag is set. + */ return reinit; } @@ -733,19 +742,16 @@ void RTC_GetTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *s if (subSeconds != NULL) { /* * The subsecond is the free-running downcounter, to be converted in milliseconds. - * Give one more to compensate the fqce_apre uncertainty */ - if (initMode == MODE_BINARY_MIX) { + if (initMode == MODE_BINARY_ONLY) { *subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX) * 1000) / fqce_apre; - *subSeconds = *subSeconds % 1000; /* nb of milliseconds [0..999] */ - } else if (initMode == MODE_BINARY_ONLY) { - *subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds + 1) & UINT32_MAX) + } else if (initMode == MODE_BINARY_MIX) { + *subSeconds = (((UINT32_MAX - RTC_TimeStruct.SubSeconds) & predivSync) * 1000) / fqce_apre; } else { /* the subsecond register value is converted in millisec on 32bit */ - *subSeconds = (((predivSync - RTC_TimeStruct.SubSeconds + 1) & predivSync) - * 1000) / fqce_apre; + *subSeconds = ((predivSync - RTC_TimeStruct.SubSeconds) * 1000) / (predivSync + 1); } } #else @@ -854,13 +860,13 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u } /* * The subsecond param is a nb of milliseconds to be converted in a subsecond - * downcounter value and to be comapred to the SubSecond register + * downcounter value and to be compared to the SubSecond register */ - if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_NONE)) { + if ((initMode == MODE_BINARY_ONLY) || (initMode == MODE_BINARY_MIX)) { /* the subsecond is the millisecond to be converted in a subsecond downcounter value */ - RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000 + 1; + RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000; } else { - RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000 + 1; + RTC_AlarmStructure.AlarmTime.SubSeconds = predivSync - (subSeconds * (predivSync + 1)) / 1000; } } else { RTC_AlarmStructure.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; @@ -922,7 +928,7 @@ void RTC_StartAlarm(alarm_t name, uint8_t day, uint8_t hours, uint8_t minutes, u RTC_AlarmStructure.AlarmSubSecondMask = mask << RTC_ALRMASSR_MASKSS_Pos; } #if defined(RTC_ICSR_BIN) - if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) { + if ((initMode == MODE_BINARY_ONLY) || (initMode == MODE_BINARY_MIX)) { /* We have an SubSecond alarm to set in RTC_BINARY_MIX or RTC_BINARY_ONLY mode */ /* The subsecond in ms is converted in ticks unit 1 tick is 1000 / fqce_apre */ RTC_AlarmStructure.AlarmTime.SubSeconds = UINT32_MAX - (subSeconds * (predivSync + 1)) / 1000; @@ -1026,11 +1032,11 @@ void RTC_GetAlarm(alarm_t name, uint8_t *day, uint8_t *hours, uint8_t *minutes, * The subsecond is the bit SS[14:0] of the ALARM SSR register (not ALARMxINR) * to be converted in milliseconds */ - if ((initMode == MODE_BINARY_MIX) || (initMode == MODE_BINARY_ONLY)) { + if ((initMode == MODE_BINARY_ONLY) || (initMode == MODE_BINARY_MIX)) { /* read the ALARM SSR register on SS[14:0] bits --> 0x7FFF */ *subSeconds = (((0x7fff - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & 0x7fff) * 1000) / fqce_apre; } else { - *subSeconds = (((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds + 1) & predivSync) * 1000) / (predivSync + 1); + *subSeconds = ((predivSync - RTC_AlarmStructure.AlarmTime.SubSeconds) * 1000) / (predivSync + 1); } } #else From 120d547a3085a834c79d76a2a5ea65ddd1acfb7a Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 3 Oct 2023 15:37:52 +0200 Subject: [PATCH 19/23] chore: harden deinit Signed-off-by: Frederic Pillon --- src/rtc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/rtc.c b/src/rtc.c index f28f68e..dd952ad 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -132,17 +132,11 @@ void HAL_RTC_MspDeInit(RTC_HandleTypeDef *rtcHandle) { if (rtcHandle->Instance == RTC) { - /* Peripheral clock disable */ - __HAL_RCC_RTC_DISABLE(); -#ifdef __HAL_RCC_RTCAPB_CLK_DISABLE - __HAL_RCC_RTCAPB_CLK_DISABLE(); -#endif /* RTC interrupt Deinit */ #if defined(STM32WLxx) /* Only the STM32WLxx series has a TAMP_STAMP_LSECSS_SSRU_IRQn */ HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); #endif /* STM32WLxx */ - HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn); } } @@ -635,6 +629,15 @@ bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool void RTC_DeInit(bool reset_cb) { HAL_RTC_DeInit(&RtcHandle); + /* Peripheral clock disable */ + __HAL_RCC_RTC_DISABLE(); +#ifdef __HAL_RCC_RTCAPB_CLK_DISABLE + __HAL_RCC_RTCAPB_CLK_DISABLE(); +#endif + HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn); +#ifdef ONESECOND_IRQn + HAL_NVIC_DisableIRQ(ONESECOND_IRQn); +#endif if (reset_cb) { RTCUserCallback = NULL; callbackUserData = NULL; From 2ccc178dc91de1ccb438ac5706f1341e59515b0f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 5 Oct 2023 09:34:33 +0200 Subject: [PATCH 20/23] chore: factorize code Signed-off-by: Frederic Pillon --- src/STM32RTC.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 1a8eb84..64b8e70 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -851,16 +851,7 @@ void STM32RTC::setAlarmSubSeconds(uint32_t subSeconds, Alarm name) #ifndef RTC_ALARM_B UNUSED(name); #endif - if (_mode == MODE_BIN) { -#ifdef RTC_ALARM_B - if (name == ALARM_B) { - _alarmBSubSeconds = subSeconds; - } else -#endif - { - _alarmSubSeconds = subSeconds; - } - } else if (subSeconds < 1000) { + if ((_mode == MODE_BIN) || (subSeconds < 1000)) { #ifdef RTC_ALARM_B if (name == ALARM_B) { _alarmBSubSeconds = subSeconds; From 82267c2564305f7cbfe349d0cb7c6b12019b871d Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 5 Oct 2023 16:01:59 +0200 Subject: [PATCH 21/23] chore: RTCSecondsIrqCallback only when ONESECOND_IRQn Signed-off-by: Frederic Pillon --- src/rtc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rtc.c b/src/rtc.c index dd952ad..c68a92f 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -63,8 +63,9 @@ static void *callbackUserData = NULL; static voidCallbackPtr RTCUserCallbackB = NULL; static void *callbackUserDataB = NULL; #endif +#ifdef ONESECOND_IRQn static voidCallbackPtr RTCSecondsIrqCallback = NULL; - +#endif static sourceClock_t clkSrc = LSI_CLOCK; static uint32_t clkVal = LSI_VALUE; static uint8_t HSEDiv = 0; @@ -645,7 +646,9 @@ void RTC_DeInit(bool reset_cb) RTCUserCallbackB = NULL; callbackUserDataB = NULL; #endif +#ifdef ONESECOND_IRQn RTCSecondsIrqCallback = NULL; +#endif } } From dccec10583947b6a22da5b6692dab5a8656f5065 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 5 Oct 2023 16:42:07 +0200 Subject: [PATCH 22/23] feat: add SubSecondinterrupt underflow api for STM32WLxx Signed-off-by: Frederic Pillon --- README.md | 8 +++++ keywords.txt | 2 ++ src/STM32RTC.cpp | 25 +++++++++++++ src/STM32RTC.h | 5 +++ src/rtc.c | 94 ++++++++++++++++++++++++++---------------------- src/rtc.h | 13 +++++-- 6 files changed, 101 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index fbf5d80..bc11b65 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,14 @@ by the RTC. Thus the getEpoch function is only to be called to get the subsecond (returned time_t is not valid). The setAlarmEpoch only uses the sub-second [0..0xFFFFFFFF] (time_t value is useless). +_SubSeconds underflow_ + +Only dor STM32WLxx. Manage interrupt (SSRU) when SubSeconds register +underflow. Used by STM32LoRaWAN. + +* **`void attachSubSecondsUnderflowInterrupt(voidFuncPtr callback);`** +* **`void detachSubSecondsUnderflowInterrupt(void);`** + Refer to the Arduino RTC documentation for the other functions http://arduino.cc/en/Reference/RTC diff --git a/keywords.txt b/keywords.txt index 0c1af19..37fcf3d 100644 --- a/keywords.txt +++ b/keywords.txt @@ -72,6 +72,8 @@ attachInterrupt KEYWORD2 detachInterrupt KEYWORD2 attachSecondsInterrupt KEYWORD2 detachSecondsInterrupt KEYWORD2 +attachSubSecondsUnderflowInterrupt KEYWORD2 +detachSubSecondsUnderflowInterrupt KEYWORD2 getClockSource KEYWORD2 setClockSource KEYWORD2 diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 64b8e70..4a29928 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -334,6 +334,31 @@ void STM32RTC::detachSecondsInterrupt(void) } #endif /* ONESECOND_IRQn */ + +#ifdef STM32WLxx +/** + * @brief attach a callback to the RTC SubSeconds underflow interrupt. + * @note only for STM32WLxx + * @param callback: pointer to the callback + * @retval None + */ +void STM32RTC::attachSubSecondsUnderflowInterrupt(voidFuncPtr callback) +{ + attachSubSecondsUnderflowIrqCallback(callback); +} + +/** + * @brief detach the RTC SubSeconds underflow callback. + * @retval None + */ +void STM32RTC::detachSubSecondsUnderflowInterrupt(void) +{ + detachSubSecondsUnderflowIrqCallback(); +} + +#endif /* STM32WLxx */ + + // Kept for compatibility. Use STM32LowPower library. void STM32RTC::standbyMode(void) { diff --git a/src/STM32RTC.h b/src/STM32RTC.h index 0854727..6235b6c 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -159,6 +159,11 @@ class STM32RTC { void detachSecondsInterrupt(void); #endif /* ONESECOND_IRQn */ +#ifdef STM32WLxx + // STM32WLxx has a dedicated IRQ + void attachSubSecondsUnderflowInterrupt(voidFuncPtr callback); + void detachSubSecondsUnderflowInterrupt(void); +#endif /* STM32WLxx */ // Kept for compatibility: use STM32LowPower library. void standbyMode(); diff --git a/src/rtc.c b/src/rtc.c index c68a92f..73c911f 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -66,6 +66,9 @@ static void *callbackUserDataB = NULL; #ifdef ONESECOND_IRQn static voidCallbackPtr RTCSecondsIrqCallback = NULL; #endif +#ifdef STM32WLxx +static voidCallbackPtr RTCSubSecondsUnderflowIrqCallback = NULL; +#endif static sourceClock_t clkSrc = LSI_CLOCK; static uint32_t clkVal = LSI_VALUE; static uint8_t HSEDiv = 0; @@ -98,49 +101,6 @@ static inline int _log2(int x) } /* Exported functions --------------------------------------------------------*/ - -/* HAL MSP function used for RTC_Init */ -void HAL_RTC_MspInit(RTC_HandleTypeDef *rtcHandle) -{ -#if defined(RTC_SCR_CSSRUF) - if (rtcHandle->Instance == RTC) { - /* In BINARY mode (MIX or ONLY), set the SSR Underflow interrupt */ - if (rtcHandle->Init.BinMode != RTC_BINARY_NONE) { -#if defined(STM32WLxx) - /* Only the STM32WLxx series has a TAMP_STAMP_LSECSS_SSRU_IRQn */ - if (HAL_RTCEx_SetSSRU_IT(rtcHandle) != HAL_OK) { - Error_Handler(); - } - /* Give init value for the RtcFeatures enable */ - rtcHandle->IsEnabled.RtcFeatures = 0; - - /* RTC interrupt Init */ - HAL_NVIC_SetPriority(TAMP_STAMP_LSECSS_SSRU_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); -#else - /* The STM32U5, STM32H5, STM32L4plus have common RTC interrupt and a SSRU flag */ - __HAL_RTC_SSRU_ENABLE_IT(rtcHandle, RTC_IT_SSRU); -#endif /* STM32WLxx */ - } - } -#else /* RTC_SCR_CSSRUF */ - UNUSED(rtcHandle); -#endif /* RTC_SCR_CSSRUF */ - /* RTC_Alarm_IRQn is enabled when enabling Alarm */ -} - -void HAL_RTC_MspDeInit(RTC_HandleTypeDef *rtcHandle) -{ - - if (rtcHandle->Instance == RTC) { - /* RTC interrupt Deinit */ -#if defined(STM32WLxx) - /* Only the STM32WLxx series has a TAMP_STAMP_LSECSS_SSRU_IRQn */ - HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); -#endif /* STM32WLxx */ - } -} - /** * @brief Get pointer to RTC_HandleTypeDef * @param None @@ -638,6 +598,9 @@ void RTC_DeInit(bool reset_cb) HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn); #ifdef ONESECOND_IRQn HAL_NVIC_DisableIRQ(ONESECOND_IRQn); +#endif +#ifdef STM32WLxx + HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); #endif if (reset_cb) { RTCUserCallback = NULL; @@ -648,6 +611,9 @@ void RTC_DeInit(bool reset_cb) #endif #ifdef ONESECOND_IRQn RTCSecondsIrqCallback = NULL; +#endif +#ifdef STM32WLxx + RTCSubSecondsUnderflowIrqCallback = NULL; #endif } } @@ -1266,6 +1232,48 @@ void RTC_WKUP_IRQHandler(void) #endif /* STM32F1xx */ #endif /* ONESECOND_IRQn */ +#ifdef STM32WLxx +/** + * @brief Attach SubSeconds underflow interrupt callback. + * @param func: pointer to the callback + * @retval None + */ +void attachSubSecondsUnderflowIrqCallback(voidCallbackPtr func) +{ + /* Callback called on SSRU interrupt */ + RTCSubSecondsUnderflowIrqCallback = func; + + /* Enable the IRQ that will trig the one-second interrupt */ + if (HAL_RTCEx_SetSSRU_IT(&RtcHandle) != HAL_OK) { + Error_Handler(); + } + HAL_NVIC_SetPriority(TAMP_STAMP_LSECSS_SSRU_IRQn, RTC_IRQ_SSRU_PRIO, RTC_IRQ_SSRU_SUBPRIO); + HAL_NVIC_EnableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); +} + +/** + * @brief Detach SubSeconds underflow interrupt callback. + * @param None + * @retval None + */ +void detachSubSecondsUnderflowIrqCallback(void) +{ + RTCSubSecondsUnderflowIrqCallback = NULL; + if (HAL_RTCEx_DeactivateSSRU(&RtcHandle) != HAL_OK) { + Error_Handler(); + } + HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_SSRU_IRQn); +} + +void HAL_RTCEx_SSRUEventCallback(RTC_HandleTypeDef *hrtc) +{ + (void)hrtc; + if (RTCSubSecondsUnderflowIrqCallback != NULL) { + RTCSubSecondsUnderflowIrqCallback(NULL); + } +} +#endif /* STM32WLxx */ + #if defined(STM32F1xx) void RTC_StoreDate(void) { diff --git a/src/rtc.h b/src/rtc.h index 4983148..8d0bcd8 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -108,8 +108,12 @@ typedef void(*voidCallbackPtr)(void *); #ifndef RTC_IRQ_SUBPRIO #define RTC_IRQ_SUBPRIO 0 #endif - - +#ifndef RTC_IRQ_SSRU_PRIO +#define RTC_IRQ_SSRU_PRIO 0 +#endif +#ifndef RTC_IRQ_SSRU_SUBPRIO +#define RTC_IRQ_SSRU_SUBPRIO 0 +#endif #define HSE_RTC_MAX 1000000U #if !defined(STM32F1xx) @@ -198,7 +202,10 @@ void detachAlarmCallback(alarm_t name); void attachSecondsIrqCallback(voidCallbackPtr func); void detachSecondsIrqCallback(void); #endif /* ONESECOND_IRQn */ - +#ifdef STM32WLxx +void attachSubSecondsUnderflowIrqCallback(voidCallbackPtr func); +void detachSubSecondsUnderflowIrqCallback(void); +#endif /* STM32WLxx */ #if defined(STM32F1xx) void RTC_StoreDate(void); #endif From 90414bcb87c41307b9a93b84a4ae589d6d621325 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 12 Oct 2023 10:44:56 +0200 Subject: [PATCH 23/23] chore: update library version to 1.4.0 Signed-off-by: Frederic Pillon --- library.json | 2 +- library.properties | 2 +- src/STM32RTC.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library.json b/library.json index 80ec1cc..5c570df 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/stm32duino/STM32RTC" }, - "version": "1.3.7", + "version": "1.4.0", "frameworks": "arduino", "platforms": "ststm32", "build": { diff --git a/library.properties b/library.properties index bd8adde..4666e3a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=STM32duino RTC -version=1.3.7 +version=1.4.0 author=STMicroelectronics maintainer=stm32duino sentence=Allows to use the RTC functionalities of STM32 based boards. diff --git a/src/STM32RTC.h b/src/STM32RTC.h index 6235b6c..fe0374c 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -52,8 +52,8 @@ * @brief STM32 RTC library version number */ #define STM32_RTC_VERSION_MAJOR (0x01U) /*!< [31:24] major version */ -#define STM32_RTC_VERSION_MINOR (0x03U) /*!< [23:16] minor version */ -#define STM32_RTC_VERSION_PATCH (0x06U) /*!< [15:8] patch version */ +#define STM32_RTC_VERSION_MINOR (0x04U) /*!< [23:16] minor version */ +#define STM32_RTC_VERSION_PATCH (0x00U) /*!< [15:8] patch version */ /* * Extra label for development: * 0: official release