ラベル DARETOKU-OS の投稿を表示しています。 すべての投稿を表示
ラベル DARETOKU-OS の投稿を表示しています。 すべての投稿を表示

2015年5月31日日曜日

LPC810でも動作するリアルタイム・オペレーティング・システムのUOS-LPC800にタスク間通信機能を追加しました!

あらまし

約二年も前の話ですが、「割と適当に動作するOS「誰得OS」のCortex-M0+版であるUOS-LPC800を作りました」で 、LPC810でも動作するリアルタイム・オペレーティング・システムを作りました。LPC800シリーズの厳しい制約(ROM: 4KB、RAM: 1KB)の中でOSを動作させてみたいという欲求と、実際にこのような制約の中で何が出来るのか、単純に技術的な興味があったからです。

当初のバージョンにおいて、タスク側から操作可能なAPIはuos_task_yieldとuos_task_sleepのみで、OSと呼ぶならば欲しいであろうタスク間通信すら追加しませんでした。 サンプル・プログラムは、片方のタスクでLEDを点滅させ、もう片方のタスクでシリアル通信を扱うだけのものです。まさに「誰得OS」の名前に相応しいアプリケーション。


なかなか思い切った割り切りだと当時は考えましたが、先日から実アプリケーションにUOS-LPC800を適用してみようと考え始めた時点で、タスク間通信の必要性を改めて感じる事になりました。各タスクがそれぞれの仕事をこなしつつ、他のタスクと協調して動作させようと考えた場合、タスク間通信は必須とも言える機能です。 やっぱり欲しいよね・・・。

設計

タスク間通信を追加する前のUOS-LPC800におけるタスクの状態遷移は以下です。タスクは、基本的にRunningとReadyを行ったり来たりしており、uos_task_sleepによってスリープ状態に遷移するようにしました。非常にシンプルな作りです。


今回、タスク間通信を追加するにあたって、方針を「出来るだけ現状の設計には手を加えないで追加する」とし、スリープ処理に手を加えない形でタスク間通信を追加する事にしました。

今回のタスク間通信(メッセージ・パッシング)のモデルは以下のようなものです。 Task Aからuos_task_event_sendに対して「送信先タスクID番号」と「32ビットの値」を渡すと、あーら不思議、uos_task_event_recvを使って待ち状態に入っているTask Bに値が渡って実行状態に遷移するというものです。モデルは至って単純。


今回、上記の単純なモデルを実現するために、カーネル内部にブロック状態を管理するタスク・コンテキスト・ブロックのキューを新設し、送信待ちタスクと受信待ちタスクをブロック状態のキューに入れてから処理する事にしました。状態遷移は以下のようになります。


本当は、スリープ状態もブロック状態の一種として扱え、相当な理由が無い限り分離する意味はなさそうなのですが、今回は既存機能に手を加えない事にしたのでそのまま。もしかしたら次のアップデートではブロック状態をBlockedに変更して、現在のBlockとSleepと統合するかもしれません。

サンプル・アプリケーション

サンプル・アプリケーションは、従来通り二つのタスクを用意しました。タスク間通信を使用する場合は、task_ttyからtask_ledに向かってタスク間通信機能を使ってLEDの点灯指令を発行します。外から見た動作は従来のサンプルと何ら変わらないのですが、タスク間通信で指令するようになったところが従来と異なります。

ちなみに、タスク間通信を使う場合、直接タスク間通信の関数を呼び出しても良いのですが、受信側タスクにサービス要求用のAPIを作って、送信側のタスクがそのサービス要求用のAPIを呼び出す方が筋が良い設計です。


巷に溢れる数多くのリアルタイム・オペレーティング・システムを使った実装例には、受信側タスクの内部事情を送信側タスクが知らなければ実装出来ないような記述が多く見られます。これではタスク間通信によって得られるはずの抽象化度を上げる事によるメリットの多くを享受出来ません。受信側タスクの事情を変更した場合(例えば、送信側に期待する送信内容を変更したとか)に、送信側タスクの実装を修正しなければならないとしたら、規模の大きな設計ではたちまちバグになります。

ダウンロード

2013年6月23日日曜日

割と適当に動作するOS「誰得OS」のCortex-M0+版であるUOS-LPC800を作りました

割と適当に動作するOS「誰得OS」のCortex-M0+版を作りました。

32ビットプロセッサとしては極めて小さいNXPセミコンダクターズ社のLPC810 (RAM=1KB、ROM=4KB) でもなんとか動作します。名付けてUOS-LPC800です。


以下の動画では、LED点滅タスクとUART送受信タスクが動作しているところを示しています。


LPC800 MiniBoardをお持ちの方はHEXファイルをダウンロードして試してみる事ができます。
「割と適当に動作する」などと言いながらも、スケジューリング・アルゴリズムはラウンド・ロビンと優先度ベースで選択できたりします。そして、カーネルの中核を成すコードはわずか300行で誰にも読み切れるサイズです。

今年中に「茶室で楽しむKOZOS拡張基板」のような企画をやりたいなぁ~と考えているところです。

2013年5月5日日曜日

ARM Cortex-M3のアセンブラ学習に最適なインストラクションを簡単に調べるツールを超適当に作ってみた

何それ?

ARM Cortex-M3のCソースコードから注釈付きアセンブラリストを得るスクリプトです。

先日の投稿で「誰得OS」を作る事を考え、インターフェースの設計を行いました。
このOSのターゲットとしてARM Cortex-M3を最初に選択しました。
ARM Cortex-M3のアセンブラを記述するのは初めてなので、カーネル内部コードを記述する際に役立つであろうインストラクションを簡単に調べるツールを超適当に作ってみた次第です。


このツールのフローは以下のようになっています。
  1. ソースコードをC言語で記述する
  2. ソースコードをコンパイルしてオブジェクトファイルにする
  3. オブジェクトファイルを逆アセンブルしてインストラクションリストにする
  4. インストラクションリストを走査して注釈を付ける
このツールで最終的に得られる出力は逆アセンブルされた命令に注釈が付いたテキストです。


上記のように、逆アセンブル結果から対応するインストラクションを列挙してくれます。
わざわざ辞書のようにインストラクションセットを引く必要もありません。

アセンブラを記述する場合、単純な「やりたい事」と「インストラクション」を繋げていく作業が大半を占めます。予めC言語で書いたソースをコンパイルし、それを逆アセンブルした結果をインストラクションセットと一緒に眺めれば学習効果が高まるだろうと考えたわけです。

ダウンロード

ダウンロードはこちらからどうぞ。
自己責任でお使い下さい。

テスト用のサンプルCソースとMakefile付き。
実行後の結果も一緒にまとめてあります。

実行したい場合、単にmakeと打つだけです。
地味ながらこれは便利。

2013年4月30日火曜日

割と適当に動作するOS「誰得OS」を作る事を考える No.1 (まずはインターフェースを考えるだけ)

先日から色々と思うことがあって、「割と適当に動作する」OSを作る事を考え始めました。
「割と適当に動作する」というのは、まぁ言ってみれば「オモチャとして動作します」という事です。

考えているOSは、リアルタイム性もないし、タスク間通信も最小限。
でも、自分が作ったからよくわかるという、その名も「誰得OS」です。

私の場合、ソフトウェアは基本的にインターフェースの設計から始めます。
この基本方針はOSになっても変わりません。

まずは「誰得OS」のインターフェースを考える事にしました。


「誰得OS」は、
  1. daretoku_kernel_initでカーネル・オブジェクトを初期化。
  2. daretoku_task_initでタスクを初期化。
  3. daretoku_kernel_startでカーネルを動作開始。
と最低限3つのインターフェースを知っていれば動作させる事ができます。
「できます」と書いていますが、まだできていないので、そうなるように作る事にします。

ただ単にマルチ・タスクなだけではOSとしてあんまりなので、タスク間通信もdaretoku_msg_send_waitとdaretoku_msg_recv_waitで実現する事にします。

優先度とかは後で考える事にして今は放置。
当然のようにリアルタイム性に対する考慮なんてしません。

残念なOS、それが「誰得OS」なのです。
という事で、インターフェースを考えるだけなら簡単です。

これからチマチマと実際に動作するOSに仕立てていく作業が始まります。
適当に作る割に先は長そうです。