diff --git a/src/core/thread/data_poll_manager.cpp b/src/core/thread/data_poll_manager.cpp index a07ad122e..6958a4771 100644 --- a/src/core/thread/data_poll_manager.cpp +++ b/src/core/thread/data_poll_manager.cpp @@ -392,18 +392,42 @@ exit: void DataPollManager::ScheduleNextPoll(PollPeriodSelector aPollPeriodSelector) { + uint32_t now; + uint32_t oldPeriod = mPollPeriod; + if (aPollPeriodSelector == kRecalculatePollPeriod) { mPollPeriod = CalculatePollPeriod(); } + now = TimerMilli::GetNow(); + if (mTimer.IsRunning()) { - mTimer.StartAt(mTimerStartTime, mPollPeriod); + if (oldPeriod != mPollPeriod) + { + // If poll interval did change and re-starting the timer from + // last start time with new poll interval would fire quickly + // (i.e., fires within window `[now, now + kMinPollPeriod]`) + // add an extra minimum delay of `kMinPollPeriod`. This + // ensures that when an internal or external request triggers + // a switch to a shorter poll interval, the first data poll + // will not be sent too quickly (and possibly before the + // response is available/prepared on the parent node). + if (TimerScheduler::IsStrictlyBefore(mTimerStartTime + mPollPeriod, now + kMinPollPeriod)) + { + mTimer.StartAt(now, kMinPollPeriod); + } + else + { + mTimer.StartAt(mTimerStartTime, mPollPeriod); + } + } + // Do nothing on the running poll timer if the poll interval doesn't change } else { - mTimerStartTime = TimerMilli::GetNow(); + mTimerStartTime = now; mTimer.StartAt(mTimerStartTime, mPollPeriod); } }