Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / FreeRTOS / SystemTimeSupport.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2018 Nest Labs, Inc.
5  *    All rights reserved.
6  *
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
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 /**
21  *    @file
22  *          Provides implementations of the CHIP System Layer platform
23  *          time/clock functions based on the FreeRTOS tick counter.
24  */
25 /* this file behaves like a config.h, comes first */
26 #include <platform/internal/CHIPDeviceLayerInternal.h>
27
28 #include <support/TimeUtils.h>
29
30 #include "FreeRTOS.h"
31
32 namespace chip {
33 namespace System {
34 namespace Platform {
35 namespace Layer {
36
37 namespace {
38
39 constexpr uint32_t kTicksOverflowShift = (configUSE_16_BIT_TICKS) ? 16 : 32;
40
41 uint64_t sBootTimeUS = 0;
42
43 #ifdef __CORTEX_M
44 BaseType_t sNumOfOverflows;
45 #endif
46 } // unnamed namespace
47
48 /**
49  * Returns the number of FreeRTOS ticks since the system booted.
50  *
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
60  * libraries.
61  */
62
63 uint64_t FreeRTOSTicksSinceBoot(void) __attribute__((weak));
64
65 uint64_t FreeRTOSTicksSinceBoot(void)
66 {
67     TimeOut_t timeOut;
68
69 #ifdef __CORTEX_M
70     if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) // running in an interrupt context
71     {
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;
76     }
77     else
78     {
79 #endif
80
81         vTaskSetTimeOutState(&timeOut);
82
83 #ifdef __CORTEX_M
84         // BaseType_t is supposed to be atomic
85         sNumOfOverflows = timeOut.xOverflowCount;
86     }
87 #endif
88
89     return static_cast<uint64_t>(timeOut.xTimeOnEntering) + (static_cast<uint64_t>(timeOut.xOverflowCount) << kTicksOverflowShift);
90 }
91
92 uint64_t GetClock_Monotonic(void)
93 {
94     return (FreeRTOSTicksSinceBoot() * kMicrosecondsPerSecond) / configTICK_RATE_HZ;
95 }
96
97 uint64_t GetClock_MonotonicMS(void)
98 {
99     return (FreeRTOSTicksSinceBoot() * kMillisecondPerSecond) / configTICK_RATE_HZ;
100 }
101
102 uint64_t GetClock_MonotonicHiRes(void)
103 {
104     return GetClock_Monotonic();
105 }
106
107 Error GetClock_RealTime(uint64_t & curTime)
108 {
109     if (sBootTimeUS == 0)
110     {
111         return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
112     }
113     curTime = sBootTimeUS + GetClock_Monotonic();
114     return CHIP_SYSTEM_NO_ERROR;
115 }
116
117 Error GetClock_RealTimeMS(uint64_t & curTime)
118 {
119     if (sBootTimeUS == 0)
120     {
121         return CHIP_SYSTEM_ERROR_REAL_TIME_NOT_SYNCED;
122     }
123     curTime = (sBootTimeUS + GetClock_Monotonic()) / 1000;
124     return CHIP_SYSTEM_NO_ERROR;
125 }
126
127 Error SetClock_RealTime(uint64_t newCurTime)
128 {
129     uint64_t timeSinceBootUS = GetClock_Monotonic();
130     if (newCurTime > timeSinceBootUS)
131     {
132         sBootTimeUS = newCurTime - timeSinceBootUS;
133     }
134     else
135     {
136         sBootTimeUS = 0;
137     }
138     return CHIP_SYSTEM_NO_ERROR;
139 }
140
141 } // namespace Layer
142 } // namespace Platform
143 } // namespace System
144 } // namespace chip