diff --git a/components/drivers/ipc/workqueue.c b/components/drivers/ipc/workqueue.c index 984c36323f..9a1301618d 100644 --- a/components/drivers/ipc/workqueue.c +++ b/components/drivers/ipc/workqueue.c @@ -94,6 +94,7 @@ static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t ticks) { rt_base_t level; + rt_err_t err; level = rt_spin_lock_irqsave(&(queue->spinlock)); @@ -125,7 +126,6 @@ static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, /* Timer started */ if (work->flags & RT_WORK_STATE_SUBMITTING) { - rt_timer_stop(&work->timer); rt_timer_control(&work->timer, RT_TIMER_CTRL_SET_TIME, &ticks); } else @@ -137,9 +137,11 @@ static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, work->workqueue = queue; /* insert delay work list */ rt_list_insert_after(queue->delayed_list.prev, &(work->list)); + + err = rt_timer_start(&(work->timer)); rt_spin_unlock_irqrestore(&(queue->spinlock), level); - rt_timer_start(&(work->timer)); - return RT_EOK; + + return err; } rt_spin_unlock_irqrestore(&(queue->spinlock), level); return -RT_ERROR; @@ -156,7 +158,11 @@ static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_wor /* Timer started */ if (work->flags & RT_WORK_STATE_SUBMITTING) { - rt_timer_stop(&(work->timer)); + if ((err = rt_timer_stop(&(work->timer))) != RT_EOK) + { + rt_spin_unlock_irqrestore(&(queue->spinlock), level); + return err; + } rt_timer_detach(&(work->timer)); work->flags &= ~RT_WORK_STATE_SUBMITTING; } @@ -174,6 +180,8 @@ static void _delayed_work_timeout_handler(void *parameter) work = (struct rt_work *)parameter; queue = work->workqueue; + + RT_ASSERT(work->flags & RT_WORK_STATE_SUBMITTING); RT_ASSERT(queue != RT_NULL); level = rt_spin_lock_irqsave(&(queue->spinlock)); diff --git a/components/drivers/serial/serial_tty.c b/components/drivers/serial/serial_tty.c index 85c30dbfeb..c31aa8e3c6 100644 --- a/components/drivers/serial/serial_tty.c +++ b/components/drivers/serial/serial_tty.c @@ -146,7 +146,6 @@ rt_inline void _setup_serial(struct rt_serial_device *serial, lwp_tty_t tp, rt_device_init(&serial->parent); - rt_work_init(&softc->work, _tty_rx_worker, tp); rt_device_control(&serial->parent, RT_DEVICE_CTRL_NOTIFY_SET, ¬ify); } @@ -295,6 +294,7 @@ rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial) if (tty) { rc = lwp_tty_register(tty, dev_name); + rt_work_init(&softc->work, _tty_rx_worker, tty); if (rc != RT_EOK) { diff --git a/include/rtdef.h b/include/rtdef.h index d8082150b2..e524800f43 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -569,13 +569,14 @@ struct rt_object_information */ #define RT_TIMER_FLAG_DEACTIVATED 0x0 /**< timer is deactive */ #define RT_TIMER_FLAG_ACTIVATED 0x1 /**< timer is active */ +#define RT_TIMER_FLAG_PROCESSING 0x2 /**< timer's timeout fuction is processing */ #define RT_TIMER_FLAG_ONE_SHOT 0x0 /**< one shot timer */ -#define RT_TIMER_FLAG_PERIODIC 0x2 /**< periodic timer */ +#define RT_TIMER_FLAG_PERIODIC 0x4 /**< periodic timer */ #define RT_TIMER_FLAG_HARD_TIMER 0x0 /**< hard timer,the timer's callback function will be called in tick isr. */ -#define RT_TIMER_FLAG_SOFT_TIMER 0x4 /**< soft timer,the timer's callback function will be called in timer thread. */ +#define RT_TIMER_FLAG_SOFT_TIMER 0x8 /**< soft timer,the timer's callback function will be called in timer thread. */ #define RT_TIMER_FLAG_THREAD_TIMER \ - (0x8 | RT_TIMER_FLAG_HARD_TIMER) /**< thread timer that cooperates with scheduler directly */ + (0x10 | RT_TIMER_FLAG_HARD_TIMER) /**< thread timer that cooperates with scheduler directly */ #define RT_TIMER_CTRL_SET_TIME 0x0 /**< set timer control command */ #define RT_TIMER_CTRL_GET_TIME 0x1 /**< get timer control command */ diff --git a/src/timer.c b/src/timer.c index 83850e5f47..4d7b352d60 100644 --- a/src/timer.c +++ b/src/timer.c @@ -402,6 +402,11 @@ static rt_err_t _timer_start(rt_list_t *timer_list, rt_timer_t timer) unsigned int tst_nr; static unsigned int random_nr; + if (timer->parent.flag & RT_TIMER_FLAG_PROCESSING) + { + return -RT_ERROR; + } + /* remove timer from list */ _timer_remove(timer); /* change status of timer */ @@ -599,6 +604,11 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg) case RT_TIMER_CTRL_SET_TIME: RT_ASSERT((*(rt_tick_t *)arg) < RT_TICK_MAX / 2); + if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED) + { + _timer_remove(timer); + timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; + } timer->init_tick = *(rt_tick_t *)arg; break; @@ -702,6 +712,8 @@ void rt_timer_check(void) { 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); @@ -714,6 +726,9 @@ void rt_timer_check(void) 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)) { @@ -788,6 +803,8 @@ static void _soft_timer_check(void) { 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])); @@ -801,6 +818,8 @@ static void _soft_timer_check(void) 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)) {