diff --git a/src/Kconfig b/src/Kconfig index 0443366051f6..36ca0b43b31f 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -181,6 +181,10 @@ if RT_USING_TIMER_SOFT int "The stack size of timer thread" default 2048 if ARCH_CPU_64BIT default 512 + + config RT_USING_TIMER_ALL_SOFT + bool "Set all timer as soft timer" + default n endif config RT_USING_CPU_USAGE_TRACER diff --git a/src/timer.c b/src/timer.c index fd362a5b0531..ec62b155a210 100644 --- a/src/timer.c +++ b/src/timer.c @@ -31,9 +31,11 @@ #define DBG_LVL DBG_INFO #include +#ifndef RT_USING_TIMER_ALL_SOFT /* hard timer list */ static rt_list_t _timer_list[RT_TIMER_SKIP_LIST_LEVEL]; static struct rt_spinlock _htimer_lock; +#endif #ifdef RT_USING_TIMER_SOFT @@ -49,7 +51,6 @@ static struct rt_spinlock _htimer_lock; static rt_list_t _soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL]; static struct rt_spinlock _stimer_lock; static struct rt_thread _timer_thread; -static struct rt_semaphore _soft_timer_sem; rt_align(RT_ALIGN_SIZE) static rt_uint8_t _timer_thread_stack[RT_TIMER_THREAD_STACK_SIZE]; #endif /* RT_USING_TIMER_SOFT */ @@ -93,6 +94,9 @@ void rt_timer_exit_sethook(void (*hook)(struct rt_timer *timer)) rt_inline struct rt_spinlock* _timerlock_idx(struct rt_timer *timer) { +#ifdef RT_USING_TIMER_ALL_SOFT + return &_stimer_lock; +#else #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { @@ -103,6 +107,7 @@ rt_inline struct rt_spinlock* _timerlock_idx(struct rt_timer *timer) { return &_htimer_lock; } +#endif } /** @@ -130,6 +135,10 @@ static void _timer_init(rt_timer_t timer, { int i; +#ifdef RT_USING_TIMER_ALL_SOFT + flag |= RT_TIMER_FLAG_SOFT_TIMER; +#endif + /* set flag */ timer->parent.flag = flag; @@ -570,6 +579,10 @@ rt_err_t rt_timer_start(rt_timer_t timer) RT_ASSERT(timer != RT_NULL); RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer); +#ifdef RT_USING_TIMER_ALL_SOFT + timer_list = _soft_timer_list; + spinlock = &_stimer_lock; +#else #ifdef RT_USING_TIMER_SOFT if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER) { @@ -582,6 +595,7 @@ rt_err_t rt_timer_start(rt_timer_t timer) timer_list = _timer_list; spinlock = &_htimer_lock; } +#endif if (timer->parent.flag & RT_TIMER_FLAG_THREAD_TIMER) { @@ -598,13 +612,6 @@ rt_err_t rt_timer_start(rt_timer_t timer) err = _timer_start(timer_list, timer); -#ifdef RT_USING_TIMER_SOFT - if (err == RT_EOK && (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)) - { - rt_sem_release(&_soft_timer_sem); - } -#endif /* RT_USING_TIMER_SOFT */ - rt_spin_unlock_irqrestore(spinlock, level); if (is_thread_timer) @@ -756,7 +763,20 @@ void rt_timer_check(void) return; } #endif + +#ifdef RT_USING_TIMER_SOFT + rt_err_t ret = RT_ERROR; + rt_tick_t next_timeout; + + ret = _timer_list_next_timeout(_soft_timer_list, &next_timeout); + if ((ret == RT_EOK) && (next_timeout <= rt_tick_get())) + { + rt_thread_resume(&_timer_thread); + } +#endif +#ifndef RT_USING_TIMER_ALL_SOFT _timer_check(_timer_list, &_htimer_lock); +#endif } /** @@ -767,13 +787,21 @@ void rt_timer_check(void) rt_tick_t rt_timer_next_timeout_tick(void) { rt_base_t level; - rt_tick_t next_timeout = RT_TICK_MAX; + rt_tick_t htimer_next_timeout = RT_TICK_MAX, stimer_next_timeout = RT_TICK_MAX; +#ifndef RT_USING_TIMER_ALL_SOFT level = rt_spin_lock_irqsave(&_htimer_lock); - _timer_list_next_timeout(_timer_list, &next_timeout); + _timer_list_next_timeout(_timer_list, &htimer_next_timeout); rt_spin_unlock_irqrestore(&_htimer_lock, level); +#endif - return next_timeout; +#ifdef RT_USING_TIMER_SOFT + level = rt_spin_lock_irqsave(&_stimer_lock); + _timer_list_next_timeout(_soft_timer_list, &stimer_next_timeout); + rt_spin_unlock_irqrestore(&_stimer_lock, level); +#endif + + return htimer_next_timeout < stimer_next_timeout ? htimer_next_timeout : stimer_next_timeout; } #ifdef RT_USING_TIMER_SOFT @@ -784,41 +812,15 @@ rt_tick_t rt_timer_next_timeout_tick(void) */ static void _timer_thread_entry(void *parameter) { - rt_err_t ret = RT_ERROR; - rt_tick_t next_timeout; - rt_base_t level; - RT_UNUSED(parameter); - rt_sem_control(&_soft_timer_sem, RT_IPC_CMD_SET_VLIMIT, (void*)1); - while (1) { - /* get the next timeout tick */ - level = rt_spin_lock_irqsave(&_stimer_lock); - ret = _timer_list_next_timeout(_soft_timer_list, &next_timeout); - rt_spin_unlock_irqrestore(&_stimer_lock, level); - - if (ret != RT_EOK) - { - rt_sem_take(&_soft_timer_sem, RT_WAITING_FOREVER); - } - else + _timer_check(_soft_timer_list, &_stimer_lock); /* check software timer */ + if (rt_thread_suspend(&_timer_thread) == RT_EOK) { - 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_sem_take(&_soft_timer_sem, next_timeout); - } + rt_schedule(); } - - _timer_check(_soft_timer_list, &_stimer_lock); /* check software timer */ } } #endif /* RT_USING_TIMER_SOFT */ @@ -830,13 +832,16 @@ static void _timer_thread_entry(void *parameter) */ void rt_system_timer_init(void) { +#ifndef RT_USING_TIMER_ALL_SOFT rt_size_t i; for (i = 0; i < sizeof(_timer_list) / sizeof(_timer_list[0]); i++) { rt_list_init(_timer_list + i); } + rt_spin_lock_init(&_htimer_lock); +#endif } /** @@ -856,7 +861,6 @@ void rt_system_timer_thread_init(void) rt_list_init(_soft_timer_list + i); } rt_spin_lock_init(&_stimer_lock); - rt_sem_init(&_soft_timer_sem, "stimer", 0, RT_IPC_FLAG_PRIO); /* start software timer thread */ rt_thread_init(&_timer_thread, "timer",