目次
前
次
タスク間通信
USOは、タスク間通信を実現する機能は持ちません。
タスク間で、情報交換するには、グローバル変数を使います。
グローバル変数を使う場合は、次の指針で定義するとよいでしょう。
- 1ビット単位の情報交換->フラグ利用
- 1バイトの情報交換 ->変数利用
- 2バイトの情報交換 ->変数利用
- 3バイト以上の情報交換->配列か構造体変数利用
1ビット単位の情報交換
1ビットで充分な情報は、イベントフラグ、信号などです。
USOは、Cで動作するので、次のように8ビットで表現できる変数の
中に1ビット単位の記憶領域を確保します。
typedef union {
struct {
unsigned B0:1;
unsigned B1:1;
unsigned B2:1;
unsigned B3:1;
unsigned B4:1;
unsigned B5:1;
unsigned B6:1;
unsigned B7:1;
} BIT ;
unsigned char DR ;
} FLAGSP ;
FLAGSP xflags ;
#define FLAG0 xflags.BIT.B0
#define FLAG1 xflags.BIT.B1
#define AFLAG xflags.BIT.B2
#define BFLAG xflags.BIT.B3
2つのタスクを交互に動かしたい場合は、次のように定義します。
#define OFF 0
#define ON OFF+1
void tsk1_proc(void)
{
if ( FLAG == OFF ) {
/* 何か動作を記述 */
FLAG0 = ON ;
}
}
void tsk2_proc(void)
{
if ( FLAG == ON ) {
/* 何か動作を記述 */
FLAG0 = OFF ;
}
}
フラグをOFFにして、システムコールsta_tskで2つのタスクをREADY
にすれば、タスク1、タスク2の順で交互に動作を繰り返します。
FLAG = OFF ;
sta_tsk( TSK_ID1 , TTS_READY ) ;
sta_tsk( TSK_ID2 , TTS_READY ) ;
1ビットのフラグを利用して、2個のLEDを交互に点滅する場合は
次のようにタスクを定義します。
#define OFF 0
#define ON OFF+1
void tsk0_proc(void)
{
if ( ENABLE_LED == ON ) {
/* 1秒周期 */
wai_tsk( 100 );
} else {
sus_tsk( TSK_ID1 );
sus_tsk( TSK_ID2 );
rsm_tsk( TSK_ID3 );
}
}
void tsk1_proc(void)
{
if ( FLAG == OFF ) {
LED_LEFT = LED_ON ;
LED_RIGHT = LED_OFF ;
}
}
void tsk2_proc(void)
{
if ( FLAG == ON ) {
LED_LEFT = LED_OFF ;
LED_RIGHT = LED_ON ;
}
}
void tsk3_proc(void)
{
LED_LEFT = LED_OFF ;
LED_RIGHT = LED_OFF ;
slp_tsk();
}
1、2バイトの情報交換->変数
1、2バイトの情報交換では、グローバル変数を用意して対処します。
1ビットのフラグを利用して、2個のLEDを交互に点滅する場合は
次のようにグローバル変数を定義し、利用します。
#define OFF 0
#define ON OFF+1
unsigned char led_pat[3] = {0x00,0x01,0x02};
#define OFF_PATTERN 0
#define RIGHT_ON_PATTERN 1
#define LEFT_ON_PATTERN 2
void tsk0_proc(void)
{
if ( ENABLE_LED == ON ) {
/* 1秒周期 */
wai_tsk( 100 );
} else {
sus_tsk( TSK_ID1 );
sus_tsk( TSK_ID2 );
rsm_tsk( TSK_ID3 );
}
}
void tsk1_proc(void)
{
if ( FLAG == OFF ) {
LED_BITS = led_pat[RIGHT_ON_PATTERN];
}
}
void tsk2_proc(void)
{
if ( FLAG == ON ) {
LED_BITS = led_pat[LEFT_ON_PATTERN];
}
}
void tsk3_proc(void)
{
LED_BITS = led_pat[OFF_PATTERN];
slp_tsk();
}
3バイト以上の情報交換->配列利用
他のコンピュータから、コマンドを与えられて動作するような
場合には、コマンドとパラメータが必要になります。
配列を利用して、受信バッファを構成するのが定石です。
コマンドを解釈し、他のタスクに指示を与えるための専用タスク
を用意して、コマンドインタプリタとします。
char sbuf[16] ;
char cmd ;
char sub_cmd ;
void tsk0_proc(void)
{
/* 受信バッファにデータなければ、そのまま抜ける */
if ( SFLAG == OFF ) return ;
/* フラグ処理 */
SFLAG = OFF ;
/* Unkownコマンドならば、そのまま抜ける */
if ( is_valid_cmd( *(sbuf+0) ) == NO ) return ;
/* branch */
switch ( *(sbuf+0) ) {
/* ID設定 */
case 'I' :
cmd = *(sbuf+1) ;
sub_cmd = *(sbuf+2) ;
rsm_tsk( TSK_ID1 ) ;
break ;
/* SPAN設定 */
case 'S' :
cmd = *(sbuf+1) ;
sub_cmd = *(sbuf+2) ;
rsm_tsk( TSK_ID2 ) ;
break ;
}
}
void tsk1_proc(void)
{
char stype ;
char snum ;
/* 形式取得 */
stype = cmd ;
/* シリアル番号 */
snum = 0 ;
if ( '0' <= sub_cmd && sub_cmd <= '9' ) {
snum = sub_cmd - '0' ;
}
if ( 'A' <= sub_cmd && sub_cmd <= 'F' ) {
snum = sub_cmd - 'A' + 10 ;
}
/* EEPROMへ保存 */
store_eeprom( stype , snum );
/* 終了 */
slp_tsk() ;
}
void tsk2_proc(void)
{
char snum ;
/* 10の位 */
snum = cmd - '0' ;
snum *= 10 ;
/* 1の位 */
snum += (sub_cmd - '0') ;
/* EEPROMへ保存 */
store_eeprom( SPAN_ADDRESS , snum );
/* 終了 */
slp_tsk() ;
}
目次
前
次