From fd6a52dba92a7570735c8358c167355b7b61008f Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Thu, 6 Jul 2017 01:07:19 +0800 Subject: [PATCH] [alarm-API] Update usec-alarm API to use single 32-bit microsecond (#1949) * Update the usec-alarm API to use single 32-bit microsecond * Update nRf52840's alarm implementation to support the new usec-alarm API * So both milliseconds timer and microsecond timer will maintain 32-bit time --- examples/platforms/nrf52840/alarm.c | 144 +++++++++++------------ include/openthread/platform/alarm.h | 2 +- include/openthread/platform/usec-alarm.h | 25 +--- src/core/api/link_raw_api.cpp | 14 +-- src/core/mac/mac.cpp | 9 +- 5 files changed, 78 insertions(+), 116 deletions(-) diff --git a/examples/platforms/nrf52840/alarm.c b/examples/platforms/nrf52840/alarm.c index 0cb1ea58e..5f033a7fb 100644 --- a/examples/platforms/nrf52840/alarm.c +++ b/examples/platforms/nrf52840/alarm.c @@ -70,9 +70,8 @@ typedef enum typedef struct { - volatile bool mFireAlarm; ///< Information for processing function, that alarm should fire. - otPlatUsecAlarmTime mT0; ///< Alarm start time, for tracking overflows. - otPlatUsecAlarmTime mTargetTime; ///< Alarm fire time. + volatile bool mFireAlarm; ///< Information for processing function, that alarm should fire. + uint32_t mTargetTime; ///< Alarm fire time (in millisecond for MsTimer, in microsecond for UsTimer) } AlarmData; typedef struct @@ -83,8 +82,8 @@ typedef struct nrf_rtc_int_t mCompareInt; } AlarmChannelData; -static volatile otPlatUsecAlarmTime sTimeOffset = { 0 }; ///< Time offset to keep track of current time. -static AlarmData sTimerData[kNumTimers]; ///< Data of the timers. +static volatile uint32_t sTimeOffset = 0; ///< Time offset to keep track of current time (in millisecond). +static AlarmData sTimerData[kNumTimers]; ///< Data of the timers. static const AlarmChannelData sChannelData[kNumTimers] = { [kMsTimer] = { @@ -106,38 +105,32 @@ static void *sUsecContext = NULL; ///< The context information static void HandleOverflow(void); -static inline uint32_t TimeToTicks(otPlatUsecAlarmTime aTime) +static inline uint32_t TimeToTicks(uint32_t aTime, AlarmIndex aIndex) { - uint64_t microseconds = US_PER_MS * (uint64_t)aTime.mMs + (uint64_t)aTime.mUs; - return (uint32_t)CEIL_DIV((microseconds * RTC_FREQUENCY), US_PER_S) & RTC_CC_COMPARE_Msk; -} + uint32_t ticks; -static inline otPlatUsecAlarmTime TicksToTime(uint32_t aTicks) -{ - uint64_t microseconds = CEIL_DIV((US_PER_S * (uint64_t)aTicks), RTC_FREQUENCY); - return (otPlatUsecAlarmTime) {microseconds / US_PER_MS, microseconds % US_PER_MS}; -} - -static inline otPlatUsecAlarmTime TimeAdd(otPlatUsecAlarmTime aTime1, otPlatUsecAlarmTime aTime2) -{ - otPlatUsecAlarmTime result = { aTime1.mMs + aTime2.mMs, aTime1.mUs + aTime2.mUs }; - - assert(result.mUs < 2 * US_PER_MS); - - if (result.mUs >= US_PER_MS) + if (aIndex == kMsTimer) { - result.mMs++; - result.mUs -= US_PER_MS; + ticks = (uint32_t)CEIL_DIV((aTime * US_PER_MS * RTC_FREQUENCY), US_PER_S) & RTC_CC_COMPARE_Msk; + } + else + { + ticks = (uint32_t)CEIL_DIV((aTime * RTC_FREQUENCY), US_PER_S) & RTC_CC_COMPARE_Msk; } - return result; + return ticks; } -static inline otPlatUsecAlarmTime AlarmGetCurrentTime(void) +static inline uint64_t TicksToTime(uint32_t aTicks) +{ + return CEIL_DIV((US_PER_S * (uint64_t)aTicks), RTC_FREQUENCY); +} + +static inline uint64_t AlarmGetCurrentTime() { uint32_t rtcValue1; uint32_t rtcValue2; - otPlatUsecAlarmTime offset; + uint32_t offset; rtcValue1 = nrf_rtc_counter_get(RTC_INSTANCE); @@ -172,46 +165,53 @@ static inline otPlatUsecAlarmTime AlarmGetCurrentTime(void) offset = sTimeOffset; } - return TimeAdd(offset, TicksToTime(rtcValue2)); + return US_PER_MS * (uint64_t)offset + TicksToTime(rtcValue2); } -static inline otPlatUsecAlarmTime AlarmGetCurrentTimeRtcProtected(void) +static inline uint32_t AlarmGetCurrentTimeRtcProtected(AlarmIndex aIndex) { - return TimeAdd(AlarmGetCurrentTime(), (otPlatUsecAlarmTime) {0, 2 * US_PER_TICK}); -} + uint64_t usecTime = AlarmGetCurrentTime() + 2 * US_PER_TICK; + uint32_t currentTime; -static inline bool TimeIsLower(otPlatUsecAlarmTime aTime1, otPlatUsecAlarmTime aTime2) -{ - return ((aTime1.mMs < aTime2.mMs) || - ((aTime1.mMs == aTime2.mMs) && (aTime1.mUs < aTime2.mUs))); -} - -static inline bool AlarmShallStrike(otPlatUsecAlarmTime aNow, AlarmIndex aIndex) -{ - if (TimeIsLower(sTimerData[aIndex].mTargetTime, sTimerData[aIndex].mT0)) + if (aIndex == kMsTimer) { - // Handle situation when timespan included timer overflow. - if (TimeIsLower(aNow, sTimerData[aIndex].mT0) && !TimeIsLower(aNow, sTimerData[aIndex].mTargetTime)) - { - return true; - } + currentTime = (uint32_t)(usecTime / US_PER_MS); } else { - if (TimeIsLower(aNow, sTimerData[aIndex].mT0) || !TimeIsLower(aNow, sTimerData[aIndex].mTargetTime)) - { - return true; - } + currentTime = (uint32_t)usecTime; } - return false; + return currentTime; +} + +static inline bool AlarmShallStrike(uint32_t aNow, AlarmIndex aIndex) +{ + uint32_t diff = aNow - sTimerData[aIndex].mTargetTime; + + // Three cases: + // 1) aNow is before mTargetTime => Difference is negative (last bit of difference is set) => Returning false. + // 2) aNow is same as mTargetTime => Difference is zero (last bit of difference is clear) => Returning true. + // 3) aNow is after mTargetTime => Difference is positive (last bit of difference is clear) => Returning true. + + return !((diff & (1UL << 31)) != 0); } static void HandleCompareMatch(AlarmIndex aIndex, bool aSkipCheck) { nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[aIndex].mCompareEvent); - otPlatUsecAlarmTime now = AlarmGetCurrentTime(); + uint64_t usecTime = AlarmGetCurrentTime(); + uint32_t now; + + if (aIndex == kMsTimer) + { + now = (uint32_t)(usecTime / US_PER_MS); + } + else + { + now = (uint32_t)usecTime; + } // In case the target time was larger than single overflow, // we should only strike the timer on final compare event. @@ -229,25 +229,24 @@ static void HandleOverflow(void) nrf_rtc_event_clear(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW); // Increment counter on overflow. - sTimeOffset = TimeAdd(sTimeOffset, (otPlatUsecAlarmTime) {MS_PER_OVERFLOW, 0}); + sTimeOffset = sTimeOffset + MS_PER_OVERFLOW; } -static void AlarmStartAt(const otPlatUsecAlarmTime *aT0, const otPlatUsecAlarmTime *aTargetTime, AlarmIndex aIndex) +static void AlarmStartAt(uint32_t aTargetTime, AlarmIndex aIndex) { uint32_t targetCounter; - otPlatUsecAlarmTime now; + uint32_t now; nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[aIndex].mCompareInt); nrf_rtc_event_enable(RTC_INSTANCE, sChannelData[aIndex].mCompareEventMask); - sTimerData[aIndex].mT0 = *aT0; - sTimerData[aIndex].mTargetTime = *aTargetTime; + sTimerData[aIndex].mTargetTime = aTargetTime; - targetCounter = TimeToTicks(sTimerData[aIndex].mTargetTime); + targetCounter = TimeToTicks(sTimerData[aIndex].mTargetTime, aIndex); nrf_rtc_cc_set(RTC_INSTANCE, sChannelData[aIndex].mChannelNumber, targetCounter); - now = AlarmGetCurrentTimeRtcProtected(); + now = AlarmGetCurrentTimeRtcProtected(aIndex); if (AlarmShallStrike(now, aIndex)) { @@ -270,8 +269,7 @@ static void AlarmStop(AlarmIndex aIndex) void nrf5AlarmInit(void) { - sTimeOffset.mMs = 0; - sTimeOffset.mUs = 0; + sTimeOffset = 0; memset(sTimerData, 0, sizeof(sTimerData)); // Setup low frequency clock. @@ -351,18 +349,15 @@ void nrf5AlarmProcess(otInstance *aInstance) uint32_t otPlatAlarmGetNow(void) { - otPlatUsecAlarmTime now = AlarmGetCurrentTime(); - - return now.mMs; + return (uint32_t)(AlarmGetCurrentTime() / US_PER_MS); } void otPlatAlarmStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) { (void)aInstance; - otPlatUsecAlarmTime T0 = (otPlatUsecAlarmTime) {aT0, 0}; - otPlatUsecAlarmTime TargetTime = (otPlatUsecAlarmTime) {aT0 + aDt, 0}; + uint32_t targetTime = aT0 + aDt; - AlarmStartAt(&T0, &TargetTime, kMsTimer); + AlarmStartAt(targetTime, kMsTimer); } void otPlatAlarmStop(otInstance *aInstance) @@ -372,23 +367,18 @@ void otPlatAlarmStop(otInstance *aInstance) AlarmStop(kMsTimer); } -void otPlatUsecAlarmGetNow(otPlatUsecAlarmTime *aNow) +uint32_t otPlatUsecAlarmGetNow(void) { - otPlatUsecAlarmTime now = AlarmGetCurrentTime(); - - memcpy(aNow, &now, sizeof(*aNow)); + return (uint32_t)AlarmGetCurrentTime(); } -void otPlatUsecAlarmStartAt(otInstance *aInstance, - const otPlatUsecAlarmTime *aT0, - const otPlatUsecAlarmTime *aDt, - otPlatUsecAlarmHandler aHandler, - void *aContext) +void otPlatUsecAlarmStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt, + otPlatUsecAlarmHandler aHandler, void *aContext) { (void)aInstance; - otPlatUsecAlarmTime TargetTime = TimeAdd(*aT0, *aDt); + uint32_t targetTime = aT0 + aDt; - AlarmStartAt(aT0, &TargetTime, kUsTimer); + AlarmStartAt(targetTime, kUsTimer); sUsecHandler = aHandler; sUsecContext = aContext; diff --git a/include/openthread/platform/alarm.h b/include/openthread/platform/alarm.h index 2ffeb44af..050ee7efe 100644 --- a/include/openthread/platform/alarm.h +++ b/include/openthread/platform/alarm.h @@ -29,7 +29,7 @@ /** * @file * @brief - * This file includes the platform abstraction for the alarm service. + * This file includes the platform abstraction for the millisecond alarm service. */ #ifndef ALARM_H_ diff --git a/include/openthread/platform/usec-alarm.h b/include/openthread/platform/usec-alarm.h index b1f263c6c..0c7dd6290 100644 --- a/include/openthread/platform/usec-alarm.h +++ b/include/openthread/platform/usec-alarm.h @@ -50,16 +50,6 @@ extern "C" { * */ -/** - * This structure represents time in microseconds. - * - */ -typedef struct -{ - uint32_t mMs; ///< Time in milliseconds. - uint16_t mUs; ///< Time fraction in microseconds. -} otPlatUsecAlarmTime; - /** * This defines the callback for indicating when the alarm has expired. * @@ -69,20 +59,17 @@ typedef struct typedef void (*otPlatUsecAlarmHandler)(void *aContext); /** - * Set the alarm to fire at @p aDt milliseconds and microseconds after @p aT0. + * Set the alarm to fire at @p aDt microseconds after @p aT0. * * @param[in] aInstance The OpenThread instance structure. * @param[in] aT0 The reference time. - * @param[in] aDt The time delay in milliseconds and microseconds from @p aT0. + * @param[in] aDt The time delay in microseconds from @p aT0. * @param[in] aHandler A pointer to a function that is called when the timer expires. * @param[in] aContext A pointer to arbitrary context information. * */ -void otPlatUsecAlarmStartAt(otInstance *aInstance, - const otPlatUsecAlarmTime *aT0, - const otPlatUsecAlarmTime *aDt, - otPlatUsecAlarmHandler aHandler, - void *aContext); +void otPlatUsecAlarmStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt, + otPlatUsecAlarmHandler aHandler, void *aContext); /** * Stop the alarm. @@ -95,10 +82,10 @@ void otPlatUsecAlarmStop(otInstance *aInstance); /** * Get the current time. * - * @param[out] aNow The current time in milliseconds and microseconds. + * @param[out] aNow The current time in microseconds. * */ -void otPlatUsecAlarmGetNow(otPlatUsecAlarmTime *aNow); +uint32_t otPlatUsecAlarmGetNow(void); /** * @} diff --git a/src/core/api/link_raw_api.cpp b/src/core/api/link_raw_api.cpp index 5e6f34def..499af271f 100644 --- a/src/core/api/link_raw_api.cpp +++ b/src/core/api/link_raw_api.cpp @@ -562,22 +562,14 @@ void LinkRaw::StartCsmaBackoff(void) backoff = (otPlatRandomGet() % (1UL << backoffExponent)); backoff *= (static_cast(Mac::kUnitBackoffPeriod) * OT_RADIO_SYMBOL_TIME); -#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER - otPlatUsecAlarmTime now; - otPlatUsecAlarmTime delay; - - otPlatUsecAlarmGetNow(&now); - delay.mMs = backoff / 1000UL; - delay.mUs = backoff - (delay.mMs * 1000UL); - otLogDebgPlat(aInstance, "LinkRaw Starting RetransmitTimeout Timer (%d ms)", backoff); mTimerReason = kTimerReasonRetransmitTimeout; - otPlatUsecAlarmStartAt(&mInstance, &now, &delay, &HandleTimer, this); + +#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER + otPlatUsecAlarmStartAt(&mInstance, otPlatUsecAlarmGetNow(), backoff, &HandleTimer, this); #else // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER - mTimerReason = kTimerReasonRetransmitTimeout; mTimer.Start(backoff / 1000UL); #endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER - } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 461f3595d..1380e25f0 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -99,14 +99,7 @@ void Mac::StartCsmaBackoff(void) backoff *= (static_cast(kUnitBackoffPeriod) * OT_RADIO_SYMBOL_TIME); #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER - otPlatUsecAlarmTime now; - otPlatUsecAlarmTime delay; - - otPlatUsecAlarmGetNow(&now); - delay.mMs = backoff / 1000UL; - delay.mUs = backoff - (delay.mMs * 1000UL); - - otPlatUsecAlarmStartAt(GetInstance(), &now, &delay, &Mac::HandleBeginTransmit, this); + otPlatUsecAlarmStartAt(GetInstance(), otPlatUsecAlarmGetNow(), backoff, &Mac::HandleBeginTransmit, this); #else // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER mBackoffTimer.Start(backoff / 1000UL); #endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_BACKOFF_TIMER