From 11d389fcea91f0f5cf2e3fe38d66edfcbc108260 Mon Sep 17 00:00:00 2001 From: tanyanquan Date: Tue, 4 Nov 2025 13:09:47 +0800 Subject: [PATCH] [csl] restart CSL timer when update last sync timestamp (#11601) This commit involves a small enhancement for CSL to optimize for power consumption after receiving a frame. Original implementation: - schedule next CSL window during current CSL timer handle - even if a frame is received, the scheduled CSL timer is not reset - SSED wakes up much earlier than required if elapsed time is large Suggested implementation: - recalculate CSL timer during `UpdateCslLastSyncTimestamp` if it is currently running - SSED can use updated mCslLastSync so that it does not wake up much earlier after receiving a frame --- src/core/mac/sub_mac.hpp | 1 + src/core/mac/sub_mac_csl_receiver.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index 6cab2ce06..5437a0a3f 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -501,6 +501,7 @@ public: private: #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE void CslInit(void); + void RestartCslTimerAfterSyncUpdate(void); void UpdateCslLastSyncTimestamp(TxFrame &aFrame, RxFrame *aAckFrame); void UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError); static void HandleCslTimer(Timer &aTimer); diff --git a/src/core/mac/sub_mac_csl_receiver.cpp b/src/core/mac/sub_mac_csl_receiver.cpp index 9c51c3403..bfe032659 100644 --- a/src/core/mac/sub_mac_csl_receiver.cpp +++ b/src/core/mac/sub_mac_csl_receiver.cpp @@ -54,6 +54,25 @@ void SubMac::CslInit(void) mCslTimer.Stop(); } +void SubMac::RestartCslTimerAfterSyncUpdate(void) +{ + // Only applies for the case where radio supports receive timing. + if (RadioSupportsReceiveTiming() && mCslTimer.IsRunning()) + { + uint32_t periodUs = mCslPeriod * kUsPerTenSymbols; + + mCslTimer.Stop(); + + // Rewind sample times by one period. HandleCslTimer() will add this + // period back, effectively re-evaluating the current CSL period's + // schedule using the updated mCslLastSync. + mCslSampleTimeRadio -= periodUs; + mCslSampleTimeLocal -= periodUs; + + HandleCslTimer(); + } +} + void SubMac::UpdateCslLastSyncTimestamp(TxFrame &aFrame, RxFrame *aAckFrame) { // Actual synchronization timestamp should be from the sent frame instead of the current time. @@ -62,6 +81,8 @@ void SubMac::UpdateCslLastSyncTimestamp(TxFrame &aFrame, RxFrame *aAckFrame) { mCslLastSync = TimeMicro(GetLocalTime()); } + + RestartCslTimerAfterSyncUpdate(); } void SubMac::UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError) @@ -82,6 +103,8 @@ void SubMac::UpdateCslLastSyncTimestamp(RxFrame *aFrame, Error aError) #endif } + RestartCslTimerAfterSyncUpdate(); + exit: return; }