1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_tick.h"
33 #include "securec.h"
34 #include "los_config.h"
35 #include "los_task.h"
36 #include "los_swtmr.h"
37 #include "los_sched.h"
38 #include "los_debug.h"
39 #include "stdint.h"
40
41 LITE_OS_SEC_BSS STATIC ArchTickTimer *g_sysTickTimer = NULL;
42 LITE_OS_SEC_BSS UINT32 g_ticksPerSec;
43 LITE_OS_SEC_BSS UINT32 g_uwCyclePerSec;
44 LITE_OS_SEC_BSS UINT32 g_cyclesPerTick;
45 LITE_OS_SEC_BSS UINT32 g_sysClock;
46 LITE_OS_SEC_BSS STATIC BOOL g_sysTimerIsInit = FALSE;
47 LITE_OS_SEC_BSS STATIC UINT64 g_tickTimerStartTime;
48
49 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
50 STATIC UINT64 g_tickTimerBase;
51 STATIC BOOL g_tickTimerBaseUpdate = FALSE;
52
OsUpdateSysTimeBase(VOID)53 LITE_OS_SEC_TEXT STATIC VOID OsUpdateSysTimeBase(VOID)
54 {
55 UINT32 period = 0;
56
57 if (g_tickTimerBaseUpdate == FALSE) {
58 (VOID)g_sysTickTimer->getCycle(&period);
59 g_tickTimerBase += period;
60 }
61 g_tickTimerBaseUpdate = FALSE;
62 }
63
OsTickTimerBaseReset(UINT64 currTime)64 LITE_OS_SEC_TEXT VOID OsTickTimerBaseReset(UINT64 currTime)
65 {
66 LOS_ASSERT(currTime > g_tickTimerBase);
67
68 g_tickTimerBase = currTime;
69 }
70 #endif
71
OsTickHandler(VOID)72 LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
73 {
74 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
75 OsUpdateSysTimeBase();
76 #endif
77
78 LOS_SchedTickHandler();
79 }
80
OsTickTimerReload(UINT64 period)81 LITE_OS_SEC_TEXT UINT64 OsTickTimerReload(UINT64 period)
82 {
83 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
84 g_tickTimerBase = LOS_SysCycleGet();
85 #endif
86 return g_sysTickTimer->reload(period);
87 }
88
LOS_SysCycleGet(VOID)89 LITE_OS_SEC_TEXT UINT64 LOS_SysCycleGet(VOID)
90 {
91 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 1)
92 return g_sysTickTimer->getCycle(NULL);
93 #else
94 STATIC UINT64 oldSchedTime = 0;
95 UINT32 period = 0;
96 UINT32 intSave = LOS_IntLock();
97 UINT64 time = g_sysTickTimer->getCycle(&period);
98 UINT64 schedTime = g_tickTimerBase + time;
99 if (schedTime < oldSchedTime) {
100 /* Turn the timer count */
101 g_tickTimerBase += period;
102 schedTime = g_tickTimerBase + time;
103 g_tickTimerBaseUpdate = TRUE;
104 }
105
106 LOS_ASSERT(schedTime >= oldSchedTime);
107
108 oldSchedTime = schedTime;
109 LOS_IntRestore(intSave);
110 return schedTime;
111 #endif
112 }
113
TickTimerCheck(const ArchTickTimer * tick)114 STATIC UINT32 TickTimerCheck(const ArchTickTimer *tick)
115 {
116 if (tick == NULL) {
117 return LOS_ERRNO_SYS_PTR_NULL;
118 }
119
120 if ((tick->freq == 0) ||
121 (LOSCFG_BASE_CORE_TICK_PER_SECOND == 0) ||
122 (LOSCFG_BASE_CORE_TICK_PER_SECOND > tick->freq)) {
123 return LOS_ERRNO_SYS_CLOCK_INVALID;
124 }
125
126 if (tick->irqNum > (INT32)LOSCFG_PLATFORM_HWI_LIMIT) {
127 return LOS_ERRNO_TICK_CFG_INVALID;
128 }
129
130 if (tick->periodMax == 0) {
131 return LOS_ERRNO_TICK_CFG_INVALID;
132 }
133
134 if ((tick->init == NULL) || (tick->reload == NULL) ||
135 (tick->lock == NULL) || (tick->unlock == NULL) ||
136 (tick->getCycle == NULL)) {
137 return LOS_ERRNO_SYS_HOOK_IS_NULL;
138 }
139
140 if (g_sysTimerIsInit) {
141 return LOS_ERRNO_SYS_TIMER_IS_RUNNING;
142 }
143
144 return LOS_OK;
145 }
146
OsTickTimerInit(VOID)147 LITE_OS_SEC_TEXT_INIT UINT32 OsTickTimerInit(VOID)
148 {
149 UINT32 ret;
150 UINT32 intSave;
151 HWI_PROC_FUNC tickHandler = (HWI_PROC_FUNC)OsTickHandler;
152
153 g_sysTickTimer = LOS_SysTickTimerGet();
154 if ((g_sysTickTimer->init == NULL) || (g_sysTickTimer->reload == NULL) ||
155 (g_sysTickTimer->lock == NULL) || (g_sysTickTimer->unlock == NULL) ||
156 (g_sysTickTimer->getCycle == NULL)) {
157 return LOS_ERRNO_SYS_HOOK_IS_NULL;
158 }
159
160 if (g_sysTickTimer->tickHandler != NULL) {
161 tickHandler = g_sysTickTimer->tickHandler;
162 }
163
164 intSave = LOS_IntLock();
165 ret = g_sysTickTimer->init(tickHandler);
166 if (ret != LOS_OK) {
167 LOS_IntRestore(intSave);
168 return ret;
169 }
170
171 if ((g_sysTickTimer->freq == 0) || (g_sysTickTimer->freq < LOSCFG_BASE_CORE_TICK_PER_SECOND)) {
172 LOS_IntRestore(intSave);
173 return LOS_ERRNO_SYS_CLOCK_INVALID;
174 }
175
176 if (g_sysTickTimer->irqNum > (INT32)LOSCFG_PLATFORM_HWI_LIMIT) {
177 LOS_IntRestore(intSave);
178 return LOS_ERRNO_TICK_CFG_INVALID;
179 }
180
181 g_sysClock = g_sysTickTimer->freq;
182 g_cyclesPerTick = g_sysTickTimer->freq / LOSCFG_BASE_CORE_TICK_PER_SECOND;
183 g_sysTimerIsInit = TRUE;
184
185 LOS_IntRestore(intSave);
186
187 return LOS_OK;
188 }
189
LOS_TickTimerRegister(const ArchTickTimer * timer,const HWI_PROC_FUNC tickHandler)190 LITE_OS_SEC_TEXT UINT32 LOS_TickTimerRegister(const ArchTickTimer *timer, const HWI_PROC_FUNC tickHandler)
191 {
192 UINT32 intSave;
193 UINT32 ret;
194
195 if ((timer == NULL) && (tickHandler == NULL)) {
196 return LOS_ERRNO_SYS_PTR_NULL;
197 }
198
199 if (timer != NULL) {
200 ret = TickTimerCheck(timer);
201 if (ret != LOS_OK) {
202 return ret;
203 }
204
205 intSave = LOS_IntLock();
206 if (g_sysTickTimer == NULL) {
207 g_sysTickTimer = LOS_SysTickTimerGet();
208 }
209
210 if (g_sysTickTimer == timer) {
211 LOS_IntRestore(intSave);
212 return LOS_ERRNO_SYS_TIMER_ADDR_FAULT;
213 }
214
215 errno_t errRet = memcpy_s(g_sysTickTimer, sizeof(ArchTickTimer), timer, sizeof(ArchTickTimer));
216 if (errRet != EOK) {
217 PRINT_ERR("%s timer addr fault! errno %d\n", __FUNCTION__, errRet);
218 ret = LOS_ERRNO_SYS_TIMER_ADDR_FAULT;
219 }
220 LOS_IntRestore(intSave);
221 return ret;
222 }
223
224 if (g_sysTimerIsInit) {
225 return LOS_ERRNO_SYS_TIMER_IS_RUNNING;
226 }
227
228 intSave = LOS_IntLock();
229 if (g_sysTickTimer == NULL) {
230 g_sysTickTimer = LOS_SysTickTimerGet();
231 }
232
233 g_sysTickTimer->tickHandler = tickHandler;
234 LOS_IntRestore(intSave);
235 return LOS_OK;
236 }
237
OsTickSysTimerStartTimeSet(UINT64 currTime)238 LITE_OS_SEC_TEXT_MINOR VOID OsTickSysTimerStartTimeSet(UINT64 currTime)
239 {
240 g_tickTimerStartTime = currTime;
241 }
242
243 /*****************************************************************************
244 Function : LOS_TickCountGet
245 Description : get current tick
246 Input : None
247 Output : None
248 Return : current tick
249 *****************************************************************************/
LOS_TickCountGet(VOID)250 LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID)
251 {
252 return OS_SYS_CYCLE_TO_TICK(LOS_SysCycleGet() - g_tickTimerStartTime);
253 }
254
255 /*****************************************************************************
256 Function : LOS_CyclePerTickGet
257 Description : Get System cycle number corresponding to each tick
258 Input : None
259 Output : None
260 Return : cycle number corresponding to each tick
261 *****************************************************************************/
LOS_CyclePerTickGet(VOID)262 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CyclePerTickGet(VOID)
263 {
264 return g_cyclesPerTick;
265 }
266
267 /*****************************************************************************
268 Function : LOS_MS2Tick
269 Description : milliseconds convert to Tick
270 Input : millisec ---------- milliseconds
271 Output : None
272 Return : Tick
273 *****************************************************************************/
LOS_MS2Tick(UINT32 millisec)274 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec)
275 {
276 if (millisec == OS_NULL_INT) {
277 return OS_NULL_INT;
278 }
279
280 return ((UINT64)millisec * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_MS_PER_SECOND;
281 }
282
283 /*****************************************************************************
284 Function : LOS_Tick2MS
285 Description : Tick convert to milliseconds
286 Input : ticks ---------- ticks
287 Output : None
288 Return : milliseconds
289 *****************************************************************************/
LOS_Tick2MS(UINT32 ticks)290 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_Tick2MS(UINT32 ticks)
291 {
292 return ((UINT64)ticks * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND;
293 }
294
295 /*****************************************************************************
296 Function : OsCpuTick2MS
297 Description : cycle convert to milliseconds
298 Input : cpuTick ---------- cycle
299 Output : msHi ---------- High 32 milliseconds
300 msLo ---------- Low 32 milliseconds
301 Return : LOS_OK on success ,or error code on failure
302 *****************************************************************************/
OsCpuTick2MS(CpuTick * cpuTick,UINT32 * msHi,UINT32 * msLo)303 LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2MS(CpuTick *cpuTick, UINT32 *msHi, UINT32 *msLo)
304 {
305 UINT64 tmpCpuTick;
306 DOUBLE temp;
307
308 if ((cpuTick == NULL) || (msHi == NULL) || (msLo == NULL)) {
309 return LOS_ERRNO_SYS_PTR_NULL;
310 }
311
312 if (g_sysClock == 0) {
313 return LOS_ERRNO_SYS_CLOCK_INVALID;
314 }
315 tmpCpuTick = ((UINT64)cpuTick->cntHi << OS_SYS_MV_32_BIT) | cpuTick->cntLo;
316 temp = tmpCpuTick / ((DOUBLE)g_sysClock / OS_SYS_MS_PER_SECOND);
317
318 tmpCpuTick = (UINT64)temp;
319
320 *msLo = (UINT32)tmpCpuTick;
321 *msHi = (UINT32)(tmpCpuTick >> OS_SYS_MV_32_BIT);
322
323 return LOS_OK;
324 }
325
326 /*****************************************************************************
327 Function : OsCpuTick2US
328 Description : cycle convert to Microsecond
329 Input : cpuTick ---------- cycle
330 Output : usHi ---------- High 32 Microsecond
331 usLo ---------- Low 32 Microsecond
332 Return : LOS_OK on success ,or error code on failure
333 *****************************************************************************/
OsCpuTick2US(CpuTick * cpuTick,UINT32 * usHi,UINT32 * usLo)334 LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2US(CpuTick *cpuTick, UINT32 *usHi, UINT32 *usLo)
335 {
336 UINT64 tmpCpuTick;
337 DOUBLE temp;
338
339 if ((cpuTick == NULL) || (usHi == NULL) || (usLo == NULL)) {
340 return LOS_ERRNO_SYS_PTR_NULL;
341 }
342
343 if (g_sysClock == 0) {
344 return LOS_ERRNO_SYS_CLOCK_INVALID;
345 }
346 tmpCpuTick = ((UINT64)cpuTick->cntHi << OS_SYS_MV_32_BIT) | cpuTick->cntLo;
347 temp = tmpCpuTick / ((DOUBLE)g_sysClock / OS_SYS_US_PER_SECOND);
348
349 tmpCpuTick = (UINT64)temp;
350
351 *usLo = (UINT32)tmpCpuTick;
352 *usHi = (UINT32)(tmpCpuTick >> OS_SYS_MV_32_BIT);
353
354 return LOS_OK;
355 }
356
357 /*****************************************************************************
358 Function : LOS_MS2Tick
359 Description : get current nanoseconds
360 Input : None
361 Output : None
362 Return : nanoseconds
363 *****************************************************************************/
LOS_CurrNanosec(VOID)364 UINT64 LOS_CurrNanosec(VOID)
365 {
366 UINT64 nanos;
367 nanos = LOS_SysCycleGet() * (OS_SYS_NS_PER_SECOND / OS_SYS_NS_PER_MS) / (g_sysClock / OS_SYS_NS_PER_MS);
368 return nanos;
369 }
370
371 /*****************************************************************************
372 Function : LOS_UDelay
373 Description : cpu delay function
374 Input : microseconds ---------- microseconds
375 Output : None
376 Return : None
377 *****************************************************************************/
LOS_UDelay(UINT64 microseconds)378 VOID LOS_UDelay(UINT64 microseconds)
379 {
380 UINT64 endTime;
381
382 if (microseconds == 0) {
383 return;
384 }
385
386 endTime = (microseconds / OS_SYS_US_PER_SECOND) * g_sysClock +
387 (microseconds % OS_SYS_US_PER_SECOND) * g_sysClock / OS_SYS_US_PER_SECOND;
388 endTime = LOS_SysCycleGet() + endTime;
389 while (LOS_SysCycleGet() < endTime) {
390 }
391 return;
392 }
393
394 /*****************************************************************************
395 Function : LOS_MDelay
396 Description : cpu delay function
397 Input : millisec ---------- milliseconds
398 Output : None
399 Return : None
400 *****************************************************************************/
LOS_MDelay(UINT32 millisec)401 VOID LOS_MDelay(UINT32 millisec)
402 {
403 UINT32 delayUs = (UINT32_MAX / OS_SYS_US_PER_MS) * OS_SYS_US_PER_MS;
404 while (millisec > UINT32_MAX / OS_SYS_US_PER_MS) {
405 LOS_UDelay(delayUs);
406 millisec -= (UINT32_MAX / OS_SYS_US_PER_MS);
407 }
408 LOS_UDelay(millisec * OS_SYS_US_PER_MS);
409 return;
410 }
411