小さなマイコンではOSなしの場合も少なくないですが、やはりOSがあると便利です。
大雑把に言えば、RTOS(リアルタイムOS)="組み込みで使われるOS"です。
OSとは
OSの最も基本的な機能
- マルチタスク
あるいは、マルチタスクのアプリケーションを(簡単に)つくるための環境を提供すること
(厳密には正しくないが、今どきシングルタスクのOSなんてないので)
その基本の上に、ハードウェアの抽象化だとかネットワーク機能などが乗ってきます。
マルチタスクとは
マルチタスクとはいくつかの処理を並列化することで、例えば
- キーを押す(押されたのを検出する)
- シリアル通信する
は、それぞれをタスクと見なすことができます。
キーが押されるまで何もしないのがシングルタスク、
キーを押されるのを待っている間、別の処理をする(シリアル受信したらその処理をする等)のがマルチタスクです。
OSなしでも、普通はマルチタスクプログラミングをしますが、この場合は
void main(void)
{
while (1)
{
if (キーが押された)
{
キー処理
}
if (シリアル受信した)
{
受信処理
}
}
}
main関数の中でループをまわすので、メインループと言います。
これが、OSを使うと以下のようになります。
void taskfunc_key(void)
{
while (1)
{
wai_flg(); // キーが押されるまで待つ
キー処理
}
}
void taskfunc_serial(void)
{
while (1)
{
wai_flg(); // 受信するまで待つ
受信処理
}
}
これらタスク関数はOSの中から呼ばれます。待つための関数(システムコール)がOSから提供されていて、
キーが押されたらこの関数から抜ける、というように、条件が成立するまでブロックします。
上記のwai_flgはiTRONのシステムコールで、FreeRTOSならxEventGroupWaitBits(のはず、あまり詳しくないので)など。
この部分はOSによる差異はほとんどないので、関数名が変わるだけでやることは同じです。
OSなしでも特に不都合なさそうにも見えますが、タスクが多くなってくると、フラグ(グローバル変数)が山のように増えて手に負えなくなってきます。
また、OSなしの場合は「キー処理」や「受信処理」に時間制限をかけるのが難しく、受信処理が長引くと、それまでキーが反応しないといったことになりかねません。
そこで、
RTOS
処理の途中でも強制的にタスクを切り替えるようにしたのが、RTOS(リアルタイムOS)です。
レジスタやスタックの退避復元などを駆使して、途中から再開できるようにしています。
例えば、変数に1を代入している最中(movとmovの間)にタスクが切り替わり、再開したときにaの値が変わっていたら正しい結果になりません。
(例はRL78、aは汎用レジスタ)
/* var = 1; */
mov a, #1
mov !_var, a
そうならないように、切り替える前にレジスタの値を(タスクごとに)退避して、再開するときに復元させているのです。
強制的に、というところはマイコンの機能(割り込み)を使って実現しているので、当然OSなしでも同じことはできますが、それを勝手にやってくれるのがRTOSです。
まとめ
OSを使うことによって得られるメリットは
- 簡単にマルチタスクプログラミングができる
- 一定の応答性を確保できる
逆にデメリットは
- OSを動作させるまでが大変
- OS自体がメモリを食う
メモリの制約が厳しければOSなし
多機能ではない、大した処理をしない場合もOSなしでよいです。
ですが、ハードウェアの抽象化(マイコンに依存しないプログラムになる)の側面もあるので、他のマイコンへの移植も考えるならOSのメリットは大きいです。