• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2009-12-22
13  * Description: 软件定时器模块的C文件
14  */
15 #include "prt_swtmr_internal.h"
16 
17 OS_SEC_BSS U32 g_swTmrMaxNum;
18 /* 定时器内存空间首地址 */
19 OS_SEC_BSS struct TagSwTmrCtrl *g_swtmrCbArray;
20 /* 软件定时器空闲链表 */
21 OS_SEC_BSS struct TagSwTmrCtrl *g_tmrFreeList;
22 /* 软件定时器Sortlink */
23 OS_SEC_BSS struct TagSwTmrSortLinkAttr g_tmrSortLink;
24 
25 /* 基于tick的软件定时器组ID,为支持独立升级,该变量需要在2022年之后版本才能删除 */
26 OS_SEC_BSS TimerGroupId g_tickSwTmrGroupId;
27 /*
28  * 描述:创建普通软件定时器组
29  */
OsSwTimerGroupCreate(struct TmrGrpUserCfg * config,TimerGroupId * groupId)30 OS_SEC_L4_TEXT U32 OsSwTimerGroupCreate(struct TmrGrpUserCfg *config, TimerGroupId *groupId)
31 {
32     U32 ret;
33     uintptr_t intSave;
34 
35     if (g_tickModInfo.tickPerSecond == 0) {
36         return OS_ERRNO_TICK_NOT_INIT;
37     }
38 
39     if (config->maxTimerNum == 0) {  // 最大定时器个数为零
40         return OS_ERRNO_TIMER_NUM_ZERO;
41     }
42 
43     if (config->maxTimerNum > (U32)OS_MAX_U16) {
44         // 软件定时器个数为UINT16型,用户传入参数不能超过UINT16的最大值
45         return OS_ERRNO_TIMER_NUM_TOO_LARGE;
46     }
47 
48     intSave = OsIntLock();
49 
50     if (g_timerApi[TIMER_TYPE_SWTMR].createTimer != NULL) {  // 定时器组已经创建
51         OsIntRestore(intSave);
52         return OS_ERRNO_TIMER_TICKGROUP_CREATED;
53     }
54 
55     g_swTmrMaxNum = config->maxTimerNum;
56 
57     ret = OsSwTmrResInit();
58     if (ret != OS_OK) {
59         OsIntRestore(intSave);
60         return ret;
61     }
62 
63     g_timerApi[TIMER_TYPE_SWTMR].createTimer = (TimerCreateFunc)OsSwTmrCreateTimer;
64     g_timerApi[TIMER_TYPE_SWTMR].startTimer = (TimerStartFunc)OsSwTmrStartTimer;
65     g_timerApi[TIMER_TYPE_SWTMR].stopTimer = (TimerStopFunc)OsSwTmrStopTimer;
66     g_timerApi[TIMER_TYPE_SWTMR].deleteTimer = (TimerDeleteFunc)OsSwTmrDeleteTimer;
67     g_timerApi[TIMER_TYPE_SWTMR].restartTimer = (TimerRestartFunc)OsSwTmrRestartTimer;
68     g_timerApi[TIMER_TYPE_SWTMR].timerQuery = (TimerQueryFunc)OsSwTmrQuery;
69 
70     *groupId = OS_TICK_SWTMR_GROUP_ID;
71 
72     OsIntRestore(intSave);
73     return OS_OK;
74 }
75 
OsSwTmrCreateTimerParaChk(struct TimerCreatePara * createPara)76 OS_SEC_ALW_INLINE INLINE U32 OsSwTmrCreateTimerParaChk(struct TimerCreatePara *createPara)
77 {
78     /* OS接管中断, 中断处理函数必须为非NULL */
79     if (createPara->callBackFunc == NULL) {
80         return OS_ERRNO_TIMER_PROC_FUNC_NULL;
81     }
82 
83     if (createPara->timerGroupId != OS_TICK_SWTMR_GROUP_ID) {
84         return OS_ERRNO_TIMERGROUP_ID_INVALID;
85     }
86 
87     if ((DIV64_REMAIN((U64)g_tickModInfo.tickPerSecond * (createPara->interval), OS_SYS_MS_PER_SECOND)) !=
88         0) {  // ms转tick时,tick不为整数
89         return OS_ERRNO_SWTMR_INTERVAL_NOT_SUITED;
90     }
91 
92     if (createPara->interval >
93         DIV64(OS_SYS_MS_PER_SECOND * ((U64)OS_MAX_U32), g_tickModInfo.tickPerSecond)) {  // 溢出判断
94         return OS_ERRNO_SWTMR_INTERVAL_OVERFLOW;
95     }
96     return OS_OK;
97 }
98 
OsSwTmrCreateTimerCbInit(struct TimerCreatePara * createPara,struct TagSwTmrCtrl * swtmr,U32 interval)99 OS_SEC_ALW_INLINE INLINE void OsSwTmrCreateTimerCbInit(struct TimerCreatePara *createPara,
100                                                        struct TagSwTmrCtrl *swtmr, U32 interval)
101 {
102     /* 设置新定时器的参数 */
103     swtmr->handler = createPara->callBackFunc;
104     swtmr->mode = (U8)createPara->mode;
105     swtmr->interval = interval;
106     swtmr->next = NULL;
107     swtmr->prev = NULL;
108     swtmr->idxRollNum = swtmr->interval;
109     swtmr->arg1 = createPara->arg1;
110     swtmr->arg2 = createPara->arg2;
111     swtmr->arg3 = createPara->arg3;
112     swtmr->arg4 = createPara->arg4;
113     swtmr->state = (U8)OS_TIMER_CREATED;
114     return;
115 }
OsSwTmrInit(U32 maxTimerNum)116 OS_SEC_L4_TEXT U32 OsSwTmrInit(U32 maxTimerNum)
117 {
118     struct TmrGrpUserCfg config;
119 
120     config.tmrGrpSrcType = OS_TIMER_GRP_SRC_TICK;
121     config.maxTimerNum = maxTimerNum;
122 
123     return OsSwTimerGroupCreate(&config, &g_tickSwTmrGroupId);
124 }
125 /*
126  * 描述:软件定时器的创建接口
127  */
OsSwTmrCreateTimer(struct TimerCreatePara * createPara,TimerHandle * tmrHandle)128 OS_SEC_L4_TEXT U32 OsSwTmrCreateTimer(struct TimerCreatePara *createPara, TimerHandle *tmrHandle)
129 {
130     struct TagSwTmrCtrl *swtmr = NULL;
131     U32 interval;
132     uintptr_t intSave;
133     U32 ret;
134 
135     ret = OsSwTmrCreateTimerParaChk(createPara);
136     if (ret != OS_OK) {
137         return ret;
138     }
139 
140     interval = (U32)DIV64(((U64)g_tickModInfo.tickPerSecond * (createPara->interval)), OS_SYS_MS_PER_SECOND);
141 
142     intSave = OsIntLock();
143 
144     if (g_tmrFreeList == NULL) {
145         OsIntRestore(intSave);
146         return OS_ERRNO_SWTMR_MAXSIZE;
147     }
148 
149     /*
150      * 从空闲链表中取出一个控制块
151      * 保证空闲链表的完整性,首节点没有前驱,尾节点没有后继节点
152      */
153     swtmr = g_tmrFreeList;
154     g_tmrFreeList = swtmr->next;
155     OsSwTmrCreateTimerCbInit(createPara, swtmr, interval);
156 
157     SWTMR_CREATE_DEL_UNLOCK();
158     OsIntRestore(intSave);
159     /* 把TimerID写入返回参数 */
160     *tmrHandle = OS_SWTMR_INDEX_2_ID(swtmr->swtmrIndex);
161 
162     return OS_OK;
163 }
164 
165 /*
166  * 描述:软件定时器的删除接口
167  */
OsSwTmrDeleteTimer(TimerHandle tmrHandle)168 OS_SEC_L4_TEXT U32 OsSwTmrDeleteTimer(TimerHandle tmrHandle)
169 {
170     struct TagSwTmrCtrl *swtmr = NULL;
171     uintptr_t intSave;
172 
173     if (OS_TIMER_GET_INDEX(tmrHandle) >= g_swTmrMaxNum) {
174         return OS_ERRNO_TIMER_HANDLE_INVALID;
175     }
176 
177     // 转化为软件定时器内部ID号
178     swtmr = g_swtmrCbArray + OS_SWTMR_ID_2_INDEX(tmrHandle);
179     intSave = OsSwtmrIqrSplLock(swtmr);
180 
181     switch (swtmr->state & OS_SWTMR_STATUS_MASK) {
182         case OS_TIMER_FREE:
183             OsSwtmrIqrSplUnlock(swtmr, intSave);
184             return OS_ERRNO_SWTMR_NOT_CREATED;
185         case OS_TIMER_EXPIRED:
186             swtmr->state = OS_SWTMR_PRE_FREE | (U8)OS_TIMER_EXPIRED;
187             OsSwtmrIqrSplUnlock(swtmr, intSave);
188             return OS_OK;
189         case OS_TIMER_RUNNING:
190             OsSwTmrStop(swtmr, TRUE);
191             break;
192         default:
193             break;
194     }
195 
196     OsSwTmrDelete(swtmr);
197 
198     OsSwtmrIqrSplUnlock(&swtmrTmp, intSave);
199 
200     return OS_OK;
201 }
202 
OsSwTmrCtrlInit(struct TagSwTmrCtrl * swtmrIn)203 OS_SEC_L4_TEXT void OsSwTmrCtrlInit(struct TagSwTmrCtrl *swtmrIn)
204 {
205     U16 idx;
206     struct TagSwTmrCtrl *temp = NULL;
207     struct TagSwTmrCtrl *swtmr = swtmrIn;
208 
209     swtmr->swtmrIndex = 0;
210     swtmr->state = (U8)OS_TIMER_FREE;
211     temp = swtmr;
212     swtmr++;
213     for (idx = 1; idx < g_swTmrMaxNum; idx++, swtmr++) {
214         swtmr->swtmrIndex = idx;
215         swtmr->state = (U8)OS_TIMER_FREE;
216         temp->next = swtmr;
217         temp = swtmr;
218     }
219 
220     g_swtmrScanHook = OsSwTmrScan;
221 }
222 
223 /*
224  * 描述:软件定时器模块的初始化接口
225  */
OsSwTmrResInit(void)226 OS_SEC_L4_TEXT U32 OsSwTmrResInit(void)
227 {
228     U32 ret;
229     U32 size;
230     U32 idx;
231     struct TagListObject *listObject = NULL;
232     struct TagSwTmrCtrl *swtmr = NULL;
233 
234     /*
235      * 为定时器控制块分配内存,内存首地址保存到g_swtmrCbArray
236      * 控制块所需内存超过0xFFFFFFFF
237      */
238     if (g_swTmrMaxNum > (OS_MAX_U32 / sizeof(struct TagSwTmrCtrl))) {
239         return OS_ERRNO_SWTMR_NO_MEMORY;
240     }
241 
242     /* 为SortLink分配内存,初始化g_tmrSortLink */
243     size = sizeof(struct TagListObject) * OS_SWTMR_SORTLINK_LEN;
244     listObject =
245         (struct TagListObject *)OsMemAllocAlign((U32)OS_MID_SWTMR, OS_MEM_DEFAULT_FSC_PT, size, MEM_ADDR_ALIGN_016);
246     if (listObject == NULL) {
247         return OS_ERRNO_SWTMR_NO_MEMORY;
248     }
249 
250     if (memset_s(listObject, size, 0, size) != EOK) {
251         OS_GOTO_SYS_ERROR1();
252     }
253     g_tmrSortLink.sortLink = listObject;
254     g_tmrSortLink.cursor = 0;
255 
256     for (idx = 0; idx < OS_SWTMR_SORTLINK_LEN; idx++, listObject++) {
257         listObject->next = listObject;
258         listObject->prev = listObject;
259     }
260 
261     size = sizeof(struct TagSwTmrCtrl) * g_swTmrMaxNum;
262     swtmr = (struct TagSwTmrCtrl *)OsMemAllocAlign((U32)OS_MID_SWTMR, OS_MEM_DEFAULT_FSC_PT, size, MEM_ADDR_ALIGN_016);
263     if (swtmr == NULL) {
264         ret = PRT_MemFree((U32)OS_MID_SWTMR, (void *)g_tmrSortLink.sortLink);
265         if (ret != OS_OK) {
266             OS_REPORT_ERROR(ret);
267         }
268 
269         return OS_ERRNO_SWTMR_NO_MEMORY;
270     }
271 
272     if (memset_s(swtmr, size, 0, size) != EOK) {
273         OS_GOTO_SYS_ERROR1();
274     }
275     g_swtmrCbArray = swtmr;
276 
277     /* 把所有定时器控制块组织成一条单向链表,存放到空闲链中,空闲了首地址g_tmrFreeList */
278     g_tmrFreeList = swtmr;
279 
280     OsSwTmrCtrlInit(swtmr);
281 
282     return OS_OK;
283 }