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