嵌入式操作系统内核原理和开发(实时系统中的定时器)


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




评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式-老费

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值