Merge pull request #3940 from RT-Thread/timer_issue
[kernel] fix the timer issue
This commit is contained in:
commit
13044b1e29
85
src/timer.c
85
src/timer.c
|
@ -25,6 +25,10 @@
|
|||
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
|
||||
#define RT_SOFT_TIMER_IDLE 1
|
||||
#define RT_SOFT_TIMER_BUSY 0
|
||||
|
||||
#ifndef RT_TIMER_THREAD_STACK_SIZE
|
||||
#define RT_TIMER_THREAD_STACK_SIZE 512
|
||||
#endif
|
||||
|
@ -33,6 +37,8 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
|||
#define RT_TIMER_THREAD_PRIO 0
|
||||
#endif
|
||||
|
||||
/* soft timer status */
|
||||
static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE;
|
||||
/* soft timer list */
|
||||
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||
static struct rt_thread timer_thread;
|
||||
|
@ -221,6 +227,8 @@ rt_err_t rt_timer_detach(rt_timer_t timer)
|
|||
level = rt_hw_interrupt_disable();
|
||||
|
||||
_rt_timer_remove(timer);
|
||||
/* stop timer */
|
||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
@ -284,6 +292,8 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
|
|||
level = rt_hw_interrupt_disable();
|
||||
|
||||
_rt_timer_remove(timer);
|
||||
/* stop timer */
|
||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
@ -408,7 +418,8 @@ rt_err_t rt_timer_start(rt_timer_t timer)
|
|||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||
{
|
||||
/* check whether timer thread is ready */
|
||||
if ((timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
|
||||
if ((soft_timer_status == RT_SOFT_TIMER_IDLE) &&
|
||||
((timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
|
||||
{
|
||||
/* resume timer thread to check soft timer */
|
||||
rt_thread_resume(&timer_thread);
|
||||
|
@ -445,13 +456,12 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
|
|||
level = rt_hw_interrupt_disable();
|
||||
|
||||
_rt_timer_remove(timer);
|
||||
/* change status */
|
||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
/* change stat */
|
||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
RTM_EXPORT(rt_timer_stop);
|
||||
|
@ -467,10 +477,13 @@ RTM_EXPORT(rt_timer_stop);
|
|||
*/
|
||||
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
|
||||
{
|
||||
register rt_base_t level;
|
||||
|
||||
/* timer check */
|
||||
RT_ASSERT(timer != RT_NULL);
|
||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_TIMER_CTRL_GET_TIME:
|
||||
|
@ -505,6 +518,7 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
@ -521,6 +535,7 @@ void rt_timer_check(void)
|
|||
struct rt_timer *t;
|
||||
rt_tick_t current_tick;
|
||||
register rt_base_t level;
|
||||
rt_list_t list = RT_LIST_OBJECT_INIT(list);
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
|
||||
|
||||
|
@ -544,7 +559,12 @@ void rt_timer_check(void)
|
|||
|
||||
/* remove timer from timer list firstly */
|
||||
_rt_timer_remove(t);
|
||||
|
||||
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
|
||||
{
|
||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
}
|
||||
/* add timer to temporary list */
|
||||
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
||||
/* call timeout function */
|
||||
t->timeout_func(t->parameter);
|
||||
|
||||
|
@ -554,6 +574,12 @@ void rt_timer_check(void)
|
|||
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
|
||||
|
||||
/* Check whether the timer object is detached or started again */
|
||||
if (rt_list_isempty(&list))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
||||
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
||||
{
|
||||
|
@ -561,14 +587,8 @@ void rt_timer_check(void)
|
|||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
rt_timer_start(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* stop timer */
|
||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
else break;
|
||||
}
|
||||
|
||||
/* enable interrupt */
|
||||
|
@ -589,18 +609,20 @@ rt_tick_t rt_timer_next_timeout_tick(void)
|
|||
|
||||
#ifdef RT_USING_TIMER_SOFT
|
||||
/**
|
||||
* This function will check timer list, if a timeout event happens, the
|
||||
* This function will check software-timer list, if a timeout event happens, the
|
||||
* corresponding timeout function will be invoked.
|
||||
*/
|
||||
void rt_soft_timer_check(void)
|
||||
{
|
||||
rt_tick_t current_tick;
|
||||
struct rt_timer *t;
|
||||
register rt_base_t level;
|
||||
rt_list_t list = RT_LIST_OBJECT_INIT(list);
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
|
||||
|
||||
/* lock scheduler */
|
||||
rt_enter_critical();
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
while (!rt_list_isempty(&rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
||||
{
|
||||
|
@ -619,17 +641,32 @@ void rt_soft_timer_check(void)
|
|||
|
||||
/* remove timer from timer list firstly */
|
||||
_rt_timer_remove(t);
|
||||
if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
|
||||
{
|
||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
}
|
||||
/* add timer to temporary list */
|
||||
rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
|
||||
|
||||
soft_timer_status = RT_SOFT_TIMER_BUSY;
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
/* not lock scheduler when performing timeout function */
|
||||
rt_exit_critical();
|
||||
/* call timeout function */
|
||||
t->timeout_func(t->parameter);
|
||||
|
||||
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
|
||||
|
||||
/* lock scheduler */
|
||||
rt_enter_critical();
|
||||
/* disable interrupt */
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
soft_timer_status = RT_SOFT_TIMER_IDLE;
|
||||
/* Check whether the timer object is detached or started again */
|
||||
if (rt_list_isempty(&list))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
||||
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
||||
|
@ -638,17 +675,11 @@ void rt_soft_timer_check(void)
|
|||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
rt_timer_start(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* stop timer */
|
||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||
}
|
||||
}
|
||||
else break; /* not check anymore */
|
||||
}
|
||||
|
||||
/* unlock scheduler */
|
||||
rt_exit_critical();
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue