Smalight OSを使おう 12タスク目 起動時パラメータを試してみる。 [Smalight OS]
μITRON仕様OSには有って、smalight osには無く、不便だなあ!と思っていた機能(μITRON仕様なら以下の様な静的API、またはサービスコール)が起動時パラメータの引渡しですが、マニュアルの「stack_iniを利用したパラメータ引渡し」に、stackini.cをいじれば可能な事が書いて有りましたので、これを試してみたいと思います。
静的API: CRE_TSK(TID_1, {TA_HLNG, 起動時引数, httpd, 7,4096, NULL}); サービスコール: sta_tsk( TID_1, 起動時引数 );
まずオリジナルは何も引数を渡さない事になっています。
マニュアルを参照すると、関数stack_iniの中で
wk >>= 16;
の下に以下の記述を追加する事で、実行時引数を渡す事が可能となるみたいです。
if(tid == 1) sp->r[1] = なんとか; else if(tid == 2 ) sp->r[1] = なんとか;
tidは勿論タスクIDです。
ポインタ型変数のspは、タスクのコンテキスト保存時の構造体で、slos.h内では以下の様に定義されています。
typedef struct _tstack { H r[4]; H a[2]; H sb; H fb; H pc; B flg; B flg_pc; } TSTACK;
つまりこの構造体は、タスクのレジスタを全退避する領域の定義を行っている物です。各タスクは、起動時にはREADYまたはWAITの状態で起動しますので、OSが初期化を行う時に、この領域に必要な情報(実際には戻り先アドレスとスタックポインタ、それ以外は重要では無い)を代入します。
しかしタスクの実行関数は基本的に関数なので”引数を持つ事が可能”です。R8Cの場合は(正確に言えばNC30WA)関数の引数の渡し方のルールとして、R1、R2レジスタに値を代入し、それを越える場合はスタック渡しに切り替えます。
※引数の型に拠って渡し方のルールが異なるので、コンパイラマニュアルを参照する必要がある。
今回のサンプルプログラムは、二つのLEDを独立に点滅させる、ひじょーうに簡単な物です。それぞれのLEDにタスクを割り当て、実行します。
そこでtsk01のプロトタイプ宣言を以下の様に変更します。
void tsk01( UB tid, H dly_tim );
つまりtidはunsigned char型なのでR1Lに代入され、dly_timはshort型なのでR2に代入されます。
このプロトタイプ宣言の変更は、config.cにも必要です。
これを踏まえてstackini.cを以下の様に変更します。※一部のみ表示しています。
sp->r[1] = tid; if(tid == 1) { sp->r[2] = 100; } else { sp->r[2] = 200; }
tid=1の時は100ms、tid=2の時は200msの遅延時間を引き数として渡します。
コンパイラの設定は、
SYSTIMEを有効
config.cの設定は、
タスク1:起動時READY
タスク2:起動時READY
ユーザー初期化関数uinitの設定は、
システムタイマーのみ起動します。周期は10msとして置いて下さい。
void uinit(void) { /* initialize */ pd2 = 0x03; p2 = 0x03; /* Processor clock init */ init_clock(); /* systime initialize */ systim_init(); /* cyclic timer initialze */ init_timerRA(); } void tsk01( UB tid, H dly_tim ) { while( 1 ) { if( tid == 1 ) p2_0 ^= 1; else p2_1 ^= 1; tslp_tsk( dly_tim ); } }
あれ!tsk02が無いですね(笑)。
実はconfig.cの内容は以下の様になっています。※一部のみ表示しています。
/*** Refer to exterior ***/ extern void tsk01( UB tid, H dly_tim ); /*** Table for start addr init ***/ const TCBADDR knl_tcbAddrInit[KNL_TCB_NUM] = { { tsk01 }, /* TCB1 */ { tsk01 }, /* TCB2 */ };
つまりタスク1、タスク2共に実行関数はtsk01を指定しています。同じ様な事をするのにわざわざ二つの関数を用意するのは無駄が多いので、一つの関数の中で区別する記述を用意する事で、両方のタスクに対応しています。
これは、例えばhttp://hamayan.ddo.jp:8080/でHOSをベースとしたWEBサーバーが実行されていますが、この中のWEBサーバータスクも同様に一つの関数を実行関数として、同時に4つのタスクが起動しています。
と、まあ、ここまで修正が完了したらビルドしてみて下さい。ビルドした時に以下の警告が出るかと思います。
E:\smalight\ner8c25\step12\config.c(47) : [Warning(ccom)] incompatible pointer types E:\smalight\ner8c25\step12\config.c(47) : [Warning(ccom)] mismatch function pointer assignment
これは、slos.h内の関数のプロトタイプ宣言と、config.c内のプロトタイプ宣言に矛盾が有るからです。このまま実行させても問題無く動きますが、もし気になるようでしたらslos.h内に以下の変更を加えます。
typedef void (*FP)(void); これを以下の様に typedef void (*FP)(UB,H);
結局のところ、smalight osでできる事は、ほぼμITRON仕様OSでも再現できますので、やはり以下の本をどうぞ。HOSは、最も低コストでμITRONを体験できます。
ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発
- 作者: 浜原 和明
- 出版社/メーカー: オーム社
- 発売日: 2005/04/25
- メディア: 単行本
コメント 0