【ThreadX】ThreadX源码阅读计划(二)

上一篇点这里

【ThreadX】ThreadX源码阅读计划(一)

上一篇开了个头,简单解读了调度器和线程管理相关的源码

这一篇开始解读各个组件 😃

ThreadX定时器

定时器分为系统内部定时器TX_TIMER_INTERNAL和系统定时器TX_TIMER
真正起作用的结构体是TX_TIMER_INTERNAL
在Systick中断里面,ThreadX会处理定时器相关的操作,如果去看tx_timer_interrupt.S,里面写了很多个汇编函数,似乎是处理定时器相关的操作的,需要重点关注~~ 😃

系统内部定时器结构体TX_TIMER_INTERNAL

在这里插入图片描述

typedef struct TX_TIMER_INTERNAL_STRUCT
{

    /* 定义剩下的Tick值和重新初始化的Tick值 */
    ULONG               tx_timer_internal_remaining_ticks;
    ULONG               tx_timer_internal_re_initialize_ticks;

    /* 定义超时回调函数和超时回调函数指针 Define the timeout function and timeout function parameter.  */
    VOID                (*tx_timer_internal_timeout_function)(ULONG id);
    ULONG               tx_timer_internal_timeout_param;


    /* 定义下一个,上一个定时器指针*/
    struct TX_TIMER_INTERNAL_STRUCT
                        *tx_timer_internal_active_next,
                        *tx_timer_internal_active_previous;

    /* 定义链表头用于追踪
     Keep track of the pointer to the head of this list as well.  */
    struct TX_TIMER_INTERNAL_STRUCT
                        **tx_timer_internal_list_head;

    /* Define optional extension to internal timer control block.  */
    TX_TIMER_INTERNAL_EXTENSION

} TX_TIMER_INTERNAL;

定时器结构体TX_TIMER

在这里插入图片描述

typedef struct TX_TIMER_STRUCT
{
    /* 定时器这个组件的ID  */
    ULONG               tx_timer_id;

    /*定时器的名字  */
    CHAR                *tx_timer_name;

    /* 定时器实际的内核  */
    TX_TIMER_INTERNAL   tx_timer_internal;

    /* 已创建定时器的链表指针  */
    struct TX_TIMER_STRUCT
                        *tx_timer_created_next,
                        *tx_timer_created_previous;

    /* Define optional extension to timer control block.  */
    TX_TIMER_EXTENSION
} TX_TIMER;
定时器相关的重要变量
volatile ULONG _tx_timer_system_clock

定时器中断周期性递增的系统时钟值

UINT _tx_timer_expired_time_slice

时间片失效标志,表明时间片曾经发生过

TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES]

定义线程和定时器的入口

TX_TIMER_INTERNAL **_tx_timer_list_start

定时器链表的开头【二级指针】

TX_TIMER_INTERNAL **_tx_timer_list_end

定时器链表的结尾【二级指针】

TX_TIMER_INTERNAL **_tx_timer_current_ptr

定义当前运行的定时器在定时器链表中的位置,在定时器中断里面顺序移动

UINT _tx_timer_expired

定义定时器失效标志,标记定时器已经失效

TX_TIMER *_tx_timer_created_ptr

定义已创建的定时器的头指针

ULONG _tx_timer_created_count

定义已创建的定时器的个数

TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr

定义已经失效并正在处理的定时器指针

TX_THREAD _tx_timer_thread

定义定时器线程的控制块

VOID *_tx_timer_stack_start

定义定时器线程的栈顶

ULONG _tx_timer_stack_size

定义定时器线程的栈大小

UINT _tx_timer_priority

定义定时器线程的优先级

ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG))- ((UINT) 1)))/(sizeof(ULONG))]

定义定时器的线程用的堆栈

ULONG _tx_timer_time_slice

定义当前时间片的值,如果非0,说明时间片是启动了,否则没有启动

系统定时器功能初始化

_tx_timer_initialize函数,里面主要的功能是初始化定时器功能相关的重要变量和创建系统定时器线程
ThreadX在初始化完毕以后会默认创建一个系统定时器线程System Timer Thread,优先级是0【最高】

VOID  _tx_timer_initialize(VOID)
{

    UINT    status;
    /* Initialize the system clock to 0.  */
    _tx_timer_system_clock =  ((ULONG) 0);

    /* Initialize the time-slice value to 0 to make sure it is disabled.  */
    _tx_timer_time_slice =  ((ULONG) 0);

    /* Clear the expired flags.  */
    _tx_timer_expired_time_slice =  TX_FALSE;
    _tx_timer_expired =             TX_FALSE;

    /* Set the currently expired timer being processed pointer to NULL.  */
    _tx_timer_expired_timer_ptr =  TX_NULL;

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

    /* First, initialize the timer list.  */
    TX_MEMSET(&_tx_timer_list[0], 0, (sizeof(_tx_timer_list)));


    /* Initialize all of the list pointers.  */
    _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.  */
    _tx_timer_list_end =     &_tx_timer_list[TX_TIMER_ENTRIES-((ULONG) 1)];
    _tx_timer_list_end =     TX_TIMER_POINTER_ADD(_tx_timer_list_end, ((ULONG) 1));


    /* Setup the variables associated with the system timer thread's stack and 
       priority.  */
    _tx_timer_stack_start =  (VOID *) &_tx_timer_thread_stack_area[0];
    _tx_timer_stack_size =   ((ULONG) TX_TIMER_THREAD_STACK_SIZE);
    _tx_timer_priority =     ((UINT) TX_TIMER_THREAD_PRIORITY);

    /* 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.  */
    do
    {
      
        /* Create the system timer thread.  */
        status =  _tx_thread_create(&_tx_timer_thread, 
                                    TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT("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);
      
        /* Define timer initialize extension.  */
        TX_TIMER_INITIALIZE_EXTENSION(status)
        
    } while (status != TX_SUCCESS);
        
    /* 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 =  TX_EMPTY;
}

下面重点分析这个线程对应的函数
_tx_timer_thread_entry

VOID  _tx_timer_thread_entry(ULONG timer_thread_input)
{

TX_INTERRUPT_SAVE_AREA

TX_TIMER_INTERNAL           *expired_timers;
TX_TIMER_INTERNAL           *reactivate_timer;
TX_TIMER_INTERNAL           *next_timer;
TX_TIMER_INTERNAL           *previous_timer;
TX_TIMER_INTERNAL           *current_timer;
VOID                        (*timeout_function)(ULONG id);
ULONG                       timeout_param =  ((ULONG) 0);
TX_THREAD                   *thread_ptr;

    /* Make sure the timer input is correct.  This also gets rid of the
       silly compiler warnings.  */
    if (timer_thread_input == TX_TIMER_ID)
    {
    
        /* Yes, valid thread entry, proceed...  */

        /* Now go into an infinite loop to process timer expirations.  */
        while (TX_LOOP_FOREVER)
        {

            /* First, move the current list pointer and clear the timer 
               expired value.  This allows the interrupt handling portion
               to continue looking for timer expirations.  */
            TX_DISABLE

            /* 保存当前定时器指针指向的定时器地址 到失效定时器指针 Save the current timer expiration list pointer.  */
            expired_timers =  *_tx_timer_current_ptr;

            /*
             如果定时器只有一个【当前定时器指针指向的定时器地址!=NULL】,修改链表中的头指针指向的第一个定时器
             Modify the head pointer in the first timer in the list, if there is one!
                */
            if (expired_timers != TX_NULL)
            {
        
                expired_timers -> tx_timer_internal_list_head =  &expired_timers;
            }

            /* 设置当前链表指针指向的定时器地址为空 Set the current list pointer to NULL.  */
            *_tx_timer_current_ptr =  TX_NULL;

            /* 向后移动当前链表指针4*/
             /* Move the current pointer up one timer entry wrap if we get to
               the end of the list.  */
            _tx_timer_current_ptr =  TX_TIMER_POINTER_ADD(_tx_timer_current_ptr, 1);
            //如果头和尾是一样的
            if (_tx_timer_current_ptr == _tx_timer_list_end)
            {
            	//那么当前指针指向头
                _tx_timer_current_ptr =  _tx_timer_list_start;
            }

            /* 清除失效标识 Clear the expired flag.  */
            _tx_timer_expired =  TX_FALSE;

            /* Restore interrupts temporarily.  */
            TX_RESTORE

            /* Disable interrupts again.  */
            TX_DISABLE

            /* 再当前时间片下处理对应定时器的失效
             Next, process the expiration of the associated timers at this
               time slot.  */
            while (expired_timers != TX_NULL)
            {

                /* 移除它,处理失效 Something is on the list.  Remove it and process the expiration.  */
                current_timer =  expired_timers;

                /* 取出下一个有效的定时器 Pickup the next timer.  */
                next_timer =  expired_timers -> tx_timer_internal_active_next;
            
                /* 设置重新启动的定时器为NULL Set the reactivate_timer to NULL.  */
                reactivate_timer =  TX_NULL;

                /* 判断是不是只有这一个定时器 Determine if this is the only timer.  */
                if (current_timer == next_timer)
                {

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

                    /* 设置头指针为NULL,没有要失效的 Set the head pointer to NULL.  */
                    expired_timers =  TX_NULL;
                }
                else
                {

                    /* 并不是唯一的失效定时器 No, not the only expired timer.  */
            
                    /* 从失效定时器链表中移除 Remove this timer from the expired list.  */
                    previous_timer =                                   current_timer -> tx_timer_internal_active_previous;
                    next_timer -> tx_timer_internal_active_previous =  previous_timer;
                    previous_timer -> tx_timer_internal_active_next =  next_timer;

                    /* Modify the next timer's list head to point at the current list head.  */
                    next_timer -> tx_timer_internal_list_head =  &expired_timers;

                    /* Set the list head pointer.  */
                    expired_timers =  next_timer;
                }

                /* 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.  */
                if (current_timer -> tx_timer_internal_remaining_ticks > TX_TIMER_ENTRIES)
                {

                    /* Timer is bigger than the timer entries and must be
                       rescheduled.  */


                    /* 定时器的剩余tick递减*/
                    current_timer -> tx_timer_internal_remaining_ticks =  
                            current_timer -> tx_timer_internal_remaining_ticks - TX_TIMER_ENTRIES;
                
                    /* 设置超时回调函数为NULL,为了跳过失效检查 */
                    timeout_function =  TX_NULL;

                    /* 使计时器看起来在中断启用时仍处于活动状态,这将允许从中断中正确处理计时器停用*/
                    current_timer -> tx_timer_internal_list_head =    &reactivate_timer;
                    current_timer -> tx_timer_internal_active_next =  current_timer;

                    /* 设置临时定时器链表头 */
                    reactivate_timer =  current_timer;
                }
                else
                {

                    /* 定时器失效了 Timer did expire.  */
                    /* 拷贝回调函数和参数到局部变量里,待会要去中断了Copy the calling function and ID into local variables before interrupts
                       are re-enabled.  */
                    timeout_function =  current_timer -> tx_timer_internal_timeout_function;
                    timeout_param =     current_timer -> tx_timer_internal_timeout_param;

                    /* Copy the reinitialize ticks into the remaining ticks.  */
                    current_timer -> tx_timer_internal_remaining_ticks =  current_timer -> tx_timer_internal_re_initialize_ticks;

                    /* 判断定时器是不是要重新激活 Determine if the timer should be reactivated.  */
                    if (current_timer -> tx_timer_internal_remaining_ticks != ((ULONG) 0))
                    {

                    	/* 使计时器看起来在中断启用时仍处于活动状态,这将允许从中断中正确处理计时器停用*/
                        current_timer -> tx_timer_internal_list_head =    &reactivate_timer;
                        current_timer -> tx_timer_internal_active_next =  current_timer;
                        
                        /* Setup the temporary timer list head pointer.  */
                        reactivate_timer =  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_timer_internal_list_head =  TX_NULL;
                    }
                }

                /* 设置已经失效的定时器指针指向当前处理了的定时器 Set pointer to indicate the expired timer that is currently being processed.  */
                _tx_timer_expired_timer_ptr =  current_timer;

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

                /* 调用定时器回调函数 */
                if (timeout_function != TX_NULL)
                {
            
                    (timeout_function) (timeout_param);
                }

                /* Lockout interrupts again.  */
                TX_DISABLE

                /* Clear expired timer pointer.  */
                _tx_timer_expired_timer_ptr =  TX_NULL;

                /* Determine if the timer needs to be reactivated.  */
                if (reactivate_timer == current_timer)
                {

                    /* Reactivate the timer.  */

                    /* Reactivate through the timer activate function.  */

                    /* 清除链表头种子很 Clear the list head for the timer activate call.  */
                    current_timer -> tx_timer_internal_list_head = TX_NULL;

                    /* 激活当前操作的定时器 */
                    _tx_timer_system_activate(current_timer);
                }

                /* Restore interrupts.  */
                TX_RESTORE

                /* Lockout interrupts again.  */
                TX_DISABLE
            }

            /* 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.  */
            if (_tx_timer_expired == TX_FALSE)
            {

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

                /* Build pointer to the timer thread.  */
                thread_ptr =  &_tx_timer_thread;

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


                /* 设置挂起标志 */
                thread_ptr -> tx_thread_suspending =  TX_TRUE;

                /*在挂起之前递增抢占禁止计数 */
                _tx_thread_preempt_disable++;

                /* Restore interrupts.  */
                TX_RESTORE

                /* Call actual thread suspension routine.  */
                _tx_thread_system_suspend(thread_ptr);
            }
            else
            {

                /* Restore interrupts.  */
                TX_RESTORE
            }
        }
    }
}

tx_timer_interrupt.S文件分析

这个汇编函数【_tx_timer_interrupt】会被Sys tick中断函数调用,这个汇编函数会调用其他函数,这个函数用来维护定时器相关的指针和变量。

_tx_timer_interrupt
在这里插入图片描述
__tx_timer_no_time_slice
在这里插入图片描述

__tx_timer_done
在这里插入图片描述

_tx_timer_expiration_process
在这里插入图片描述

_tx_thread_time_slice
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值