⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sos_timer.c

📁 嵌入式操作系统内核
💻 C
📖 第 1 页 / 共 2 页
字号:
   do{	       if ((tt->pid == pid) &&          (tt->tid == tid))		{		  list_remove((list_t*)tt);		  return tt;		}	  tt = (sos_timer_t*)tt->list.l_next;   } while ((list_t*)tt != &timer_pool);      return NULL;}/** * @brief Remove a timer from the deltaq */static int8_t timer_remove_timer(sos_timer_t *tt){		if((tt->list.l_next == NULL) ||	   (tt->list.l_prev == NULL)) {		return -EINVAL;	}	// if I am not the tail... and I have positive delta	if((tt->list.l_next != &deltaq) && (tt->delta > 0 )) {		((sos_timer_t*)(tt->list.l_next))->delta += tt->delta;	}	list_remove((list_t*)tt);    return SOS_OK;}/** * @brief update delta queue * traverse each item in the queue until no more delta left * NOTE: this is executed in interrupt handler, so NO lock necessary */static void timer_update_delta(void){	list_link_t *link;	int32_t delta;	HAS_CRITICAL_SECTION;		ENTER_CRITICAL_SECTION();	delta = outstanding_ticks;	outstanding_ticks = 0;	LEAVE_CRITICAL_SECTION();		if(list_empty(&deltaq) == true) {		return;	}	DEBUG("update delta = %d\n", delta);	for(link = deltaq.l_next;			link != (&deltaq); link = link->l_next) {		sos_timer_t *h = (sos_timer_t*)link;         		if(h->delta >= delta) {			// if we use all ticks...			h->delta -= delta;			return;		} else {			int32_t tmp = h->delta;			h->delta -= delta;			delta -= tmp;		}	}}/** * @brief Post the timeout messages *///------------------------------------------------------------------------// TIMER API//------------------------------------------------------------------------//! Assumption - This function is never called from an interrupt contextint8_t ker_timer_init(sos_pid_t pid, uint8_t tid, uint8_t type){  sos_timer_t* tt;  tt = find_timer_in_periodic_pool(pid, tid);  if (tt != NULL) {      tt->type = type;	  list_insert_tail(&timer_pool, (list_link_t*)tt);	  return SOS_OK;  }  //! re-initialize an existing timer by stoping it and updating the type  tt = find_timer_block(pid, tid);  if (tt != NULL){      ker_timer_stop(pid,tid);      tt->type = type;      return SOS_OK;  }    //! Search if pre-initialized timer exists  tt = alloc_from_timer_pool(pid, tid);    //! Look for pre-allocated timers or try to get dynamic memory  if (tt == NULL){	tt = alloc_from_preallocated_timer_pool(pid);	if (tt == NULL)	  tt = (sos_timer_t*)malloc_longterm(sizeof(sos_timer_t), TIMER_PID);	//! Init will fail if the system does not have sufficient resources	if (tt == NULL)	  return -ENOMEM;  }    //! Fill up the data structure and insert into the timer pool  tt->pid = pid;  tt->tid = tid;  tt->type = type;    list_insert_tail(&timer_pool, (list_link_t*)tt);  return SOS_OK;}int8_t ker_permanent_timer_init(sos_timer_t* tt, sos_pid_t pid, uint8_t tid, uint8_t type){   //! Fill up the data structures and insert into the timer pool   tt->pid = pid;   tt->tid = tid;   tt->type = type;   list_insert_tail(&timer_pool, (list_link_t*)tt);   return SOS_OK; }int8_t ker_timer_start(sos_pid_t pid, uint8_t tid, int32_t interval){  sos_timer_t* tt;  //! Start the timer from the timer pool  tt = alloc_from_timer_pool(pid, tid);    //! If the timer does not exist, then it is already in use or not initialized  if (tt == NULL) {	DEBUG_PID(TIMER_PID, "ker_timer_start: tt == NULL\n");	return -EINVAL;  }    //  tt->ticks = PROCESSOR_TICKS(interval);  tt->ticks = interval;  tt->delta = interval;    //DEBUG("timer_start(%d) %d %d %d\n", tt->pid, tt->tid, tt->type, tt->ticks);    //! insert into delta queue  print_all_timers("timer_start_start");  timer_delta_q_insert(tt, true);  print_all_timers("timer_start_end");  ker_log( SOS_LOG_TIMER_START, pid, tid );  return SOS_OK;}//! The implementation of this call can be optimized to include the find with//! the remove. We will do it laterint8_t ker_timer_stop(sos_pid_t pid, uint8_t tid){  sos_timer_t* tt;  tt = find_timer_in_periodic_pool(pid, tid);  if( tt == NULL ) {	  //! Find the timer block	  tt = find_timer_block(pid, tid);	  if (tt == NULL) {		  return -EINVAL;	  } else {		  //! Remove the timer from the deltaq and any pending messages in the queue		  timer_remove_timer(tt);	  }  }  //timer_remove_timeout_from_scheduler(tt);  //! Re-insert timer into the pool  list_insert_tail(&timer_pool, (list_link_t*)tt);  ker_log( SOS_LOG_TIMER_STOP, pid, tid );  return SOS_OK;}//! Free the first timer block beloning to pid in the timer_poolint8_t ker_timer_release(sos_pid_t pid, uint8_t tid){  sos_timer_t* tt;  //! First stop the timer if it is running  ker_timer_stop(pid, tid);  //! Get the timer block from the pool  tt = alloc_from_timer_pool(pid, tid);    if (tt == NULL) 	return -EINVAL;  //! Deep free of the timer  ker_free(tt);     return SOS_OK;   }int8_t ker_timer_restart(sos_pid_t pid, uint8_t tid, int32_t interval){  sos_timer_t* tt;    tt = find_timer_in_periodic_pool(pid, tid);  if (tt == NULL) {	  //! Locate a running timer or from the timer pool	  tt = find_timer_block(pid, tid);	  if (tt != NULL){		  timer_remove_timer(tt);		  //timer_remove_timeout_from_scheduler(tt);	  }	  else {		  tt = alloc_from_timer_pool(pid, tid);	  }  }      //! The timer is neither running nor initialized  if (tt == NULL)	return -EINVAL;  /* Special Case restart with existing ticks field */  if( interval <= 0 )      interval = tt->ticks;  if(interval < TIMER_MIN_INTERVAL){      /* Need to put the timer back in to the pool          as an initialized timer that was never started */      list_insert_tail(&timer_pool, (list_link_t*)tt);      return -EPERM;  }  //! Initialize the data structure  tt->ticks = interval;  //  tt->ticks = PROCESSOR_TICKS(interval);  tt->delta = interval;  //! Insert into the delta queue  timer_delta_q_insert(tt, true);  ker_log( SOS_LOG_TIMER_RESTART, pid, tid );  return SOS_OK;}int8_t ker_sys_timer_start(uint8_t tid, int32_t interval, uint8_t type){                                                             	sos_pid_t my_id = ker_get_current_pid();                  	if( (ker_timer_init(my_id, tid, type) != SOS_OK) ||       			(ker_timer_start(my_id, tid, interval) != SOS_OK)) {  		return ker_mod_panic(my_id);                                 	}                                                         	return SOS_OK;                                            }                                                             int8_t ker_sys_timer_restart(uint8_t tid, int32_t interval)       {                                                             	sos_pid_t my_id = ker_get_current_pid();                  	if( ker_timer_restart(my_id, tid, interval) != SOS_OK ) { 		return ker_mod_panic(my_id);                                 	}                                                         	return SOS_OK;                                            }                                                             int8_t ker_sys_timer_stop(uint8_t tid)              {                                                             	sos_pid_t my_id = ker_get_current_pid();                  	if( (ker_timer_stop(my_id, tid) != SOS_OK) ||             			(ker_timer_release(my_id, tid) != SOS_OK) ) {         		return ker_mod_panic(my_id);                                 	}                                                         	return SOS_OK;                                            }                   	// called from schedulerstatic void soft_interrupt( void ){	HAS_CRITICAL_SECTION;	timer_update_delta();	while(list_empty(&deltaq) == false) {		sos_timer_t *h = (sos_timer_t*)(deltaq.l_next);         		if(h->delta <= 0) {			sos_pid_t pid = h->pid;			uint8_t tid = h->tid;			uint8_t flag;			list_remove_head(&deltaq);			if(((h->type) & SLOW_TIMER_MASK) == 0){				flag = SOS_MSG_HIGH_PRIORITY;			} else {				flag = 0;			}			if (((h->type) & ONE_SHOT_TIMER_MASK) == 0){				//! periocic timer				while(h->delta <= 0) {					// make sure it is positive					h->delta += h->ticks;				}				list_insert_tail(&periodic_pool, (list_t*) h);			} else {				list_insert_tail(&timer_pool, (list_link_t*)h);			}			sched_dispatch_short_message(pid, TIMER_PID,					MSG_TIMER_TIMEOUT, 					tid, 0,					flag);		} else {			break;		}	}	while(list_empty(&periodic_pool) == false) {		list_link_t *link = periodic_pool.l_next;		list_remove_head(&periodic_pool);		timer_delta_q_insert((sos_timer_t*)link, false);	}	if(list_empty(&deltaq) == false) {		sos_timer_t *h = (sos_timer_t*)(deltaq.l_next);		int32_t hw_cnt;		ENTER_CRITICAL_SECTION();		hw_cnt = outstanding_ticks - timer_hardware_get_counter();		if( h->delta - hw_cnt > 0) {			LEAVE_CRITICAL_SECTION();			timer_set_hw_top(h->delta - hw_cnt, true);			} else {			LEAVE_CRITICAL_SECTION();			sched_add_interrupt(SCHED_TIMER_INT, soft_interrupt);		}	} else {		ENTER_CRITICAL_SECTION();		timer_set_hw_top(MAX_SLEEP_INTERVAL, false);		LEAVE_CRITICAL_SECTION();	}}static void timer_realtime_set_hw_top(uint16_t value){	// compute the time it takes to have next interrupt	if(list_empty(&deltaq) == true) {		timer_set_hw_top(value, false);	} else {		uint8_t hw_interval = timer_getInterval();		uint8_t hw_cnt = timer_hardware_get_counter();		if( (hw_interval - hw_cnt) >= value ) {			if(list_empty(&deltaq) == true) {				timer_set_hw_top(value, false);			} else {				timer_set_hw_top(value, true);			}		}	}}int8_t timer_realtime_start(uint16_t value, uint16_t interval, timer_callback_t f){	uint8_t i;	HAS_CRITICAL_SECTION;	ENTER_CRITICAL_SECTION();	if( num_realtime_clock == MAX_REALTIME_CLOCK ) {		LEAVE_CRITICAL_SECTION();		return -ENOMEM;	}	for( i = 0; i < MAX_REALTIME_CLOCK; i++ ) {		if( realtime[i].f == NULL ) {			timer_realtime_set_hw_top(value);			num_realtime_clock++;			realtime[i].value = value;			realtime[i].interval = interval;			realtime[i].f = f;			LEAVE_CRITICAL_SECTION();			return SOS_OK;		}	}		LEAVE_CRITICAL_SECTION();	return -ENOMEM;}int8_t timer_realtime_stop(timer_callback_t f){	uint8_t i;	HAS_CRITICAL_SECTION;	ENTER_CRITICAL_SECTION();	for( i = 0; i < MAX_REALTIME_CLOCK; i++ ) {		if( realtime[i].f == f ) {			realtime[i].f = NULL;			num_realtime_clock--;			LEAVE_CRITICAL_SECTION();			return SOS_OK;		}	}	LEAVE_CRITICAL_SECTION();	return -EINVAL;}static uint16_t timer_update_realtime_clock(uint8_t cnt){	uint8_t i;	uint16_t min_cnt = 65535;	timer_callback_t f[MAX_REALTIME_CLOCK];	// iterate through all realtime clock	for( i = 0; i < MAX_REALTIME_CLOCK; i++ ) {		f[i] = NULL;		if( realtime[i].f != NULL ) {			if( realtime[i].value <= cnt ) {				f[i] = realtime[i].f;				if( realtime[i].interval != 0 ) {					realtime[i].value += (realtime[i].interval - cnt);				} else {					realtime[i].f = NULL;					num_realtime_clock--;					continue;				}			} else {				realtime[i].value -= cnt;			}			if( realtime[i].value < min_cnt ) {                 				min_cnt = realtime[i].value;                    			}		}	}	for( i = 0; i < MAX_REALTIME_CLOCK; i++ ) {		if( f[i] != NULL ) {			(f[i])();		}	}	return min_cnt;}timer_interrupt(){	uint8_t cnt = timer_getInterval();	outstanding_ticks += cnt;	sched_add_interrupt(SCHED_TIMER_INT, soft_interrupt);	if( num_realtime_clock > 0 ) {		timer_set_hw_interval(	timer_update_realtime_clock(cnt) );	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -