目次
前
次
コンフィグレータ
USOを使う場合、システムコールやタイマー割込みを利用する
マイコンに合わせて記述しなければなりません。
見本となるファイルを用意し、コピー&ペーストでシステムコール
とタイマー割込み等の貼付けでは、見落としが起きやすくなります。
見落としが少なくなるように、タスク数とファイル名を与えると
スケルトンのCソースコードを生成するアプリケーションソフト
(コンフィグレータ)を用意しました。
マルチプラットホームを考え、Tcl/TkでGUIをもったコンフィグレータ
を作成します。
Tcl/Tkから、CUIのプログラムyconfig.exeを呼び出し、Cのソースコード
を作成します。
コンフィグレータGUI
- タスク数を、▲か▼のクリックで確定します。
- 緑のシート部分に、ファイル名を入力します。(拡張子は不要です。)
- makeボタンをクリックします。
- 終了は、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から、ファイル名、タスク数を入力します。
内部でリストを生成してから、一気呵成に
タスク関係に関係するマクロ、関数を出力
します。
目次
前
次