Threadx system timer thread _tx_timer_thread_entry

"System Timer Thread" system timer thread is used to determine the timer expires, and call timer timeout handler.

_tx_timer_initialize

Let's look at the timer initialization thread creation. _tx_timer_initialize system initialization series of related global variables, linked lists, and other threads of time, the timer.

VOID    _tx_timer_initialize(VOID)
{

    REG_1 UINT                  i;              /* Working index variable     */
    REG_2 TX_INTERNAL_TIMER     **timer_ptr;    /* Working timer pointer      */

    UINT32 b_is_os_test = 0;

    /* Initialize the system clock to 0.  */
    #def 系统时钟,用于时间相关
    _tx_timer_system_clock =  0;

    /* Initialize the time-slice value to 0 to make sure it is disabled.  */
    #def 初始化时间片全局变量,用于基于时间片的线程调度
    _tx_timer_time_slice =  0;

    /* Clear the expired flags.  */
    #def 时间片耗尽标志
    _tx_timer_expired_time_slice =  TX_FALSE;
    #def 定时器超时标志
    _tx_timer_expired =             TX_FALSE;

    /* Initialize the thread and application timer management control structures.  */

    /* First, initialize the timer list.  */
    #def 激活定时器数组链表初始化为NULL
    timer_ptr =  &_tx_timer_list[0];
    for (i = 0; i < TX_TIMER_ENTRIES; i++)
        *timer_ptr++ =  TX_NULL;

    /* Initialize all of the list pointers.  */
    #def 记录定时器数组链表的头,初始化当前指针_tx_timer_current_ptr 
    _tx_timer_list_start =   &_tx_timer_list[0];
    _tx_timer_current_ptr =  &_tx_timer_list[0];

    /* Set the timer list end pointer to one past the actual timer list.  This is done
       to make the timer interrupt handling in assembly language a little easier.  */
     #def  记录定时器链表尾
    _tx_timer_list_end =     &_tx_timer_list[TX_TIMER_ENTRIES - 1];
    _tx_timer_list_end =     _tx_timer_list_end + 1;


    /* Setup the variables associated with the system timer thread's stack and
       priority.  */
    #def 初始化定时器线程堆栈空间起始地址,栈大小,线程优先级,默认线程优先级为0,系统中最高优先级
    _tx_timer_stack_start = (VOID *) &_tx_timer_thread_stack_area[0];
    _tx_timer_stack_size =   TX_TIMER_THREAD_STACK_SIZE;
    _tx_timer_priority =     TX_TIMER_THREAD_PRIORITY;

    b_is_os_test = os_test_flag_check();
    if (b_is_os_test != OS_TEST_FLAG_TRUE)
    {
        /* Create the system timer thread.  This thread processes all of the timer
           expirations and reschedules.  Its stack and priority are defined in the
           low-level initialization component.  */
        #def 创建系统定时器线程,默认线程创建后挂起TX_DONT_START
        _tx_thread_create(&_tx_timer_thread, "System Timer Thread", _tx_timer_thread_entry,
                          (ULONG) TX_TIMER_ID,  _tx_timer_stack_start, _tx_timer_stack_size,
                          _tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE, TX_DONT_START);
    }

    /* Initialize the head pointer of the created application timer list.  */
    _tx_timer_created_ptr =  TX_NULL;

    /* Set the created count to zero.  */
    _tx_timer_created_count =  0;
}

_tx_timer_thread_entry

_tx_timer_thread_entry timer thread processing functions, the main work:
1, to obtain _tx_timer_current_ptr points list, check the list of all timer
2, if the timer expires, call a timeout handler for processing
3, if you need to restart the timer, reset timer value, insert the list array
4, if the timer has not timed out, the timer value is reset, is inserted into the list array
5, _tx_timer_current_ptr plus 1, execution of the next beat list

The default system timer thread is suspended, if awakened it?
Clock timer interrupt arrives, the timer interrupt handler, check _tx_timer_current_ptr is not empty, that is _tx_timer_list [n] list is not empty, then that needs to be processed has a timer activated beat of the current list, so wake-up timer interrupt handler in the system timer thread.
If
_tx_timer_current_ptr is empty, you do not need to wake up the system timer interrupt, just _tx_timer_current_ptr add 1 point to the next list, wait for a timer interrupt.

VOID    _tx_timer_thread_entry(ULONG timer_thread_input)
{

    TX_INTERRUPT_SAVE_AREA

    TX_INTERNAL_TIMER           *expired_timers;            /* Head of expired timers list  */
    TX_INTERNAL_TIMER           *reactivate_timer;          /* Dummy list head pointer      */

#ifdef TX_REACTIVATE_INLINE
    TX_INTERNAL_TIMER           **timer_list;               /* Timer list pointer           */
    REG_1 UINT                  expiration_time;            /* Value used for pointer offset*/
#endif
    REG_2  TX_INTERNAL_TIMER    *current_timer;             /* Current timer pointer        */
    VOID (*timeout_function)(ULONG);                        /* Local timeout function ptr   */
    ULONG                       timeout_param;              /* Local timeout parameter      */

    /* Make sure the timer input is correct.  This also gets rid of the
       silly compiler warnings.  */
       #def 超时函数入参必须为TX_TIMER_ID
    if (timer_thread_input != TX_TIMER_ID)
        return;

    /* Set the reactivate_timer to NULL.  */
    reactivate_timer =  TX_NULL;

    /* Now go into an infinite loop to process timer expirations.  */
    do
    {

        /* First, move the current list pointer and clear the timer
           expired value.  This allows the interrupt handling portion
           to continue looking for timer expirations.  */
        #def 禁止中断,防止打断
        TX_DISABLE

        /* Clear the expired flag.  */
        /* NOTICE: _tx_timer_expired flag is set during ISR, real timer share this with timer. */
        #def 时钟中断,在中断处理函数中如果发现当前*_tx_timer_current_ptr不为空,就置_tx_timer_expired 为true
        #def 这里清除
        _tx_timer_expired =  TX_FALSE;
		
		#def 记录当前节拍 对应的链表头指针
        expired_timers =  *_tx_timer_current_ptr;

        /* Modify the head pointer in the first timer in the list, if there
           is one!  */
          #def 后面开始处理第一个定时器,所以让链表头先指向自己
        if (expired_timers)
            expired_timers -> tx_list_head =  &expired_timers;

        /* Set the current list pointer to NULL.  */
        #def 让数组指针为空,后面定时器都重新选择位置插入
        *_tx_timer_current_ptr =  TX_NULL;

        /* Move the current pointer up one timer entry wrap if we get to
           the end of the list.  */
        #def _tx_timer_current_ptr指向下一个节拍对应数组元素指针;如果到了_tx_timer_list_end,从头开始
        _tx_timer_current_ptr++;
        if (_tx_timer_current_ptr == _tx_timer_list_end)
            _tx_timer_current_ptr =  _tx_timer_list_start;

        TX_RESTORE

        /* Next, process the expiration of the associated timers at this
           time slot.  */
        TX_DISABLE
        #def 循环处理链表中所有定时器
        #def 有的定时器超时了,调用超时处理函数,如果是周期性,重新激活,插入合适链表
        #def 有的定时器没有超时,只是挂入了这个链表,那么重新激活,插入合适链表
        while (expired_timers)
        {
            /* Something is on the list.  Remove it and process the expiration.  */
            current_timer =  expired_timers;
			
			#def 先把expired_timers从链表中移除
            /* Determine if this is the only timer.  */
            if (current_timer == expired_timers -> tx_active_next)
            {

                /* Yes, this is the only timer in the list.  */

                /* Set the head pointer to NULL.  */
                expired_timers =  TX_NULL;
            }
            else
            {

                /* No, not the only expired timer.  */

                /* Remove this timer from the expired list.  */
                (current_timer -> tx_active_next) -> tx_active_previous =
                    current_timer -> tx_active_previous;
                (current_timer -> tx_active_previous) -> tx_active_next =
                    current_timer -> tx_active_next;

                /* Modify the next timer's list head to point at the current list head.  */
                (current_timer -> tx_active_next) -> tx_list_head =  &expired_timers;
                /* Set the list head pointer.  */
                expired_timers =  current_timer -> tx_active_next;
            }

            /* In any case, the timer is now off of the expired list.  */

            /* Determine if the timer has expired or if it is just a really
               big timer that needs to be placed in the list again.  */
               #def 如果tx_remaining_ticks 大于32,说明之前挂到这个节拍对应数组链表中,现在正好过去了32个节拍,只需把
               #def 剩余时间减去32,并没有超时
            if (current_timer -> tx_remaining_ticks > TX_TIMER_ENTRIES)
            {
				#def 还没有超时,需要重新激活
                /* Timer is bigger than the timer entries and must be
                   rescheduled.  */

                /* Decrement the remaining ticks of the timer.  */
                current_timer -> tx_remaining_ticks =
                    current_timer -> tx_remaining_ticks - TX_TIMER_ENTRIES;

                /* Set the timeout function to NULL in order to bypass the
                   expiration.  */
                timeout_function =  TX_NULL;

                /* Make the timer appear that it is still active while interrupts
                   are enabled.  This will permit proper processing of a timer
                   deactivate from an ISR.  */
                  #def 做个标记reactivate_timer,后面需要重新激活
                current_timer -> tx_list_head =    &reactivate_timer;
                current_timer -> tx_active_next =  current_timer;
            }
            else
            {
				#def 小于32,走到这正好到了定时值,需要进行超时处理
                /* Timer did expire.  Copy the calling function and ID
                   into local variables before interrupts are re-enabled.  */
                timeout_function =  current_timer -> tx_timeout_function;
                timeout_param =     current_timer -> tx_timeout_param;

                /* Copy the reinitialize ticks into the remaining ticks.  */
                #def 如果tx_re_initialize_ticks不为0,说明是周期性定时器,需要重新激活
                current_timer -> tx_remaining_ticks =  current_timer -> tx_re_initialize_ticks;

                /* Determine if the timer should be reactivated.  */
                if (current_timer -> tx_remaining_ticks)
                {

                    /* Make the timer appear that it is still active while processing
                       the expiration routine and with interrupts enabled.  This will
                       permit proper processing of a timer deactivate from both the
                       expiration routine and an ISR.  */
                       #def 做个标记reactivate_timer,后面需要重新激活
                    current_timer -> tx_list_head =    &reactivate_timer;
                    current_timer -> tx_active_next =  current_timer;
                }
                else
                {

                    /* Set the list pointer of this timer to NULL.  This is used to indicate
                       the timer is no longer active.  */
                    current_timer -> tx_list_head =  TX_NULL;
                }
            }

            /* Restore interrupts for timer expiration call.  */
            TX_RESTORE

            /* Call the timer-expiration function, if non-NULL.  */
            #def timeout_function不为空,调用超时处理函数
            if (timeout_function)
                (timeout_function)(timeout_param);

            /* Lockout interrupts again.  */
            TX_DISABLE

            /* Determine if the timer needs to be reactivated.  */
            #def 前面做了标记reactivate_timer,需要重新激活
            if (current_timer -> tx_list_head == &reactivate_timer)
            {

#ifdef TX_REACTIVATE_INLINE

                /* Reactivate the timer.  */
				#def 需要重新根据tx_remaining_ticks 剩余时间选择下一个节拍数组链表
                /* Calculate the amount of time remaining for the timer.  */
                if (current_timer -> tx_remaining_ticks > TX_TIMER_ENTRIES)
                {

                    /* Set expiration time to the maximum number of entries.  */
                    expiration_time =  TX_TIMER_ENTRIES - 1;
                }
                else
                {

                    /* Timer value fits in the timer entries.  */

                    /* Set the expiration time.  */
                    expiration_time = (UINT) current_timer -> tx_remaining_ticks - 1;
                }

                /* At this point, we are ready to put the timer back on one of
                   the timer lists.  */

                /* Calculate the proper place for the timer.  */
                timer_list =  _tx_timer_current_ptr + expiration_time;
                if (timer_list >= _tx_timer_list_end)
                {

                    /* Wrap from the beginning of the list.  */
                    timer_list =  _tx_timer_list_start +
                                  (timer_list - _tx_timer_list_end);
                }
				
				#def 插入链表
                /* Now put the timer on this list.  */
                if (*timer_list)
                {

                    /* This list is not NULL, add current timer to the end. */
                    current_timer -> tx_active_next =                          *timer_list;
                    current_timer -> tx_active_previous = (*timer_list) -> tx_active_previous;
                    (current_timer -> tx_active_previous) -> tx_active_next =  current_timer;
                    (*timer_list) -> tx_active_previous =                      current_timer;
                    current_timer -> tx_list_head =                            timer_list;
                }
                else
                {

                    /* This list is NULL, just put the new timer on it.  */

                    /* Setup the links in this timer.  */
                    current_timer -> tx_active_next =      current_timer;
                    current_timer -> tx_active_previous =  current_timer;
                    current_timer -> tx_list_head =        timer_list;

                    /* Setup the list head pointer.  */
                    *timer_list =  current_timer;
                }
#else
                /* Reactivate through the timer activate function.  */

                /* Clear the list head for the timer activate call.  */
                current_timer -> tx_list_head = TX_NULL;

                /* Activate the current timer.  */
                _tx_timer_activate(current_timer);
#endif
            }

            /* Restore interrupts.  */
            TX_RESTORE
			#def 这里开中断,给中断一次机会,这时有可能下一个时钟中断来了,然后重新设置了_tx_timer_expired为 true
			#def 在进入这个函数时设置了_tx_timer_expired为false
            /* Lockout interrupts again.  */
            TX_DISABLE
        }  // while (expired_timers)

        /* Finally, suspend this thread and wait for the next expiration.  */

        /* Determine if another expiration took place while we were in this
           thread.  If so, process another expiration.  */
        #def 如果为0,说明前面链表处理过程中,没有再次发生超时事件,中断处理函数没有设置_tx_timer_expired为true
        #def 自我挂起线程
        if (!_tx_timer_expired)
        {

            /* Otherwise, no timer expiration, so suspend the thread.  */

            /* Set the status to suspending, in order to indicate the
               suspension is in progress.  */
            _tx_thread_current_ptr -> tx_state =  TX_SUSPENDED;

            /* Set the suspending flag. */
            _tx_thread_current_ptr -> tx_suspending =  TX_TRUE;

            /* Increment the preempt disable count prior to suspending.  */
            _tx_thread_preempt_disable++;

            /* Restore interrupts.  */
            TX_RESTORE

            /* Call actual thread suspension routine.  */
            _tx_thread_suspend(_tx_thread_current_ptr);
        }
        else
        {

            /* Restore interrupts.  */
            TX_RESTORE
        }

    }
    while (TX_LOOP_FOREVER);
}

_tx_timer_interrupt

Timer interrupt handler, the following is threadx 3.0 version timer interrupt handler, similar version 4.0, implemented in assembly code

VOID   _tx_timer_interrupt(VOID)
{
    _tx_timer_system_clock++;                                           /*  系统滴答时间加              */
    if (_tx_timer_time_slice) {                                         /*  如果有剩余的时间片          */
		_tx_timer_time_slice--;                                         /*  时间片调整、减一            */
		if (_tx_timer_time_slice == 0) {                                /*  如果当前时间片耗尽          */
			_tx_timer_expired_time_slice =  TX_TRUE;                    /*  设置标识                    */
		}
    }

    if (*_tx_timer_current_ptr) {                                       /*  是否有定时器需要处理        */
        _tx_timer_expired =  TX_TRUE;
    } else {
        _tx_timer_current_ptr++;                                        /*  指向下一时刻定时器就绪链表头*/
        if (_tx_timer_current_ptr == _tx_timer_list_end){
            _tx_timer_current_ptr =  _tx_timer_list_start;
		}
    }

    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) {        /*  有事情要做                  */
		if (_tx_timer_expired) {
		    _tx_timer_expired   = TX_FALSE;
			_tx_thread_preempt_disable++;
	
			_tx_thread_resume(&_tx_timer_thread);                       /*  恢复定时器线程              */
		}
		if (_tx_timer_expired_time_slice) {
    		_tx_timer_expired_time_slice    = TX_FALSE;
			if (_tx_thread_time_slice() == TX_FALSE) {                  /*  不需要切换,载入分配的时间片*/
				_tx_timer_time_slice =  _tx_thread_current_ptr -> tx_time_slice;
			}
		 } 
    }
}
发布了41 篇原创文章 · 获赞 2 · 访问量 3173

Guess you like

Origin blog.csdn.net/qq_45683435/article/details/104237287