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 }