【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱: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;
}
定时器的删除函数和定时器的停止函数是一样的,主要是判断逻辑不一样的。删除定时器,只要定时器的状态不是已经删除就可以了,其他的操作都是一样的。