dnl (c)INRIA,ROBOSOFT 2000 Tony.NOEL@inria.fr Pierre@robosoft.fr divert(-1) # SynDEx v5 generic executive kernel customization for RTAI/Linux. ifdef(`syndex.m4x_already_included',,`errprint( __file__:__line__: m4: syndex.m4x must be included before __file__! )m4exit(1)')dnl ifdef( __file__`_already_included',`error_(`already included')m4exit(1)', `define(__file__`_already_included')')dnl # ---------------------------------------------------------------------------- # This file defines all TARGET LANGUAGE DEPENDENT macros (prefixed by `basic') # which customize the generic executive macros defined in the syndex.m4x file. # SynDEx generates for each processor one macro-executive file starting with a # `processor_' macro taking as argument the processor type, which is stored in # the `processorType_' macro, and used to include the processorType_.m4x file. # Application specific macros may be conditionned by `processorType_' # to generate different codes for different target processor types; # they may also be conditionned by `lang_' which may be defined # identically by different processorType_.m4x files: define(`lang_',`rtai386') # uncomment this line if you want a trace of macro calls define(`NOTRACEDEF') dnl TN: How to parametrize the stack size of the real-time tasks ??? define(`main_stacksize',`3000') define(`comm_stacksize',`1000') ############################################### # CHANGEMENT POUR ULTRASON ############################################### # Periode de repetition des boucles dnl Loop period in nanoseconds: CyCab loop period is fixed to 70 ms define(`loop_period',`70000000') dnl Tasks counter define(`task_counter', 1) ############ # DIVERTIONS define(`normal', `0') define(`headers', `21') define(`definitions', `22') define(`declarations', `23') define(`comm_functions', `24') define(`main_functions', `25') define(`main_init', `26') define(`main_loop', `27') define(`main_end', `28') define(`task_to_delete', `31') define(`misc', `32') define(`download_handler', `33') ############ # DATA TYPES # -------- # typedef_(name, size) defines a new type with its size in address units: typedef_(`bool', 1) # MUST be defined typedef_(`char', 1) # SHOULD be defined typedef_(`int', 4) # SHOULD be defined typedef_(`float', 4) # SHOULD be defined typedef_(`double',8) # SHOULD be defined ################### # MEMORY ALLOCATION # ----------- # basicAlloc_(label, memoryBank) define(`basicAlloc_', `define(`$1_base_', $1)dnl for `basicCopy_' divert(declarations)$1_type_ $1[$1_size_]; divert(normal)') # ----------- # basicAlias_(newLabel,oldLabel[,offset=0]) define(`basicAlias_', `define(`$1_base_', $2_base_)dnl for `basicCopy_' divert(definitions)`#define' $1 ifelse($3,,`$2',`($2+$3)') divert(normal)') ################## # MEMORY TRANSFERS # ---------- # basicCopy_(destLabel,srceLabel,size) define(`basicCopy_', `ifelse($3,1,`_($1[0] = $2[0];)', `dnl check overlap: _(ifelse($1_base_,$2_base_,memmove,memcpy)($1, $2, $3*sizeof($2_type_));)')') ############### # SYNCHRONIZERS # To synchronize main (priority=1) and communication sequences (priority=0). # ---------------- # semaphores_(...) allocate and initialize the list of named semaphores define(`semaphores_',`divert(normal)'define(`SEM_',`ifelse($1,,,` static SEM $1;`'SEM_(shift($*))')')`dnl divert(declarations)dnl /* ------------------- Semaphores ------------------ */dnl SEM_($*) static SEM loadDnto_sem; /* ------------------ Variables ------------------ */ divert(normal)'define(`SEMinit_',`ifelse($1,,,` rt_sem_init(&$1, 0);`'SEMinit_(shift($*))')')` divert(main_loop)SEMinit_($*) rt_sem_init(&loadDnto_sem, 0); divert(normal)') # Pre0(s) ; priority 1->0 precedence def(`Pre0_', `rt_sem_signal(&$1);') # Suc0_(s) ; priority 0<-1 precedence def(`Suc0_', `rt_sem_wait(&$1);') # Pre1_(s) ; priority 0->1 or 1->1 precedence dnl def(`Pre1_', `ifelse(substr(_task_,6),`task',,`divert(misc) ')dnl dnl rt_sem_signal(&$1);divert(main_functions)') dnl def(`Pre1_', `rt_sem_signal(&$1); /* '_task_`:'index(_task_,`task')` */') def(`Pre1_',`ifelse(_task_,`_main_',`divert(misc) dnl rt_sem_signal(&$1);divert(main_functions)',`rt_sem_signal(&$1);')') # Suc1_(s) ; priority 1<-0 or 1<-1 precedence def(`Suc1_', `rt_sem_wait(&$1);') #################### # CONTROL STRUCTURES # -------- # basicIf_(bool, tagforElseOrEndif) define(`basicIf_', `_(if($1[0]) { /* $2 */)') # ----------- # basicIfnot_(bool, tagForElseOrEndif) define(`basicIfnot_',`_(if(!$1[0]) { /* $2 */)') # ---------- # basicElse_(tagFromIf, tagForEndif) define(`basicElse_', `_(/* $1 */ } else { /* $2 */)') # ----------- # basicEndif_(tagFromIfOrElse) define(`basicEndif_', `_(} /* end $1 */)') # ------------------------- # basicLoop_(tagForEndloop) define(`basicLoop_', `divert(main_functions)dnl 'define(`ITER',`ifdef(`NBITERATIONS', `dnl for(sdx_i=0; sdx_i /* Linux module */ #include /* Linux pci functions */ #include #include /* RTAI core */ #include /* RTAI scheduler */ #include /* RTAI fifos */ #include /* RTAI shared memory */ #include divert(declarations) /* -------------- Realtime task & user `declarations' ------------- */ RT_TASK main_task; divert(task_to_delete)dnl rt_task_delete(&main_task); divert(main_init) int init_module(void) { /* module entry point */ RTIME `loop_period'; divert(main_loop)dnl /* A RTfifo is needed for the download procedure. An external linux * process (called bin2rtfifos) forwards all SynDEx binaries, for station * download, to loaders through the rt-fifo 0 device. */ rtf_create(0, 1000000); rtf_reset(0); /* An other rt_fifo is needed to start the download process. * A write into /dev/rtf1 (fifo #1) indicate that all executives are * writed into /dev/rtf0 (fifo #0), then we can start the download * procedure */ rtf_create(1, 1); rtf_reset(1); rtf_create_handler(1, loadDnto); /* main_thread must have an higher priority than all other non SynDEx tasks * but a lower priority than SynDEx communication threads. Its Stack size * is fixed by default to main_stacksize and it can use the floating * point unit * TN: How to parametrize the stack size of the main thread ??? */ rt_task_init(&main_task, main_thread, 0, main_stacksize, 1, 1, 0); /* Loop period of the application is fixed to loop_period ns */ `loop_period'=start_rt_timer(nano2count(loop_period)); rt_task_make_periodic(&main_task, rt_get_time(), `loop_period'); divert(normal)') # --------------- # basicEndmain_() define(`basicEndmain_',`divert(main_loop) return 0; } /* end of init_module */divert(normal)dnl /* TN: ----- INCLUDED FILES --------------------------------------- */ undivert(headers)dnl /* TN: ----- DEFINITIONS ------------------------------------------ */ undivert(definitions)dnl /* TN: ----- DECLARATIONS ----------------------------------------- */ undivert(declarations)dnl /* TN: ----- COMMUNICATION & USER FUNCTIONS ----------------------- */ undivert(comm_functions)dnl /* TN: ----- DOWNLOAD HANDLER ----------------------------------- */ int loadDnto (unsigned int fifo){ int i; /* Beginning of the download procedure */ undivert(download_handler) /* delete fifos used during the download process */ rtf_destroy(0); rtf_destroy(1); /* resume tasks previously suspended (during the download process) */ for(i=0 ; i<`'task_counter ; i++) rt_sem_signal(&loadDnto_sem); return 0; } /* TN: ----- MAIN FUNCTIONS --------------------------------------- */dnl undivert(main_functions)dnl /* TN: ----- MAIN INITIALIZATION ---------------------------------- */ undivert(main_init)dnl /* TN: ----- MAIN LOOP -------------------------------------------- */ undivert(main_loop) /* TN: ----- MAIN END --------------------------------------------- */ void cleanup_module(void){ /*undid whatever init_module did */ stop_rt_timer(); rt_busy_sleep(1E7); /* PP: from a newfifos RTAI examples */dnl undivert(main_end)dnl undivert(task_to_delete)dnl } /* TN: ----- END OF FILE ------------------------------------------ */') # ------------------------ # spawn_thread_(mediaName) def(`spawn_thread_',`divert(declarations)dnl RT_TASK comm_$1_task; divert(main_loop)dnl /* comm_thread_$1 must have an higher priority than main_thread. * Its stack size is fixed by default to comm_stacksize. * TN: How to parametrize the stack size of the communication thread ??? */ rt_task_init(&comm_$1_task, comm_thread_$1, 0, comm_stacksize, 0, 0, 0); rt_task_resume(&comm_$1_task); /* comm_thread_$1 is running */ define(`PREV_COMM_TASK',`comm_$1_task')dnl divert(main_init)') # ----------------------- # basicThread_(mediaName) define(`basicThread_', `define(`task_counter', eval(task_counter + 1)) divert(main_functions) void comm_thread_$1(int notused){ /* start of communication sequence */ define(`_task_',`_thread_$1')dnl ifdef(`NBITERATIONS',` int sdx_i; /* main loop counter */') /* Communication thread must be suspended during the download process */ rt_sem_wait(&loadDnto_sem); ') # -------------------------- # basicEndthread_(mediaName) define(`basicEndthread_',`divert(main_functions)dnl indent_(+)} /* end of comm_thread_$1 */divert(task_to_delete)dnl rt_task_delete(&comm_$1_task); divert(normal)') # -------------------------- # wait_endthread_(mediaName) ; def(`wait_endthread_', `') ################## # Subroutine calls # For interfacing separately compiled C functions. # ------ # Cincl_(file) # Example m4 declaration and corresponding generated C code: # Cincl_(my_header_file) # | #include "my_header_file" def(`Cincl_', `divert(headers)dnl ifdef(`$1_already_declared',,`define($1_already_declared) #include "$1" divert(main_functions)')') # ------ # Cdecl_(ret,label,args) # Example m4 declaration and corresponding generated C code: # Cdecl_(int, my_fun, int arg1, int* arg2, float arg3) # | int my_fun(int arg1, int* arg2, float arg3); def(`Cdecl_', `divert(declarations)dnl _(`$1 $2('shift(shift($*))`);')divert(main_functions)') # ------ # Ccall_(ret,label,args) # Example m4 declaration and macro-call with generated C code: # def(`myfun', `Ccall_(int $3, my_fun, const 5, int *$1, float $2)') # myfun(arg1,arg2,res) /* macro-call; generated code: */ # | res=myfun(5, arg1, arg2[0]); define(`Ccall_', `dnl return value: pushdef(`Ctyp_', patsubst($1,` .*'))dnl Extract argument type. pushdef(`Carg_', patsubst($1,`.* +'))dnl Extract argument name. divert(main_functions)dnl ifelse(Ctyp_,`void',`_(`$2(')',`defined_(Carg_)_(Carg_`[0] = $2(')')dnl Cargs_(shift(shift($@)))`);'popdef(`Carg_')popdef(`Ctyp_')') # Cargs_([[* ]