組み込みまするβ

組み込みソフトウェア初学者向けブログ

タスクスイッチのコスト

マルチタスク環境において、何かの待ちや定期処理の実行後は sleepやセマフォ待ち等で間接的に他のタスクへスイッチさせ、CPUの処理能力を有効に活用していると思いますが、 待ちがあるからと安易にタスクスイッチさせてしまうと非効率な動作となる場合があります。 本記事ではNOR-Flashの制御を例として具体的に考えてみましょう。

間接的なタスクスイッチ

例えばNOR-Flashのセクタイレーズの完了を待つ場合、 一般的なセクタイレーズ時間のtyp.が数百msec、max.が数secくらいなのでuITRON仕様OSならばdly_tsktslp_tskが使えそうですね。 以下のサンプルコードでは10msec遅延ですが、もっと長く待ってもよいでしょう。

startSectorErase(addr);

while (!eraseDone()) {
    dly_tsk(10/MSEC);
}

直接的なタスクスイッチ

では、typ.が数usec、max.が数十usecの単ワードプログラムの完了を待つ場合も同じようにdly_tsk関数等で対応すればよいでしょうか?

Tickの間隔は一般的には10msec程度での運用が多いので、 指定したTick数分の時間を待ってしまうdly_tskでは単ワードプログラムだけを考えると非常に効率が悪くなります。 また、tslp_tskを使うにしても、このケースでは起床させる契機を作ることが難しいです。

このような短い時間を待ちたい場合、 rot_rdq(TPRI_SELF)によってタスクスイッチさせるとTick単位の待ちにならずに効率が良くなります。

TPRI_SELFを引数にrot_rdq関数を実行しているのですから当然自タスクと同じ優先度の他タスクが存在することが前提です

unlock(addr);
write_io(addr, kCMD_PROG_SETUP);
write_io(addr, data);

while (!programDone()) {
    rot_rdq(TPRI_SELF);
}

タスクスイッチのコスト

他にも実行させたいタスクがあるならばrot_rdq(TPRI_SELF)によるタスクスイッチは良い選択になると思いますが、 単ワードプログラムの実行時間にフォーカスして考えてみるとどうでしょうか?

仮に単ワードプログラムの時間が 5usec、タスクスイッチが 15usecとし、1024ワード分をプログラムさせるとします。 上記の例で単ワードプログラムの時間がタスクスイッチ時間の裏で実行されると考えても15×1024=15,360usec かかりますが、 タスクスイッチをしなければ 5×1024=5,120usec で済むことになります。

元のタスクに戻ってくるまでの時間は、 単純に計算しても待ち行列に存在するタスクの数だけ、その実行時間とタスクスイッチ時間がかかります

まとめ

待ち時間とタスクスイッチのコストを考慮しないと処理能力を無駄にしてしまう場合があるという事です。

本記事のような単ワードプログラムを連続して実行するケースでは、 例えば256ワードプログラムしたらタスクスイッチする等である程度のパフォーマンスを改善でき、 他のタスクにも実行権がまわってくるようにできます。 このように組み込みソフトウェアは開発対象のシステムに応じて、 柔軟性のための汎用化よりパフォーマンスを優先して専用化しなければならない時があります。

最近ではNOR-Flashの単ワードプログラムが非推奨とされており、代わりにバッファプログラムを使用するのが一般的です。