• 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 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