@@ -28,12 +28,10 @@ static rt_device_t systick_dev;
2828
2929/**
3030 * @brief Systick ISR callback
31- *
3231 */
3332static void systick_isr_cb (void )
3433{
3534 __systime .msPeriod += __systime .msPerPeriod ;
36-
3735 rt_tick_increase ();
3836}
3937
@@ -96,20 +94,35 @@ uint64_t systime_now_us(void)
9694{
9795 uint32_t systick_us = 0 ;
9896 uint64_t time_now_ms ;
97+ uint64_t now_us ;
98+ static uint64_t monotonic_us = 0 ;
9999 uint32_t level ;
100100
101101 if (systick_dev == NULL ) {
102102 return 0 ;
103103 }
104104
105- rt_device_read (systick_dev , SYSTICK_RD_TIME_US , & systick_us , sizeof (uint32_t ));
106-
107105 level = rt_hw_interrupt_disable ();
106+ rt_device_read (systick_dev , SYSTICK_RD_TIME_US , & systick_us , sizeof (uint32_t ));
108107 /* atomic read */
109108 time_now_ms = __systime .msPeriod ;
109+
110+ now_us = time_now_ms * 1000ULL + systick_us ;
111+
112+ /* Fix the race condition where the SysTick hardware timer has wrapped around */
113+ if (now_us < monotonic_us ) {
114+ now_us += (uint64_t )__systime .msPerPeriod * 1000ULL ;
115+ }
116+
117+ /* Ensure strict monotonicity */
118+ if (now_us > monotonic_us ) {
119+ monotonic_us = now_us ;
120+ } else {
121+ now_us = monotonic_us ;
122+ }
110123 rt_hw_interrupt_enable (level );
111124
112- return time_now_ms * ( uint64_t ) 1000 + systick_us ;
125+ return now_us ;
113126}
114127
115128/**
@@ -189,7 +202,8 @@ fmt_err_t systime_init(void)
189202 systick_device = (systick_dev_t )systick_dev ;
190203
191204 __systime .msPeriod = 0 ;
192- __systime .msPerPeriod = systick_device -> ticks_per_isr / systick_device -> ticks_per_us / 1e3 ;
205+ /* Calculate integer ms without losing precision */
206+ __systime .msPerPeriod = systick_device -> ticks_per_isr / (systick_device -> ticks_per_us * 1000 );
193207
194208 systick_device -> systick_isr_cb = systick_isr_cb ;
195209
0 commit comments