summaryrefslogtreecommitdiff
path: root/src/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/timer.c')
-rw-r--r--src/timer.c545
1 files changed, 283 insertions, 262 deletions
diff --git a/src/timer.c b/src/timer.c
index 29bfecd3d8..f6857798e3 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -17,6 +17,7 @@
* 2009-11-11 LiJin add soft timer
* 2010-05-12 Bernard fix the timer check bug.
* 2010-11-02 Charlie re-implement tick overflow issue
+ * 2012-12-15 Bernard fix the next timeout issue in soft timer
*/
#include <rtthread.h>
@@ -26,6 +27,14 @@
static rt_list_t rt_timer_list = RT_LIST_OBJECT_INIT(rt_timer_list);
#ifdef RT_USING_TIMER_SOFT
+#ifndef RT_TIMER_THREAD_STACK_SIZE
+#define RT_TIMER_THREAD_STACK_SIZE 512
+#endif
+
+#ifndef RT_TIMER_THREAD_PRIO
+#define RT_TIMER_THREAD_PRIO 0
+#endif
+
/* soft timer list */
static rt_list_t rt_soft_timer_list;
static struct rt_thread timer_thread;
@@ -52,42 +61,42 @@ static void (*rt_timer_timeout_hook)(struct rt_timer *timer);
*/
void rt_timer_timeout_sethook(void (*hook)(struct rt_timer *timer))
{
- rt_timer_timeout_hook = hook;
+ rt_timer_timeout_hook = hook;
}
/*@}*/
#endif
static void _rt_timer_init(rt_timer_t timer,
- void (*timeout)(void *parameter), void *parameter,
- rt_tick_t time, rt_uint8_t flag)
+ void (*timeout)(void *parameter), void *parameter,
+ rt_tick_t time, rt_uint8_t flag)
{
- /* set flag */
- timer->parent.flag = flag;
+ /* set flag */
+ timer->parent.flag = flag;
- /* set deactivated */
- timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ /* set deactivated */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- timer->timeout_func = timeout;
- timer->parameter = parameter;
+ timer->timeout_func = timeout;
+ timer->parameter = parameter;
- timer->timeout_tick = 0;
- timer->init_tick = time;
+ timer->timeout_tick = 0;
+ timer->init_tick = time;
- /* initialize timer list */
- rt_list_init(&(timer->list));
+ /* initialize timer list */
+ rt_list_init(&(timer->list));
}
static rt_tick_t rt_timer_list_next_timeout(rt_list_t *timer_list)
{
- struct rt_timer *timer;
+ struct rt_timer *timer;
- if (rt_list_isempty(timer_list))
- return RT_TICK_MAX;
-
- timer = rt_list_entry(timer_list->next, struct rt_timer, list);
+ if (rt_list_isempty(timer_list))
+ return RT_TICK_MAX;
+
+ timer = rt_list_entry(timer_list->next, struct rt_timer, list);
- return timer->timeout_tick;
+ return timer->timeout_tick;
}
/**
@@ -108,17 +117,17 @@ static rt_tick_t rt_timer_list_next_timeout(rt_list_t *timer_list)
* @param flag the flag of timer
*/
void rt_timer_init(rt_timer_t timer,
- const char *name,
- void (*timeout)(void *parameter), void *parameter,
- rt_tick_t time, rt_uint8_t flag)
+ const char *name,
+ void (*timeout)(void *parameter), void *parameter,
+ rt_tick_t time, rt_uint8_t flag)
{
- /* timer check */
- RT_ASSERT(timer != RT_NULL);
+ /* timer check */
+ RT_ASSERT(timer != RT_NULL);
- /* timer object initialization */
- rt_object_init((rt_object_t)timer, RT_Object_Class_Timer, name);
+ /* timer object initialization */
+ rt_object_init((rt_object_t)timer, RT_Object_Class_Timer, name);
- _rt_timer_init(timer, timeout, parameter, time, flag);
+ _rt_timer_init(timer, timeout, parameter, time, flag);
}
RTM_EXPORT(rt_timer_init);
@@ -131,23 +140,23 @@ RTM_EXPORT(rt_timer_init);
*/
rt_err_t rt_timer_detach(rt_timer_t timer)
{
- register rt_base_t level;
+ register rt_base_t level;
- /* timer check */
- RT_ASSERT(timer != RT_NULL);
+ /* timer check */
+ RT_ASSERT(timer != RT_NULL);
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- /* remove it from timer list */
- rt_list_remove(&(timer->list));
+ /* remove it from timer list */
+ rt_list_remove(&(timer->list));
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
- rt_object_detach((rt_object_t)timer);
+ rt_object_detach((rt_object_t)timer);
- return -RT_EOK;
+ return -RT_EOK;
}
RTM_EXPORT(rt_timer_detach);
@@ -164,20 +173,20 @@ RTM_EXPORT(rt_timer_detach);
* @return the created timer object
*/
rt_timer_t rt_timer_create(const char *name, void (*timeout)(void *parameter),
- void *parameter, rt_tick_t time, rt_uint8_t flag)
+ void *parameter, rt_tick_t time, rt_uint8_t flag)
{
- struct rt_timer *timer;
+ struct rt_timer *timer;
- /* allocate a object */
- timer = (struct rt_timer *)rt_object_allocate(RT_Object_Class_Timer, name);
- if (timer == RT_NULL)
- {
- return RT_NULL;
- }
+ /* allocate a object */
+ timer = (struct rt_timer *)rt_object_allocate(RT_Object_Class_Timer, name);
+ if (timer == RT_NULL)
+ {
+ return RT_NULL;
+ }
- _rt_timer_init(timer, timeout, parameter, time, flag);
+ _rt_timer_init(timer, timeout, parameter, time, flag);
- return timer;
+ return timer;
}
RTM_EXPORT(rt_timer_create);
@@ -190,23 +199,23 @@ RTM_EXPORT(rt_timer_create);
*/
rt_err_t rt_timer_delete(rt_timer_t timer)
{
- register rt_base_t level;
+ register rt_base_t level;
- /* timer check */
- RT_ASSERT(timer != RT_NULL);
+ /* timer check */
+ RT_ASSERT(timer != RT_NULL);
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- /* remove it from timer list */
- rt_list_remove(&(timer->list));
+ /* remove it from timer list */
+ rt_list_remove(&(timer->list));
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
- rt_object_delete((rt_object_t)timer);
+ rt_object_delete((rt_object_t)timer);
- return -RT_EOK;
+ return -RT_EOK;
}
RTM_EXPORT(rt_timer_delete);
#endif
@@ -220,76 +229,76 @@ RTM_EXPORT(rt_timer_delete);
*/
rt_err_t rt_timer_start(rt_timer_t timer)
{
- struct rt_timer *t;
- register rt_base_t level;
- rt_list_t *n, *timer_list;
+ struct rt_timer *t;
+ register rt_base_t level;
+ rt_list_t *n, *timer_list;
- /* timer check */
- RT_ASSERT(timer != RT_NULL);
- if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
- return -RT_ERROR;
+ /* timer check */
+ RT_ASSERT(timer != RT_NULL);
+ if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+ return -RT_ERROR;
- RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent)));
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent)));
- /* get timeout tick, the max timeout tick shall not great than RT_TICK_MAX/2 */
- RT_ASSERT(timer->init_tick < RT_TICK_MAX/2);
- timer->timeout_tick = rt_tick_get() + timer->init_tick;
+ /* get timeout tick, the max timeout tick shall not great than RT_TICK_MAX/2 */
+ RT_ASSERT(timer->init_tick < RT_TICK_MAX/2);
+ timer->timeout_tick = rt_tick_get() + timer->init_tick;
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
#ifdef RT_USING_TIMER_SOFT
- if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
- {
- /* insert timer to soft timer list */
- timer_list = &rt_soft_timer_list;
- }
- else
+ if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
+ {
+ /* insert timer to soft timer list */
+ timer_list = &rt_soft_timer_list;
+ }
+ else
#endif
- {
- /* insert timer to system timer list */
- timer_list = &rt_timer_list;
- }
+ {
+ /* insert timer to system timer list */
+ timer_list = &rt_timer_list;
+ }
- for (n = timer_list->next; n != timer_list; n = n->next)
- {
- t = rt_list_entry(n, struct rt_timer, list);
-
- /*
- * It supposes that the new tick shall less than the half duration of
- * tick max.
- */
- if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX/2)
- {
- rt_list_insert_before(n, &(timer->list));
- break;
- }
- }
- /* no found suitable position in timer list */
- if (n == timer_list)
- {
- rt_list_insert_before(n, &(timer->list));
- }
+ for (n = timer_list->next; n != timer_list; n = n->next)
+ {
+ t = rt_list_entry(n, struct rt_timer, list);
+
+ /*
+ * It supposes that the new tick shall less than the half duration of
+ * tick max.
+ */
+ if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX/2)
+ {
+ rt_list_insert_before(n, &(timer->list));
+ break;
+ }
+ }
+ /* no found suitable position in timer list */
+ if (n == timer_list)
+ {
+ rt_list_insert_before(n, &(timer->list));
+ }
- timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
+ timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
#ifdef RT_USING_TIMER_SOFT
- if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
- {
- /* check whether timer thread is ready */
- if (timer_thread.stat != RT_THREAD_READY)
- {
- /* resume timer thread to check soft timer */
- rt_thread_resume(&timer_thread);
- rt_schedule();
- }
- }
+ if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
+ {
+ /* check whether timer thread is ready */
+ if (timer_thread.stat != RT_THREAD_READY)
+ {
+ /* resume timer thread to check soft timer */
+ rt_thread_resume(&timer_thread);
+ rt_schedule();
+ }
+ }
#endif
- return -RT_EOK;
+ return -RT_EOK;
}
RTM_EXPORT(rt_timer_start);
@@ -302,28 +311,28 @@ RTM_EXPORT(rt_timer_start);
*/
rt_err_t rt_timer_stop(rt_timer_t timer)
{
- register rt_base_t level;
+ register rt_base_t level;
- /* timer check */
- RT_ASSERT(timer != RT_NULL);
- if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
- return -RT_ERROR;
+ /* timer check */
+ RT_ASSERT(timer != RT_NULL);
+ if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+ return -RT_ERROR;
- RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent)));
+ RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(timer->parent)));
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- /* remove it from timer list */
- rt_list_remove(&(timer->list));
+ /* remove it from timer list */
+ rt_list_remove(&(timer->list));
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
- /* change stat */
- timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ /* change stat */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- return RT_EOK;
+ return RT_EOK;
}
RTM_EXPORT(rt_timer_stop);
@@ -338,29 +347,29 @@ RTM_EXPORT(rt_timer_stop);
*/
rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void *arg)
{
- /* timer check */
- RT_ASSERT(timer != RT_NULL);
+ /* timer check */
+ RT_ASSERT(timer != RT_NULL);
- switch (cmd)
- {
- case RT_TIMER_CTRL_GET_TIME:
- *(rt_tick_t *)arg = timer->init_tick;
- break;
+ switch (cmd)
+ {
+ case RT_TIMER_CTRL_GET_TIME:
+ *(rt_tick_t *)arg = timer->init_tick;
+ break;
- case RT_TIMER_CTRL_SET_TIME:
- timer->init_tick = *(rt_tick_t *)arg;
- break;
+ case RT_TIMER_CTRL_SET_TIME:
+ timer->init_tick = *(rt_tick_t *)arg;
+ break;
- case RT_TIMER_CTRL_SET_ONESHOT:
- timer->parent.flag &= ~RT_TIMER_FLAG_PERIODIC;
- break;
+ case RT_TIMER_CTRL_SET_ONESHOT:
+ timer->parent.flag &= ~RT_TIMER_FLAG_PERIODIC;
+ break;
- case RT_TIMER_CTRL_SET_PERIODIC:
- timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
- break;
- }
+ case RT_TIMER_CTRL_SET_PERIODIC:
+ timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
+ break;
+ }
- return RT_EOK;
+ return RT_EOK;
}
RTM_EXPORT(rt_timer_control);
@@ -372,61 +381,61 @@ RTM_EXPORT(rt_timer_control);
*/
void rt_timer_check(void)
{
- struct rt_timer *t;
- rt_tick_t current_tick;
- register rt_base_t level;
+ struct rt_timer *t;
+ rt_tick_t current_tick;
+ register rt_base_t level;
- RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
- current_tick = rt_tick_get();
+ current_tick = rt_tick_get();
- /* disable interrupt */
- level = rt_hw_interrupt_disable();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- while (!rt_list_isempty(&rt_timer_list))
- {
- t = rt_list_entry(rt_timer_list.next, struct rt_timer, list);
+ while (!rt_list_isempty(&rt_timer_list))
+ {
+ t = rt_list_entry(rt_timer_list.next, struct rt_timer, list);
- /*
- * 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_timeout_hook, (t));
+ /*
+ * 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_timeout_hook, (t));
- /* remove timer from timer list firstly */
- rt_list_remove(&(t->list));
+ /* remove timer from timer list firstly */
+ rt_list_remove(&(t->list));
- /* call timeout function */
- t->timeout_func(t->parameter);
+ /* call timeout function */
+ t->timeout_func(t->parameter);
- /* re-get tick */
- current_tick = rt_tick_get();
+ /* re-get tick */
+ current_tick = rt_tick_get();
- RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
- if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
- (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
- {
- /* start it */
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- rt_timer_start(t);
- }
- else
- {
- /* stop timer */
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- }
- }
- else
- break;
- }
+ if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
+ (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+ {
+ /* start it */
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ rt_timer_start(t);
+ }
+ else
+ {
+ /* stop timer */
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ }
+ else
+ break;
+ }
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
- RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}
/**
@@ -436,7 +445,7 @@ void rt_timer_check(void)
*/
rt_tick_t rt_timer_next_timeout_tick(void)
{
- return rt_timer_list_next_timeout(&rt_timer_list);
+ return rt_timer_list_next_timeout(&rt_timer_list);
}
#ifdef RT_USING_TIMER_SOFT
@@ -446,84 +455,96 @@ rt_tick_t rt_timer_next_timeout_tick(void)
*/
void rt_soft_timer_check(void)
{
- rt_tick_t current_tick;
- rt_list_t *n;
- struct rt_timer *t;
+ rt_tick_t current_tick;
+ rt_list_t *n;
+ struct rt_timer *t;
- RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
- current_tick = rt_tick_get();
+ current_tick = rt_tick_get();
- for (n = rt_soft_timer_list.next; n != &(rt_soft_timer_list);)
- {
- t = rt_list_entry(n, struct rt_timer, list);
+ for (n = rt_soft_timer_list.next; n != &(rt_soft_timer_list);)
+ {
+ t = rt_list_entry(n, struct rt_timer, list);
- /*
- * 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_timeout_hook, (t));
+ /*
+ * 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_timeout_hook, (t));
- /* move node to the next */
- n = n->next;
+ /* move node to the next */
+ n = n->next;
- /* remove timer from timer list firstly */
- rt_list_remove(&(t->list));
+ /* remove timer from timer list firstly */
+ rt_list_remove(&(t->list));
- /* call timeout function */
- t->timeout_func(t->parameter);
+ /* call timeout function */
+ t->timeout_func(t->parameter);
- /* re-get tick */
- current_tick = rt_tick_get();
+ /* re-get tick */
+ current_tick = rt_tick_get();
- RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
- if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
- (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
- {
- /* start it */
- 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 */
- }
+ if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
+ (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+ {
+ /* start it */
+ 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 */
+ }
- RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
+ RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
}
/* system timer thread entry */
static void rt_thread_timer_entry(void *parameter)
{
- rt_tick_t next_timeout;
-
- while (1)
- {
- next_timeout = rt_timer_list_next_timeout(&rt_soft_timer_list);
- if (next_timeout == RT_TICK_MAX)
- {
- rt_thread_suspend(rt_thread_self());
- rt_schedule();
- }
- else
- {
- rt_thread_delay(next_timeout);
- }
+ rt_tick_t next_timeout;
+
+ while (1)
+ {
+ /* get the next timeout tick */
+ next_timeout = rt_timer_list_next_timeout(&rt_soft_timer_list);
+ if (next_timeout == RT_TICK_MAX)
+ {
+ /* no software timer exist, suspend self. */
+ rt_thread_suspend(rt_thread_self());
+ rt_schedule();
+ }
+ else
+ {
+ rt_tick_t current_tick;
+
+ /* get current tick */
+ current_tick = rt_tick_get();
+
+ if ((next_timeout - current_tick) < RT_TICK_MAX/2)
+ {
+ /* get the delta timeout tick */
+ next_timeout = next_timeout - current_tick;
+ rt_thread_delay(next_timeout);
+ }
+ }
- /* lock scheduler */
- rt_enter_critical();
- /* check software timer */
- rt_soft_timer_check();
- /* unlock scheduler */
- rt_exit_critical();
- }
+ /* lock scheduler */
+ rt_enter_critical();
+ /* check software timer */
+ rt_soft_timer_check();
+ /* unlock scheduler */
+ rt_exit_critical();
+ }
}
#endif
@@ -547,17 +568,17 @@ void rt_system_timer_init(void)
void rt_system_timer_thread_init(void)
{
#ifdef RT_USING_TIMER_SOFT
- rt_list_init(&rt_soft_timer_list);
+ rt_list_init(&rt_soft_timer_list);
- /* start software timer thread */
- rt_thread_init(&timer_thread,
- "timer",
- rt_thread_timer_entry, RT_NULL,
- &timer_thread_stack[0], sizeof(timer_thread_stack),
- RT_TIMER_THREAD_PRIO, 10);
+ /* start software timer thread */
+ rt_thread_init(&timer_thread,
+ "timer",
+ rt_thread_timer_entry, RT_NULL,
+ &timer_thread_stack[0], sizeof(timer_thread_stack),
+ RT_TIMER_THREAD_PRIO, 10);
- /* startup */
- rt_thread_startup(&timer_thread);
+ /* startup */
+ rt_thread_startup(&timer_thread);
#endif
}