2525static rt_list_t rt_timer_list [RT_TIMER_SKIP_LIST_LEVEL ];
2626
2727#ifdef RT_USING_TIMER_SOFT
28+
29+ #define RT_SOFT_TIMER_IDLE 1
30+ #define RT_SOFT_TIMER_BUSY 0
31+
2832#ifndef RT_TIMER_THREAD_STACK_SIZE
2933#define RT_TIMER_THREAD_STACK_SIZE 512
3034#endif
@@ -33,6 +37,8 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
3337#define RT_TIMER_THREAD_PRIO 0
3438#endif
3539
40+ /* soft timer status */
41+ static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE ;
3642/* soft timer list */
3743static rt_list_t rt_soft_timer_list [RT_TIMER_SKIP_LIST_LEVEL ];
3844static struct rt_thread timer_thread ;
@@ -221,6 +227,8 @@ rt_err_t rt_timer_detach(rt_timer_t timer)
221227 level = rt_hw_interrupt_disable ();
222228
223229 _rt_timer_remove (timer );
230+ /* stop timer */
231+ timer -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
224232
225233 /* enable interrupt */
226234 rt_hw_interrupt_enable (level );
@@ -284,6 +292,8 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
284292 level = rt_hw_interrupt_disable ();
285293
286294 _rt_timer_remove (timer );
295+ /* stop timer */
296+ timer -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
287297
288298 /* enable interrupt */
289299 rt_hw_interrupt_enable (level );
@@ -408,7 +418,8 @@ rt_err_t rt_timer_start(rt_timer_t timer)
408418 if (timer -> parent .flag & RT_TIMER_FLAG_SOFT_TIMER )
409419 {
410420 /* check whether timer thread is ready */
411- if ((timer_thread .stat & RT_THREAD_STAT_MASK ) == RT_THREAD_SUSPEND )
421+ if ((soft_timer_status == RT_SOFT_TIMER_IDLE ) &&
422+ ((timer_thread .stat & RT_THREAD_STAT_MASK ) == RT_THREAD_SUSPEND ))
412423 {
413424 /* resume timer thread to check soft timer */
414425 rt_thread_resume (& timer_thread );
@@ -445,13 +456,12 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
445456 level = rt_hw_interrupt_disable ();
446457
447458 _rt_timer_remove (timer );
459+ /* change status */
460+ timer -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
448461
449462 /* enable interrupt */
450463 rt_hw_interrupt_enable (level );
451464
452- /* change stat */
453- timer -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
454-
455465 return RT_EOK ;
456466}
457467RTM_EXPORT (rt_timer_stop );
@@ -467,10 +477,13 @@ RTM_EXPORT(rt_timer_stop);
467477 */
468478rt_err_t rt_timer_control (rt_timer_t timer , int cmd , void * arg )
469479{
480+ register rt_base_t level ;
481+
470482 /* timer check */
471483 RT_ASSERT (timer != RT_NULL );
472484 RT_ASSERT (rt_object_get_type (& timer -> parent ) == RT_Object_Class_Timer );
473485
486+ level = rt_hw_interrupt_disable ();
474487 switch (cmd )
475488 {
476489 case RT_TIMER_CTRL_GET_TIME :
@@ -505,6 +518,7 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
505518 default :
506519 break ;
507520 }
521+ rt_hw_interrupt_enable (level );
508522
509523 return RT_EOK ;
510524}
@@ -521,6 +535,7 @@ void rt_timer_check(void)
521535 struct rt_timer * t ;
522536 rt_tick_t current_tick ;
523537 register rt_base_t level ;
538+ rt_list_t list = RT_LIST_OBJECT_INIT (list );
524539
525540 RT_DEBUG_LOG (RT_DEBUG_TIMER , ("timer check enter\n" ));
526541
@@ -544,7 +559,12 @@ void rt_timer_check(void)
544559
545560 /* remove timer from timer list firstly */
546561 _rt_timer_remove (t );
547-
562+ if (!(t -> parent .flag & RT_TIMER_FLAG_PERIODIC ))
563+ {
564+ t -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
565+ }
566+ /* add timer to temporary list */
567+ rt_list_insert_after (& list , & (t -> row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]));
548568 /* call timeout function */
549569 t -> timeout_func (t -> parameter );
550570
@@ -554,21 +574,21 @@ void rt_timer_check(void)
554574 RT_OBJECT_HOOK_CALL (rt_timer_exit_hook , (t ));
555575 RT_DEBUG_LOG (RT_DEBUG_TIMER , ("current tick: %d\n" , current_tick ));
556576
577+ /* Check whether the timer object is detached or started again */
578+ if (rt_list_isempty (& list ))
579+ {
580+ continue ;
581+ }
582+
557583 if ((t -> parent .flag & RT_TIMER_FLAG_PERIODIC ) &&
558584 (t -> parent .flag & RT_TIMER_FLAG_ACTIVATED ))
559585 {
560586 /* start it */
561587 t -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
562588 rt_timer_start (t );
563589 }
564- else
565- {
566- /* stop timer */
567- t -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
568- }
569590 }
570- else
571- break ;
591+ else break ;
572592 }
573593
574594 /* enable interrupt */
@@ -589,18 +609,20 @@ rt_tick_t rt_timer_next_timeout_tick(void)
589609
590610#ifdef RT_USING_TIMER_SOFT
591611/**
592- * This function will check timer list, if a timeout event happens, the
612+ * This function will check software- timer list, if a timeout event happens, the
593613 * corresponding timeout function will be invoked.
594614 */
595615void rt_soft_timer_check (void )
596616{
597617 rt_tick_t current_tick ;
598618 struct rt_timer * t ;
619+ register rt_base_t level ;
620+ rt_list_t list = RT_LIST_OBJECT_INIT (list );
599621
600622 RT_DEBUG_LOG (RT_DEBUG_TIMER , ("software timer check enter\n" ));
601623
602- /* lock scheduler */
603- rt_enter_critical ();
624+ /* disable interrupt */
625+ level = rt_hw_interrupt_disable ();
604626
605627 while (!rt_list_isempty (& rt_soft_timer_list [RT_TIMER_SKIP_LIST_LEVEL - 1 ]))
606628 {
@@ -619,17 +641,32 @@ void rt_soft_timer_check(void)
619641
620642 /* remove timer from timer list firstly */
621643 _rt_timer_remove (t );
644+ if (!(t -> parent .flag & RT_TIMER_FLAG_PERIODIC ))
645+ {
646+ t -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
647+ }
648+ /* add timer to temporary list */
649+ rt_list_insert_after (& list , & (t -> row [RT_TIMER_SKIP_LIST_LEVEL - 1 ]));
650+
651+ soft_timer_status = RT_SOFT_TIMER_BUSY ;
652+ /* enable interrupt */
653+ rt_hw_interrupt_enable (level );
622654
623- /* not lock scheduler when performing timeout function */
624- rt_exit_critical ();
625655 /* call timeout function */
626656 t -> timeout_func (t -> parameter );
627657
628658 RT_OBJECT_HOOK_CALL (rt_timer_exit_hook , (t ));
629659 RT_DEBUG_LOG (RT_DEBUG_TIMER , ("current tick: %d\n" , current_tick ));
630660
631- /* lock scheduler */
632- rt_enter_critical ();
661+ /* disable interrupt */
662+ level = rt_hw_interrupt_disable ();
663+
664+ soft_timer_status = RT_SOFT_TIMER_IDLE ;
665+ /* Check whether the timer object is detached or started again */
666+ if (rt_list_isempty (& list ))
667+ {
668+ continue ;
669+ }
633670
634671 if ((t -> parent .flag & RT_TIMER_FLAG_PERIODIC ) &&
635672 (t -> parent .flag & RT_TIMER_FLAG_ACTIVATED ))
@@ -638,17 +675,11 @@ void rt_soft_timer_check(void)
638675 t -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
639676 rt_timer_start (t );
640677 }
641- else
642- {
643- /* stop timer */
644- t -> parent .flag &= ~RT_TIMER_FLAG_ACTIVATED ;
645- }
646678 }
647679 else break ; /* not check anymore */
648680 }
649-
650- /* unlock scheduler */
651- rt_exit_critical ();
681+ /* enable interrupt */
682+ rt_hw_interrupt_enable (level );
652683
653684 RT_DEBUG_LOG (RT_DEBUG_TIMER , ("software timer check leave\n" ));
654685}
0 commit comments