• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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