“System Timer Thread” 系统定时器线程用于判断定时器超时,并调用定时器超时处理函数。
_tx_timer_initialize
先来看看定时器线程创建初始化。_tx_timer_initialize初始化系统一系列与时间,定时器相关全局变量,链表,线程等。
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为定时器线程处理函数,主要工作:
1,获取_tx_timer_current_ptr指向的链表,检查链表中所有定时器
2,如果定时器超时,就调用超时处理函数进行处理
3,如果定时器需要重启,重新设置定时器值,插入数组链表
4,如果定时器没有超时,重新设置定时器值,插入数组链表
5,_tx_timer_current_ptr加1,执行下一个节拍的链表
系统定时器线程默认是挂起的,如果唤醒的呢?
定时器时钟中断到来,在定时器中断处理函数中,检查 _tx_timer_current_ptr不为空,也就是_tx_timer_list[n]链表不为空,那么说明有定时器在当前节拍的激活链表中需要进行处理,所以在定时器中断处理函数中唤醒了系统定时器线程。
如果_tx_timer_current_ptr为空,不需要唤醒系统定时器中断,只需_tx_timer_current_ptr加1,指向下一个链表,等待下一次定时器中断。
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
定时器中断处理函数,下面是threadx 3.0版本定时器中断处理函数, 4.0版本类似,用汇编代码实现
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;
}
}
}
}