3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2018 Nest Labs, Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 * Provides implementations of the CHIP System Layer platform
23 * time/clock functions based on the FreeRTOS tick counter.
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
28 #include <support/TimeUtils.h>
39 constexpr uint32_t kTicksOverflowShift = (configUSE_16_BIT_TICKS) ? 16 : 32;
41 uint64_t sBootTimeUS = 0;
44 BaseType_t sNumOfOverflows;
46 } // unnamed namespace
49 * Returns the number of FreeRTOS ticks since the system booted.
51 * NOTE: The default implementation of this function uses FreeRTOS's
52 * vTaskSetTimeOutState() function to get the total number of ticks,
53 * irrespective of tick counter overflows. Unfortunately, this function cannot
54 * be called in interrupt context, no equivalent ISR function exists, and
55 * FreeRTOS provides no portable way of determining whether a function is being
56 * called in an interrupt context. Adaptations that need to use the Chip
57 * Get/SetClock methods from within an interrupt handler must override this
58 * function with a suitable alternative that works on the target platform. The
59 * provided version is safe to call on ARM Cortex platforms with CMSIS
63 uint64_t FreeRTOSTicksSinceBoot(void) __attribute__((weak));
65 uint64_t FreeRTOSTicksSinceBoot(void)
70 if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) // running in an interrupt context
72 // Note that sNumOverflows may be quite stale, and under those
73 // circumstances, the function may violate monotonicity guarantees
74 timeOut.xTimeOnEntering = xTaskGetTickCountFromISR();
75 timeOut.xOverflowCount = sNumOfOverflows;
81 vTaskSetTimeOutState(&timeOut);
84 // BaseType_t is supposed to be atomic
85 sNumOfOverflows = timeOut.xOverflowCount;
89 return static_cast<uint64_t>(timeOut.xTimeOnEntering) + (static_cast<uint64_t>(timeOut.xOverflowCount) << kTicksOverflowShift);
92 uint64_t GetClock_Monotonic(void)
94 return (FreeRTOSTicksSinceBoot() * kMicrosecondsPerSecond) / configTICK_RATE_HZ;
97 uint64_t GetClock_MonotonicMS(void)
99 return (FreeRTOSTicksSinceBoot() * kMillisecondPerSecond) / configTICK_RATE_HZ;
102 uint64_t GetClock_MonotonicHiRes(void)
104 return GetClock_Monotonic();
107 Error GetClock_RealTime(uint64_t & curTime)
109 if (sBootTimeUS == 0)
111 return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
113 curTime = sBootTimeUS + GetClock_Monotonic();
114 return CHIP_SYSTEM_NO_ERROR;
117 Error GetClock_RealTimeMS(uint64_t & curTime)
119 if (sBootTimeUS == 0)
121 return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
123 curTime = (sBootTimeUS + GetClock_Monotonic()) / 1000;
124 return CHIP_SYSTEM_NO_ERROR;
127 Error SetClock_RealTime(uint64_t newCurTime)
129 uint64_t timeSinceBootUS = GetClock_Monotonic();
130 if (newCurTime > timeSinceBootUS)
132 sBootTimeUS = newCurTime - timeSinceBootUS;
138 return CHIP_SYSTEM_NO_ERROR;
142 } // namespace Platform
143 } // namespace System