From 570e262c9b2d54a17f3677c4a53de020d2eb1559 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Tue, 9 Apr 2024 15:31:46 +0800 Subject: [PATCH] lib/tntimer:add tntimer module and adpation for systick --- ci/defconfigs/raspi-arm64-uktest | 1 + lib/Makefile.uk | 1 + lib/tnsystick/include/tn/systick.h | 6 + lib/tnsystick/tnsystick.c | 6 +- lib/tntimer/Config.uk | 12 ++ lib/tntimer/Makefile.uk | 14 ++ lib/tntimer/exportsyms.uk | 7 + lib/tntimer/include/tn/tntimer.h | 141 ++++++++++++++++++ lib/tntimer/tests/internal_timer.h | 29 ++++ lib/tntimer/tests/test_tntimer.c | 224 +++++++++++++++++++++++++++++ lib/tntimer/tntimer.c | 189 ++++++++++++++++++++++++ lib/ukboot/boot.c | 10 +- 12 files changed, 630 insertions(+), 10 deletions(-) create mode 100644 lib/tntimer/Config.uk create mode 100644 lib/tntimer/Makefile.uk create mode 100644 lib/tntimer/exportsyms.uk create mode 100644 lib/tntimer/include/tn/tntimer.h create mode 100644 lib/tntimer/tests/internal_timer.h create mode 100644 lib/tntimer/tests/test_tntimer.c create mode 100644 lib/tntimer/tntimer.c diff --git a/ci/defconfigs/raspi-arm64-uktest b/ci/defconfigs/raspi-arm64-uktest index 8a0654d2..b5ba62c0 100644 --- a/ci/defconfigs/raspi-arm64-uktest +++ b/ci/defconfigs/raspi-arm64-uktest @@ -27,3 +27,4 @@ CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS=y CONFIG_LIBVFSCORE_FSTAB=y CONFIG_LIBUKBOOT_BANNER_POWEREDBY=y CONFIG_LIBUKTTY_PL011=y +CONFIG_LIBTNTIMER=y diff --git a/lib/Makefile.uk b/lib/Makefile.uk index d392af3a..b6ed07da 100644 --- a/lib/Makefile.uk +++ b/lib/Makefile.uk @@ -70,3 +70,4 @@ $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/ukrust)) $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/ukreloc)) $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/ukofw)) $(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/tnsystick)) +$(eval $(call import_lib,$(CONFIG_UK_BASE)/lib/tntimer)) diff --git a/lib/tnsystick/include/tn/systick.h b/lib/tnsystick/include/tn/systick.h index 3f6a9ba9..d2291e6e 100644 --- a/lib/tnsystick/include/tn/systick.h +++ b/lib/tnsystick/include/tn/systick.h @@ -19,6 +19,12 @@ #include #include + /**< Maximum number of UINT32 */ +#define TICK_UINT32_MAX 0xffffffff + /**< Maximum number of UINT64 */ +#define TICK_UINT64_MAX 0xffffffffffffffff +#define TICK_MAX TICK_UINT64_MAX + typedef uint64_t systick_t; /* sysclock oprations */ diff --git a/lib/tnsystick/tnsystick.c b/lib/tnsystick/tnsystick.c index 315914b9..80cf4424 100644 --- a/lib/tnsystick/tnsystick.c +++ b/lib/tnsystick/tnsystick.c @@ -100,14 +100,14 @@ int sys_timer_irq_handler(void *arg __unused) #ifndef CONFIG_LIBTNSYSTICK_TICKLESS sysclock.ops->set_next(tot_counts_per_tick, 0); #endif /* CONFIG_LIBTNSYSTICK_TICKLESS */ - /* 2、todo :expired timer functions */ + tn_timer_announce(); /* 3、todo :schedprio to check timeout threads */ /* 4、set next time-base irq */ #ifdef CONFIG_LIBTNSYSTICK_TICKLESS - uint64_t timeout; + systick_t timeout; - timeout = get_current_smallest_timeout(); + timeout = tn_timer_next_tick(); sysclock.ops->set_next(ticks_to_counts(timeout), 0); #endif /* CONFIG_LIBTNSYSTICK_TICKLESS */ __uk_test_and_clear_bit(0, &sched_have_pending_events); diff --git a/lib/tntimer/Config.uk b/lib/tntimer/Config.uk new file mode 100644 index 00000000..df7c278c --- /dev/null +++ b/lib/tntimer/Config.uk @@ -0,0 +1,12 @@ +menuconfig LIBTNTIMER + bool "timer: Kernel timer configuration" + depends on HAVE_SYSTICK + default n + + +if LIBTNTIMER + config LIBTNTIMER_TEST + bool "Enable unit tests" + default n + select LIBUKTEST +endif diff --git a/lib/tntimer/Makefile.uk b/lib/tntimer/Makefile.uk new file mode 100644 index 00000000..8e001a7d --- /dev/null +++ b/lib/tntimer/Makefile.uk @@ -0,0 +1,14 @@ +$(eval $(call addlib_s,libtntimer,$(CONFIG_LIBTNTIMER))) + +ASINCLUDES-$(CONFIG_LIBTNTIMER) += -I$(LIBTNTIMER_BASE)/include +CINCLUDES-$(CONFIG_LIBTNTIMER) += -I$(LIBTNTIMER_BASE)/include +CXXINCLUDES-$(CONFIG_LIBTNTIMER) += -I$(LIBTNTIMER_BASE)/include +LIBTNTIMER_ASINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include +LIBTNTIMER_CINCLUDES-y += -I$(UK_PLAT_COMMON_BASE)/include + +LIBTNTIMER_SRCS-$(CONFIG_LIBTNTIMER) += $(LIBTNTIMER_BASE)/tntimer.c + + +ifneq ($(filter y,$(CONFIG_LIBTNTIMER_TEST) $(CONFIG_LIBUKTEST_ALL)),) +LIBTNTIMER_SRCS-y += $(LIBTNTIMER_BASE)/tests/test_tntimer.c +endif diff --git a/lib/tntimer/exportsyms.uk b/lib/tntimer/exportsyms.uk new file mode 100644 index 00000000..6d3652ac --- /dev/null +++ b/lib/tntimer/exportsyms.uk @@ -0,0 +1,7 @@ +tn_timer_create +tn_timer_start +tn_timer_delete +tn_timer_init +tn_timer_add +tn_timer_next_tick +tn_timer_announce \ No newline at end of file diff --git a/lib/tntimer/include/tn/tntimer.h b/lib/tntimer/include/tn/tntimer.h new file mode 100644 index 00000000..2e22a3dd --- /dev/null +++ b/lib/tntimer/include/tn/tntimer.h @@ -0,0 +1,141 @@ +/* Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TN_TIMER_H__ +#define __TN_TIMER_H__ + +#include +#include +#include + + +#define TN_TIMER_FLAG_PERIODIC 0x01 +#define TN_TIMER_FLAG_ONE_SHOT 0x02 + + + +struct timer { + /*List node which contains pointers for traversing prev and next*/ + struct uk_list_head list; + + /* + * The relative difference in timeout occurs. + * The tick passed as a parameter when the external component is + * invoked for creation will modify this value + */ + systick_t init_tick; + /* + * an absolute time and is not subject to external modification; + * it can only be altered during 'start' (added to the list). + */ + systick_t timeout_tick; + /* + * Timeout callback function. + * When this timeout expires, this function will be executed. + */ + void (*timeout_func)(void *parameter); + /*Parameters of the timeout callback function.*/ + void *parameter; + /*Timer flag*/ + unsigned long flag; +}; + +/** + * tn_timer_create - Creates a new timer object. + * + * @param init_tick The initial tick count for the timer. + * @param timeout_func: The function to be called upon timer timeout. + * @param parameter: The parameter to be passed to the timeout function. + * @param flag Timer flags (e.g., periodic or one-shot). + * @return timer a pointer to the newly created timer + * Allocates memory for a new timer and initializes its members. + * Returns a pointer to the newly created timer or NULL + * if memory allocation fails. + */ +struct timer *tn_timer_create( + systick_t init_tick, + void (*timeout_func)(void *parameter), + void *parameter, + unsigned long flag); + + +/** + * tn_timer_start - Starts a timer and schedules it in the active timer list. + * @param t: The timer object to start. + * + * Calculates the timeout tick based on the current systick + * value and the timer's initial tick.Adds the timer to the appropriate + * list based on whether an overflow has occurred. + */ +void tn_timer_start(struct timer *timer); + + +/** + * tn_timer_delete - Removes a timer from the active timer list. + * @param t: The timer object to be removed. + * + * Removes the specified timer from the list and handles cleanup if necessary. + */ +void tn_timer_delete(struct timer *timer); + +/** + * tn_timer_init - Initializes a timer object. + * @param t The timer object to initialize. + * @param init_tick: The initial tick count for the timer. + * @param timeout_func: The function to be called upon timer timeout. + * @param parameter: The parameter to be passed to the timeout function. + * @param flag: Timer flags (e.g., periodic or one-shot). + * + * Initializes the members of a timer object. + */ +void tn_timer_init( + struct timer *t, + systick_t init_tick, + void (*timeout_func)(void *parameter), + void *parameter, + unsigned long flag); + +/** + * tn_timer_add - Adds a timer to the specified list based on its timeout tick. + * @param in: The timer object to be added. + * @param head: The list head where the timer will be added. + * + * Iterates through the specified list and inserts + * the timer in the correct position + * based on its timeout tick value. + */ +void tn_timer_add(struct timer *in, struct uk_list_head *head); + +/* + * tn_timer_next_tick - Retrieves the tick value of the soonest expiring timer. + * + * Returns the tick value of the soonest expiring timer or + * TICK_MAX if no timers are active. + */ +systick_t tn_timer_next_tick(void); + + +/* + * tn_timer_announce - Handles timer timeouts and executes associated functions. + * + * Retrieves the current systick value and iterates through + * the active timer list.For each timer with a timeout tick + * less than or equal to the current systick,the associated + * timeout function is called, and the timer is removed from the list. + * If the timer is periodic, it is restarted. + */ +void tn_timer_announce(void); + +#endif /* __TN_TIMER_H__ */ diff --git a/lib/tntimer/tests/internal_timer.h b/lib/tntimer/tests/internal_timer.h new file mode 100644 index 00000000..c63817e8 --- /dev/null +++ b/lib/tntimer/tests/internal_timer.h @@ -0,0 +1,29 @@ +/* Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TN_INTERNAL_TIMER_H__ +#define __TN_INTERNAL_TIMER_H__ + +void tn_timer_list_switch(void); + +struct uk_list_head *tn_timer_get_overflow_list(void); + +/* + * tn_timer_get_list - Retrieves the global timer list. + * + * Returns a pointer to the head of the timer list. + */ +struct uk_list_head *tn_timer_get_list(void); +#endif /* __TN_INTERNAL_TIMER_H__ */ diff --git a/lib/tntimer/tests/test_tntimer.c b/lib/tntimer/tests/test_tntimer.c new file mode 100644 index 00000000..475d7852 --- /dev/null +++ b/lib/tntimer/tests/test_tntimer.c @@ -0,0 +1,224 @@ +/* Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "internal_timer.h" + +#define pr_info(fmt, ...) \ + _uk_printk(KLVL_INFO, __NULL, __NULL, 0x0, fmt, ##__VA_ARGS__) + + +int excution; + +void timeout_func1(void *parameter) +{ + pr_info("timeout func1\n"); +} + +void timeout_func3(void *parameter) +{ + pr_info("timeout func3\n"); +} + +void timeout_func2(void *parameter) +{ + excution++; +} + +void dump_timer(void) +{ + struct timer *node; + struct uk_list_head *timer_list_head; + + timer_list_head = tn_timer_get_list(); + UK_ASSERT(timer_list_head != NULL); + uk_list_for_each_entry(node, timer_list_head, list) { + pr_info("node timeout is %x,flag is %d\n", + node->timeout_tick, node->flag); + }; +} + + + +UK_TESTCASE(tntimer, test_tn_timer_list_operations) +{ + systick_t t1 = 0x100000; + systick_t t2 = 0x200000; + systick_t t3 = 0x300000; + systick_t t4 = 0x260000; + systick_t t5 = 0x50000; + + systick_t cur = tn_systick_get_tick(); + struct timer *temp; + + struct timer *timer1 = tn_timer_create( + t1, *timeout_func1, NULL, TN_TIMER_FLAG_PERIODIC); + + + struct timer *timer2 = tn_timer_create( + t2, *timeout_func1, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer3 = tn_timer_create( + t3, *timeout_func1, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer4 = tn_timer_create( + t4, *timeout_func1, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer5 = tn_timer_create( + t5, *timeout_func1, NULL, TN_TIMER_FLAG_ONE_SHOT); + + UK_TEST_EXPECT_NOT_NULL(timer1); + UK_TEST_EXPECT_NOT_NULL(timer2); + UK_TEST_EXPECT_NOT_NULL(timer3); + UK_TEST_EXPECT_NOT_NULL(timer4); + + tn_timer_init(timer1, t1, *timeout_func1, NULL, TN_TIMER_FLAG_ONE_SHOT); + UK_TEST_EXPECT(timer1->flag == TN_TIMER_FLAG_ONE_SHOT); + + tn_timer_start(timer1); + tn_timer_start(timer2); + tn_timer_start(timer3); + tn_timer_start(timer4); + tn_timer_start(timer5); + + struct timer *node; + struct uk_list_head *timer_list_head = tn_timer_get_list(); + + dump_timer(); + + tn_timer_delete(timer2); + dump_timer(); + timer2 = tn_timer_create( + t2, *timeout_func1, NULL, TN_TIMER_FLAG_ONE_SHOT); + + systick_t last_tick = tn_timer_next_tick() + cur; + + tn_timer_start(timer2); + dump_timer(); + + temp = uk_list_first_entry_or_null(timer_list_head, struct timer, list); + UK_TEST_EXPECT_NOT_NULL(temp); + UK_TEST_EXPECT_SNUM_LT(temp->timeout_tick - last_tick, 10); + tn_timer_delete(temp); + + temp = uk_list_first_entry_or_null(timer_list_head, struct timer, list); + UK_TEST_EXPECT_NOT_NULL(temp); + UK_TEST_EXPECT_SNUM_LT(temp->timeout_tick - last_tick-0xB0000, + 10); + tn_timer_delete(temp); + + temp = uk_list_first_entry_or_null(timer_list_head, struct timer, list); + UK_TEST_EXPECT_NOT_NULL(temp); + UK_TEST_EXPECT_SNUM_LT(temp->timeout_tick - last_tick - 0x1B0000, + 10); + tn_timer_delete(temp); + + + temp = uk_list_first_entry_or_null(timer_list_head, struct timer, list); + UK_TEST_EXPECT_NOT_NULL(temp); + UK_TEST_EXPECT_SNUM_LT(temp->timeout_tick - last_tick - 0x210000, + 10); + tn_timer_delete(temp); + + temp = uk_list_first_entry_or_null(timer_list_head, struct timer, list); + UK_TEST_EXPECT_NOT_NULL(temp); + UK_TEST_EXPECT_SNUM_LT(temp->timeout_tick - last_tick - 0x2B0000, + 10); + tn_timer_delete(temp); + + UK_INIT_LIST_HEAD(tn_timer_get_list()); + +} + + + +UK_TESTCASE(tntimer, test_tn_timer_announce) +{ + systick_t t1 = 100; + systick_t t2 = 200; + systick_t t3 = 200; + systick_t t4 = 300; + systick_t t5 = 302; + + systick_t cur = tn_systick_get_tick(); + + struct timer *node; + struct uk_list_head *timer_list_head = tn_timer_get_list(); + + struct timer *timer1 = tn_timer_create( + t1, *timeout_func2, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer2 = tn_timer_create( + t2, *timeout_func2, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer3 = tn_timer_create( + t3, *timeout_func2, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer4 = tn_timer_create( + t4, *timeout_func2, NULL, TN_TIMER_FLAG_ONE_SHOT); + struct timer *timer5 = tn_timer_create( + t5, *timeout_func2, NULL, TN_TIMER_FLAG_ONE_SHOT); + + UK_TEST_EXPECT_NOT_NULL(timer1); + UK_TEST_EXPECT_NOT_NULL(timer2); + UK_TEST_EXPECT_NOT_NULL(timer3); + + tn_timer_start(timer1); + tn_timer_start(timer2); + tn_timer_start(timer3); + tn_timer_start(timer4); + tn_timer_start(timer5); + + while (excution < 1) { + asm volatile("" ::: "memory"); + /* + *do nothing,wait for timeout func + */ + } + UK_TEST_EXPECT_SNUM_LT(tn_systick_get_tick() - cur - 100, 10); + while (excution < 2) { + asm volatile("" ::: "memory"); + /* + *do nothing,wait for timeout func + */ + } + UK_TEST_EXPECT_SNUM_EQ(excution, 3); + UK_TEST_EXPECT_SNUM_LT(tn_systick_get_tick() - cur - 200, 10); + while (excution < 4) { + asm volatile("" ::: "memory"); + /* + *do nothing,wait for timeout func + */ + } + UK_TEST_EXPECT_SNUM_LT(tn_systick_get_tick() - cur - 300, 10); + while (excution < 5) { + asm volatile("" ::: "memory"); + /* + *do nothing,wait for timeout func + */ + } + UK_TEST_EXPECT_SNUM_LT(tn_systick_get_tick() - cur - 302, 10); + dump_timer(); + UK_TEST_EXPECT_SNUM_EQ(excution, 5); + + UK_INIT_LIST_HEAD(tn_timer_get_list()); + +} + + +uk_testsuite_register(tntimer, NULL); diff --git a/lib/tntimer/tntimer.c b/lib/tntimer/tntimer.c new file mode 100644 index 00000000..64446c33 --- /dev/null +++ b/lib/tntimer/tntimer.c @@ -0,0 +1,189 @@ +/* Copyright 2024 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ssANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +static UK_LIST_HEAD(timer_list_head); +static UK_LIST_HEAD(overflow_timer_list_head); +static uint8_t timoutListsOverflowed; + +static systick_t last_tick; +/* + * tn_timer_get_list - Retrieves the global timer list. + * + * Returns a pointer to the head of the timer list. + */ +struct uk_list_head *tn_timer_get_list(void) +{ + return &timer_list_head; +} + +struct uk_list_head *tn_timer_get_overflow_list(void) +{ + return &overflow_timer_list_head; +} + +struct timer *tn_timer_create(systick_t init_tick, + void (*timeout_func)(void *parameter), + void *parameter, unsigned long flag) +{ + struct timer *t; + + t = uk_malloc(uk_alloc_get_default(), sizeof(struct timer)); + if (!t) + return NULL; + + t->timeout_func = timeout_func; + t->parameter = parameter; + t->init_tick = init_tick; + t->flag = flag; + + return t; +} + +void tn_timer_init(struct timer *t, systick_t init_tick, + void (*timeout_func)(void *parameter), void *parameter, + unsigned long flag) +{ + UK_ASSERT(t); + + t->timeout_func = timeout_func; + t->parameter = parameter; + t->init_tick = init_tick; + t->flag = flag; +} + +systick_t tn_timer_next_tick(void) +{ + struct timer *t; + systick_t cur; + + cur = tn_systick_get_tick(); + + t = uk_list_first_entry_or_null(&timer_list_head, struct timer, list); + if (t) + return t->timeout_tick - cur; + if (timoutListsOverflowed) { + t = uk_list_first_entry(&overflow_timer_list_head, struct timer, + list); + return t->timeout_tick - cur; + } + + return TICK_MAX; +} + +void tn_timer_delete(struct timer *t) +{ + UK_ASSERT(t); + + uk_list_del(&t->list); + if (timoutListsOverflowed && uk_list_empty(&timer_list_head)) + tn_timer_list_switch(); +} + +/* + * tn_timer_list_switch + * Handles timer list overflow by switching the active list. + * + * This function is called when the timer list has overflowed + * and needs to switch to the overflow list to maintain + * correct ordering of timers. + */ +void tn_timer_list_switch(void) +{ + struct uk_list_head *temp; + + UK_ASSERT(!uk_list_empty(&overflow_timer_list_head)); + + timer_list_head.next = overflow_timer_list_head.next; + overflow_timer_list_head.next->prev = &timer_list_head; + UK_INIT_LIST_HEAD(&overflow_timer_list_head); + timoutListsOverflowed = 0; +} + +void tn_timer_start(struct timer *t) +{ + systick_t cur; + systick_t sum; + + cur = tn_systick_get_tick(); + sum = cur + t->init_tick; + t->timeout_tick = sum; + if (sum < cur || sum < t->init_tick) { + // 发生了溢出 + tn_timer_add(t, &overflow_timer_list_head); + timoutListsOverflowed = 1; + } else { + tn_timer_add(t, &timer_list_head); + } + last_tick = cur; +} + +void tn_timer_add(struct timer *in, struct uk_list_head *head) +{ + struct timer *node; + struct timer *t; + + uk_list_for_each_entry(t, head, list) { + if (t->timeout_tick <= in->timeout_tick) + continue; + + uk_list_add(&(in)->list, t->list.prev); + return; + } + uk_list_add_tail(&in->list, head); +} + +void tn_timer_announce(void) +{ + struct timer *t; + systick_t cur; + + cur = tn_systick_get_tick(); + + //current tick overflowed,clean the first list + if (cur < last_tick) { + while (!uk_list_empty(&timer_list_head)) { + t = uk_list_first_entry( + &timer_list_head, struct timer, list); + + uk_list_del(&t->list); + t->timeout_func(t->parameter); + if (t->flag & TN_TIMER_FLAG_PERIODIC) + tn_timer_start(t); + } + if (uk_list_empty(&timer_list_head) && timoutListsOverflowed) + tn_timer_list_switch(); + } + + + + while (!uk_list_empty(&timer_list_head)) { + t = uk_list_first_entry( + &timer_list_head, struct timer, list); + if (t->timeout_tick <= cur) { + uk_list_del(&t->list); + t->timeout_func(t->parameter); + if (t->flag & TN_TIMER_FLAG_PERIODIC) + tn_timer_start(t); + } else{ + break; + } + } + + last_tick = cur; +} diff --git a/lib/ukboot/boot.c b/lib/ukboot/boot.c index 338ed434..64f39c85 100644 --- a/lib/ukboot/boot.c +++ b/lib/ukboot/boot.c @@ -381,6 +381,9 @@ void ukplat_entry(int argc, char *argv[]) /* Enable interrupts before starting the application */ ukplat_lcpu_enable_irq(); +#if CONFIG_HAVE_SYSTICK + tn_systick_start(); +#endif /* CONFIG_HAVE_SYSTICK */ /** * Run init table */ @@ -514,13 +517,6 @@ static inline int do_main(int argc, char *argv[]) uk_pr_info("])\n"); #endif /* CONFIG_LIBUKDEBUG_PRINTK_INFO */ -#if CONFIG_HAVE_SYSTICK - tn_systick_start(); -#endif /* CONFIG_HAVE_SYSTICK */ - -#if CONFIG_HAVE_SYSTICK - tn_systick_start(); -#endif /* CONFIG_HAVE_SYSTICK */ ret = main(argc, argv); uk_pr_info("main returned %d\n", ret); -- Gitee