ISIX-RTOS - small operating system for ARM microcontrollers 1.2
|
00001 /* 00002 * irqtimers.c 00003 * 00004 * Created on: 05-03-2011 00005 * Author: lucck 00006 */ 00007 /*-----------------------------------------------------------------------*/ 00008 #include <prv/irqtimers.h> 00009 #include <isix/irqtimers.h> 00010 #include <isix/memory.h> 00011 #include <prv/list.h> 00012 #include <prv/scheduler.h> 00013 #include <string.h> 00014 00015 /*-----------------------------------------------------------------------*/ 00016 #ifdef ISIX_CONFIG_USE_TIMERS //If timers are enabled 00017 /*-----------------------------------------------------------------------*/ 00018 //List entry for the virtual timers 00019 static list_entry_t vtimer_list[2]; 00020 //Overflowed and not overflowed list 00021 static list_entry_t *p_vtimer_list; 00022 static list_entry_t *pov_vtimer_list; 00023 /*-----------------------------------------------------------------------*/ 00024 //Initialize vtimers infrastructure 00025 void isixp_vtimer_init(void) 00026 { 00027 list_init( &vtimer_list[0] ); 00028 list_init( &vtimer_list[1] ); 00029 //Initialize overflow waiting list 00030 p_vtimer_list = &vtimer_list[0]; 00031 pov_vtimer_list = &vtimer_list[1]; 00032 } 00033 00034 /*-----------------------------------------------------------------------*/ 00035 //Move selected task to waiting list 00036 static void add_vtimer_to_list(vtimer_t *timer) 00037 { 00038 //Scheduler lock 00039 isixp_enter_critical(); 00040 timer->jiffies = isix_get_jiffies() + timer->timeout; 00041 if(timer->jiffies < isix_get_jiffies()) 00042 { 00043 //Insert on overflow waiting list in time order 00044 vtimer_t *waitl; 00045 list_for_each_entry(pov_vtimer_list,waitl,inode) 00046 { 00047 if(timer->jiffies<waitl->jiffies) break; 00048 } 00049 list_insert_before(&waitl->inode,&timer->inode); 00050 } 00051 else 00052 { 00053 //Insert on waiting list in time order no overflow 00054 vtimer_t *waitl; 00055 list_for_each_entry(p_vtimer_list,waitl,inode) 00056 { 00057 if(timer->jiffies<waitl->jiffies) break; 00058 } 00059 list_insert_before(&waitl->inode,&timer->inode); 00060 } 00061 //Scheduler unlock 00062 isixp_exit_critical(); 00063 } 00064 00065 /*-----------------------------------------------------------------------*/ 00066 //Call timer funcs in the interrupt context 00067 void isixp_vtimer_handle_time(tick_t jiffies) 00068 { 00069 if(jiffies == 0) 00070 { 00071 list_entry_t *tmp = p_vtimer_list; 00072 p_vtimer_list = pov_vtimer_list; 00073 pov_vtimer_list = tmp; 00074 } 00075 vtimer_t *vtimer; 00076 while( !list_isempty(p_vtimer_list) && 00077 jiffies>=(vtimer = list_get_first(p_vtimer_list,inode,vtimer_t))->jiffies 00078 ) 00079 { 00080 vtimer->timer_handler( vtimer->arg ); 00081 list_delete(&vtimer->inode); 00082 add_vtimer_to_list(vtimer); 00083 } 00084 } 00085 00086 /*-----------------------------------------------------------------------*/ 00087 //Create the virtual timer 00088 vtimer_t* isix_vtimer_create(void (*func)(void*),void *arg ) 00089 { 00090 vtimer_t * const timer = (vtimer_t*)isix_alloc(sizeof(vtimer_t)); 00091 if( func == NULL ) return NULL; 00092 if( timer == NULL ) return NULL; 00093 memset( timer, 0, sizeof(*timer) ); 00094 timer->arg = arg; 00095 timer->timer_handler = func; 00096 return timer; 00097 } 00098 00099 /*-----------------------------------------------------------------------*/ 00100 //Start the virtual timer 00101 int isix_vtimer_start(vtimer_t* timer, tick_t timeout) 00102 { 00103 if( timer == NULL ) return ISIX_EINVARG; 00104 isixp_enter_critical(); 00105 //Search on ov list 00106 if( list_is_elem_assigned( &timer->inode ) ) 00107 { 00108 list_delete( &timer->inode ); 00109 } 00110 //Add timer to waiting list 00111 if( timeout > 0 ) 00112 { 00113 timer->timeout = timeout; 00114 add_vtimer_to_list( timer ); 00115 } 00116 isixp_exit_critical(); 00117 return ISIX_EOK; 00118 } 00119 00120 /*-----------------------------------------------------------------------*/ 00121 //Destroy the virtual timer 00122 int isix_vtimer_destroy(vtimer_t* timer) 00123 { 00124 if( timer == NULL ) return ISIX_EINVARG; 00125 isixp_enter_critical(); 00126 if( list_is_elem_assigned( &timer->inode ) ) 00127 { 00128 isixp_exit_critical(); 00129 return ISIX_EBUSY; 00130 } 00131 isix_free( timer ); 00132 isixp_exit_critical(); 00133 return ISIX_EOK; 00134 } 00135 /*-----------------------------------------------------------------------*/ 00136 00137 00138 #endif /* ISIX_CONFIG_USE_TIMERS */ 00139