[kernel] fix the timer issue
This commit is contained in:
parent
c758168877
commit
1c6700acfd
85
src/timer.c
85
src/timer.c
|
@ -25,6 +25,10 @@
|
||||||
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||||
|
|
||||||
#ifdef RT_USING_TIMER_SOFT
|
#ifdef RT_USING_TIMER_SOFT
|
||||||
|
|
||||||
|
#define RT_SOFT_TIMER_IDLE 1
|
||||||
|
#define RT_SOFT_TIMER_BUSY 0
|
||||||
|
|
||||||
#ifndef RT_TIMER_THREAD_STACK_SIZE
|
#ifndef RT_TIMER_THREAD_STACK_SIZE
|
||||||
#define RT_TIMER_THREAD_STACK_SIZE 512
|
#define RT_TIMER_THREAD_STACK_SIZE 512
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +37,8 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||||
#define RT_TIMER_THREAD_PRIO 0
|
#define RT_TIMER_THREAD_PRIO 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* soft timer status */
|
||||||
|
static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE;
|
||||||
/* soft timer list */
|
/* soft timer list */
|
||||||
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
|
||||||
static struct rt_thread timer_thread;
|
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();
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
_rt_timer_remove(timer);
|
_rt_timer_remove(timer);
|
||||||
|
/* stop timer */
|
||||||
|
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||||
|
|
||||||
/* enable interrupt */
|
/* enable interrupt */
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
@ -284,6 +292,8 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
_rt_timer_remove(timer);
|
_rt_timer_remove(timer);
|
||||||
|
/* stop timer */
|
||||||
|
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||||
|
|
||||||
/* enable interrupt */
|
/* enable interrupt */
|
||||||
rt_hw_interrupt_enable(level);
|
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)
|
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||||
{
|
{
|
||||||
/* check whether timer thread is ready */
|
/* 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 */
|
/* resume timer thread to check soft timer */
|
||||||
rt_thread_resume(&timer_thread);
|
rt_thread_resume(&timer_thread);
|
||||||
|
@ -445,13 +456,12 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
_rt_timer_remove(timer);
|
_rt_timer_remove(timer);
|
||||||
|
/* change status */
|
||||||
|
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||||
|
|
||||||
/* enable interrupt */
|
/* enable interrupt */
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
/* change stat */
|
|
||||||
timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
||||||
|
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
RTM_EXPORT(rt_timer_stop);
|
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)
|
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
|
register rt_base_t level;
|
||||||
|
|
||||||
/* timer check */
|
/* timer check */
|
||||||
RT_ASSERT(timer != RT_NULL);
|
RT_ASSERT(timer != RT_NULL);
|
||||||
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
|
||||||
|
|
||||||
|
level = rt_hw_interrupt_disable();
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case RT_TIMER_CTRL_GET_TIME:
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
@ -521,6 +535,7 @@ void rt_timer_check(void)
|
||||||
struct rt_timer *t;
|
struct rt_timer *t;
|
||||||
rt_tick_t current_tick;
|
rt_tick_t current_tick;
|
||||||
register rt_base_t level;
|
register rt_base_t level;
|
||||||
|
rt_list_t list = RT_LIST_OBJECT_INIT(list);
|
||||||
|
|
||||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
|
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 */
|
/* remove timer from timer list firstly */
|
||||||
_rt_timer_remove(t);
|
_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 */
|
/* call timeout function */
|
||||||
t->timeout_func(t->parameter);
|
t->timeout_func(t->parameter);
|
||||||
|
|
||||||
|
@ -554,6 +574,12 @@ void rt_timer_check(void)
|
||||||
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
||||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
|
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) &&
|
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
||||||
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
||||||
{
|
{
|
||||||
|
@ -561,14 +587,8 @@ void rt_timer_check(void)
|
||||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||||
rt_timer_start(t);
|
rt_timer_start(t);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* stop timer */
|
|
||||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable interrupt */
|
/* enable interrupt */
|
||||||
|
@ -589,18 +609,20 @@ rt_tick_t rt_timer_next_timeout_tick(void)
|
||||||
|
|
||||||
#ifdef RT_USING_TIMER_SOFT
|
#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.
|
* corresponding timeout function will be invoked.
|
||||||
*/
|
*/
|
||||||
void rt_soft_timer_check(void)
|
void rt_soft_timer_check(void)
|
||||||
{
|
{
|
||||||
rt_tick_t current_tick;
|
rt_tick_t current_tick;
|
||||||
struct rt_timer *t;
|
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"));
|
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
|
||||||
|
|
||||||
/* lock scheduler */
|
/* disable interrupt */
|
||||||
rt_enter_critical();
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
while (!rt_list_isempty(&rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
|
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 */
|
/* remove timer from timer list firstly */
|
||||||
_rt_timer_remove(t);
|
_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 */
|
/* call timeout function */
|
||||||
t->timeout_func(t->parameter);
|
t->timeout_func(t->parameter);
|
||||||
|
|
||||||
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
|
||||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
|
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
|
||||||
|
|
||||||
/* lock scheduler */
|
/* disable interrupt */
|
||||||
rt_enter_critical();
|
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) &&
|
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
|
||||||
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
|
||||||
|
@ -638,17 +675,11 @@ void rt_soft_timer_check(void)
|
||||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
||||||
rt_timer_start(t);
|
rt_timer_start(t);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* stop timer */
|
|
||||||
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else break; /* not check anymore */
|
else break; /* not check anymore */
|
||||||
}
|
}
|
||||||
|
/* enable interrupt */
|
||||||
/* unlock scheduler */
|
rt_hw_interrupt_enable(level);
|
||||||
rt_exit_critical();
|
|
||||||
|
|
||||||
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
|
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue