1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2022 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_swtmr.h"
33 #include "securec.h"
34 #include "los_interrupt.h"
35 #include "los_task.h"
36 #include "los_memory.h"
37 #include "los_queue.h"
38 #include "los_debug.h"
39 #include "los_hook.h"
40 #include "los_sched.h"
41
42
43 #if (LOSCFG_BASE_CORE_SWTMR == 1)
44
45 LITE_OS_SEC_BSS UINT32 g_swtmrHandlerQueue; /* Software Timer timeout queue ID */
46 LITE_OS_SEC_BSS SWTMR_CTRL_S *g_swtmrCBArray = NULL; /* first address in Timer memory space */
47 LITE_OS_SEC_BSS SWTMR_CTRL_S *g_swtmrFreeList = NULL; /* Free list of Software Timer */
48 LITE_OS_SEC_BSS SortLinkAttribute *g_swtmrSortLinkList = NULL; /* The software timer count list */
49
50 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
51 typedef struct SwtmrAlignDataStr {
52 UINT32 times : 24;
53 UINT32 : 5;
54 UINT32 canMultiple : 1;
55 UINT32 canAlign : 1;
56 UINT32 isAligned : 1;
57 } SwtmrAlignData;
58 LITE_OS_SEC_BSS SwtmrAlignData g_swtmrAlignID[LOSCFG_BASE_CORE_SWTMR_LIMIT] = {0}; /* store swtmr align */
59 #endif
60
61 #define SWTMR_MAX_RUNNING_TICKS 2
62 #define OS_SWTMR_MAX_TIMERID ((0xFFFFFFFF / LOSCFG_BASE_CORE_SWTMR_LIMIT) * LOSCFG_BASE_CORE_SWTMR_LIMIT)
63
64 STATIC VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr);
65
66 /*****************************************************************************
67 Function : OsSwtmrTask
68 Description : Swtmr task main loop, handle time-out timer.
69 Input : None
70 Output : None
71 Return : None
72 *****************************************************************************/
OsSwtmrTask(VOID)73 LITE_OS_SEC_TEXT VOID OsSwtmrTask(VOID)
74 {
75 SwtmrHandlerItem swtmrHandle;
76 SWTMR_CTRL_S *swtmr = NULL;
77 UINT32 intSave;
78 UINT32 readSize;
79 UINT32 ret;
80 UINT64 tick;
81
82 for (;;) {
83 readSize = sizeof(SwtmrHandlerItem);
84 ret = LOS_QueueReadCopy(g_swtmrHandlerQueue, &swtmrHandle, &readSize, LOS_WAIT_FOREVER);
85 if ((ret == LOS_OK) && (readSize == sizeof(SwtmrHandlerItem))) {
86 if ((swtmrHandle.handler == NULL) || (swtmrHandle.swtmrID >= OS_SWTMR_MAX_TIMERID)) {
87 continue;
88 }
89
90 intSave = LOS_IntLock();
91 swtmr = g_swtmrCBArray + swtmrHandle.swtmrID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
92 if (swtmr->usTimerID != swtmrHandle.swtmrID) {
93 LOS_IntRestore(intSave);
94 continue;
95 }
96 if (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) {
97 OsSwtmrDelete(swtmr);
98 }
99 LOS_IntRestore(intSave);
100
101 tick = LOS_TickCountGet();
102 swtmrHandle.handler(swtmrHandle.arg);
103 tick = LOS_TickCountGet() - tick;
104 if (tick >= SWTMR_MAX_RUNNING_TICKS) {
105 PRINT_WARN("timer_handler(%p) cost too many ms(%d)\n",
106 swtmrHandle.handler,
107 (UINT32)((tick * OS_SYS_MS_PER_SECOND) / LOSCFG_BASE_CORE_TICK_PER_SECOND));
108 }
109 }
110 }
111 }
112
113 /*****************************************************************************
114 Function : OsSwtmrTaskCreate
115 Description : Create Software Timer
116 Input : None
117 Output : None
118 Return : LOS_OK on success or error code on failure
119 *****************************************************************************/
OsSwtmrTaskCreate(VOID)120 LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrTaskCreate(VOID)
121 {
122 UINT32 ret;
123 TSK_INIT_PARAM_S swtmrTask;
124
125 // Ignore the return code when matching CSEC rule 6.6(4).
126 (VOID)memset_s(&swtmrTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
127
128 swtmrTask.pfnTaskEntry = (TSK_ENTRY_FUNC)OsSwtmrTask;
129 swtmrTask.uwStackSize = LOSCFG_BASE_CORE_TSK_SWTMR_STACK_SIZE;
130 swtmrTask.pcName = "Swt_Task";
131 swtmrTask.usTaskPrio = 0;
132 ret = LOS_TaskCreate(&g_swtmrTaskID, &swtmrTask);
133 if (ret == LOS_OK) {
134 OS_TCB_FROM_TID(g_swtmrTaskID)->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;
135 }
136 return ret;
137 }
138
139 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
OsSwtmrCalcStartTime(UINT64 currTime,SWTMR_CTRL_S * swtmr,const SWTMR_CTRL_S * alignSwtmr)140 STATIC UINT64 OsSwtmrCalcStartTime(UINT64 currTime, SWTMR_CTRL_S *swtmr, const SWTMR_CTRL_S *alignSwtmr)
141 {
142 UINT64 usedTime, startTime;
143 UINT64 alignEnd = OS_SYS_TICK_TO_CYCLE(alignSwtmr->uwInterval);
144 UINT64 swtmrTime = OS_SYS_TICK_TO_CYCLE(swtmr->uwInterval);
145 UINT64 remainTime = OsSortLinkGetRemainTime(currTime, &alignSwtmr->stSortList);
146 if (remainTime == 0) {
147 startTime = GET_SORTLIST_VALUE(&alignSwtmr->stSortList);
148 } else {
149 usedTime = alignEnd - remainTime;
150 startTime = alignSwtmr->startTime + (usedTime / swtmrTime) * swtmrTime;
151 }
152
153 return startTime;
154 }
155
OsSwtmrFindAlignPos(UINT64 currTime,SWTMR_CTRL_S * swtmr)156 UINT64 OsSwtmrFindAlignPos(UINT64 currTime, SWTMR_CTRL_S *swtmr)
157 {
158 SWTMR_CTRL_S *minInLarge = (SWTMR_CTRL_S *)NULL;
159 SWTMR_CTRL_S *maxInLittle = (SWTMR_CTRL_S *)NULL;
160 UINT32 minInLargeVal = OS_NULL_INT;
161 UINT32 maxInLittleVal = OS_NULL_INT;
162 LOS_DL_LIST *listHead = &g_swtmrSortLinkList->sortLink;
163 SwtmrAlignData swtmrAlgInfo = g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT];
164 LOS_DL_LIST *listObject = listHead->pstNext;
165
166 if (LOS_ListEmpty(listHead)) {
167 goto RETURN_PERIOD;
168 }
169
170 do {
171 SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject, SortLinkList, sortLinkNode);
172 SWTMR_CTRL_S *swtmrListNode = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
173 SwtmrAlignData alignListNode = g_swtmrAlignID[swtmrListNode->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT];
174
175 /* swtmr not start */
176 if ((alignListNode.isAligned == 0) || (alignListNode.canAlign == 0)) {
177 goto CONTINUE_NEXT_NODE;
178 }
179
180 /* find same interval timer, directly return */
181 if (swtmrListNode->uwInterval == swtmr->uwInterval) {
182 return OsSwtmrCalcStartTime(currTime, swtmr, swtmrListNode);
183 }
184
185 if ((swtmrAlgInfo.canMultiple != 1) || (alignListNode.times == 0)) {
186 goto CONTINUE_NEXT_NODE;
187 }
188
189 if (swtmrAlgInfo.times == 0) {
190 goto RETURN_PERIOD;
191 }
192
193 if ((alignListNode.times >= swtmrAlgInfo.times) && ((alignListNode.times % swtmrAlgInfo.times) == 0)) {
194 if (minInLargeVal > (alignListNode.times / swtmrAlgInfo.times)) {
195 minInLargeVal = alignListNode.times / swtmrAlgInfo.times;
196 minInLarge = swtmrListNode;
197 }
198 } else if ((alignListNode.times < swtmrAlgInfo.times) && ((swtmrAlgInfo.times % alignListNode.times) == 0)) {
199 if (maxInLittleVal > (swtmrAlgInfo.times / alignListNode.times)) {
200 maxInLittleVal = swtmrAlgInfo.times / alignListNode.times;
201 maxInLittle = swtmrListNode;
202 }
203 }
204
205 CONTINUE_NEXT_NODE:
206 listObject = listObject->pstNext;
207 } while (listObject != listHead);
208
209 if (minInLarge != NULL) {
210 return OsSwtmrCalcStartTime(currTime, swtmr, minInLarge);
211 } else if (maxInLittle != NULL) {
212 return OsSwtmrCalcStartTime(currTime, swtmr, maxInLittle);
213 }
214
215 RETURN_PERIOD:
216 return currTime;
217 }
218 #endif
219
220 /*****************************************************************************
221 Function : OsSwtmrStart
222 Description : Start Software Timer
223 Input : currTime ------- Current system time
224 Input : swtmr ---------- Need to start Software Timer
225 Output : None
226 Return : None
227 *****************************************************************************/
OsSwtmrStart(UINT64 currTime,SWTMR_CTRL_S * swtmr)228 LITE_OS_SEC_TEXT VOID OsSwtmrStart(UINT64 currTime, SWTMR_CTRL_S *swtmr)
229 {
230 swtmr->ucState = OS_SWTMR_STATUS_TICKING;
231
232 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
233 if ((g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].canAlign == 1) &&
234 (g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned == 0)) {
235 g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 1;
236 swtmr->startTime = OsSwtmrFindAlignPos(currTime, swtmr);
237 }
238 #endif
239 OsAdd2SortLink(&swtmr->stSortList, swtmr->startTime, swtmr->uwInterval, OS_SORT_LINK_SWTMR);
240 OsSchedUpdateExpireTime();
241 }
242
243 /*****************************************************************************
244 Function : OsSwtmrDelete
245 Description : Delete Software Timer
246 Input : swtmr --- Need to delete Software Timer, When using, Ensure that it can't be NULL.
247 Output : None
248 Return : None
249 *****************************************************************************/
OsSwtmrDelete(SWTMR_CTRL_S * swtmr)250 STATIC VOID OsSwtmrDelete(SWTMR_CTRL_S *swtmr)
251 {
252 if (swtmr->usTimerID < (OS_SWTMR_MAX_TIMERID - LOSCFG_BASE_CORE_SWTMR_LIMIT)) {
253 swtmr->usTimerID += LOSCFG_BASE_CORE_SWTMR_LIMIT;
254 } else {
255 swtmr->usTimerID %= LOSCFG_BASE_CORE_SWTMR_LIMIT;
256 }
257
258 /* insert to free list */
259 swtmr->pstNext = g_swtmrFreeList;
260 g_swtmrFreeList = swtmr;
261 swtmr->ucState = OS_SWTMR_STATUS_UNUSED;
262
263 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
264 (VOID)memset_s((VOID *)&g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT],
265 sizeof(SwtmrAlignData), 0, sizeof(SwtmrAlignData));
266 #endif
267 }
268
269
OsSwtmrStop(SWTMR_CTRL_S * swtmr)270 LITE_OS_SEC_TEXT VOID OsSwtmrStop(SWTMR_CTRL_S *swtmr)
271 {
272 OsDeleteSortLink(&swtmr->stSortList);
273 swtmr->ucState = OS_SWTMR_STATUS_CREATED;
274
275 swtmr->ucOverrun = 0;
276 OsSchedUpdateExpireTime();
277 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
278 g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 0;
279 #endif
280 }
281
OsSwtmrTimeoutHandle(UINT64 currTime,SWTMR_CTRL_S * swtmr)282 STATIC VOID OsSwtmrTimeoutHandle(UINT64 currTime, SWTMR_CTRL_S *swtmr)
283 {
284 SwtmrHandlerItem swtmrHandler;
285
286 swtmrHandler.handler = swtmr->pfnHandler;
287 swtmrHandler.arg = swtmr->uwArg;
288 swtmrHandler.swtmrID = swtmr->usTimerID;
289
290 (VOID)LOS_QueueWriteCopy(g_swtmrHandlerQueue, &swtmrHandler, sizeof(SwtmrHandlerItem), LOS_NO_WAIT);
291 if (swtmr->ucMode == LOS_SWTMR_MODE_PERIOD) {
292 swtmr->ucOverrun++;
293 OsSwtmrStart(currTime, swtmr);
294 } else if (swtmr->ucMode == LOS_SWTMR_MODE_NO_SELFDELETE) {
295 swtmr->ucState = OS_SWTMR_STATUS_CREATED;
296 }
297 }
298
OsSwtmrScan(VOID)299 STATIC BOOL OsSwtmrScan(VOID)
300 {
301 BOOL needSchedule = FALSE;
302 LOS_DL_LIST *listObject = &g_swtmrSortLinkList->sortLink;
303
304 if (LOS_ListEmpty(listObject)) {
305 return needSchedule;
306 }
307
308 SortLinkList *sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
309 UINT64 currTime = OsGetCurrSchedTimeCycle();
310 while (sortList->responseTime <= currTime) {
311 SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
312 swtmr->startTime = GET_SORTLIST_VALUE(sortList);
313
314 OsDeleteNodeSortLink(sortList);
315 OsHookCall(LOS_HOOK_TYPE_SWTMR_EXPIRED, swtmr);
316 OsSwtmrTimeoutHandle(currTime, swtmr);
317
318 needSchedule = TRUE;
319 if (LOS_ListEmpty(listObject)) {
320 break;
321 }
322
323 sortList = LOS_DL_LIST_ENTRY(listObject->pstNext, SortLinkList, sortLinkNode);
324 }
325
326 return needSchedule;
327 }
328
OsSwtmrResponseTimeReset(UINT64 startTime)329 LITE_OS_SEC_TEXT VOID OsSwtmrResponseTimeReset(UINT64 startTime)
330 {
331 LOS_DL_LIST *listHead = &g_swtmrSortLinkList->sortLink;
332 LOS_DL_LIST *listNext = listHead->pstNext;
333
334 while (listNext != listHead) {
335 SortLinkList *sortList = LOS_DL_LIST_ENTRY(listNext, SortLinkList, sortLinkNode);
336 SWTMR_CTRL_S *swtmr = LOS_DL_LIST_ENTRY(sortList, SWTMR_CTRL_S, stSortList);
337 OsDeleteNodeSortLink(sortList);
338 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
339 g_swtmrAlignID[swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT].isAligned = 0;
340 #endif
341 swtmr->startTime = startTime;
342 OsSwtmrStart(startTime, swtmr);
343 listNext = listNext->pstNext;
344 }
345 }
346
347 /*****************************************************************************
348 Function : OsSwtmrGetNextTimeout
349 Description : Get next timeout
350 Input : None
351 Output : None
352 Return : Count of the Timer list
353 *****************************************************************************/
OsSwtmrGetNextTimeout(VOID)354 LITE_OS_SEC_TEXT UINT32 OsSwtmrGetNextTimeout(VOID)
355 {
356 UINT32 intSave = LOS_IntLock();
357 UINT64 time = OsSortLinkGetNextExpireTime(g_swtmrSortLinkList);
358 LOS_IntRestore(intSave);
359 time = OS_SYS_CYCLE_TO_TICK(time);
360 if (time > OS_NULL_INT) {
361 time = OS_NULL_INT;
362 }
363 return time;
364 }
365
OsSwtmrTimeGet(const SWTMR_CTRL_S * swtmr)366 LITE_OS_SEC_TEXT UINT32 OsSwtmrTimeGet(const SWTMR_CTRL_S *swtmr)
367 {
368 UINT64 time = OsSortLinkGetTargetExpireTime(OsGetCurrSchedTimeCycle(), &swtmr->stSortList);
369 time = OS_SYS_CYCLE_TO_TICK(time);
370 if (time > OS_NULL_INT) {
371 time = OS_NULL_INT;
372 }
373 return (UINT32)time;
374 }
375
376 /*****************************************************************************
377 Function : OsSwtmrInit
378 Description : Initializes Software Timer
379 Input : None
380 Output : None
381 Return : LOS_OK on success or error code on failure
382 *****************************************************************************/
OsSwtmrInit(VOID)383 LITE_OS_SEC_TEXT_INIT UINT32 OsSwtmrInit(VOID)
384 {
385 UINT32 size;
386 UINT16 index;
387 UINT32 ret;
388
389 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
390 // Ignore the return code when matching CSEC rule 6.6(1).
391 (VOID)memset_s((VOID *)g_swtmrAlignID, sizeof(SwtmrAlignData) * LOSCFG_BASE_CORE_SWTMR_LIMIT,
392 0, sizeof(SwtmrAlignData) * LOSCFG_BASE_CORE_SWTMR_LIMIT);
393 #endif
394
395 size = sizeof(SWTMR_CTRL_S) * LOSCFG_BASE_CORE_SWTMR_LIMIT;
396 SWTMR_CTRL_S *swtmr = (SWTMR_CTRL_S *)LOS_MemAlloc(m_aucSysMem0, size);
397 if (swtmr == NULL) {
398 return LOS_ERRNO_SWTMR_NO_MEMORY;
399 }
400 // Ignore the return code when matching CSEC rule 6.6(3).
401 (VOID)memset_s((VOID *)swtmr, size, 0, size);
402 g_swtmrCBArray = swtmr;
403 g_swtmrFreeList = swtmr;
404 swtmr->usTimerID = 0;
405 SWTMR_CTRL_S *temp = swtmr;
406 swtmr++;
407 for (index = 1; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
408 swtmr->usTimerID = index;
409 temp->pstNext = swtmr;
410 temp = swtmr;
411 }
412
413 ret = LOS_QueueCreate((CHAR *)NULL, OS_SWTMR_HANDLE_QUEUE_SIZE,
414 &g_swtmrHandlerQueue, 0, sizeof(SwtmrHandlerItem));
415 if (ret != LOS_OK) {
416 (VOID)LOS_MemFree(m_aucSysMem0, swtmr);
417 return LOS_ERRNO_SWTMR_QUEUE_CREATE_FAILED;
418 }
419
420 ret = OsSwtmrTaskCreate();
421 if (ret != LOS_OK) {
422 (VOID)LOS_MemFree(m_aucSysMem0, swtmr);
423 return LOS_ERRNO_SWTMR_TASK_CREATE_FAILED;
424 }
425
426 g_swtmrSortLinkList = OsGetSortLinkAttribute(OS_SORT_LINK_SWTMR);
427 if (g_swtmrSortLinkList == NULL) {
428 (VOID)LOS_MemFree(m_aucSysMem0, swtmr);
429 return LOS_NOK;
430 }
431
432 ret = OsSortLinkInit(g_swtmrSortLinkList);
433 if (ret != LOS_OK) {
434 (VOID)LOS_MemFree(m_aucSysMem0, swtmr);
435 return LOS_NOK;
436 }
437
438 ret = OsSchedSwtmrScanRegister((SchedScan)OsSwtmrScan);
439 if (ret != LOS_OK) {
440 (VOID)LOS_MemFree(m_aucSysMem0, swtmr);
441 return LOS_NOK;
442 }
443
444 return LOS_OK;
445 }
446
447 /*****************************************************************************
448 Function : LOS_SwtmrCreate
449 Description : Create software timer
450 Input : interval
451 mode
452 handler
453 arg
454 Output : swtmrId
455 Return : LOS_OK on success or error code on failure
456 *****************************************************************************/
457 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
LOS_SwtmrCreate(UINT32 interval,UINT8 mode,SWTMR_PROC_FUNC handler,UINT32 * swtmrId,UINT32 arg,UINT8 rouses,UINT8 sensitive)458 LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval,
459 UINT8 mode,
460 SWTMR_PROC_FUNC handler,
461 UINT32 *swtmrId,
462 UINT32 arg,
463 UINT8 rouses,
464 UINT8 sensitive)
465 #else
466 LITE_OS_SEC_TEXT_INIT UINT32 LOS_SwtmrCreate(UINT32 interval,
467 UINT8 mode,
468 SWTMR_PROC_FUNC handler,
469 UINT32 *swtmrId,
470 UINT32 arg)
471 #endif
472 {
473 SWTMR_CTRL_S *swtmr = NULL;
474 UINT32 intSave;
475
476 if (interval == 0) {
477 return LOS_ERRNO_SWTMR_INTERVAL_NOT_SUITED;
478 }
479
480 if ((mode != LOS_SWTMR_MODE_ONCE) &&
481 (mode != LOS_SWTMR_MODE_PERIOD) &&
482 (mode != LOS_SWTMR_MODE_NO_SELFDELETE)) {
483 return LOS_ERRNO_SWTMR_MODE_INVALID;
484 }
485
486 if (handler == NULL) {
487 return LOS_ERRNO_SWTMR_PTR_NULL;
488 }
489
490 if (swtmrId == NULL) {
491 return LOS_ERRNO_SWTMR_RET_PTR_NULL;
492 }
493
494 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
495 if ((rouses != OS_SWTMR_ROUSES_IGNORE) && (rouses != OS_SWTMR_ROUSES_ALLOW)) {
496 return OS_ERRNO_SWTMR_ROUSES_INVALID;
497 }
498
499 if ((sensitive != OS_SWTMR_ALIGN_INSENSITIVE) && (sensitive != OS_SWTMR_ALIGN_SENSITIVE)) {
500 return OS_ERRNO_SWTMR_ALIGN_INVALID;
501 }
502 #endif
503
504 intSave = LOS_IntLock();
505 if (g_swtmrFreeList == NULL) {
506 LOS_IntRestore(intSave);
507 return LOS_ERRNO_SWTMR_MAXSIZE;
508 }
509
510 swtmr = g_swtmrFreeList;
511 g_swtmrFreeList = swtmr->pstNext;
512 LOS_IntRestore(intSave);
513 swtmr->pfnHandler = handler;
514 swtmr->ucMode = mode;
515 swtmr->uwInterval = interval;
516 swtmr->pstNext = (SWTMR_CTRL_S *)NULL;
517 swtmr->uwArg = arg;
518 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
519 swtmr->ucRouses = rouses;
520 swtmr->ucSensitive = sensitive;
521 #endif
522 swtmr->ucState = OS_SWTMR_STATUS_CREATED;
523 swtmr->ucOverrun = 0;
524 *swtmrId = swtmr->usTimerID;
525 SET_SORTLIST_VALUE(&swtmr->stSortList, OS_SORT_LINK_INVALID_TIME);
526 OsHookCall(LOS_HOOK_TYPE_SWTMR_CREATE, swtmr);
527 return LOS_OK;
528 }
529
530 /*****************************************************************************
531 Function : LOS_SwtmrStart
532 Description : Start software timer
533 Input : swtmrId ------- Software timer ID
534 Output : None
535 Return : LOS_OK on success or error code on failure
536 *****************************************************************************/
LOS_SwtmrStart(UINT32 swtmrId)537 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStart(UINT32 swtmrId)
538 {
539 UINT32 intSave;
540 UINT32 ret = LOS_OK;
541
542 if (swtmrId >= OS_SWTMR_MAX_TIMERID) {
543 return LOS_ERRNO_SWTMR_ID_INVALID;
544 }
545
546 intSave = LOS_IntLock();
547 SWTMR_CTRL_S *swtmr = g_swtmrCBArray + swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
548 if (swtmr->usTimerID != swtmrId) {
549 LOS_IntRestore(intSave);
550 return LOS_ERRNO_SWTMR_NOT_CREATED;
551 }
552
553 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
554 if ((swtmr->ucSensitive == OS_SWTMR_ALIGN_INSENSITIVE) && (swtmr->ucMode == LOS_SWTMR_MODE_PERIOD)) {
555 UINT32 swtmrAlignIdIndex = swtmr->usTimerID % LOSCFG_BASE_CORE_SWTMR_LIMIT;
556 g_swtmrAlignID[swtmrAlignIdIndex].canAlign = 1;
557 if ((swtmr->uwInterval % LOS_COMMON_DIVISOR) == 0) {
558 g_swtmrAlignID[swtmrAlignIdIndex].canMultiple = 1;
559 g_swtmrAlignID[swtmrAlignIdIndex].times = swtmr->uwInterval / LOS_COMMON_DIVISOR;
560 }
561 }
562 #endif
563
564 switch (swtmr->ucState) {
565 case OS_SWTMR_STATUS_UNUSED:
566 ret = LOS_ERRNO_SWTMR_NOT_CREATED;
567 break;
568 case OS_SWTMR_STATUS_TICKING:
569 OsSwtmrStop(swtmr);
570 /* fall through */
571 case OS_SWTMR_STATUS_CREATED:
572 swtmr->startTime = OsGetCurrSchedTimeCycle();
573 OsSwtmrStart(swtmr->startTime, swtmr);
574 break;
575 default:
576 ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
577 break;
578 }
579
580 LOS_IntRestore(intSave);
581 OsHookCall(LOS_HOOK_TYPE_SWTMR_START, swtmr);
582 return ret;
583 }
584
585 /*****************************************************************************
586 Function : LOS_SwtmrStop
587 Description : Stop software timer
588 Input : swtmrId ------- Software timer ID
589 Output : None
590 Return : LOS_OK on success or error code on failure
591 *****************************************************************************/
LOS_SwtmrStop(UINT32 swtmrId)592 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrStop(UINT32 swtmrId)
593 {
594 SWTMR_CTRL_S *swtmr = NULL;
595 UINT32 intSave;
596 UINT16 swtmrCbId;
597 UINT32 ret = LOS_OK;
598
599 if (swtmrId >= OS_SWTMR_MAX_TIMERID) {
600 return LOS_ERRNO_SWTMR_ID_INVALID;
601 }
602 intSave = LOS_IntLock();
603 swtmrCbId = swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
604 swtmr = g_swtmrCBArray + swtmrCbId;
605 if (swtmr->usTimerID != swtmrId) {
606 LOS_IntRestore(intSave);
607 return LOS_ERRNO_SWTMR_NOT_CREATED;
608 }
609
610 switch (swtmr->ucState) {
611 case OS_SWTMR_STATUS_UNUSED:
612 ret = LOS_ERRNO_SWTMR_NOT_CREATED;
613 break;
614 case OS_SWTMR_STATUS_CREATED:
615 ret = LOS_ERRNO_SWTMR_NOT_STARTED;
616 break;
617 case OS_SWTMR_STATUS_TICKING:
618 OsSwtmrStop(swtmr);
619 break;
620 default:
621 ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
622 break;
623 }
624
625 LOS_IntRestore(intSave);
626 OsHookCall(LOS_HOOK_TYPE_SWTMR_STOP, swtmr);
627 return ret;
628 }
629
LOS_SwtmrTimeGet(UINT32 swtmrId,UINT32 * tick)630 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrTimeGet(UINT32 swtmrId, UINT32 *tick)
631 {
632 SWTMR_CTRL_S *swtmr = NULL;
633 UINT32 intSave;
634 UINT32 ret = LOS_OK;
635 UINT16 swtmrCbId;
636
637 if (swtmrId >= OS_SWTMR_MAX_TIMERID) {
638 return LOS_ERRNO_SWTMR_ID_INVALID;
639 }
640
641 if (tick == NULL) {
642 return LOS_ERRNO_SWTMR_TICK_PTR_NULL;
643 }
644
645 intSave = LOS_IntLock();
646 swtmrCbId = swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
647 swtmr = g_swtmrCBArray + swtmrCbId;
648 if (swtmr->usTimerID != swtmrId) {
649 LOS_IntRestore(intSave);
650 return LOS_ERRNO_SWTMR_NOT_CREATED;
651 }
652 switch (swtmr->ucState) {
653 case OS_SWTMR_STATUS_UNUSED:
654 ret = LOS_ERRNO_SWTMR_NOT_CREATED;
655 break;
656 case OS_SWTMR_STATUS_CREATED:
657 ret = LOS_ERRNO_SWTMR_NOT_STARTED;
658 break;
659 case OS_SWTMR_STATUS_TICKING:
660 *tick = OsSwtmrTimeGet(swtmr);
661 break;
662 default:
663 ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
664 break;
665 }
666 LOS_IntRestore(intSave);
667 return ret;
668 }
669
670 /*****************************************************************************
671 Function : LOS_SwtmrDelete
672 Description : Delete software timer
673 Input : swtmrId ------- Software timer ID
674 Output : None
675 Return : LOS_OK on success or error code on failure
676 *****************************************************************************/
LOS_SwtmrDelete(UINT32 swtmrId)677 LITE_OS_SEC_TEXT UINT32 LOS_SwtmrDelete(UINT32 swtmrId)
678 {
679 SWTMR_CTRL_S *swtmr = NULL;
680 UINT32 intSave;
681 UINT32 ret = LOS_OK;
682 UINT16 swtmrCbId;
683
684 if (swtmrId >= OS_SWTMR_MAX_TIMERID) {
685 return LOS_ERRNO_SWTMR_ID_INVALID;
686 }
687 intSave = LOS_IntLock();
688 swtmrCbId = swtmrId % LOSCFG_BASE_CORE_SWTMR_LIMIT;
689 swtmr = g_swtmrCBArray + swtmrCbId;
690 if (swtmr->usTimerID != swtmrId) {
691 LOS_IntRestore(intSave);
692 return LOS_ERRNO_SWTMR_NOT_CREATED;
693 }
694
695 switch (swtmr->ucState) {
696 case OS_SWTMR_STATUS_UNUSED:
697 ret = LOS_ERRNO_SWTMR_NOT_CREATED;
698 break;
699 case OS_SWTMR_STATUS_TICKING:
700 OsSwtmrStop(swtmr);
701 /* fall through */
702 case OS_SWTMR_STATUS_CREATED:
703 OsSwtmrDelete(swtmr);
704 break;
705 default:
706 ret = LOS_ERRNO_SWTMR_STATUS_INVALID;
707 break;
708 }
709
710 LOS_IntRestore(intSave);
711 OsHookCall(LOS_HOOK_TYPE_SWTMR_DELETE, swtmr);
712 return ret;
713 }
714
715 #endif /* (LOSCFG_BASE_CORE_SWTMR == 1) */
716