SSブログ
Smalight OS ブログトップ
前の10件 | -

Smalight OS本が来る前に [Smalight OS]

P1010002.jpg本の方は明日の配送予定となっています(※本は届いております)が、先にルネサス北セミからパスワードを頂きましたので、森北出版のサイト上からSmalight OSのお試し版(と言っても機能はver.3そのままで、ターゲットのマイコンが3664Fと3694Fに制限されているのみ)を落してきて、手元の3694Fマイコン(例のトラ技の付録基板)上で動かしてみました。

いきなりSmalight OSを使ったアプリケーションを用意できないので、サンプルとして入っている”u-ap”を動かしています。
smalightos_001.png実際にパスワード申請し、落して見てください。
この”u-ap”は、3つのタスクを実行します。それぞれのタスクの属性ですが、task01が優先度タスク、task02とtask03はローテーションタスクとして生成され、3つとも初期状態はREADYとなっています。

このアプリケーションは何ら出力を持たないので、動作確認にはE8エミュレータを使っています。E8エミュレータ上で動かす時は、RAMの一部の制限領域を避けてセクションを配置する必要があります。

このアプリケーションの動作を簡単に説明しますと、
1.task01がRUNNING→slp_tskでWAITINGに遷移
2.task02がRUNNING→rot_rdqでローテーションタスク内の実行タスクの切り換え
3.task03がRUNNING→wup_tskでtask01を起床、そのままREADYに遷移
4.task01がRUNNING→しかしすぐにslp_tskでWAITINGに遷移
5.task03がRUNNING→しかしすぐにslp_tskでWAITINGに遷移
6.task02がRUNNING→wup_tskでtask03を起床、しかしそのままRUNNING
7.task02がRUNNING→wup_tskでtask01を起床、そのままREADYに遷移
8.task01がRUNNING→しかしすぐにslp_tskでWAITINGに遷移
9.task02がRUNNING→しかしすぐにslp_tskでWAITINGに遷移
10.task03がRUNNING→rot_rdqでキューを廻すが、特に切り替えるべきタスクが存在しないのので、そのまま
11.task03がslp_tskでWAITINGに遷移
12.全てのタスクがWAITINGになってしまったので、”idle”が実行される。
と言った流れで動きます。

※実際にはここまで激しく実行状態を他のタスクに依存するプログラムはやらない方が良いと思う。
プログラムサイズが大きくなって見通しが悪くなった時、うっかり全部のタスクがWAITINGなんて事になりかねない。つまりデッドロックしてしまう。
機能分割と言う点でも、なるべく他のタスクとの繋がりは、疎結合にした方が。

※取り敢えず2章の途中まで読んだのですが、もっとも基本的なサービスコールを、図解を使ってみっちり解説されている所が、μITRONの入門本としてきわめて適していると思います。これだけ基本的なサービスコールを解説してあれば、後は拡張機能みたいなもので、自分で使いながら十分習得可能だと思います。


図解 μITRONによる組込みシステム入門 - H8マイコンで学ぶリアルタイムOS

図解 μITRONによる組込みシステム入門 - H8マイコンで学ぶリアルタイムOS

  • 作者: 武井 正彦
  • 出版社/メーカー: 森北出版
  • 発売日: 2008/01/29
  • メディア: 単行本(ソフトカバー)



Smalight OS本 その後 [Smalight OS]


図解 μITRONによる組込みシステム入門 - H8マイコンで学ぶリアルタイムOS

図解 μITRONによる組込みシステム入門 - H8マイコンで学ぶリアルタイムOS

  • 作者: 武井 正彦
  • 出版社/メーカー: 森北出版
  • 発売日: 2008/01/29
  • メディア: 単行本(ソフトカバー)


いやすいません、まだ購入していなかったのですが、先ほどアマゾンに注文しましたとも。

久しぶりにアマゾンの該当ページを見たら、書評が3つになっています。じょじょに評価は高まっているようです。
この本の最大のネックは、発売開始当初に無償版または低価格なSmalight OSの用意が出来ていなかったため、理論面だけで、実際に動かしてみる実践的な要素が少なかった点だと思いますが、なんと森北出版のサイト上で無償版を落せるようになったのですね。

事前にルネサス北セミへパスワードの申請が必要ですが、「教育関係、ホビーユースで使用したい方は云々」と、学生さんやホビーユーザー向けの対応も取ってくれるみたいですので、是非これを機会にRTOSを試してみては如何でしょうか。
私も、本が来たら、是非Smalight OS V3を手持ちのH8に入れて試してみたいと思います。

※TRON協会の「1時間で判る組み込みリアルタイムOS」もなかなか良いドキュメントです。
http://www.assoc.tron.org/jpn/seminar/index.html
製作に関わった人の中に武井さんの名前が。しかもシミュレータの提供はルネサスでしょ。

もちろん以下の本も宜しくね。

ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発

ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発

  • 作者: 濱原 和明
  • 出版社/メーカー: オーム社
  • 発売日: 2005/04/25
  • メディア: 単行本



新しいμITRON (Smalight OS)本が出るようです [Smalight OS]

図解 μITRONによる組込みシステム入門 - H8マイコンで学ぶリアルタイムOS

図解 μITRONによる組込みシステム入門 - H8マイコンで学ぶリアルタイムOS

  • 作者: 武井 正彦, 中島 敏彦
  • 出版社/メーカー: 森北出版
  • 発売日: 2008/01/24
  • メディア: 単行本(ソフトカバー)


発売日はもう少し先と言う事ですな。
出版社の解説はここで読めます。
http://www.morikita.co.jp/mkj/78451.html

書籍の題名がμITRONとなっていますが、勿論μITRONの説明も入っていますが、実際にシステムを組むのはSmalight OSです、、、。
うーんあれをμITRONと言って良いのだろうか?。実践に入るまでの解説と、実際の動作の食い違いが混乱を招く様な。

ところでCDとか付いて来て、それにSmalight OSが入っているのかなぁ。
Smalight OSがおまけなら、結構欲しい。

こちらも宜しくです。

ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発

ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発

  • 作者: 濱原 和明
  • 出版社/メーカー: オーム社
  • 発売日: 2005/04/25
  • メディア: 単行本

※追加情報
内容物については、先の森北出版のホームページから問い合わせをしてみて下さい。
発売前に反響が有れば、著者の方も、出版社の方も嬉しいでしょうから。
先程メールが届いて、目次と付録2の製版直前の原稿(縁に合わせマークみたいなのが入っている。懐かしい(笑)。)をPDFで頂きました。著作物なので、内容等はこちらからは言えませんけれど。

Smalight OS、利用できるならとても良いと思いますよ。
HOSはRTOSの勉強を最大の性能として、ちゃんと成功しているし、支持もされていますが、商用RTOSなら速度や必要リソースの小ささ、何よりもバグが無い事が最大の性能でしょうからね。

本は買います。あそこのセミナーのドキュメントは良くできているし、昔からTRON協会に何かと言えば協力を求められて来た所ですから。
※人を出してくれ~~!とか、ドキュメント作ってくれ~~!とか。


某誌のなんとかアカデミー最終回 [Smalight OS]

今頃になって某誌6月18日号を読んでみました。
まあ記事全般は面白かったのです。アナログ放送の停波にはムカッと来ましたが。

でまあ、例によってなんとかアカデミーも読んでみましたが、相変わらず無茶を書く。

記事の内容は、高負荷時の割り込みと、それによって発生するスラッシングのメカニズムの解説と言った所でしょうか。
記事を転載できないので要約すると、「高負荷時に非同期の割り込みが集中発生すると、スラッシングと言う状態に陥り、実行し損ねた割り込みを実行しようとして、徐々にスタック領域を食いつぶし、最後にはシステムクラッシュに陥る」との事です。

うーーん!割り込みって、割り込み処理が終わる度にスタック領域が返却される事になっているので、割り込みが集中したとしても、全体の使用量は決まっているんですけれどね。
返却し切れていないスタックが有ったとすれば、それはプログラムに問題が有るのですよ(普通にC言語で開発すればそんな事にはならない筈。アセンブラ等を使って自分でスタックをいじった場合は、返却し損ねは可能性として有る。)。

多分、多重割り込みが発生した時にスタックオーバーフローになると言いたかったのかもしれませんが、本来多重割り込みが発生する事を想定してシステムを作っているのでしょうから、ワーストケースのスタック使用量は事前に盛り込んだ上でシステム設計するのが普通でしょう。最近の統合開発環境ならば、自動的にスタックサイズも計算してくれたりしますし。

つまりそこでスタックオーバーフローしているシステムは、高負荷状態でなくともスタックオーバーフローする可能性が有ると言う事になります(非同期割り込みですから。)。

ではスラッシングとは?になりますが、簡単に言えば、割り込みの出入り口処理の様な、本来の処理に関係しない処理に掛かる時間が、本来の処理に必要な時間を圧迫している状態。

対策は!、CPUを速い物に交換してください(*^。^*)。だって、処理が間に合わないからそうなっているんだから。後はプログラムを工夫するとか、メモリやメモリ配置を工夫して、メモリアクセスに掛かる時間を減らすとか。

他に対策できる要素を検討してみると、結局割り込みの数を減らせばよい訳で、例えば低価格なマイコンのSCIって1byte位しかバッファが有りませんので、転送スピードが速く、転送数が多いと、結構マイコンは苦しくなって来ます。もし使えるなら、NS16550の様に16byte位のバッファを内蔵している周辺チップを使えば、かなーり楽になる筈です。
ネットワークコントローラなんかも、一々パケットを受信する度に対応するのではなく、大概はコントローラ内部に大きなバッファを持っていますので、しばらく放って置いてから複数のパケットをまとめて処理すれば、割り込みのオーバーヘッドをかなり削減できます。DMAを使うのも有効でしょう。
TCP/IPなんかはリアルタイム性を保障しなくてもいいので、受信パケットは暫く放って置けます。

結局高負荷での実行中に「割り込みを制限する」なんてのは多分無理なので、システム設計の段階で、十分検討し、必要ならばCPUの負担を減らす対応をするしか無いですね。

あと、右側の注1)ですが、それはCISC、RISCの違いではないでしょう。割り込みコントローラの違いだと思うんだが。


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で始める組み込み開発

ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発

  • 作者: 浜原 和明
  • 出版社/メーカー: オーム社
  • 発売日: 2005/04/25
  • メディア: 単行本


Smalight OSを使おう 11タスク目 イベントフラグの使用3 [Smalight OS]

この記事は、某SNSで書いているものを転載しています。
今回は、イベントフラグのクリアについて解説します。と言いましても、既に何度かサンプルの中で使っているので、もう用済みかな。

まずイベントフラグのクリアの方法には、二つの方法が有ります。
1.初期化時に、クリア属性を指定。
2.ユーザーがタスクの中でclr_flgを使用してクリア。

プログラムが一見簡単に構築できそうなのは、1.です。一々プログラムの中でクリアの処理を記述しなくても良いですから。
しかしこのクリア属性、そのクリアの仕方に落とし穴が有り、符号無し16bitを一気にクリアしてしまう為、もしビットそれぞれに意味が有ったとしたら、その意味を正しく受け取る前に、クリアされてしまうかも知れません。

この状況がどの様な時に問題になるのか説明します。
おそらく、一つのイベントフラグに、一つのタスクのみ待ち状態になるなら、wai_flgの戻り値を受ける事で、ビットの意味を失う事は無いでしょう。
しかし、一つのイベントフラグに複数のタスクが待ち状態になる時、それは起きます。

では実際にプログラムを動かして、その様子を見てみます。

コンパイラの設定は、
  EVENTFLGを有効
config.cの設定は、
  tsk01:優先度1、起動時READY
  tsk02:優先度2、起動時READY
  tsk03:優先度3、起動時READY
ユーザー初期化関数uinitの設定は、
  EVTFLG_ATTR(FID_1, EVFLG_TA_AND | EVFLG_TA_CLR | EVFLG_TA_TPRI );

#define TID_1		1	/**/
#define TID_2		2	/**/
#define TID_3		3	/**/
#define FID_1		1	/**/
#define FLG_WAIT_PTN_01	0x0001	/**/
#define FLG_WAIT_PTN_02	0x0002	/**/

void uinit(void)
{
  /* initialize */
  /* event flag initialize  */
  evtflg_init();
  EVTFLG_ATTR(FID_1, EVFLG_TA_AND | EVFLG_TA_CLR | EVFLG_TA_TFIFO );
}

void tsk01( void )
{
  wai_flg( FID_1, FLG_WAIT_PTN_01 );
  slp_tsk();  /*ここにブレークポイントを設定*/
}

void tsk02( void )
{
  wai_flg( FID_1, FLG_WAIT_PTN_02 );
  slp_tsk();  /*ここにブレークポイントを設定*/
}

void tsk03( void )
{
  set_flg( FID_1, FLG_WAIT_PTN_01 | FLG_WAIT_PTN_02 );
  while( 1 ) ;
}

さて、二箇所にブレークポイントを設定しましたが、tsk02のブレークポイントに達したでしょうか?。
答えは否ですね。
動作を説明すると、まずtsk01が起動し、イベントフラグの待ち状態に入ります。続いてtsk02が起動し、やはり同様に待ち状態に入ります。最後にtsk03が起動し、二つのビットをセットします。

このset_flgの中でtsk01がイベントフラグ待ち状態である事を検知したOSは、tsk01の待ち状態を解除し、戻り値に現在のフラグをコピーした後、イベントフラグがクリア属性である為、フラグの内容を全てクリアしてしまいます。
その為、tsk02のWAITが解除とならず、このプログラムではそのまま待ち続ける事となってしまいました。
この様にクリア属性をうっかり使用すると、思わぬバグとなってしまいます。

では、複数のタスクが一つのイベントフラグの待ち状態になっても事故を起さない方法は、それは勿論無関係なビットのクリアを行わない事!これに尽きる訳です。
上のプログラムを下記の様に書き換えて動かしてみます。

void uinit(void)
{
  /* initialize */

  /* event flag initialize  */
  evtflg_init();
  EVTFLG_ATTR(FID_1, EVFLG_TA_AND | EVFLG_TA_TFIFO );
}

void tsk01( void )
{
  wai_flg( FID_1, FLG_WAIT_PTN_01 );
  clr_flg( FID_1, ~FLG_WAIT_PTN_01 );
  slp_tsk();  /*ここにブレークポイントを設定*/
}

void tsk02( void )
{
  wai_flg( FID_1, FLG_WAIT_PTN_02 );
  clr_flg( FID_1, ~FLG_WAIT_PTN_02 );
  slp_tsk();  /*ここにブレークポイントを設定*/
}

void tsk03( void )
{
  set_flg( FID_1, FLG_WAIT_PTN_01 | FLG_WAIT_PTN_02 );
  while( 1 ) ;
}


EVTFLG_ATTRマクロのEVFLG_TA_CLRを削除しています。
wai_flgの後にclr_flgを追加しています。
どうでしょうか、今度はtsk01、tsk02の両方のブレークポイントに到達した筈です。

最近、新しい本が出ましたね。

組み込みソフトウェアの設計&検証―割り込み動作からRTOSを使った設計、ツールによる動作検証まで

組み込みソフトウェアの設計&検証―割り込み動作からRTOSを使った設計、ツールによる動作検証まで

  • 作者: 藤倉 俊幸
  • 出版社/メーカー: CQ出版
  • 発売日: 2007/02
  • メディア: 単行本


もしR8Cを入手するとなると [Smalight OS]

おお、DIGIKEYで689円で1個から購入できるんですね。
http://catalog.digikey.com/scripts/partsearch.dll?lang=ja&site=JP&keywords=R5F21256&x=22&y=12
もう、海外メーカばかりが安いとは言わせないぞ!ってところでしょうか。
16bit、20MHz、ROM 32K、RAM 2Kですし。開発環境も揃っているし。

ちなみにMSP430F4270の価格は、1個で買うと960円。


Smalight OSを使おう 10タスク目 イベントフラグの使用2 [Smalight OS]

この記事は、某SNSで書いているものを転載しています。
さて今回はイベントフラグの隠れた機能である、タスク間通信について書いてみます。
以前通信機能が無い!と書いてしまいましたが、実はリザルトコードの中にこっそり、待ち解除時の受信パターンが存在する事に気が付きまして、ならばタスク間通信についてもご紹介しておこうと言う次第です。

まず受信側のサービスコールであるwai_flgについておさらいしますが、書式は以下の様になります。

W wai_flg( UB FLG_ID、UH flg_ptn );
  戻り値:E_OK(=0)と待ち解除時のパターンのOR。符号付32bitである事から、戻り値の上位16bitが0x0000であれば正常に受信したと判断でき、下位の16bitを待ち解除時のパターンとして取得できます。
※マニュアルの記述は間違っていますね。
  UB FLG_ID:フラグID
  UH flg_ptn:待ちパターン(複数ビットを一度にセットしてもOK)
  適用:タスク部で使用可能。初期化関数のマクロで生成した待ち条件が成立するまでWAITとなります。例えば待ちパターンを0x00ffとし、待ち条件がAND条件ならば、下位の8bit全てセットされるまでWAITを継続します。待ち条件がOR条件ならば、下位8bitの何れかがセットされた時点でWAIT状態が解除されます。

イベントフラグは符号無し16ビットなので、戻り値の符号付32ビットに収納可能です。
普通に
  UH rcv_ptn;

  rcv_ptn = ercd;

とすれば、受信パターンが取得できます。
※twai_flgの場合は、場合に拠っては上位側のエラーコードを調べる必要が有るかもしれません。

さて、この様にデータの受け渡しが可能なのですが、唯一転送できないデータが有ります。
元々イベントフラグは、任意のビットの何れかをセットする事で相手タスクとの同期を取りますので、16bitのいずれもセットされていないと、相手にイベントの通知をしません。
つまり0x0000は送れないということになります。

また、前回も書きましたが、ビットパターンは上書きされますので、送るタイミングと受け取るタイミングも重要になって来ます。
※単にイベントの発生のみ通知するなら、つまりスイッチが押されている等の”状態”をイベントとする場合は、上書きされてもあまり影響は無いかもしれません。しかし押された数をカウントする場合は、上書きされてしまう事で、数が少なくカウントされる可能性が有ると言う事です。

とまあ、ここまでの説明でなんとなく判ったと思いますので、サンプルプログラムに入ってみたいと思います。
コンパイラの設定は、
  EVENTFLGを有効
config.cの設定は、
  tsk01:優先度1、起動時READY
  tsk02:優先度2、起動時READY
ユーザー初期化関数uinitの設定は、
  EVTFLG_ATTR(FID_1, (EVFLG_TA_OR) | EVFLG_TA_TFIFO );

#define TID_1		1	/**/
#define TID_2		2	/**/
#define FID_1		1	/**/

void uinit(void)
{
  /* initialize */
  /* event flag initialize  */
  evtflg_init();
  EVTFLG_ATTR(FID_1, EVFLG_TA_OR | EVFLG_TA_TFIFO );
}

void tsk01( void )
{
  UH rcv_ptn;

  while( 1 )
  {
    rcv_ptn = wai_flg( FID_1, 0xffff );
    clr_flg( FID_1, ~rcv_ptn );	/*ここにブレークポイント*/
  }
}

void tsk02( void )
{
  int i;

  for( i = 10; i >= 0; i-- )
  {
    set_flg( FID_1, i );
  }

  while( 1 ) ;
}

コメントでブレークを貼る位置を指定しておきますので、そこにブレークポイントを設定します。
またこの時、tsk01のrcv_ptnをWATCHしておくと、その動作がよく判ります。

tsk01は起動直後のwai_flgによってWAITに遷移します。
この時の起床条件ですが、OR属性で、待ちパターンが0xffffであることから、16bitのいずれかがセットされた場合、待ち状態が解除される事が判ります。

tsk01が待ち状態に入ったので、tsk02が起動し、ループの中で10~0までの数字を一回ずつセットします。

tsk02で10~1までの数字が送られる度にtsk01の待ち状態が解除され、ブレークポイントの位置で停止しますので、WATCHしているrcv_flgを見てみます。ちゃんと10~1まで受け取っているでしょうか?。

最後に0を送信していますが、tsk01は起床されず、またtsk02もその後whileループに入ってしまいますので、結局0を受け取る事は出来ませんでした。

上の例題は、受ける側のタスクの優先度を高く、送る側の優先度を低く設定している為に、とりあえず10~1までは正常に受ける事ができました。
では、この優先度を逆にしてしまうとどうなるのか試して見ます。つまり、tsk01が送る側であり、tsk02が受ける側です。
以下の様にプログラムを変更します。

void tsk01( void )
{
  int i;

  for( i = 10; i >= 0; i-- )
  {
    set_flg( FID_1, i );
  }

  slp_tsk();
}

void tsk02( void )
{
  UH rcv_ptn;

  while( 1 )
  {
    rcv_ptn = wai_flg( FID_1, 0xffff );
    clr_flg( FID_1, ~rcv_ptn );	/*ここにブレークポイント*/
  }
}


今回の結果は、まずブレークポイントでの停止が一回しか行われず(※set_flgを発行してもWAITには遷移しない為)、また受信したパターンを見ると、0x000fとなっている事が判ります。つまり、10~0までのすべてのビットがORされてしまった結果です。

この事を踏まえて、あらためてタスク間通信の方法を考えてみると、例えば以下の様な方法が有ります。
送る側の優先度を低く、受ける側の優先度を高く設定する。
送るデータは0~0x7fffの範囲とし、最上位ビットはイベントとして利用する。
つまり送る側では0x8000 | dataとし、受ける側は待ちパターンを0x8000とすれば良いと言う事です。
送る側
  set_flg( FID_1, 0x8000 | data );
受ける側
  rcv_ptn = wai_flg( FID_1, 0x8000 );

CQ出版のセミナーで講師をされている方の本です。


Smalight OSを使おう 9タスク目 イベントフラグの使用1 [Smalight OS]

この記事は、某SNSで書いているものを転載しています。
今回は、使うと便利なイベントフラグの説明に入ります。

イベントフラグは、特定の待ちパターン(ビットパターン)を送る側と、受ける側に別れてタスクの同期を取る為に利用します。
受ける側は必ずタスクでなければなりません。送る側はタスクの場合と、OS管理下のタスク以外の状態(簡単に言えばOS管理下の割り込みハンドラ)から可能です。

送る時は、符号無し16bitの中の任意のbitを1にセットします。
例えば0x0001を送る側のサービスコールであるset_flg等の引数とし、bit0をセットします。
この時0x0001を連続で10回セットすれば、相手側も10回起床するか?と言えば答えはNOで、実際にはOS内部のフラグに毎回引数がORされる為、相手が即座に起床してそのビットがセットされた事を認識できれば10回可能ですが、相手が起床する前にこちらが上書きしてしまう可能性も有ります。
つまり相手がちゃんとこのイベントを認識したかどうかの保証は、プログラマが別の手段で確保する必要が有ります。

受ける時は、符号無し16bitの中の任意のビットがセット条件になる事を待ちます。
この時、ビットの待ち方には二つの方法が有ります。
  1.複数のビットの内の1ビットでもセットされれば、待ち状態から解除される物:OR条件。
  2.複数のビットの全部がセットされるまで、待ち状態を継続する物:AND条件。
※既に該当ビットがセットされていたら、待ち状態に入らずに戻って来る。

この二つの使い分けは、ユーザー初期化関数(uinit)実行時に決定されます。
具体的には「EVTFLG_ATTR」マクロの記述で属性に
  EVFLG_TA_OR:OR条件
  EVFLG_TA_AND:AND条件
の何れかを記述します。

ついでに他の属性を説明します。
  EVFLG_TA_CLR:受信側が待ち状態から解除される時、ビットパターンをOSがクリアする。
※この属性は一見便利に見えますが、複数のタスクが一つのイベントフラグの待ち状態になる場合、注意して使わないと思わぬバグになります。

  EVFLG_TA_TFIFO:タスクの待ち状態からの解除を、先着順にする。
  EVFLG_TA_TPRI:タスクの待ち状態からの解除を、優先度順にする。
の何れかを記述します。

これら属性の指定方法は、以下の様に記述します。

  EVTFLG_ATTR(1, (EVFLG_TA_ANDまたはEVFLG_TA_OR) | EVFLG_TA_CLR | (EVFLG_TA_TFIFOまたはEVFLG_TA_TPRI));

※属性の先頭の1はフラグID番号。

なお、初期状態の属性は
  EVFLG_TA_TFIFO | EVFLG_TA_AND
となっています。

では具体的にsmalight osに用意されているサービスコールの使い方を説明します。
※ちょっと説明に手抜きしています。

void set_flg( UB FLG_ID、UH flg_ptn );
  戻り値:有りません。
  UB FLG_ID:フラグID
  UH flg_ptn:ビットパターン(複数ビットを一度にセットしてもOK)
  適用:タスク部で使用可能。割り込みから使用する時は、先頭に"i"を付けたiset_flgを使用します。

W wai_flg( UB FLG_ID、UH flg_ptn );
  戻り値:E_OK(=0)と待ち解除時のパターンのOR。符号付32bitである事から、戻り値の上位16bitが0x0000であれば正常に受信したと判断でき、下位の16bitを待ち解除時のパターンとして取得できます。
※マニュアルの記述は間違っていますね。
  UB FLG_ID:フラグID
  UH flg_ptn:待ちパターン(複数ビットを一度にセットしてもOK)
  適用:タスク部で使用可能。初期化関数のマクロで生成した待ち条件が成立するまでWAITとなります。例えば待ちパターンを0x00ffとし、待ち条件がAND条件ならば、下位の8bit全てセットされるまでWAITを継続します。待ち条件がOR条件ならば、下位8bitの何れかがセットされた時点でWAIT状態が解除されます。

W twai_flg( UB FLG_ID、UH flg_ptn, W rel_tim );
  戻り値:E_OK(=0)、またはE_TMOUT(=0x00CE0000L)と待ち解除時のパターンのOR。符号付32bitである事から、戻り値の上位16bitが0x0000であれば正常に受信したと判断でき、下位の16bitを待ち解除時のパターンとして取得できます。
逆に上位16bitが0でなければタイムアウトしたと判断できます。
  UB FLG_ID:フラグID
  UH flg_ptn:待ちパターン(複数ビットを一度にセットしてもOK)
  適用:基本的にwai_flgと同じですが、時間管理の仕様はtslp_tskと同じです。

W clr_flg( UB FLG_ID、UH flg_ptn );
  戻り値:有りません。
  UB FLG_ID:フラグID
  UH flg_ptn:クリアパターン
  適用:タスク部で使用可能。EVFLG_TA_CLR属性を使用していない時、OSが管理しているフラグと引数のクリアパターンのAND積を取ります。
つまりですね、bit0をクリアしたい時は、~0x0001をクリアパターンとして引数に代入すればよいと言う事です。

それでは具体的にプログラムを組んでイベントフラグの動作を実感してみましょう。
コンパイラの設定は、
  EVENTFLGを有効
config.cの設定は、
  tsk01:優先度1、起動時READY
  tsk02:優先度2、起動時READY
ユーザー初期化関数uinitの設定は、
  EVTFLG_ATTR(FID_1, (EVFLG_TA_ANDまたはEVFLG_TA_OR) | EVFLG_TA_TFIFO );

#define TID_1		1	/**/
#define TID_2		2	/**/
#define FID_1		1	/**/

void uinit(void)
{
  /* initialize */
  /* event flag initialize  */
  evtflg_init();
#if 0
  EVTFLG_ATTR(FID_1, EVFLG_TA_AND | EVFLG_TA_TFIFO );
#else
  EVTFLG_ATTR(FID_1, EVFLG_TA_OR | EVFLG_TA_TFIFO );
#endif
}

void tsk01( void )
{
  W ercd;

  while( 1 )
  {
    ercd = wai_flg( FID_1, 0x00ff );
    clr_flg( FID_1, ~ercd );	/*ここにブレークポイント*/
  }
}

void tsk02( void )
{
  int i;
  UH flg_ptn;

  for( i = flg_ptn = 0; i < 16; i++ )
  {
    flg_ptn >>= 1;
    flg_ptn |= 0x8000;
    set_flg( FID_1, flg_ptn );	/*ここにブレークポイント*/
  }

  while( 1 ) ;	/*ここにブレークポイント*/
}


uinitの中の#if~#elseの条件を切り替えてオンチップデバッカーで試してみて下さい。
コメントでブレークを貼る位置を指定しておきますので、そこにブレークポイントを設定します。
またこの時、tsk02のflg_ptnをWATCHしておくと、その動作がよく判ります。

まず#if 1とした時ですが、この時はAND属性となる為に、待ち側では指定したビットの全てがセットされるまで待つ事になります。

tsk01は起動直後のwai_flgによってWAITに遷移します。

続いてtsk02が起動し、変数flg_ptnの左側から1で埋めていきます。
ループを継続している間set_flgにてセットパターンを送信していますが、tsk01の起床条件と一致しない為に、ディスパッチが発生していません。

最後のループでflg_ptnが0xffffとなり、そのセットパターンが送信されると、tsk01がWAITからREADYに遷移し、更に優先度からプリエンプトしてclr_flgの位置で停止します。

tsk01は、ループが回って再びwai_flgのところでWAITに遷移しますので、READYであったtsk02の実行が再開され、while文のところで停止します。

次に#if 0とした時ですが、この時はOR属性となる為に、待ち側では指定したビットの何れかがセットされるまで待つ事になります。

tsk01は起動直後のwai_flgによってWAITに遷移します。

続いてtsk02が起動し、変数flg_ptnの左側から1で埋めていきます。
ループを継続している間set_flgにてセットパターンを送信していますが、tsk01の起床条件と一致しない為に、ディスパッチが発生していません。

9回ループが回ったところででflg_ptnが0xff80となり、そのセットパターンが送信されると、tsk01がWAITからREADYに遷移し、更に優先度からプリエンプトしてclr_flgの位置で停止します。

その後7回clr_flgの位置で停止します。

RTOS理論系

リアルタイムシステムとその応用

リアルタイムシステムとその応用

  • 作者: 白川 洋充, 竹垣 盛一
  • 出版社/メーカー: 朝倉書店
  • 発売日: 2001/08
  • メディア: 単行本


Smalight OSを使おう 余談 [Smalight OS]


今までsmalight osに付いて色々書いて来て、一部疑問を投げ掛ける事で私がsmalight osに付いて非難しており、まるで使うな!と書いている様に思えるかもしれませんが、そうじゃあないんです。あくまでもタイトルの通り「Smalight OSを使おう!」なんですよ。
色々苦言みたいに書いている所は、もっと良くして欲しい!と言う気持ちの表れですから。

折角ルネサスさんが読者の方の為にsmalight osやE8エミュレータ回路のパーツを提供して頂いたんだから、皆さん是非smalight osを使ってみましょうよ。
何よりも応答性や信頼性に付いては問題ないのだろうから、RTOSとしてはちゃんと出来ているものだろうし、そう考えればサービスコールが少ない!なんて小さい事です。

実際ルネサス北セミだけでなく、ルネサス内部でもsmalight osの評価は高いみたいで、例えばルネサスのH8/300HシリーズのITRON製品は、μITRON ver.3で停止してしまっていますが、その後釜にsmalight osを据えようとしているのでしょう。
※ルネサスのサイトでH8/300H用ITRON製品を探したが、あれ!H8S用は有るけれど、H8/300H用が見当たらない。

そんな訳でルネサスさん、まあ多分見ている事は無いでしょうけれど、お願いだから今回のR8C/25用のsmalight osの利用制限を、日経エレクトロニクス基板限定ではなく、R8C/25を使った非商用利用(ホビーユース)にまで広げてくれませんか。
もう、あの基板はどうにもこうにも、、、。

あと、、、コンフィギュレータは用意した方が良いと思うよ。


前の10件 | - Smalight OS ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。