目次
前
次
コンフィグレータ
USOを使う場合、システムコールやタイマー割込み部分を利用する
マイコンに合わせて記述しなければなりません。
見本となるファイルを用意し、コピー&ペーストでシステムコール
とタイマー割込み等の貼付けでは、見落としが起きやすくなります。
見落としが少なくなるように、タスク数とファイル名を与えると
スケルトンのCソースコードを生成するアプリケーションソフト
(コンフィグレータ)を用意しました。
CUI(Character User Interface)で使うと考え、xconfig.cを作成しました。
GUI(Graphic User Interface)が好ましい時は、confuso.tclを使います。
両ファイルとも、ソースコードは、最後に載せています。
コンフィグレータ用ファイル
コンフィグレータを使うには、コンパイル、リンク作業が必要です。
CUIだけでよい場合は、xconfig.cを使い、コンパイル、リンクして
xconfig.exeを作成します。
GUIを使いたい場合は、xconfig.exeの他に、confuso.tclが必要です。
CUI版コンフィグレータ(Windows用)
DOS窓で、次のように入力します。
c:\confuso>xconfig 4 utest.c{enter}
CUI版コンフィグレータ(UNIX用)
ソースコードをコピーして、コンパイルしてから使います。
$~ gcc -o xconfig xconfig.c{enter}
$~ chmod +x xconfig{enter}
$~ ./xconfig 4 utest.c{enter}
GUI版コンフィグレータ(Windows用)
CUI操作が苦手な場合は、Tcl/Tkで作成したGUI版を使ってください。
Tcl/TkのGUIインタフェースで、タスク数とファイル名を入力できます。
同一フォルダに、次のファイルを用意して使います。
xconfig.exe
confuso.tcl
CUI版のコンフィグレータに、GUIインタフェースをTcl/Tkで被せます。
Tcl/Tkは、ActiveTclをダウンロード後に、インストールしてください。
スケルトンのCソースコードを作成する手順は以下です。
- Explorerでフォルダを開き、「confuso.tcl」をダブルクリックします。
- タスク数を、▲か▼のクリックで確定します。
- 緑のシート部分に、ファイル名を入力します。(拡張子は不要です。)
- makeボタンをクリックします。
- 終了は、EXITボタンをクリックします。
GUI版コンフィグレータ(UNIX用)
CUI操作が苦手な場合は、Tcl/Tkで作成したGUI版を使ってください。
Tcl/TkのGUIインタフェースで、タスク数とファイル名を入力できます。
同一ディレクトリに、次のファイルを用意して使います。
xconfig.exe
confuso.tcl
CUI版のコンフィグレータに、GUIインタフェースをTcl/Tkで被せます。
システムに、Tcl/Tkの環境が入っているかを確認します。
$~ which wish{enter}
wishが存在するディレクトリが表示されないときは、ソースコードを
ダウンロード後、インストールしてください。
スケルトンのCソースコードを作成する手順は以下です。
- コマンドラインで、「wish confuso.tcl{enter}」と入力します。
- タスク数を、▲か▼のクリックで確定します。
- 緑のシート部分に、ファイル名を入力します。(拡張子は不要です。)
- makeボタンをクリックします。
- 終了は、EXITボタンをクリックします。
コンフィグレータソースコード
ファイル名は、「xconfig.c」です。
#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 , "xconfig 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 */
if ( x > 7 ) {
fprintf( f , "UWORD ready ;\n");
fprintf( f , "UWORD suspend;\n");
fprintf( f , "UWORD vldtsk ;\n\n");
} else {
fprintf( f , "UBYTE ready ;\n");
fprintf( f , "UBYTE suspend;\n");
fprintf( f , "UBYTE vldtsk ;\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 ) {\n");
fprintf( f , "\t\t (*(pcur_tsk.tsk))();\n");
fprintf( f , "\t\t}\n");
fprintf( f , "\t\trun_tsk++;\n");
fprintf( f , "\t\tif ( run_tsk == TSK_ID_MAX ) {\n");
fprintf( f , "\t\t run_tsk = TSK_ID0 ;\n");
fprintf( f , "\t\t}\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 = vldtsk = 0 ;\n");
fprintf( f , "}\n\n");
/* create task */
fprintf( f , "void cre_tsk(UBYTE tid,void (*tsk)(void))\n");
fprintf( f , "{\n");
fprintf( f , "\tif ( tid >= TSK_ID_MAX ) return ;\n");
fprintf( f , "\tvldtsk |= (1 << tid) ;\n");
fprintf( f , "\ttcb[tid].tsk = tsk;\n");
fprintf( f , "\ttcb[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 , "\tif ( tid >= TSK_ID_MAX ) return ;\n");
fprintf( f , "\tif ( sta == TTS_READY ) {\n");
fprintf( f , "\t ready |= (1 << tid);\n");
fprintf( f , "\t suspend &= ~(1 << tid);\n");
fprintf( f , "\t}\n");
fprintf( f , "\tif ( sta == TTS_WAIT ) {\n");
fprintf( f , "\t ready &= ~(1 << tid);\n");
fprintf( f , "\t suspend &= ~(1 << tid);\n");
fprintf( f , "\t}\n");
fprintf( f , "\tif ( sta == TTS_SUSPEND ) {\n");
fprintf( f , "\t ready &= ~(1 << tid);\n");
fprintf( f , "\t suspend |= (1 << tid);\n");
fprintf( f , "\t}\n");
fprintf( f , "}\n\n");
/* resume task */
fprintf( f , "void rsm_tsk(UBYTE tid)\n");
fprintf( f , "{\n");
fprintf( f , "\tif ( tid >= TSK_ID_MAX ) return ;\n");
fprintf( f , "\tready |= (1 << tid);\n");
fprintf( f , "\tsuspend &= ~(1 << tid);\n");
fprintf( f , "}\n\n");
/* suspend task */
fprintf( f , "void sus_tsk(UBYTE tid)\n");
fprintf( f , "{\n");
fprintf( f , "\tif ( tid >= TSK_ID_MAX ) return ;\n");
fprintf( f , "\tready &= ~(1 << tid);\n");
fprintf( f , "\tsuspend |= (1 << tid);\n");
fprintf( f , "}\n\n");
/* sleep task */
fprintf( f , "void slp_tsk(void)\n");
fprintf( f , "{\n");
fprintf( f , "\tsus_tsk(run_tsk);\n");
fprintf( f , "}\n\n");
/* delay task */
fprintf( f , "void wai_tsk(UWORD x)\n");
fprintf( f , "{\n");
fprintf( f , "\tready &= ~(1 << run_tsk);\n");
fprintf( f , "\tsuspend &= ~(1 << run_tsk);\n");
fprintf( f , "\ttcb[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 , "\treturn( (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");
if ( x > 7 ) { fprintf( f , " UWORD tmp;\n"); }
else { fprintf( f , " UBYTE tmp;\n"); }
fprintf( f , " UBYTE i ;\n");
fprintf( f , "\n");
fprintf( f , " tmp = (ready ^ vldtsk) ^ suspend ;\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");
}
GUI用Tcl/Tkコード
ファイル名は、「confuso.tcl」です。
UNIXの場合は、1行目のファイルパスを環境にあわせてください。
#!/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"
}
# 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 xconfig $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
目次
前
次