Repository navigation
Expand file tree
/
Copy pathticktask.h
More file actions
456 lines (367 loc) · 11.4 KB
/
Copy pathticktask.h
File metadata and controls
456 lines (367 loc) · 11.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
/**The configuration item
* 配置项
* #define TSysTickCnt - the SysTick count // SysTick计数值
* #define TSystemCoreClock - Disable automatic detection // 禁用自动检测(未使用)
* #define TSysTick_open() - open and start systick // 打开并启动systick
* #define TickTIMx_MAX
* #define USE_TimerWheel
* */
/**The Usage
* 使用方法
* configuration item // 配置项
* ...
* #define STB_task
* #include "task.h"
* */
#ifndef _TASK_H_
#define _TASK_H_
#include <stdint.h>
#include <stdio.h>
#ifndef TSysTickCnt
#error You must first define the SysTick count to use this component.
#endif
#ifndef TSysTickMAX
#error You must first define the Max SysTick count to use this component.
#endif
#ifndef TUsCnt
#error You must first define the SystemCoreClock value to use this component.
#endif
#ifndef TSysTick_open /* TSysTick_open() */
#error You must first define the SysTick open funcation to use this component.
#endif
#ifndef TickTIMx_MAX
#define TickTIMx_MAX 8
#endif
#define TWHEEL_TIME_STR_SIZE (21)
#define __TaskInit(task, ticks, call) \
task_t task = {.period = ticks, .compare = 0, .proc = call}; \
task.compare = task.period + TSysTickCnt; \
TaskAdd (&task);
typedef struct list_node lnode_t;
struct list_node {
lnode_t *next;
};
lnode_t * list_search(lnode_t* node);
typedef struct task {
struct task *next;
void (*proc)();
uint32_t period;
uint32_t compare;
uint32_t overflow;
} task_t;
typedef union {
struct {
uint32_t s: 6;
uint32_t m: 6;
uint32_t h: 20;
};
uint32_t value;
} twheel_t;
typedef void (*callback_t)(void);
typedef struct twtimer {
struct twtimer* next;
struct twtimer* prev;
callback_t callback;
uint32_t period;
uint32_t compare;
uint32_t overflow;
uint32_t cycle;
#define TTIM_Once 1
#define TTIM_Cycle 0
} twtimer_t;
#define TASK_NULL (task_t){NULL,NULL,0,0,0}
#define TWTIM_NULL (twtimer_t){NULL,NULL,NULL,0,0,0,0}
static uint32_t p_us = 0U;
static uint32_t p_ms = 0U;
static twheel_t twheel = {0U, 0U, 0U};
static task_t taskHead = TASK_NULL;
static twtimer_t timerHead = TWTIM_NULL;
static twtimer_t timerPool[TickTIMx_MAX] = {0};
struct {
uint32_t free;
uint32_t used;
twtimer_t* pool[TickTIMx_MAX];
size_t capacity;
} twtmgr = {.capacity = sizeof(twtmgr.pool) / sizeof(twtmgr.pool[0])};
void TaskManager_Init (void);
void TaskAdd (task_t *pt);
void TaskDelete(task_t *pt);
void TaskRun(void);
/* TwtimerInit() */
void TwtimerAdd(twheel_t tm, uint32_t cycle, callback_t cb);
void TwtimerDelete(twtimer_t *twt);
void TaskTwheelInit(void);
void twheel_entry(void);
uint8_t timerPoolalloc(twtimer_t **tw);
void TDelay_Us(uint32_t n);
void TDelay_Ms(uint32_t n);
uint32_t Get_UsTicks (uint32_t n) { return n * p_us; }
uint32_t Get_MsTicks (uint32_t n) { return n * p_ms; }
uint32_t Get_sTicks (uint32_t n) { return n * p_ms * 1000U; }
void TaskManager_Init (void)
{
p_us = TUsCnt;
p_ms = p_us * 1000;
TSysTick_open();
TaskTwheelInit();
}
void TaskInit(task_t *pt)
{
pt->compare = pt->period + TSysTickCnt;
TaskAdd (pt);
}
void TaskAdd (task_t *pt)
{
task_t *node = pt;
/* 避免重复添加 */ // Avoid duplicate addition
if (taskHead.next == node) {
return;
}
pt->next = taskHead.next;
taskHead.next = node;
}
void TaskDelete(task_t *pt)
{
if (pt == NULL) return;
task_t *prev = &taskHead;
while (prev->next != NULL && prev->next != pt)
{
prev = prev->next;
}
if (prev->next == NULL) return;
prev->next = pt->next;
pt->next = NULL;
}
void TaskRun(void)
{
task_t *pt = taskHead.next;
register uint32_t syscnt;
while (pt != NULL && pt->proc != NULL)
{
syscnt = TSysTickCnt;
if (syscnt < pt->overflow) {
pt->overflow = 0;
}
if (pt->compare <= syscnt && pt->overflow == 0) {
pt->proc();
uint32_t compare = syscnt + pt->period;
compare %= TSysTickMAX;
if (compare < pt->compare) {
pt->overflow = pt->compare;
}
pt->compare = compare;
}
pt = pt->next;
}
}
void TwtimerAdd(twheel_t tm, uint32_t cycle, callback_t cb)
{
static uint32_t used = 0;
twtimer_t* node = NULL;
if (twtmgr.used == twtmgr.free) return;
node = twtmgr.pool[twtmgr.used++];
twtmgr.used %= twtmgr.capacity;
if (node == NULL) return;
/* 避免重复添加 */ // Avoid duplicate addition
if (timerHead.next == node) return;
node->period = tm.value;
node->callback = cb;
node->compare = tm.value + twheel.value;
node->cycle = cycle;
node->next = timerHead.next;
timerHead.next = node;
node->prev = &timerHead;
used += 1;
}
void TwtimerDelete(twtimer_t *twt)
{
/* 重复删除判断 */ // Duplicate deletion check
if (twt->prev == NULL) return;
twt->prev->next = twt->next;
/* 尾节点判断 */ // Tail node check
if (twt->next == NULL) return;
twt->next->prev = twt->prev;
/* 清理 */ // Cleanup
twt->next = NULL;
twt->prev = NULL;
*twt = (twtimer_t) {0, 0, 0, 0, 0, 0};
if ((twtmgr.free + 1) % twtmgr.capacity == twtmgr.used) {
return ;
}
twtmgr.pool[twtmgr.free++] = twt;
twtmgr.free %= twtmgr.capacity;
}
void TaskTwheelInit(void)
{
#ifdef USE_TimerWheel
static task_t twheel_task = {.proc = twheel_entry};
// 初始化软定时器内存池 // Initialize soft timer memory pool
twtmgr.free = 0;
twtmgr.used = 0;
for (int i = 0; i < twtmgr.capacity; i++) {
twtmgr.pool[twtmgr.free] = &timerPool[i];
if ((twtmgr.free + 1) % twtmgr.capacity == twtmgr.used) break;
twtmgr.free = (twtmgr.free + 1) % twtmgr.capacity;
}
TaskAdd(&twheel_task);
twheel_task.period = Get_MsTicks(1);
twheel_task.compare = twheel_task.period + TSysTickCnt;
}
/* period 937500 us*/
void twheel_entry(void)
{
static uint32_t msCnt = 0U;
msCnt += 1U;
if (msCnt == 1000U) {
twheel.s += 1U;
msCnt = 0;
}
if (twheel.s == 60U) {
twheel.s = 0U;
twheel.m += 1U;
}
if (twheel.m == 60U) {
twheel.m = 0U;
twheel.h += 1U;
}
twtimer_t* ptt = &timerHead;
while (ptt = ptt->next, ptt != NULL )
{
ptt->overflow = (twheel.value < ptt->overflow) ? ptt->overflow : 0U;
if (ptt->compare <= twheel.value && ptt->overflow == 0U) {
ptt->callback();
uint32_t compare = twheel.value + ptt->period;
ptt->overflow = (compare < ptt->compare) ? ptt->compare : 0U;
ptt->compare = compare;
if (ptt->cycle == 1U) {
TwtimerDelete(ptt);
/* clean */ /* 清理 */
*ptt = TWTIM_NULL;
}
else if ( ptt -> cycle == 0U) {;}
else {
ptt->cycle -= 1U;
}
}
}
}
#else /* USE_TimerWheel */
}
#endif /* USE_TimerWheel */
uint32_t Get_twheelValue(void) { return twheel.value; }
twheel_t Get_twheelTime(void) { return twheel; }
char* uint2str(uint64_t value, char* buffer)
{
// 边界处理:直接处理 0 的情况 // Boundary handling: handle 0 directly
if (value == 0) {
buffer[0] = '0';
buffer[1] = '\0';
return buffer;
}
// 1. 使用 __builtin_clzll 快速确定位数(基于二进制位数映射) // Use __builtin_clzll to quickly determine digit count (based on binary length mapping)
int digit_count = (((64 - __builtin_clzll(value)) * 1233) >> 12) + 1;
// 2. 创建一个临时缓冲区反向写入 // Create temporary buffer for reverse writing
char temp[21];
int pos = digit_count; // 从最高位开始填充 // Start filling from most significant digit
temp[pos] = '\0'; // 设置字符串终止符 // Set string terminator
// 3. 根据位数选择处理策略 // Choose processing strategy based on digit count
// 如果位数较多(>= 4 位),我们使用除以 100 的方式,一次处理两位 // If digits >= 4, use divide by 100 to process two digits at a time
// 这样可以将循环次数减少一半(例如 12 位数字只需要 6 次循环) // This halves loop count (e.g., 12 digits -> 6 iterations)
while (digit_count >= 4) {
// 取模 100,得到当前最低的两位数字 // Mod 100 to get lowest two digits
uint64_t two_digits = value % 100;
// 整除 100,去掉最低的两位 // Divide by 100 to remove lowest two digits
value /= 100;
// 处理两位数字 // Process two digits
// 由于不使用查表,需要分别处理个位和十位 // Without lookup table, handle units and tens separately
uint8_t low = two_digits % 10; // 个位 // units
uint8_t high = two_digits / 10; // 十位 // tens
// 逆序写入字符 // Write characters in reverse order
temp[--pos] = (char)(low + 0x30); // 个位字符 // units char
temp[--pos] = (char)(high + 0x30); // 十位字符 // tens char
digit_count -= 2; // 处理了两位 // processed two digits
}
// 处理剩余的 1~3 位数字 // Process remaining 1~3 digits
while (digit_count > 0) {
// 对于最后几位,直接使用加 0x30 的方式(效率最高) // For last digits, use +0x30 (most efficient)
uint64_t digit = value % 10;
value /= 10;
temp[--pos] = (char)(digit + 0x30);
digit_count--;
}
// 4. 将结果拷贝到输出缓冲区 // Copy result to output buffer
char *dst = buffer;
char *src = temp;
while (*src) {
*dst++ = *src++;
}
*dst = '\0';
return buffer;
}
const char* Get_twheelTimeStr(void)
{
const char zero[TWHEEL_TIME_STR_SIZE] = {0};
static char str[TWHEEL_TIME_STR_SIZE] = {0};
typedef struct {char _[TWHEEL_TIME_STR_SIZE];}*pcopy;
*((pcopy)str) = *((pcopy)zero);
uint8_t index = 0;
uint2str(twheel.h, str);
while (str[index] != '\0') index++;
str[index++] = ':';
uint2str(twheel.m, &str[index]);
while (str[index] != '\0') index++;
str[index++] = ':';
uint2str(twheel.s, &str[index]);
return str;
}
/*********************************************************************
* @fn TDelay_Us
*
* @brief Microsecond Delay Time. // 微秒延时
*
* @param n - Microsecond number. // 微秒数
*
* @return None
*/
void TDelay_Us(uint32_t n)
{
uint32_t ticks = n * p_us;
uint32_t now = 0;
uint32_t elapsed = 0;
uint32_t start = TSysTickCnt;
do {
now = TSysTickCnt;
if (now > start) {
elapsed = now - start;
}
else {
elapsed = (TSysTickMAX - start) + now + 1;
}
} while (elapsed < ticks);
}
/*********************************************************************
* @fn TDelay_Ms
*
* @brief Millisecond Delay Time. // 毫秒延时
*
* @param n - Millisecond number. // 毫秒数
*
* @return None
*/
void TDelay_Ms(uint32_t n)
{
uint32_t ticks = n * p_ms;
uint32_t now = 0;
uint32_t elapsed = 0;
uint32_t start = TSysTickCnt;
do {
now = TSysTickCnt;
if (now > start) {
elapsed = now - start;
}
else {
elapsed = (TSysTickMAX - start) + now + 1;
}
} while (elapsed < ticks);
}
#endif /* _TASK_H_ */