Threadx定时器timer
⽂章⽬录
Threadx 操作系统定时器提供单次定时和周期性定时功能。定时器由周期性定时中断驱动,每⼀个定时中断称为⼀个时钟节拍(tick)。时钟节拍值由系统平台决定,⽐如5ms⼀个时钟节拍,需要综合硬件条件和应⽤需求,系统性能决定。
定时时间长度⽤时钟节拍个数衡量,⽐如时钟节拍为5ms,应⽤程序设置定时时间为1.5s,那么1.5s/5ms=300,调⽤_tx_timer_create 创建定时器时,定时器值设置为300。
定时器管理结构
TX_TIMER为定时器管理结构,包含了TX_INTERNAL_TIMER公共结构。
/* Define the basic timer management structures.  These are the structures
used to manage thread sleep, timeout, and user timer requests.  */
/* Define the common internal timer control block.  */
typedef struct TX_INTERNAL_TIMER_STRUCT
{
/* Define the remaining ticks and re-initialization tick value.  */
ULONG      tx_remaining_ticks;
ULONG      tx_re_initialize_ticks;
/* Need to define remaining ticks, type, next and previous pointers, etc.  */
VOID (*tx_timeout_function)(ULONG);
ULONG      tx_timeout_param;
/* Define the next and previous internal link pointers for active
internal timers.  */
struct TX_INTERNAL_TIMER_STRUCT
*tx_active_next,
*tx_active_previous;
/* Keep track of the pointer to the head of this list as well.  */
struct TX_INTERNAL_TIMER_STRUCT
**tx_list_head;
ULONG      os_timer_type;
timeout on t2 timer
} TX_INTERNAL_TIMER;
域意义
tx_remaining_ticks定时剩余的节拍数
tx_re_initialize_ticks周期性定时器节拍数
tx_timeout_function定时超时处理函数
tx_timeout_param定时超时函数参数
tx_active_next指向下⼀个TX_INTERNAL_TIMER指针
tx_active_previous指向前⼀个TX_INTERNAL_TIMER指针
tx_list_head指向TX_INTERNAL_TIMER头部指针的指针
os_timer_type定时器类型
/* Define the timer structure utilized by the application.  */
typedef struct TX_TIMER_STRUCT
{
/* Define the timer ID used for error checking.  */
ULONG      tx_timer_id;
/* Define the timer's name.  */
CHAR_PTR    tx_timer_name;
/* Define the expiration routine, parameter, initial expiration, and
reschedule expiration.  */
/* Define the actual contents of the timer.  This is the block that
is used in the actual timer expiration processing.  */
TX_INTERNAL_TIMER  tx_timer_internal;
/* Define the pointers for the created list.  */
struct TX_TIMER_STRUCT
*tx_timer_created_next,
*tx_timer_created_previous;
} TX_TIMER;
域意义
tx_timer_id定时器id
tx_timer_name定时器名字指针
tx_timer_internal定时器内部公共管理结构
tx_timer_created_next指向下⼀个定时器指针
tx_timer_created_previous指向前⼀个定时器指针
tx_timer_created_next,tx_timer_created_previous和tx_timer_created_next,tx_timer_created_previous不同,指向管理结构不同。tx_timer_created_next,tx_timer_created_previous⽤于指向系统定时器结
构,tx_timer_created_next,tx_timer_created_previous⽤于定时器激活链表中指向内部结构TX_INTERNAL_TIMER 。
后⾯再详解。
定时器链表
定时器_tx_timer_created_ptr⽤来记录系统中所有创建的定时器,管理结构是TX_TIMER。不论定时器是否激活,只要创建后就插⼊这个链表。
定时器激活链表
threadx 定义了_tx_timer_list[TX_TIMER_ENTRIES]定时器激活链表数组,数组元素是指向TX_INTERNAL_TIMER 指针,也就是指向激活链表的头指针。_tx_timer_list数组有32个元素
#define TX_TIMER_ENTRIES 32
/* Define the thread and application timer entry list.  This list provides a direct access
method for insertion of times less than TX_TIMER_ENTRIES.  */
TIMER_DECLARE TX_INTERNAL_TIMER *_tx_timer_list[TX_TIMER_ENTRIES];
/* Define the boundary pointers to the list.  These are setup to easily manage
wrapping the list.  */
TIMER_DECLARE TX_INTERNAL_TIMER **_tx_timer_list_start;
TIMER_DECLARE TX_INTERNAL_TIMER **_tx_timer_list_end;
/* Define the current timer pointer in the list.  This pointer is moved sequentially
through the timer list by the timer interrupt handler.  */
TIMER_DECLARE TX_INTERNAL_TIMER **_tx_timer_current_ptr;
tx_timer_created_next,tx_timer_created_previous⽤于定时器激活链表中指向内部结构TX_INTERNAL_TIMER
tx_list_head都执⾏链表中第⼀个TX_INTERNAL_TIMER 的指针的指针。
定时器⼯作原理
1,创建优先级为0定时器线程。
2,所有激活的定时器挂载到定时器激活链表中
3,定时器时钟中断,中断处理函数中唤醒定时器线程
4,定时器线程中检查链表中定时器是否超时,如果超时就回调超时处理函数。处理完后挂起定时器线程,等待下⼀次中断。
定时器线程创建
在 系统初始化时,_tx_timer_initialize定时器初始函数中创建系统定时器线程,处理函数为_tx_timer_thread_entry。
线程优先级为0,最⾼优先级,保证定时事件能够最快的响应处理。
#define TX_TIMER_THREAD_PRIORITY    0      /* Default timer thread priority    */
_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);
定时器激活链表维护
定时器激活链表_tx_timer_list有32个元素,从0-31,每个元素指向⼀个链表,同时也表⽰节拍计数。
0代表节拍0,1代表节拍1,。。31代表节拍31,_tx_timer_list[0]代表节拍0, _tx_timer_list[0]代表节拍31。
_tx_timer_current_ptr全局指针初始化时指向_tx_timer_list[0], 每⼀个时钟中断到来,_tx_timer_current_ptr加1,如果到了31,就从0开始,再次指向_tx_timer_list[0]。中断处理函数会判断*_tx_timer_current_ptr是否为空,也就是对应链表是否⽤激活定时器,如果不为空,就唤醒定时器线程进⾏处理。
定时器线程,获取*_tx_timer_current_ptr链表中激活定期器,判断激活定时剩余时间是否为0.如果为0,说明超时,调⽤超时处理函数处理。如果激活定时剩余时间不为0,再次插⼊tx_timer_list 激活链表中。
如果是周期性定时器,定时器超时处理后,要再次把定时器插⼊激活链表中。
TX_INTERNAL_TIMER *_tx_timer_list[TX_TIMER_ENTRIES];
/* Define the current timer pointer in the list.  This pointer is moved sequentially
through the timer list by the timer interrupt handler.  */
TX_INTERNAL_TIMER **_tx_timer_current_ptr;
定时器激活链表插⼊
定时器激活时,或周期性定时器超时后,需要把定时器TX_INTERNAL_TIMER 再次插⼊激活链表。
插⼊_tx_timer_list[TX_TIMER_ENTRIES]中哪⼀个链表呢?
⾸先tx_remaining_ticks剩余节拍是否⼤于32,如果tx_remaining_ticks⼤于32就从当前节拍开始到32个节拍中最后⼀个,也就是(_tx_timer_current_ptr+32)%32 对应的链表:_tx_timer_list[(_tx_timer_current_ptr+32)%32];如果tx_remaining_ticks⼩于32,就选择(_tx_timer_current_ptr+tx_remaining_ticks)%32对应的链表:
_tx_timer_list[(_tx_timer_current_ptr+tx_remaining_ticks)%32]。
也就是⼤于32时直接从当前开始到最后⼀个(加32)个链表,因为⾄少需要32个节拍,定时器也不会超时,所以放到最后⼀个,在每个时钟中断到来时判断*_tx_timer_current_ptr为空时,不⽤唤醒定时器线程,减少了线程切换开销。
总之使⽤数组+链表⽅式,为了减少系统开销。只有当前节拍对应数组链表不为空时,才唤醒线程。
当前节拍下对应数组链表不为空时,线程被唤醒处理,但并不代表定时已经超时,tx_remaining_ticks不⼀定为0,⾄少过了32个节拍周期,需要重新把定时器重新计算合适位置插⼊链表。如何设计能够减少这种⽆效唤醒呢?
激活链表按照先进先出FIFO原则处理,并没有优先级属性。
定时器API
函数描述
tx_timer_create创建定时器
函数描述
tx_timer_delete删除定时器
tx_timer_activate激活定时器
tx_timer_deactivate去激活定时器
tx_timer_change修改定时器定时值
tx_timer_info_get获取定时信息
定时器创建_tx_timer_create
参数意义
timer_ptr指向创建定时器的指针
name_ptr指向定时器名字字符串指针
expiration_function定时器超时处理函数
expiration_input定时器超时处理函数参数
initial_ticks定时器第⼀次定时值
reschedule_ticks定时器重启定时值
auto_activate定时器⾃动激活标志
定时器超时后会回调函数expiration_function;
激活定时器后第⼀次超时时间为initial_ticks,如果reschedule_ticks不为0,使⽤reschedule_ticks作为定时器值重新激活定时器,后续⼀直使⽤reschedule_ticks作为定时器值。
auto_activate为true时表⽰创建定时器并激活定时器,否则需要单独调⽤tx_timer_activate激活定时器。
把定时器timer_ptr插⼊_tx_timer_created_ptr链表
UINT    _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr,
VOID (*expiration_function)(ULONG), ULONG expiration_input,
ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate)
{
TX_INTERRUPT_SAVE_AREA
TX_TIMER        *tail_ptr;/* Working timer pointer      */
/* Setup the basic timer fields.  */
#def 保持初始化值
timer_ptr -> tx_timer_name =                            name_ptr;
timer_ptr -> tx__remaining_ticks =    initial_ticks;
timer_ptr -> tx__re_initialize_ticks = reschedule_ticks;
timer_ptr -> tx__timeout_function =    expiration_function;
timer_ptr -> tx__timeout_param =      expiration_input;
timer_ptr -> tx__list_head =          TX_NULL;
timer_ptr -> tx_timer_internal.os_timer_type = OS_TIMER_TYPE_REL;
/* Disable interrupts to put the timer on the created list.  */
#def 禁⽌中断,禁⽌中断后,下⾯代码不会被中断或其它线程打断。处理全局变量
TX_DISABLE
/* Setup the timer ID to make it valid.  */
timer_ptr -> tx_timer_id =  TX_TIMER_ID;
/* Place the timer on the list of created application timers.  First,
check for an empty list.  */
#def 定时器插⼊_tx_timer_created_ptr列表

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。