嵌入 式 操作 系统 内核 原理 和 开发 ( 实时 系统 中的 定时器 ) 【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 关于 定时器 的内容,其实我们之前也讨论过,也书写过相应的代码,但是表达得比较晦涩,效率也比较低
嵌入式操作系统内核原理和开发(实时系统中的定时器)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
关于定时器的内容,其实我们之前也讨论过,也书写过相应的代码,但是表达得比较晦涩,效率也比较低。所以我们这里重新再讲一下定时器的相关代码,看看嵌入式系统中的定时器是怎么实现的。在我们之前讨论线程延时的时候就使用hash的方法,将不同的线程归类到不同的延时队列当中,并且按照时间长短先后排列,这样在最短的时间内就可以寻找到最合适的线程了。本质上,线程延时和定时器的基本原理是一样的。唯一的区别就是,线程延时响应的优先级要高一些,而定时器一般由独立线程完成,rawos也是这么做的。
void timer_task(void *pa) { RAW_U16 position; LIST *timer_head_ptr; LIST *iter; LIST *iter_temp; RAW_TIMER *timer_ptr; timer_sem.count = 0; while (1) { /*timer task will be blocked after call this function*/ raw_semaphore_get(&timer_sem, RAW_WAIT_FOREVER); /*Disable the system schedule we do not need disable interrupt since nothing to do with interrupt*/ raw_disable_sche(); /*calculate which timer_head*/ raw_timer_count++; position = (RAW_U16)(raw_timer_count & (TIMER_HEAD_NUMBERS - 1) ); timer_head_ptr = &timer_head[position]; iter =timer_head_ptr->next; while (RAW_TRUE) { /*if timer exits*/ if (iter !=timer_head_ptr) { /*Must use iter_temp because iter may be remove later.*/ iter_temp = iter->next; timer_ptr = list_entry(iter, RAW_TIMER, timer_list); /*if timeout*/ if (raw_timer_count == timer_ptr->match) { /*remove form timer list*/ timer_list_remove(timer_ptr); /*if timer is reschedulable*/ if (timer_ptr->reschedule_ticks) { /*Sort by remain time*/ timer_ptr->remain = timer_ptr->reschedule_ticks; timer_ptr->match = raw_timer_count + timer_ptr->remain; position = (RAW_U16)(timer_ptr->match & (TIMER_HEAD_NUMBERS - 1)); timer_ptr->to_head = &timer_head[position]; timer_list_priority_insert(&timer_head[position], timer_ptr); } /*Any way both condition need to call registered timer function*/ if (timer_ptr->raw_timeout_function) { timer_ptr->raw_timeout_function(timer_ptr->raw_timeout_param); } iter = iter_temp; } else { break; } } /*exit because timer is not exit*/ else { break; } } raw_enable_sche(); } }由于基本原理和之前的线程延时是一样的,所以这里就不重复了。定时器的基本操作其实也不多,主要包括定时器创建、启动定时器、修改定时器、关闭定时器、删除定时器共五个基本函数,大家可以和我一起慢慢看过来。
RAW_U16 raw_timer_create(RAW_TIMER *timer_ptr, RAW_U8 *name_ptr, RAW_VOID (*expiration_function)(RAW_U32), RAW_U32 expiration_input, RAW_U32 initial_ticks, RAW_U32 reschedule_ticks, RAW_U8 auto_activate) { #if (RAW_TIMER_FUNCTION_CHECK > 0) if (timer_ptr == 0) { return RAW_NULL_OBJECT; } if (expiration_function == 0) { return RAW_NULL_POINTER; } #endif timer_ptr->name = name_ptr; timer_ptr->raw_timeout_function = expiration_function; timer_ptr->raw_timeout_param = expiration_input; timer_ptr->init_count = initial_ticks; timer_ptr->reschedule_ticks = reschedule_ticks; timer_ptr->remain = 0; timer_ptr->match = 0; timer_ptr->timer_state = TIMER_DEACTIVE; timer_ptr->to_head = 0; list_init(&timer_ptr->timer_list); if (auto_activate) { raw_timer_activate(timer_ptr); } return RAW_SUCCESS; }创建定时器的操作很简单,主要是把输入的参数存入到RAW_TIMER结构里面。相关的参数包括名称、函数指针、函数参数、初始tick、循环tick、标志参数。当然,由于定时器分为单次定时和循环定时两种,所以这里会有两个参数,如果不是循环定时器,循环tick参数可以不用配置。
RAW_U16 raw_timer_activate(RAW_TIMER *timer_ptr) { RAW_U16 position; RAW_SR_ALLOC(); #if (RAW_TIMER_FUNCTION_CHECK > 0) if (timer_ptr == 0) { return RAW_NULL_OBJECT; } #endif /*Timer state TIMER_ACTIVE TIMER_DELETED is not allowed to delete*/ if (timer_ptr->timer_state == TIMER_ACTIVE) return RAW_TIMER_STATE_INVALID; if (timer_ptr->timer_state == TIMER_DELETED) return RAW_TIMER_STATE_INVALID; RAW_CRITICAL_ENTER(); timer_ptr->match = raw_timer_count + timer_ptr->init_count; position = (RAW_U16)(timer_ptr->match & (TIMER_HEAD_NUMBERS - 1) ); /*Sort by remain time*/ timer_ptr->remain = timer_ptr->init_count; /*Used by timer delete*/ timer_ptr->to_head = &timer_head[position]; timer_list_priority_insert(&timer_head[position], timer_ptr); timer_ptr->timer_state = TIMER_ACTIVE; RAW_CRITICAL_EXIT(); return RAW_SUCCESS; }启动定时器,就是把tick加入到定时器队列当中,看看timer_list_priority_insert这个函数你就明白了。因为整个函数的处理过程涉及到 全局变量timer_head,所以需要在前后面添加中断的处理动作。
RAW_U16 raw_timer_change(RAW_TIMER *timer_ptr, RAW_U32 initial_ticks, RAW_U32 reschedule_ticks) { RAW_SR_ALLOC(); #if (RAW_TIMER_FUNCTION_CHECK > 0) if (timer_ptr == 0) { return RAW_NULL_OBJECT; } #endif /*Only timer state TIMER_DEACTIVE is not allowed here*/ if (timer_ptr->timer_state != TIMER_DEACTIVE) { return RAW_TIMER_STATE_INVALID; } if (timer_ptr->timer_state == TIMER_DELETED) { return RAW_TIMER_STATE_INVALID; } RAW_CRITICAL_ENTER(); timer_ptr->init_count = initial_ticks; timer_ptr->reschedule_ticks = reschedule_ticks; RAW_CRITICAL_EXIT(); return RAW_SUCCESS; }定时器修改函数就是把初始tick和循环tick修改一下,当然如果此时定时器还没有运行,初始tick还有用。但是一旦定时器起作用了,起作用的就只能是循环tick了,这一点大家要好好注意。
RAW_U16 raw_timer_deactivate(RAW_TIMER *timer_ptr) { RAW_SR_ALLOC(); #if (RAW_TIMER_FUNCTION_CHECK > 0) if (timer_ptr == 0) { return RAW_NULL_OBJECT; } #endif /*Timer state TIMER_DEACTIVE TIMER_DELETED is not allowed to delete*/ if (timer_ptr->timer_state == TIMER_DEACTIVE) { return RAW_TIMER_STATE_INVALID; } if (timer_ptr->timer_state == TIMER_DELETED) { return RAW_TIMER_STATE_INVALID; } RAW_CRITICAL_ENTER(); timer_list_remove(timer_ptr); timer_ptr->timer_state = TIMER_DEACTIVE; RAW_CRITICAL_EXIT(); return RAW_SUCCESS; }
停止定时器,顾名思义就是将定时器从队列中删除,同时设置状态为TIMER_DEACTIVE。当然在进行操作之前需要判断一下当前定时器的属性,如果定时器本身已经删除或者停止,那什么也不用做了。
RAW_U16 raw_timer_delete(RAW_TIMER *timer_ptr) { RAW_SR_ALLOC(); #if (RAW_TIMER_FUNCTION_CHECK > 0) if (timer_ptr == 0) { return RAW_NULL_OBJECT; } #endif if (timer_ptr->timer_state == TIMER_DELETED) { return RAW_TIMER_STATE_INVALID; } RAW_CRITICAL_ENTER(); timer_list_remove(timer_ptr); timer_ptr->timer_state = TIMER_DELETED; RAW_CRITICAL_EXIT(); return RAW_SUCCESS; }定时器的删除函数和定时器的停止函数是一样的,主要是判断逻辑不一样的。删除定时器,只要定时器的状态不是已经删除就可以了,其他的操作都是一样的。