|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2006-2022, RT-Thread Development Team
|
|
|
+ * Copyright (c) 2006-2024, RT-Thread Development Team
|
|
|
*
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
*
|
|
@@ -21,6 +21,7 @@
|
|
|
* 2022-04-19 Stanley Correct descriptions
|
|
|
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
|
|
|
* 2024-01-25 Shell add RT_TIMER_FLAG_THREAD_TIMER for timer to sync with sched
|
|
|
+ * 2024-05-01 wdfk-prog The rt_timer_check and _soft_timer_check functions are merged
|
|
|
*/
|
|
|
|
|
|
#include <rtthread.h>
|
|
@@ -472,6 +473,84 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer)
|
|
|
return RT_EOK;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * @brief This function will check timer list, if a timeout event happens,
|
|
|
+ * the corresponding timeout function will be invoked.
|
|
|
+ *
|
|
|
+ * @param timer_list The timer list to check.
|
|
|
+ * @param lock The lock for the timer list.
|
|
|
+ */
|
|
|
+static void _timer_check(rt_list_t *timer_list, struct rt_spinlock *lock)
|
|
|
+{
|
|
|
+ struct rt_timer *t;
|
|
|
+ rt_tick_t current_tick;
|
|
|
+ rt_base_t level;
|
|
|
+ rt_list_t list;
|
|
|
+
|
|
|
+ level = rt_spin_lock_irqsave(lock);
|
|
|
+
|
|
|
+ current_tick = rt_tick_get();
|
|
|
+
|
|
|
+ rt_list_init(&list);
|
|
|
+
|
|
|
+ while (!rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
|
|
+ {
|
|
|
+ t = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
|
|
|
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
|
|
|
+
|
|
|
+ /* re-get tick */
|
|
|
+ current_tick = rt_tick_get();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * It supposes that the new tick shall less than the half duration of
|
|
|
+ * tick max.
|
|
|
+ */
|
|
|
+ if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
|
|
|
+ {
|
|
|
+ RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
|
|
|
+
|
|
|
+ /* remove timer from timer list firstly */
|
|
|
+ _timer_remove(t);
|
|
|
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
|
|
|
+ {
|
|
|
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
|
+ }
|
|
|
+
|
|
|
+ t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
|
|
|
+ /* add timer to temporary list */
|
|
|
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
|
|
+
|
|
|
+ rt_spin_unlock_irqrestore(lock, level);
|
|
|
+
|
|
|
+ /* call timeout function */
|
|
|
+ t->timeout_func(t->parameter);
|
|
|
+
|
|
|
+ RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
|
|
+ LOG_D("current tick: %d", current_tick);
|
|
|
+
|
|
|
+ level = rt_spin_lock_irqsave(lock);
|
|
|
+
|
|
|
+ t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
|
|
|
+
|
|
|
+ /* Check whether the timer object is detached or started again */
|
|
|
+ if (rt_list_isempty(&list))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
|
|
+ if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
|
|
+ (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
|
|
+ {
|
|
|
+ /* start it */
|
|
|
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
|
+ _timer_start(timer_list, t);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else break;
|
|
|
+ }
|
|
|
+ rt_spin_unlock_irqrestore(lock, level);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief This function will start the timer
|
|
|
*
|
|
@@ -669,83 +748,19 @@ RTM_EXPORT(rt_timer_control);
|
|
|
*/
|
|
|
void rt_timer_check(void)
|
|
|
{
|
|
|
- struct rt_timer *t;
|
|
|
- rt_tick_t current_tick;
|
|
|
- rt_base_t level;
|
|
|
- rt_list_t list;
|
|
|
-
|
|
|
RT_ASSERT(rt_interrupt_get_nest() > 0);
|
|
|
|
|
|
LOG_D("timer check enter");
|
|
|
|
|
|
- level = rt_spin_lock_irqsave(&_htimer_lock);
|
|
|
-
|
|
|
- current_tick = rt_tick_get();
|
|
|
-
|
|
|
#ifdef RT_USING_SMP
|
|
|
/* Running on core 0 only */
|
|
|
if (rt_cpu_get_id() != 0)
|
|
|
{
|
|
|
- rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
|
|
return;
|
|
|
}
|
|
|
#endif
|
|
|
+ _timer_check(_timer_list, &_htimer_lock);
|
|
|
|
|
|
- rt_list_init(&list);
|
|
|
-
|
|
|
- while (!rt_list_isempty(&_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
|
|
- {
|
|
|
- t = rt_list_entry(_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
|
|
|
- struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
|
|
|
-
|
|
|
- /*
|
|
|
- * It supposes that the new tick shall less than the half duration of
|
|
|
- * tick max.
|
|
|
- */
|
|
|
- if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
|
|
|
- {
|
|
|
- RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
|
|
|
-
|
|
|
- /* remove timer from timer list firstly */
|
|
|
- _timer_remove(t);
|
|
|
- if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
|
|
|
- {
|
|
|
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
|
- }
|
|
|
-
|
|
|
- t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
|
|
|
- /* add timer to temporary list */
|
|
|
- rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
|
|
- rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
|
|
- /* call timeout function */
|
|
|
- t->timeout_func(t->parameter);
|
|
|
-
|
|
|
- /* re-get tick */
|
|
|
- current_tick = rt_tick_get();
|
|
|
-
|
|
|
- RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
|
|
- LOG_D("current tick: %d", current_tick);
|
|
|
- level = rt_spin_lock_irqsave(&_htimer_lock);
|
|
|
-
|
|
|
- t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
|
|
|
-
|
|
|
- /* Check whether the timer object is detached or started again */
|
|
|
- if (rt_list_isempty(&list))
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
|
|
- if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
|
|
- (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
|
|
- {
|
|
|
- /* start it */
|
|
|
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
|
- _timer_start(_timer_list, t);
|
|
|
- }
|
|
|
- }
|
|
|
- else break;
|
|
|
- }
|
|
|
- rt_spin_unlock_irqrestore(&_htimer_lock, level);
|
|
|
LOG_D("timer check leave");
|
|
|
}
|
|
|
|
|
@@ -767,81 +782,6 @@ rt_tick_t rt_timer_next_timeout_tick(void)
|
|
|
}
|
|
|
|
|
|
#ifdef RT_USING_TIMER_SOFT
|
|
|
-/**
|
|
|
- * @brief This function will check software-timer list, if a timeout event happens, the
|
|
|
- * corresponding timeout function will be invoked.
|
|
|
- */
|
|
|
-static void _soft_timer_check(void)
|
|
|
-{
|
|
|
- rt_tick_t current_tick;
|
|
|
- struct rt_timer *t;
|
|
|
- rt_base_t level;
|
|
|
- rt_list_t list;
|
|
|
-
|
|
|
- rt_list_init(&list);
|
|
|
- LOG_D("software timer check enter");
|
|
|
- level = rt_spin_lock_irqsave(&_stimer_lock);
|
|
|
-
|
|
|
- while (!rt_list_isempty(&_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
|
|
- {
|
|
|
- t = rt_list_entry(_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
|
|
|
- struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
|
|
|
-
|
|
|
- current_tick = rt_tick_get();
|
|
|
-
|
|
|
- /*
|
|
|
- * It supposes that the new tick shall less than the half duration of
|
|
|
- * tick max.
|
|
|
- */
|
|
|
- if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)
|
|
|
- {
|
|
|
- RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
|
|
|
-
|
|
|
- /* remove timer from timer list firstly */
|
|
|
- _timer_remove(t);
|
|
|
- if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
|
|
|
- {
|
|
|
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
|
- }
|
|
|
-
|
|
|
- t->parent.flag |= RT_TIMER_FLAG_PROCESSING;
|
|
|
- /* add timer to temporary list */
|
|
|
- rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
|
|
-
|
|
|
- rt_spin_unlock_irqrestore(&_stimer_lock, level);
|
|
|
-
|
|
|
- /* call timeout function */
|
|
|
- t->timeout_func(t->parameter);
|
|
|
-
|
|
|
- RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
|
|
- LOG_D("current tick: %d", current_tick);
|
|
|
-
|
|
|
- level = rt_spin_lock_irqsave(&_stimer_lock);
|
|
|
-
|
|
|
- t->parent.flag &= ~RT_TIMER_FLAG_PROCESSING;
|
|
|
-
|
|
|
- /* Check whether the timer object is detached or started again */
|
|
|
- if (rt_list_isempty(&list))
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- rt_list_remove(&(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
|
|
- if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
|
|
- (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
|
|
- {
|
|
|
- /* start it */
|
|
|
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
|
- _timer_start(_soft_timer_list, t);
|
|
|
- }
|
|
|
- }
|
|
|
- else break; /* not check anymore */
|
|
|
- }
|
|
|
-
|
|
|
- rt_spin_unlock_irqrestore(&_stimer_lock, level);
|
|
|
-
|
|
|
- LOG_D("software timer check leave");
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* @brief System timer thread entry
|
|
|
*
|
|
@@ -884,7 +824,11 @@ static void _timer_thread_entry(void *parameter)
|
|
|
}
|
|
|
|
|
|
/* check software timer */
|
|
|
- _soft_timer_check();
|
|
|
+ LOG_D("software timer check enter");
|
|
|
+
|
|
|
+ _timer_check(_soft_timer_list, &_stimer_lock);
|
|
|
+
|
|
|
+ LOG_D("software timer check leave");
|
|
|
}
|
|
|
}
|
|
|
#endif /* RT_USING_TIMER_SOFT */
|