• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * Description: Provides timer driver source \n
16  *
17  * History: \n
18  * 2022-11-07, Create file. \n
19  */
20 #include <stdbool.h>
21 #include <limits.h>
22 #include "securec.h"
23 #include "common_def.h"
24 #include "interrupt/osal_interrupt.h"
25 #include "tcxo.h"
26 #include "timer_porting.h"
27 #include "timer.h"
28 
29 #ifndef UINT64_MAX
30 #define UINT64_MAX (0xFFFFFFFFFFFFFFFFUL)
31 #endif
32 
33 #if defined(CONFIG_TIMER_USING_OLD_VERSION)
34 #define TIMER_OLD_VERSION_LOAD_COUNT_MASK 0x0F
35 #endif
36 
37 #ifdef CONFIG_TIMER_MAX_TIMERS_NUM
38 #ifndef CONFIG_TIMER_MAX_TIMERS_NUM_0
39 #define CONFIG_TIMER_MAX_TIMERS_NUM_0 CONFIG_TIMER_MAX_TIMERS_NUM
40 #endif
41 #ifndef CONFIG_TIMER_MAX_TIMERS_NUM_1
42 #define CONFIG_TIMER_MAX_TIMERS_NUM_1 CONFIG_TIMER_MAX_TIMERS_NUM
43 #endif
44 #ifndef CONFIG_TIMER_MAX_TIMERS_NUM_2
45 #define CONFIG_TIMER_MAX_TIMERS_NUM_2 CONFIG_TIMER_MAX_TIMERS_NUM
46 #endif
47 #ifndef CONFIG_TIMER_MAX_TIMERS_NUM_3
48 #define CONFIG_TIMER_MAX_TIMERS_NUM_3 CONFIG_TIMER_MAX_TIMERS_NUM
49 #endif
50 #ifndef CONFIG_TIMER_MAX_TIMERS_NUM_EXTRA
51 #define CONFIG_TIMER_MAX_TIMERS_NUM_EXTRA CONFIG_TIMER_MAX_TIMERS_NUM
52 #endif
53 #endif
54 
55 typedef enum timer_flag {
56     TIMER_FLAG_NORMAL,
57     TIMER_FLAG_PERMANENT
58 } timer_flag_t;
59 
60 typedef struct timer_info {
61     timer_handle_t      key;
62     timer_index_t       index;
63     bool                enable;
64     bool                is_run;
65     timer_flag_t        flag;
66     uint64_t            cycle;
67     timer_callback_t    callback;
68     uintptr_t           data;
69 } timer_info_t;
70 
71 typedef struct soft_timer_cfg {
72     uintptr_t   timer_addr;
73     uint8_t     timer_num;
74 } soft_timer_cfg_t;
75 
76 #define CUR_MAX_HARDWARE_TIMER_NUM 4
77 #define TIMER_SIZE_0 0
78 #define TIMER_SIZE_1 1
79 #define TIMER_SIZE_2 2
80 #define TIMER_SIZE_3 3
81 #define TIMER_SIZE_4 4
82 
83 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_0)
84 static timer_info_t g_timerlist_0[CONFIG_TIMER_MAX_TIMERS_NUM_0];
85 #endif
86 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_1)
87 static timer_info_t g_timerlist_1[CONFIG_TIMER_MAX_TIMERS_NUM_1];
88 #endif
89 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_2)
90 static timer_info_t g_timerlist_2[CONFIG_TIMER_MAX_TIMERS_NUM_2];
91 #endif
92 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_3)
93 static timer_info_t g_timerlist_3[CONFIG_TIMER_MAX_TIMERS_NUM_3];
94 #endif
95 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_4)
96 static timer_info_t \
97     g_timerlist_extra[CONFIG_TIMER_MAX_NUM - CUR_MAX_HARDWARE_TIMER_NUM][CONFIG_TIMER_MAX_TIMERS_NUM_EXTRA];
98 #endif
99 typedef struct timers_manager {
100     uint64_t            last_time_load_cycle;
101     timer_info_t        *timers;
102     uint32_t            hw_timer_irq_id;
103     uint16_t            hw_timer_int_priority;
104     bool                in_timer_irq;
105     uint8_t             soft_time_num;
106 } timers_manager_t;
107 
108 static bool g_timer_inited = false;
109 static bool g_timer_adapted[CONFIG_TIMER_MAX_NUM];
110 timers_manager_t g_timers_manager[CONFIG_TIMER_MAX_NUM];
111 
112 /*
113  * Reduces the time left for all the timers by timer us amount
114  */
timer_update_timers_time(timer_index_t index,uint64_t update_amount_cycle)115 STATIC bool timer_update_timers_time(timer_index_t index, uint64_t update_amount_cycle)
116 {
117     bool has_new_timer = false;
118     uint32_t irq_sts = osal_irq_lock();
119     uint8_t soft_time_num = g_timers_manager[index].soft_time_num;
120     for (uint8_t i = 0; i < soft_time_num; i++) {
121         if (g_timers_manager[index].timers[i].cycle <= update_amount_cycle) {
122             g_timers_manager[index].timers[i].cycle = 0;
123             if (g_timers_manager[index].timers[i].is_run) {
124                 has_new_timer = true;
125             }
126         } else {
127             g_timers_manager[index].timers[i].cycle -= (uint32_t)update_amount_cycle;
128         }
129     }
130     osal_irq_restore(irq_sts);
131     return has_new_timer;
132 }
133 
134 /*
135  * Loops through the timers to see if any need to be processed
136  */
timer_process_timers(timer_index_t index)137 STATIC bool timer_process_timers(timer_index_t index)
138 {
139     bool re_run = false;
140     uint64_t start_time = uapi_tcxo_get_count();
141     uint8_t soft_time_num = g_timers_manager[index].soft_time_num;
142     for (uint8_t i = 0; i < soft_time_num; i++) {
143         if (g_timers_manager[index].timers[i].enable &&
144             g_timers_manager[index].timers[i].cycle == 0 &&
145             g_timers_manager[index].timers[i].is_run) {
146             g_timers_manager[index].timers[i].is_run = false;
147             if (g_timers_manager[index].timers[i].callback) {
148                 g_timers_manager[index].timers[i].callback(g_timers_manager[index].timers[i].data);
149             }
150             re_run = true;
151         }
152     }
153 
154     if (re_run) {
155         uint64_t end_time = uapi_tcxo_get_count();
156         uint64_t diff = end_time - start_time;
157         uint64_t cycle = 0;
158         cycle = timer_porting_compensat_by_tcxo(diff);
159         re_run = timer_update_timers_time(index, cycle);
160     }
161 
162     return re_run;
163 }
164 
165 /*
166  * Gets the index of the next timer to expire
167  */
timer_get_next_timer(timer_index_t index)168 STATIC uint32_t timer_get_next_timer(timer_index_t index)
169 {
170     uint64_t shortest_time_found = UINT64_MAX;
171     uint8_t soft_time_num = g_timers_manager[index].soft_time_num;
172     uint32_t timer_found = soft_time_num;
173     for (uint8_t i = 0; i < soft_time_num; i++) {
174         if (g_timers_manager[index].timers[i].enable &&
175             g_timers_manager[index].timers[i].cycle <= shortest_time_found &&
176             g_timers_manager[index].timers[i].is_run) {
177             shortest_time_found = (uint32_t)g_timers_manager[index].timers[i].cycle;
178             timer_found = i;
179         }
180     }
181     return timer_found;
182 }
183 
184 /*
185  * Gets the time in us till the next interrupt, UINT64_MAX indicates that no timer is set
186  */
timer_get_time_till_interrupt(timer_index_t index)187 STATIC uint64_t timer_get_time_till_interrupt(timer_index_t index)
188 {
189     uint64_t current_value = hal_timer_get_current_value(index);
190     if (current_value != 0) {
191         return (uint32_t)current_value;
192     }
193 
194     uint32_t next_timer = timer_get_next_timer(index);
195     if (next_timer >= g_timers_manager[index].soft_time_num) {
196         return UINT64_MAX;
197     }
198 
199     uint64_t cycle = (uint32_t)g_timers_manager[index].timers[next_timer].cycle;
200     if (g_timers_manager[index].in_timer_irq) {
201         return cycle;
202     }
203 
204     hal_timer_stop(index);
205     hal_timer_config_load(index, cycle);
206     hal_timer_start(index);
207     return cycle;
208 }
209 
210 /*
211  * Searches through the timers to find the one with the lowest callback time
212  */
timer_set_next_timer_interrupt(timer_index_t index)213 STATIC void timer_set_next_timer_interrupt(timer_index_t index)
214 {
215     uint32_t irq_sts = osal_irq_lock();
216     hal_timer_stop(index);
217     uint32_t timer_found = timer_get_next_timer(index);
218     if (timer_found < g_timers_manager[index].soft_time_num) {
219         uint64_t cycle_with_mask;
220 #if defined(CONFIG_TIMER_USING_OLD_VERSION)
221     cycle_with_mask = g_timers_manager[index].timers[timer_found].cycle | TIMER_OLD_VERSION_LOAD_COUNT_MASK;
222 #else
223     cycle_with_mask = g_timers_manager[index].timers[timer_found].cycle;
224 #endif
225         hal_timer_config_load(index, cycle_with_mask);
226         hal_timer_start(index);
227         g_timers_manager[index].last_time_load_cycle = cycle_with_mask;
228     }
229     osal_irq_restore(irq_sts);
230 }
231 
timer_int_callback(timer_index_t index)232 STATIC void timer_int_callback(timer_index_t index)
233 {
234     uint32_t irq_sts = osal_irq_lock();
235     g_timers_manager[index].in_timer_irq = true;
236     timer_update_timers_time(index, g_timers_manager[index].last_time_load_cycle);
237     g_timers_manager[index].last_time_load_cycle = 0;
238     osal_irq_restore(irq_sts);
239 
240     while (timer_process_timers(index)) {
241     }
242 
243     timer_set_next_timer_interrupt(index);
244     g_timers_manager[index].in_timer_irq = false;
245 }
246 
soft_timer_list_cfg_get(uint32_t index,soft_timer_cfg_t * timer_info)247 STATIC errcode_t soft_timer_list_cfg_get(uint32_t index, soft_timer_cfg_t *timer_info)
248 {
249     switch (index) {
250 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_0)
251         case TIMER_SIZE_0:
252             timer_info->timer_num = CONFIG_TIMER_MAX_TIMERS_NUM_0;
253             timer_info->timer_addr = (uintptr_t)g_timerlist_0;
254             break;
255 #endif
256 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_1)
257         case TIMER_SIZE_1:
258             timer_info->timer_num = CONFIG_TIMER_MAX_TIMERS_NUM_1;
259             timer_info->timer_addr = (uintptr_t)g_timerlist_1;
260             break;
261 #endif
262 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_2)
263         case TIMER_SIZE_2:
264             timer_info->timer_num = CONFIG_TIMER_MAX_TIMERS_NUM_2;
265             timer_info->timer_addr = (uintptr_t)g_timerlist_2;
266             break;
267 #endif
268 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_3)
269         case TIMER_SIZE_3:
270             timer_info->timer_num = CONFIG_TIMER_MAX_TIMERS_NUM_3;
271             timer_info->timer_addr = (uintptr_t)g_timerlist_3;
272             break;
273 #endif
274 
275         default:
276 #if defined(CONFIG_TIMER_MAX_NUM) && (CONFIG_TIMER_MAX_NUM > TIMER_SIZE_4)
277             timer_info->timer_num = CONFIG_TIMER_MAX_TIMERS_NUM_EXTRA;
278             timer_info->timer_addr = (uintptr_t)&g_timerlist_extra[index - CUR_MAX_HARDWARE_TIMER_NUM];
279 #endif
280             break;
281     }
282     if (memset_s((uint8_t *)timer_info->timer_addr, sizeof(timer_info_t) * timer_info->timer_num, 0,
283         sizeof(timer_info_t) * timer_info->timer_num) != EOK) {
284         return ERRCODE_MEMSET;
285     }
286     return ERRCODE_SUCC;
287 }
288 
uapi_timer_init(void)289 errcode_t uapi_timer_init(void)
290 {
291     uint32_t irq_sts = osal_irq_lock();
292     if (g_timer_inited) {
293         osal_irq_restore(irq_sts);
294         return ERRCODE_SUCC;
295     }
296     if (memset_s(&g_timers_manager, sizeof(g_timers_manager), 0, sizeof(g_timers_manager)) != EOK) {
297         osal_irq_restore(irq_sts);
298         return ERRCODE_MEMSET;
299     }
300 
301 #if defined(CONFIG_TIMER_SUPPORT_LPC)
302     timer_port_clock_enable(true);
303 #endif
304 
305     for (uint32_t i = 0; i < CONFIG_TIMER_MAX_NUM; i++) {
306         soft_timer_cfg_t time_info;
307         uint32_t ret;
308         g_timer_adapted[i] = false;
309         ret = soft_timer_list_cfg_get(i, &time_info);
310         if (ret != ERRCODE_SUCC) {
311             osal_irq_restore(irq_sts);
312             return ret;
313         }
314         g_timers_manager[i].soft_time_num = time_info.timer_num;
315         g_timers_manager[i].timers = (timer_info_t *)time_info.timer_addr;
316     }
317 
318     g_timer_inited = true;
319     osal_irq_restore(irq_sts);
320     return ERRCODE_SUCC;
321 }
322 
uapi_timer_adapter(timer_index_t index,uint32_t int_id,uint16_t int_priority)323 errcode_t uapi_timer_adapter(timer_index_t index, uint32_t int_id, uint16_t int_priority)
324 {
325     uint32_t irq_sts = osal_irq_lock();
326     if (!g_timer_inited) {
327         osal_irq_restore(irq_sts);
328         return ERRCODE_TIMER_NOT_INIT;
329     }
330 
331     if (g_timer_adapted[index]) {
332         osal_irq_restore(irq_sts);
333         return ERRCODE_SUCC;
334     }
335 
336     errcode_t ret = hal_timer_init(index, timer_int_callback);
337     if (ret != ERRCODE_SUCC) {
338         osal_irq_restore(irq_sts);
339         return ret;
340     }
341 
342     timer_port_register_irq(index, int_id, int_priority);
343 
344     g_timers_manager[index].hw_timer_irq_id = int_id;
345     g_timers_manager[index].hw_timer_int_priority = int_priority;
346 
347     g_timer_adapted[index] = true;
348     osal_irq_restore(irq_sts);
349     return ERRCODE_SUCC;
350 }
351 
uapi_timer_deinit(void)352 errcode_t uapi_timer_deinit(void)
353 {
354     uint32_t irq_sts = osal_irq_lock();
355     if (!g_timer_inited) {
356         osal_irq_restore(irq_sts);
357         return ERRCODE_SUCC;
358     }
359 
360     for (uint32_t i = 0; i < CONFIG_TIMER_MAX_NUM; i++) {
361         if (g_timer_adapted[i]) {
362             hal_timer_stop(i);
363             timer_port_unregister_irq(i, g_timers_manager[i].hw_timer_irq_id);
364         }
365     }
366 
367     if (memset_s(&g_timers_manager, sizeof(g_timers_manager), 0, sizeof(g_timers_manager)) != EOK) {
368         osal_irq_restore(irq_sts);
369         return ERRCODE_MEMSET;
370     }
371 
372     for (uint32_t i = 0; i < CONFIG_TIMER_MAX_NUM; i++) {
373         if (g_timer_adapted[i]) {
374             hal_timer_deinit(i);
375         }
376     }
377 
378 #if defined(CONFIG_TIMER_SUPPORT_LPC)
379     timer_port_clock_enable(false);
380 #endif
381 
382     g_timer_inited = false;
383     for (uint32_t i = 0; i < CONFIG_TIMER_MAX_NUM; i++) {
384         g_timer_adapted[i] = false;
385     }
386     osal_irq_restore(irq_sts);
387     return ERRCODE_SUCC;
388 }
389 
uapi_timer_create(timer_index_t index,timer_handle_t * timer)390 errcode_t uapi_timer_create(timer_index_t index, timer_handle_t *timer)
391 {
392     if (timer == NULL) {
393         return ERRCODE_INVALID_PARAM;
394     }
395 
396     uint32_t irq_sts = osal_irq_lock();
397     for (uint32_t i = 0; i < g_timers_manager[index].soft_time_num; i++) {
398         if (g_timers_manager[index].timers[i].enable == false) {
399             g_timers_manager[index].timers[i].enable = true;
400             g_timers_manager[index].timers[i].is_run = false;
401             g_timers_manager[index].timers[i].index = index;
402             g_timers_manager[index].timers[i].key = (timer_handle_t)&g_timers_manager[index].timers[i];
403 
404             *timer = g_timers_manager[index].timers[i].key;
405             osal_irq_restore(irq_sts);
406             return ERRCODE_SUCC;
407         }
408     }
409 
410     *timer = NULL;
411     osal_irq_restore(irq_sts);
412     return ERRCODE_TIMER_NO_ENOUGH;
413 }
414 
uapi_timer_delete(timer_handle_t timer)415 errcode_t uapi_timer_delete(timer_handle_t timer)
416 {
417     if (timer == NULL) {
418         return ERRCODE_INVALID_PARAM;
419     }
420     timer_info_t *timer_info = (timer_info_t *)timer;
421     uint32_t irq_sts = osal_irq_lock();
422     timer_info->enable = false;
423     osal_irq_restore(irq_sts);
424     return ERRCODE_SUCC;
425 }
426 
uapi_timer_get_max_us(void)427 uint32_t uapi_timer_get_max_us(void)
428 {
429     return timer_porting_cycle_2_us(UINT32_MAX);
430 }
431 
uapi_timer_start(timer_handle_t timer,uint32_t time_us,timer_callback_t callback,uintptr_t data)432 errcode_t uapi_timer_start(timer_handle_t timer, uint32_t time_us, timer_callback_t callback, uintptr_t data)
433 {
434     timer_index_t index;
435 
436     if (timer == NULL || callback == NULL || time_us == 0 || time_us > uapi_timer_get_max_us()) {
437         return ERRCODE_INVALID_PARAM;
438     }
439 
440     timer_info_t *timer_info = (timer_info_t *)timer;
441     uint32_t irq_sts = osal_irq_lock();
442     if (timer_info->enable == false) {
443         osal_irq_restore(irq_sts);
444         return ERRCODE_TIEMR_NOT_CREATED;
445     }
446 
447     uint64_t cycle;
448 #if defined(CONFIG_TIMER_USING_OLD_VERSION)
449     cycle = timer_porting_us_2_cycle(time_us) | TIMER_OLD_VERSION_LOAD_COUNT_MASK;
450 #else
451     cycle = timer_porting_us_2_cycle(time_us);
452 #endif
453     index = timer_info->index;
454     timer_info->cycle = cycle;
455     timer_info->callback = callback;
456     timer_info->data = data;
457 
458     uint64_t remain_time_cycle = timer_get_time_till_interrupt(index);
459     if (cycle <= remain_time_cycle) {
460         if (remain_time_cycle != UINT64_MAX && g_timers_manager[index].last_time_load_cycle != 0) {
461             timer_update_timers_time(index, g_timers_manager[index].last_time_load_cycle - remain_time_cycle);
462         }
463         g_timers_manager[index].last_time_load_cycle = cycle;
464         hal_timer_stop(index);
465         hal_timer_config_load(index, cycle);
466         hal_timer_start(index);
467     } else {
468         timer_info->cycle += (g_timers_manager[index].last_time_load_cycle - remain_time_cycle);
469     }
470     timer_info->is_run = true;
471     osal_irq_restore(irq_sts);
472     return ERRCODE_SUCC;
473 }
474 
uapi_timer_stop(timer_handle_t timer)475 errcode_t uapi_timer_stop(timer_handle_t timer)
476 {
477     if (timer == NULL) {
478         return ERRCODE_INVALID_PARAM;
479     }
480 
481     timer_info_t *timer_info = (timer_info_t *)timer;
482 
483     uint32_t irq_sts = osal_irq_lock();
484     if (unlikely(timer_info->enable == false)) {
485         osal_irq_restore(irq_sts);
486         return ERRCODE_TIEMR_NOT_CREATED;
487     }
488 
489     if (unlikely(timer_info->is_run == false)) {
490         osal_irq_restore(irq_sts);
491         return ERRCODE_SUCC;
492     }
493 
494     timer_info->is_run = false;
495     timer_info->cycle = 0;
496     timer_info->callback = NULL;
497     timer_info->data = 0;
498 
499     /* 检查当前是否还有在运行的定时器, 若没有定时器则停止硬件计时 */
500     timer_index_t index = timer_info->index;
501     uint32_t next_timer = timer_get_next_timer(index);
502     if (next_timer >= g_timers_manager[index].soft_time_num) {
503         hal_timer_stop(index);
504     }
505     osal_irq_restore(irq_sts);
506     return ERRCODE_SUCC;
507 }
508 
uapi_timer_get_current_time_us(timer_index_t index,uint32_t * current_time_us)509 errcode_t uapi_timer_get_current_time_us(timer_index_t index, uint32_t *current_time_us)
510 {
511     if (unlikely(index >= TIMER_MAX_NUM || current_time_us == NULL)) {
512         return ERRCODE_INVALID_PARAM;
513     }
514 
515     uint32_t irq_sts = osal_irq_lock();
516     uint64_t current_value = hal_timer_get_current_value(index);
517     osal_irq_restore(irq_sts);
518     *current_time_us = timer_porting_cycle_2_us(current_value);
519     return ERRCODE_SUCC;
520 }
521 
522 #if defined(CONFIG_TIMER_SUPPORT_LPM)
uapi_timer_suspend(uintptr_t val)523 errcode_t uapi_timer_suspend(uintptr_t val)
524 {
525     unused(val);
526     uint32_t int_sts = osal_irq_lock();
527     for (uint32_t index = 0; index < TIMER_MAX_NUM; index++) {
528         if (g_timer_adapted[index] == false) {
529             continue;
530         }
531         timer_update_timers_time(index,
532             g_timers_manager[index].last_time_load_cycle - hal_timer_get_current_value(index));
533         g_timers_manager[index].last_time_load_cycle = 0;
534         timer_set_next_timer_interrupt(index);
535     }
536     osal_irq_restore(int_sts);
537     return ERRCODE_SUCC;
538 }
539 
uapi_timer_resume(uintptr_t val)540 errcode_t uapi_timer_resume(uintptr_t val)
541 {
542     uint32_t int_sts = osal_irq_lock();
543     uint64_t compansation_count = *(uint64_t *)val;
544     for (uint32_t index = 0; index < TIMER_MAX_NUM; index++) {
545         if (g_timer_adapted[index] == false) {
546             continue;
547         }
548         g_timers_manager[index].last_time_load_cycle = compansation_count;
549         hal_timer_stop(index);
550         hal_timer_config_load(index, timer_porting_us_2_cycle(1));
551         hal_timer_start(index);
552     }
553     osal_irq_restore(int_sts);
554     return ERRCODE_SUCC;
555 }
556 #endif /* CONFIG_TIMER_SUPPORT_LPM */