Skip to content

Commit c5d7fda

Browse files
committed
OS/FreeRTOS: fix tick drift caused by wrong elapsed time calculation
When WFI wakes up but MTIME has not yet incremented, xModifiableIdleTime equals XLastLoadValue. The previous '>' comparison would fall through to the else branch and compute a bogus wraparound value (0xFFFFFFFF cycles), causing vTaskStepTick() to advance the system tick by a huge amount. Change '>' to '>=' so that equal values correctly yield zero elapsed time. Signed-off-by: Huaqi Fang <578567190@qq.com>
1 parent 906b2a5 commit c5d7fda

2 files changed

Lines changed: 6 additions & 1 deletion

File tree

OS/FreeRTOS/Source/portable/port.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,11 @@ __attribute__((weak)) void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTi
681681
periods (not the ulReload value which accounted for part
682682
ticks). */
683683
xModifiableIdleTime = SysTimer_GetLoadValue();
684-
if (xModifiableIdleTime > XLastLoadValue) {
684+
/* Use >= to handle the case where WFI wakes up but MTIME has not
685+
yet incremented (xModifiableIdleTime == XLastLoadValue), in which
686+
case elapsed time is 0 instead of wrapping around via the else
687+
branch which would produce a bogus large tick count. */
688+
if (xModifiableIdleTime >= XLastLoadValue) {
685689
ulCompletedSysTickDecrements = (xModifiableIdleTime - XLastLoadValue);
686690
} else {
687691
ulCompletedSysTickDecrements = (xModifiableIdleTime + portMAX_BIT_NUMBER - XLastLoadValue);

doc/source/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ This is release version of ``0.9.0`` of Nuclei SDK.
169169
- Fix FreeRTOS port macro interrupt masking implementation in ``portmacro.h`` to ensure pending interrupts are properly handled after enabling interrupts, preventing assertion failures from executing code before interrupt response
170170
- Fix RT-Thread and UCOSII interrupt masking implementation in ``cpuport.c`` and ``os_cpu_port.h`` to add memory barriers after CSR operations, ensuring pending interrupts are properly handled after enabling interrupts
171171
- Fix FreeRTOS tickless sleep mode by removing unnecessary ``__FENCE_I()`` call in ``vPortSuppressTicksAndSleep`` function to avoid i-cache misses and reduce interrupt latency. The ``__RWMB()`` memory barrier is sufficient for proper interrupt enable propagation
172+
- Fix FreeRTOS tickless sleep elapsed time calculation in ``vPortSuppressTicksAndSleep`` function by changing ``>`` to ``>=`` comparison, which prevents bogus tick count when WFI wakes up but MTIME has not yet incremented, avoiding incorrect system tick advancement
172173
- Upgrade FreeRTOS to v11.2.0 and update porting layer to match new API requirements (critical nesting macros and recursive lock functions now accept core ID parameter for SMP systems)
173174
- Fix ThreadX ``tx_port.h`` interrupt disable/restore macros (``TX_DISABLE``/``TX_RESTORE``) by adding ``volatile`` keyword and ``memory`` clobber to inline assembly to prevent compiler reordering and ensure proper memory barrier semantics
174175
- Add memory barriers to ThreadX UP and SMP ports after interrupt control operations (such as ``__enable_irq()`` and ``CSR_MSTATUS`` access) to ensure proper synchronization and prevent potential compiler/CPU reordering issues

0 commit comments

Comments
 (0)