summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwdfk-prog <[email protected]>2026-02-03 14:43:02 +0800
committerR b b666 <[email protected]>2026-02-03 18:50:17 +0800
commitf9de2909915079449aae444eeefd361b66e239f0 (patch)
tree7b65fcfaff0604f4f3c4dab297f1a9b86790c75c
parent06e829b1b3d8bfd39c9e602baf23fe34a669a291 (diff)
fix[STM32][RTC]: Compute tv_usec from SecondFraction/SubSeconds and skip during shift pending
Use the generic SecondFraction/SubSeconds formula when SSR/PRER are available. If SHPF is present and a shift is pending, keep tv_usec at 0. Platforms without SSR/PRER (e.g. F1) default to 0.
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drivers/drv_rtc.c29
1 files changed, 25 insertions, 4 deletions
diff --git a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_rtc.c b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_rtc.c
index b86c4ba93b..fcf3494458 100644
--- a/bsp/stm32/libraries/HAL_Drivers/drivers/drv_rtc.c
+++ b/bsp/stm32/libraries/HAL_Drivers/drivers/drv_rtc.c
@@ -10,6 +10,7 @@
* 2021-02-05 Meco Man fix the problem of mixing local time and UTC time
* 2021-07-05 iysheng implement RTC framework V2.0
* 2025-06-05 RCSN add local time conversion for get timeval and set stamp
+ * 0206-02-03 wdfk_prog compute tv_usec from SecondFraction/SubSeconds
*/
#include "board.h"
@@ -85,10 +86,30 @@ static rt_err_t stm32_rtc_get_timeval(struct timeval *tv)
#else
tv->tv_sec = timegm(&tm_new);
#endif
-#if defined(SOC_SERIES_STM32H7)
- tv->tv_usec = (255.0 - RTC_TimeStruct.SubSeconds * 1.0) / 256.0 * 1000.0 * 1000.0;
-#endif
-
+ tv->tv_usec = 0U;
+/* F1 RTC does not have SSR/PRER */
+#if defined(RTC_SSR_SS) && defined(RTC_PRER_PREDIV_S)
+ /*
+ * You can use SubSeconds and SecondFraction (sTime structure fields
+ * returned) to convert SubSeconds value in second fraction ratio with
+ * time unit following generic formula:
+ * Second fraction ratio * time_unit =
+ * [(SecondFraction - SubSeconds) / (SecondFraction + 1)] * time_unit
+ * This conversion can be performed only if no shift operation is pending
+ * (ie. SHFP=0) when PREDIV_S >= SS
+ */
+#if defined(RTC_ISR_SHPF)
+ if (READ_BIT(RTC->ISR, RTC_ISR_SHPF) == 0U)
+#endif /* RTC_ISR_SHPF */
+ {
+ uint32_t sf = RTC_TimeStruct.SecondFraction;
+ uint32_t ss = RTC_TimeStruct.SubSeconds;
+ if ((sf != 0U) && (ss <= sf))
+ {
+ tv->tv_usec = (uint32_t)(((sf - ss) * 1000000ULL) / (sf + 1U));
+ }
+ }
+#endif /* defined(RTC_SSR_SS) && defined(RTC_PRER_PREDIV_S) */
return RT_EOK;
}