目次

コンフィグレータ

 USOを使う場合、システムコールやタイマー割込みを利用する
 マイコンに合わせて記述しなければなりません。

 見本となるファイルを用意し、コピー&ペーストでシステムコール
 とタイマー割込み等の貼付けでは、見落としが起きやすくなります。

 見落としが少なくなるように、タスク数とファイル名を与えると
 スケルトンのCソースコードを生成するアプリケーションソフト
 (コンフィグレータ)を用意しました。

 マルチプラットホームを考え、Tcl/TkでGUIをもったコンフィグレータ
 を作成します。
 Tcl/Tkから、CUIのプログラムyconfig.exeを呼び出し、Cのソースコード
 を作成します。


コンフィグレータGUI

  1. タスク数を、▲か▼のクリックで確定します。
  2. 緑のシート部分に、ファイル名を入力します。(拡張子は不要です。)
  3. makeボタンをクリックします。
  4. 終了は、EXITボタンをクリックします。

Tcl/Tkコンフィグレータコード

 ファイル名は、「confuso2.tcl」です。  UNIXの場合は、1行目のファイルパスを環境にあわせてください。 #!/usr/local/bin/wish . configure -width 250 -height 250 wm title . "Configure source code with USO2" # initialize file name set theFileName "unknown" set tFileName $theFileName # initialize acount of tasks set theAcountOfTasks 7 # define labels label .lblAcountOfTasks -width 16 -text "Acount of tasks" spinbox .sbxSpan -width 10 -state readonly -from 2 -to 16 -increment 1 label .lblAcount -width 10 -text "7" -bg lightblue label .lblFileName -width 10 -text "File Name" entry .edtFileName -width 10 -bg green -textvariable tFileName # sub procedure proc updateAcount { s } { global theAcountOfTasks # get acount set theAcountOfTasks $s # puts digit to label .lblAcount configure -text "$theAcountOfTasks" } # define buttons button .btnEXIT -bg gray -text "EXIT" -command "exit" -width 10 button .btnMAKE -width 10 -bg yellow -text "make" -command { # create file name set theAcountOfTasks [.sbxSpan get] # create file name set theFileName [format "%s.c" $tFileName] # make exec YCONFIG $theAcountOfTasks $theFileName } # window area placing grid .lblAcountOfTasks -column 0 -row 0 grid .sbxSpan -column 1 -row 0 grid .lblFileName -column 0 -row 2 grid .edtFileName -column 1 -row 2 grid .btnMAKE -column 0 -row 3 grid .btnEXIT -column 1 -row 3

CUIコンフィグレータ

 従来のUSOで利用した内容を、一部修正しています。  システムコールの定義を、変更します。  また、タスク数は最大16個と規定しているので  変数ready、suspend、waitqを符号なし16ビットとします。  Windowsの場合は、コンパイル、リンクして「YCONFIG.EXE」を  作成します。この実行形式ファイルを、GUIである「confuso2.tcl」  と同じディレクトリに保存します。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define PARAMETER_MAX 3 #define BUF_SIZE 40 typedef unsigned char UBYTE ; typedef char SBYTE ; void send_tsk_max(FILE *f,UBYTE x); void send_prototype(FILE *f,UBYTE x); void send_main_function(FILE *f,UBYTE x); void send_task_function(FILE *f,UBYTE x); void send_system_call(FILE *f); void send_timer_handler(FILE *f,UBYTE x); void main(int argc,char *argv[]) { UBYTE tsk_count ; FILE *fp ; /* parameter acount check */ if ( argc != PARAMETER_MAX ) { fprintf( stderr , "yconfig task_number file_name{enter}\n"); return ; } /* open file */ fp = fopen( argv[2] , "w+t" ); /* send count */ tsk_count = atoi( argv[1] ); send_tsk_max(fp,tsk_count); send_prototype(fp,tsk_count); send_main_function(fp,tsk_count); send_task_function(fp,tsk_count); send_system_call(fp); send_timer_handler(fp,tsk_count); /* close file */ fclose( fp ); } void send_tsk_max(FILE *f,UBYTE x) { UBYTE i ; fprintf(f,"#define TSK_ID_MAX %d\n\n",x); for ( i = 0 ; i < x ; i++ ) { fprintf(f,"#define TSK_ID%d %d\n",i,i); } fprintf(f,"\n"); /* declare data type */ fprintf(f,"typedef unsigned char UBYTE ;\n"); fprintf(f,"typedef unsigned short UWORD ;\n"); fprintf(f,"typedef unsigned long ULONG ;\n"); fprintf(f,"typedef signed char SBYTE ;\n"); fprintf(f,"typedef signed short SWORD ;\n"); fprintf(f,"typedef signed long SLONG ;\n\n"); fprintf(f,"typedef unsigned char B ;\n"); fprintf(f,"typedef unsigned short H ;\n"); fprintf(f,"typedef unsigned long W ;\n\n"); /* declare TCB type */ fprintf(f,"typedef struct {\n"); fprintf(f," void (*tsk)(void);\n"); fprintf(f," UWORD wcount ;\n"); fprintf(f,"} TCBP ;\n\n"); /* declare TCB type */ fprintf(f,"#define TTS_SUSPEND 0\n"); fprintf(f,"#define TTS_WAIT TTS_SUSPEND+1\n"); fprintf(f,"#define TTS_READY TTS_SUSPEND+2\n\n"); fprintf(f,"#define NO 0\n"); fprintf(f,"#define YES 1\n\n"); /* declare status */ fprintf(f,"UWORD ready ;\n"); fprintf(f,"UWORD suspend;\n"); fprintf(f,"UWORD waitq ;\n\n"); fprintf(f,"UBYTE run_tsk;\n\n"); /* declare status */ fprintf(f,"TCBP tcb[TSK_ID_MAX];\n\n" ); } void send_prototype(FILE *f,UBYTE x) { UBYTE i ; /* function prototype */ fprintf(f,"/*------------------------*/\n"); fprintf(f,"/* task function protoype */\n"); fprintf(f,"/*------------------------*/\n"); for ( i = 0 ; i < x ; i++ ) { fprintf(f,"void tsk%d_proc(void);\n",i); } fprintf(f,"\n"); /* system call prototype */ fprintf(f,"/*-----------------------*/\n"); fprintf(f,"/* system call prototype */\n"); fprintf(f,"/*-----------------------*/\n"); fprintf(f,"void init_os(void);\n"); fprintf(f,"void cre_tsk(UBYTE tid,void (*tsk)(void));\n"); fprintf(f,"void sta_tsk(UBYTE tid,UBYTE sta);\n"); fprintf(f,"void rsm_tsk(UBYTE tid);\n"); fprintf(f,"void sus_tsk(UBYTE tid);\n"); fprintf(f,"void slp_tsk(void);\n"); fprintf(f,"void wai_tsk(UWORD x);\n"); fprintf(f,"UBYTE is_tsk_ready(UBYTE tid);\n\n"); /* user function prototype */ fprintf(f,"/*--------------------------------*/\n"); fprintf(f,"/* Insert user functions protoype */\n"); fprintf(f,"/*--------------------------------*/\n"); fprintf(f,"void user_initialize(void);\n\n"); } void send_main_function(FILE *f,UBYTE x) { UBYTE i ; /* main */ fprintf(f,"/*------*/\n"); fprintf(f,"/* main */\n"); fprintf(f,"/*------*/\n"); fprintf(f,"void main(void)\n"); fprintf(f,"{\n"); fprintf(f,"\tTCBP pcur_tsk ;\n\n"); /* initialize os */ fprintf(f,"\t/* initialize monitor */\n"); fprintf(f,"\tinit_os();\n\n"); /* create task */ for ( i = 0 ; i < x ; i++ ) { fprintf(f,"\tcre_tsk(TSK_ID%d,tsk%d_proc);\n",i,i); } fprintf(f,"\n"); /* start task task */ for ( i = 0 ; i < x ; i++ ) { fprintf(f,"\tsta_tsk(TSK_ID%d,TTS_READY);\n",i); } fprintf(f,"\n"); /* user initialization */ fprintf(f,"\tuser_initialize();\n"); fprintf(f,"\n"); /* task scheduler and dispatcher */ fprintf(f,"\t/* loop */\n"); fprintf(f,"\trun_tsk = TSK_ID0 ;\n"); fprintf(f,"\twhile ( 1 ) {\n"); fprintf(f,"\t\tpcur_tsk = tcb[run_tsk] ;\n"); fprintf(f,"\t\tif ( is_tsk_ready( run_tsk ) == YES ) { (*(pcur_tsk.tsk))(); }\n"); fprintf(f,"\t\trun_tsk++;\n"); fprintf(f,"\t\tif ( run_tsk == TSK_ID_MAX ) { run_tsk = TSK_ID0 ; }\n"); fprintf(f,"\t}\n"); /* close main function */ fprintf(f,"}\n\n"); } void send_task_function(FILE *f,UBYTE x) { UBYTE i ; /* title */ fprintf(f,"/*----------------*/\n"); fprintf(f,"/* task functions */\n"); fprintf(f,"/*----------------*/\n"); /* body */ for ( i = 0 ; i < x ; i++ ) { fprintf(f,"void tsk%d_proc(void)\n",i); fprintf(f,"{\n"); fprintf(f,"\n"); fprintf(f,"}\n\n"); } } void send_system_call(FILE *f) { /* title */ fprintf(f,"/*------------------*/\n"); fprintf(f,"/* system call body */\n"); fprintf(f,"/*------------------*/\n"); /* init_os */ fprintf(f,"void init_os(void)\n"); fprintf(f,"{\n"); fprintf(f,"\tready = suspend = waitq = 0 ;\n"); fprintf(f,"}\n\n"); /* create task */ fprintf(f,"void cre_tsk(UBYTE tid,void (*tsk)(void))\n"); fprintf(f,"{\n"); fprintf(f," tcb[tid].tsk = tsk;\n"); fprintf(f," tcb[tid].wcount = 0;\n"); fprintf(f,"}\n\n"); /* start task */ fprintf(f,"void sta_tsk(UBYTE tid,UBYTE sta)\n"); fprintf(f,"{\n"); fprintf(f," UWORD tmp ;\n"); fprintf(f," tmp = (1 << tid);\n"); fprintf(f," if ( sta == TTS_READY ) { ready |= tmp; }\n"); fprintf(f," if ( sta == TTS_SUSPEND ) { suspend |= tmp; }\n"); fprintf(f," if ( sta == TTS_WAIT ) { waitq |= tmp; }\n"); fprintf(f,"}\n\n"); /* resume task */ fprintf(f,"void rsm_tsk(UBYTE tid)\n"); fprintf(f,"{\n"); fprintf(f," UWORD tmp ;\n"); fprintf(f," tmp = (1 << tid);\n"); fprintf(f," ready |= tmp;\n"); fprintf(f," suspend &= ~tmp;\n"); fprintf(f," waitq &= ~tmp;\n"); fprintf(f,"}\n\n"); /* suspend task */ fprintf(f,"void sus_tsk(UBYTE tid)\n"); fprintf(f,"{\n"); fprintf(f," UWORD tmp ;\n"); fprintf(f," tmp = (1 << tid);\n"); fprintf(f," ready &= ~tmp;\n"); fprintf(f," suspend |= tmp;\n"); fprintf(f," waitq &= ~tmp;\n"); fprintf(f,"}\n\n"); /* sleep task */ fprintf(f,"void slp_tsk(void)\n"); fprintf(f,"{\n"); fprintf(f," sus_tsk(run_tsk);\n"); fprintf(f,"}\n\n"); /* delay task */ fprintf(f,"void wai_tsk(UWORD x)\n"); fprintf(f,"{\n"); fprintf(f," UWORD tmp ;\n"); fprintf(f," tmp = (1 << run_tsk);\n"); fprintf(f," ready &= ~tmp;\n"); fprintf(f," suspend &= ~tmp;\n"); fprintf(f," waitq |= tmp;\n"); fprintf(f," tcb[run_tsk].wcount = x ;\n"); fprintf(f,"}\n\n"); /* Is task ready ? */ fprintf(f,"UBYTE is_tsk_ready(UBYTE tid)\n"); fprintf(f,"{\n"); fprintf(f," return( (ready >> tid) & 1 ) ;\n"); fprintf(f,"}\n\n"); } void send_timer_handler(FILE *f,UBYTE x) { fprintf(f,"/*-----------------------------*/\n"); fprintf(f,"/* timer handler */\n"); fprintf(f,"/* call from timer interrupt */\n"); fprintf(f,"/*-----------------------------*/\n"); fprintf(f,"void timer_handler(void)\n"); fprintf(f,"{\n"); fprintf(f," UWORD tmp;\n"); fprintf(f," UBYTE i ;\n"); fprintf(f,"\n"); fprintf(f," tmp = waitq ;\n"); fprintf(f," for ( i = 0 ; i < TSK_ID_MAX ; i++ ) {\n"); fprintf(f," if ( tmp & 1 ) {\n"); fprintf(f," tcb[i].wcount-- ;\n"); fprintf(f," if ( tcb[i].wcount == 0 ) { rsm_tsk(i); }\n"); fprintf(f," }\n"); fprintf(f," tmp >>= 1 ;\n"); fprintf(f," }\n"); fprintf(f,"}\n\n"); /* user function */ fprintf(f,"/*-----------------------*/\n"); fprintf(f,"/* Insert user functions */\n"); fprintf(f,"/*-----------------------*/\n"); fprintf(f,"void user_initialize(void)\n"); fprintf(f,"{\n"); fprintf(f,"}\n\n"); }

Tcl/Tkのみのコンフィグレータコード

 UNIX、Windows、MacOSXのどの環境でも  動作するコンフィグレータコードが必要  になったので、Tcl/Tkのスクリプトのみ  で記述し直してみました。 #!/usr/local/bin/wish . configure -width 250 -height 250 wm title . "Configure source code with USO" # initialize file name set theFileName "unknown" set tFileName $theFileName # initialize acount of tasks set theAcountOfTasks 7 # define labels label .lblAcountOfTasks -width 16 -text "Acount of tasks" spinbox .sbxSpan -width 10 -state readonly -from 2 -to 16 -increment 1 label .lblAcount -width 10 -text "7" -bg lightblue label .lblFileName -width 10 -text "File Name" entry .edtFileName -width 10 -bg green -textvariable tFileName # sub procedure proc updateAcount { s } { global theAcountOfTasks # get acount set theAcountOfTasks $s # puts digit to label .lblAcount configure -text "$theAcountOfTasks" } proc genlist {x} { set last $x set result "" for {set i 0} {$i < $last} {incr i} { set result "$result $i" } return $result } proc gencfile { x } { global tFileName # open file set f [open $tFileName "w"] # store strings puts $f "/*" puts $f " FileName $tFileName " puts $f "" puts $f " task $x " puts $f "" puts $f "*/" # store strings puts $f "#define OFF 0" puts $f "#define ON OFF+1" puts $f "" puts $f "#define NO 0" puts $f "#define YES NO+1" puts $f "" set result [genlist $x] set last [llength $result] puts $f "#define TSK_ID_MAX $last" puts $f "" foreach n $result { puts $f "#define TSK_ID$n $n" } puts $f "/* redefine data types" puts $f "typedef unsigned char UBYTE ;" puts $f "typedef signed char SBYTE ;" puts $f "typedef unsigned short UWORD ;" puts $f "typedef signed short SWORD ;" puts $f "typedef unsigned long ULONG ;" puts $f "" puts $f "/* define TCB */" puts $f "typedef struct \{" puts $f " void (*tsk)(void);" puts $f " UWORD wcount ;" puts $f "\} TCBP ;" puts $f "" puts $f "TCBP tcb\[TSK_ID_MAX\];" puts $f "" puts $f "/* define TASK state */" puts $f "#define TTS_SUSPEND 0" puts $f "#define TTS_WAIT TTS_SUSPEND+1" puts $f "#define TTS_READY TTS_SUSPEND+2" puts $f "" puts $f "volatile UWORD ready ;" puts $f "volatile UWORD suspend;" puts $f "volatile UWORD waitq ;" puts $f "volatile UWORD run_tsk;" puts $f "volatile UBYTE tflag;" puts $f "" puts $f "/*-----------------------*/" puts $f "/* system call prototype */" puts $f "/*-----------------------*/" puts $f "void init_os(void);" puts $f "void cre_tsk(UBYTE tid,void (*tsk)(void));" puts $f "void sta_tsk(UBYTE tid,UBYTE sta);" puts $f "void rsm_tsk(UBYTE tid);" puts $f "void sus_tsk(UBYTE tid);" puts $f "void slp_tsk(void);" puts $f "void wai_tsk(UWORD x);" puts $f "UBYTE is_tsk_ready(UBYTE tid);" puts $f "void timer_handler(void);" puts $f "" puts $f "/*--------------------------------*/" puts $f "/* Insert user functions protoype */" puts $f "/*--------------------------------*/" puts $f "void user_initialize(void);" puts $f "" puts $f "/*------*/" puts $f "/* main */" puts $f "/*------*/" puts $f "int main(void)" puts $f "\{" puts $f " TCBP pcur_tsk ;" puts $f "" puts $f " user_initialize();" puts $f "" puts $f " cli() ;" puts $f " /* initialize monitor */" puts $f " init_os();" puts $f "" foreach n $result { puts $f " cre_tsk(TSK_ID$n,tsk$n\_proc);" } puts $f "" foreach n $result { puts $f " sta_tsk(TSK_ID$n,TTS_SUSPEND);" } puts $f "" puts $f " sei() ;" puts $f " /* loop */" puts $f " run_tsk = TSK_ID0 ;" puts $f " while ( ON ) \{" puts $f " /* dispatcher */" puts $f " pcur_tsk = tcb\[run_tsk\] ;" puts $f " if ( is_tsk_ready( run_tsk ) == YES ) \{ (*(pcur_tsk.tsk))(); \}" puts $f " run_tsk++;" puts $f " if ( run_tsk == TSK_ID_MAX ) \{ run_tsk = TSK_ID0 ; \}" puts $f " /* timer */" puts $f " if ( tflag == ON ) \{" puts $f " tflag = OFF ;" puts $f " timer_handler();" puts $f " \}" puts $f " \}" puts $f " /* dummy */" puts $f " return 0 ;" puts $f "\}" puts $f "" puts $f "/*-----------------------*/" puts $f "/* Insert user functions */" puts $f "/*-----------------------*/" puts $f "void user_initialize(void)" puts $f "\{" puts $f "" puts $f "\}" puts $f "" puts $f "/*----------------*/" puts $f "/* task functions */" puts $f "/*----------------*/" foreach n $result { puts $f "void tsk$n\_proc(void)" puts $f "\{" puts $f "" puts $f "\}" puts $f "" } puts $f "/*------------------*/" puts $f "/* system call body */" puts $f "/*------------------*/" puts $f "void init_os(void)" puts $f "\{" puts $f " ready = 0 ;" puts $f " suspend = 0 ;" puts $f " waitq = 0 ;" puts $f " tflag = OFF ;" puts $f "\}" puts $f "" puts $f "void cre_tsk(UBYTE tid,void (*tsk)(void))" puts $f "\{" puts $f " tcb\[tid\].tsk = tsk;" puts $f " tcb\[tid\].wcount = 0;" puts $f "\}" puts $f "" puts $f "void sta_tsk(UBYTE tid,UBYTE sta)" puts $f "\{" puts $f " UWORD tmp ;" puts $f " tmp = (1 << tid);" puts $f " if ( sta == TTS_READY ) \{ ready |= tmp; \}" puts $f " if ( sta == TTS_SUSPEND ) \{ suspend |= tmp; \}" puts $f " if ( sta == TTS_WAIT ) \{ waitq |= tmp; \}" puts $f "\}" puts $f "" puts $f "void rsm_tsk(UBYTE tid)" puts $f "\{" puts $f " UWORD tmp ;" puts $f " tmp = (1 << tid);" puts $f " ready |= tmp;" puts $f " suspend &= ~tmp;" puts $f " waitq &= ~tmp;" puts $f "\}" puts $f "" puts $f "void sus_tsk(UBYTE tid)" puts $f "\{" puts $f " UWORD tmp ;" puts $f " tmp = (1 << tid);" puts $f " ready &= ~tmp;" puts $f " suspend |= tmp;" puts $f " waitq &= ~tmp;" puts $f "\}" puts $f "" puts $f "void slp_tsk(void)" puts $f "\{" puts $f " sus_tsk(run_tsk);" puts $f "\}" puts $f "" puts $f "void wai_tsk(UWORD x)" puts $f "\{" puts $f " UWORD tmp ;" puts $f " tmp = (1 << run_tsk);" puts $f " ready &= ~tmp;" puts $f " suspend &= ~tmp;" puts $f " waitq |= tmp;" puts $f " tcb\[run_tsk\].wcount = x ;" puts $f "\}" puts $f "" puts $f "UBYTE is_tsk_ready(UBYTE tid)" puts $f "\{" puts $f " return( (ready >> tid) & 1 ) ;" puts $f "\}" puts $f "" puts $f "void timer_handler(void)" puts $f "\{" puts $f " volatile UWORD xtmp;" puts $f " volatile UBYTE loop;" puts $f " /* call timer handling */" puts $f " xtmp = waitq ;" puts $f " for ( loop = 0 ; loop < TSK_ID_MAX ; loop++ ) \{" puts $f " if ( xtmp & 1 ) \{" puts $f " tcb\[loop\].wcount-- ;" puts $f " if ( tcb\[loop\].wcount == 0 ) \{ rsm_tsk(loop); \}" puts $f " \}" puts $f " xtmp >>= 1 ;" puts $f " \}" puts $f "\}" # close file close $f } # define buttons button .btnEXIT -bg gray -text "EXIT" -command "exit" -width 10 button .btnMAKE -width 10 -bg yellow -text "make" -command { # create file name set theAcountOfTasks [.sbxSpan get] # create file name set theFileName [format "%s.c" $tFileName] # make gencfile $theAcountOfTasks } # window area placing grid .lblAcountOfTasks -column 0 -row 0 grid .sbxSpan -column 1 -row 0 grid .lblFileName -column 0 -row 2 grid .edtFileName -column 1 -row 2 grid .btnMAKE -column 0 -row 3 grid .btnEXIT -column 1 -row 3  GUIから、ファイル名、タスク数を入力します。  内部でリストを生成してから、一気呵成に  タスク関係に関係するマクロ、関数を出力  します。
目次

inserted by FC2 system