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 UINT64 g_oldTickTimerBase;
52 STATIC BOOL g_tickTimerBaseUpdate = FALSE;
53
OsUpdateSysTimeBase(VOID)54 LITE_OS_SEC_TEXT STATIC VOID OsUpdateSysTimeBase(VOID)
55 {
56 UINT32 period = 0;
57
58 if (g_tickTimerBaseUpdate == FALSE) {
59 (VOID)g_sysTickTimer->getCycle(&period);
60 g_tickTimerBase += period;
61 }
62 g_tickTimerBaseUpdate = FALSE;
63 }
64
OsTickTimerBaseReset(UINT64 currTime)65 LITE_OS_SEC_TEXT VOID OsTickTimerBaseReset(UINT64 currTime)
66 {
67 LOS_ASSERT(currTime > g_tickTimerBase);
68
69 g_tickTimerBase = currTime;
70 }
71 #endif
72
OsTickHandler(VOID)73 LITE_OS_SEC_TEXT VOID OsTickHandler(VOID)
74 {
75 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
76 OsUpdateSysTimeBase();
77 #endif
78
79 LOS_SchedTickHandler();
80 }
81
OsTickTimerReload(UINT64 period)82 LITE_OS_SEC_TEXT UINT64 OsTickTimerReload(UINT64 period)
83 {
84 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
85 g_tickTimerBase = LOS_SysCycleGet();
86 #endif
87 return g_sysTickTimer->reload(period);
88 }
89
LOS_SysCycleGet(VOID)90 LITE_OS_SEC_TEXT UINT64 LOS_SysCycleGet(VOID)
91 {
92 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 1)
93 return g_sysTickTimer->getCycle(NULL);
94 #else
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 < g_oldTickTimerBase) {
100 /* Turn the timer count */
101 g_tickTimerBase += period;
102 schedTime = g_tickTimerBase + time;
103 g_tickTimerBaseUpdate = TRUE;
104 }
105
106 LOS_ASSERT(schedTime >= g_oldTickTimerBase);
107
108 g_oldTickTimerBase = 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
LOS_SysTickClockFreqAdjust(const SYS_TICK_FREQ_ADJUST_FUNC handler,UINTPTR param)238 UINT32 LOS_SysTickClockFreqAdjust(const SYS_TICK_FREQ_ADJUST_FUNC handler, UINTPTR param)
239 {
240 UINT32 intSave;
241 UINT32 freq;
242 UINT32 oldFreq = g_sysClock;
243
244 if (handler == NULL) {
245 return LOS_ERRNO_SYS_HOOK_IS_NULL;
246 }
247
248 intSave = LOS_IntLock();
249 g_sysTickTimer->lock();
250 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
251 UINT64 currTimeCycle = LOS_SysCycleGet();
252 #endif
253
254 freq = handler(param);
255 if ((freq == 0) || (freq == g_sysClock)) {
256 g_sysTickTimer->unlock();
257 LOS_IntRestore(intSave);
258 return LOS_ERRNO_SYS_CLOCK_INVALID;
259 }
260
261 g_sysTickTimer->reload(LOSCFG_BASE_CORE_TICK_RESPONSE_MAX);
262 g_sysTickTimer->unlock();
263
264 #if (LOSCFG_BASE_CORE_TICK_WTIMER == 0)
265 g_tickTimerBase = OsTimeConvertFreq(currTimeCycle, oldFreq, freq);
266 g_oldTickTimerBase = OsTimeConvertFreq(g_oldTickTimerBase, oldFreq, freq);
267 g_tickTimerStartTime = OsTimeConvertFreq(g_tickTimerStartTime, oldFreq, freq);
268 #endif
269
270 g_sysTickTimer->freq = freq;
271 g_sysClock = g_sysTickTimer->freq;
272 g_cyclesPerTick = g_sysTickTimer->freq / LOSCFG_BASE_CORE_TICK_PER_SECOND;
273 OsSchedTimeConvertFreq(oldFreq);
274 LOS_IntRestore(intSave);
275
276 return LOS_OK;
277 }
278
OsTickSysTimerStartTimeSet(UINT64 currTime)279 LITE_OS_SEC_TEXT_MINOR VOID OsTickSysTimerStartTimeSet(UINT64 currTime)
280 {
281 g_tickTimerStartTime = currTime;
282 }
283
284 /*****************************************************************************
285 Function : LOS_TickCountGet
286 Description : get current tick
287 Input : None
288 Output : None
289 Return : current tick
290 *****************************************************************************/
LOS_TickCountGet(VOID)291 LITE_OS_SEC_TEXT_MINOR UINT64 LOS_TickCountGet(VOID)
292 {
293 return OS_SYS_CYCLE_TO_TICK(LOS_SysCycleGet() - g_tickTimerStartTime);
294 }
295
296 /*****************************************************************************
297 Function : LOS_CyclePerTickGet
298 Description : Get System cycle number corresponding to each tick
299 Input : None
300 Output : None
301 Return : cycle number corresponding to each tick
302 *****************************************************************************/
LOS_CyclePerTickGet(VOID)303 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CyclePerTickGet(VOID)
304 {
305 return g_cyclesPerTick;
306 }
307
308 /*****************************************************************************
309 Function : LOS_MS2Tick
310 Description : milliseconds convert to Tick
311 Input : millisec ---------- milliseconds
312 Output : None
313 Return : Tick
314 *****************************************************************************/
LOS_MS2Tick(UINT32 millisec)315 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_MS2Tick(UINT32 millisec)
316 {
317 if (millisec == OS_NULL_INT) {
318 return OS_NULL_INT;
319 }
320
321 return ((UINT64)millisec * LOSCFG_BASE_CORE_TICK_PER_SECOND) / OS_SYS_MS_PER_SECOND;
322 }
323
324 /*****************************************************************************
325 Function : LOS_Tick2MS
326 Description : Tick convert to milliseconds
327 Input : ticks ---------- ticks
328 Output : None
329 Return : milliseconds
330 *****************************************************************************/
LOS_Tick2MS(UINT32 ticks)331 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_Tick2MS(UINT32 ticks)
332 {
333 return ((UINT64)ticks * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND;
334 }
335
336 /*****************************************************************************
337 Function : OsCpuTick2MS
338 Description : cycle convert to milliseconds
339 Input : cpuTick ---------- cycle
340 Output : msHi ---------- High 32 milliseconds
341 msLo ---------- Low 32 milliseconds
342 Return : LOS_OK on success ,or error code on failure
343 *****************************************************************************/
OsCpuTick2MS(CpuTick * cpuTick,UINT32 * msHi,UINT32 * msLo)344 LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2MS(CpuTick *cpuTick, UINT32 *msHi, UINT32 *msLo)
345 {
346 UINT64 tmpCpuTick;
347 DOUBLE temp;
348
349 if ((cpuTick == NULL) || (msHi == NULL) || (msLo == NULL)) {
350 return LOS_ERRNO_SYS_PTR_NULL;
351 }
352
353 if (g_sysClock == 0) {
354 return LOS_ERRNO_SYS_CLOCK_INVALID;
355 }
356 tmpCpuTick = ((UINT64)cpuTick->cntHi << OS_SYS_MV_32_BIT) | cpuTick->cntLo;
357 temp = tmpCpuTick / ((DOUBLE)g_sysClock / OS_SYS_MS_PER_SECOND);
358
359 tmpCpuTick = (UINT64)temp;
360
361 *msLo = (UINT32)tmpCpuTick;
362 *msHi = (UINT32)(tmpCpuTick >> OS_SYS_MV_32_BIT);
363
364 return LOS_OK;
365 }
366
367 /*****************************************************************************
368 Function : OsCpuTick2US
369 Description : cycle convert to Microsecond
370 Input : cpuTick ---------- cycle
371 Output : usHi ---------- High 32 Microsecond
372 usLo ---------- Low 32 Microsecond
373 Return : LOS_OK on success ,or error code on failure
374 *****************************************************************************/
OsCpuTick2US(CpuTick * cpuTick,UINT32 * usHi,UINT32 * usLo)375 LITE_OS_SEC_TEXT_INIT UINT32 OsCpuTick2US(CpuTick *cpuTick, UINT32 *usHi, UINT32 *usLo)
376 {
377 UINT64 tmpCpuTick;
378 DOUBLE temp;
379
380 if ((cpuTick == NULL) || (usHi == NULL) || (usLo == NULL)) {
381 return LOS_ERRNO_SYS_PTR_NULL;
382 }
383
384 if (g_sysClock == 0) {
385 return LOS_ERRNO_SYS_CLOCK_INVALID;
386 }
387 tmpCpuTick = ((UINT64)cpuTick->cntHi << OS_SYS_MV_32_BIT) | cpuTick->cntLo;
388 temp = tmpCpuTick / ((DOUBLE)g_sysClock / OS_SYS_US_PER_SECOND);
389
390 tmpCpuTick = (UINT64)temp;
391
392 *usLo = (UINT32)tmpCpuTick;
393 *usHi = (UINT32)(tmpCpuTick >> OS_SYS_MV_32_BIT);
394
395 return LOS_OK;
396 }
397
398 /*****************************************************************************
399 Function : LOS_MS2Tick
400 Description : get current nanoseconds
401 Input : None
402 Output : None
403 Return : nanoseconds
404 *****************************************************************************/
LOS_CurrNanosec(VOID)405 UINT64 LOS_CurrNanosec(VOID)
406 {
407 UINT64 nanos;
408 nanos = LOS_SysCycleGet() * (OS_SYS_NS_PER_SECOND / OS_SYS_NS_PER_MS) / (g_sysClock / OS_SYS_NS_PER_MS);
409 return nanos;
410 }
411
412 /*****************************************************************************
413 Function : LOS_UDelay
414 Description : cpu delay function
415 Input : microseconds ---------- microseconds
416 Output : None
417 Return : None
418 *****************************************************************************/
LOS_UDelay(UINT64 microseconds)419 VOID LOS_UDelay(UINT64 microseconds)
420 {
421 UINT64 endTime;
422
423 if (microseconds == 0) {
424 return;
425 }
426
427 endTime = (microseconds / OS_SYS_US_PER_SECOND) * g_sysClock +
428 (microseconds % OS_SYS_US_PER_SECOND) * g_sysClock / OS_SYS_US_PER_SECOND;
429 endTime = LOS_SysCycleGet() + endTime;
430 while (LOS_SysCycleGet() < endTime) {
431 }
432 return;
433 }
434
435 /*****************************************************************************
436 Function : LOS_MDelay
437 Description : cpu delay function
438 Input : millisec ---------- milliseconds
439 Output : None
440 Return : None
441 *****************************************************************************/
LOS_MDelay(UINT32 millisec)442 VOID LOS_MDelay(UINT32 millisec)
443 {
444 UINT32 delayUs = (UINT32_MAX / OS_SYS_US_PER_MS) * OS_SYS_US_PER_MS;
445 while (millisec > UINT32_MAX / OS_SYS_US_PER_MS) {
446 LOS_UDelay(delayUs);
447 millisec -= (UINT32_MAX / OS_SYS_US_PER_MS);
448 }
449 LOS_UDelay(millisec * OS_SYS_US_PER_MS);
450 return;
451 }
452