(1) (挨拶) それでは、KOZOSのARM系プロセッサの移植に関する発表を行います。 概要、ですが… (2) (本を取り出す) ご覧の通り、12ステップで作る組み込みOS自作入門で使われたH8用KOZOSを、Interface雑誌〜のARM基板に移植し、動作させたという話です。 まずは、動いている様子をお見せしましょう。 (3) 実演 minicom load, run, echo ABCDE H8版と同様にブートローダーが起動し、XMODEMでOS本体を流し込み、それが動作するようになっています。 (4) 移植元と移植先のSoC, Sysem-On-Chipのスペックを簡単に書いておくと、こうなるでしょうか。おそらく型番だけ書いておけば分かる方も多いかと思われますが、片方はH8と呼ばれるCPUコアを載せたチップ、もう片方はARMと呼ばれるCPUコアを載せたチップです。 ROMの容量とRAMの容量が出ていますが、64KB程度のメモリが内蔵されていればチップ単体で動作する程度の意味しかありません。KOZOS本に載っているH8版は秋月電子のボードを使っていますが、あれはボード上の2MBのメモリを使用して動いています。 (5) 動作デモでお見せしたブートローダとOS本体のやっていることを簡単にまとめると、大体こんな感じです。 ブートローダはボードの初期化とシリアルポート越しにOS本体のロード、あとload, runのコマンド処理があります。 OS本体はシリアルポートを使用したコマンド処理を行っていますが、この裏ではOSのサービスを使用して三つのタスクが動いています。シリアルポートを使って通信する部分、コマンドを処理する部分、何もしないという処理をする部分ですね。 移植という作業は、動作環境が変わってもこれと同じ動作を行うものを作る作業になります。作るなんて言っていますが、実際は使える物はそのまま使います。 (6) KOZOSの場合、チップが変わっても大体この辺りの領域は変わりません。むしろ、変わってもらっては困ります。 (7) チップが変わると変わる部分としては、チップに密接した部分全てということになります。ボードが起動したらまずは最初にCPUがボードを使えるよう各種の初期化を行う必要がありますし、シリアルポートを使用して通信を行うとありますが、通信を行うためのコントローラも違うのでこれもどうにかしないといけません。 次の項目で触れることでもありますが、CPUコアが違うのでそれに関わる部分についても大幅に手を入れることになります。 (ここでホワイトボードを使って図を描く) ちょっと簡単に図を書いてしまいますが、大体こんな感じになるでしょうか。 OS本体を中心に据えるなら、その手足となる部分が違うので、この違いをどうやって埋めるのさ、そんな話です。 (8) まず、違う部分その一ということで、CPUの違いです。 考えるべき問題は4つあります。 命令セットの違い…Cで書いたソースコードはコンパイラが面倒を見てくれますが、アセンブラを使う必要があるので多少は知っておかないと困ります。 残りの三つに関しては、後で触れるのでここでは列挙するだけに留めておきます。 (9) CPUに繋がった周辺ペリフェラルの違いですが、こればかりはもう何もかもが違うので、正直頑張れとしか。 KOZOS本のKOZOSの場合、基本的に使う物はここにかかれた物しかありませんから、これらについて知っておけばどうにかなるのかなと思います。 (10) さて、移植における厄介な点…自分がぶち当たった壁とも言いますが、それについて話をさせてください。具体的にはこの三つがあります。 (11) ディスパッチャについては、図を書いて説明する方が早そうなのでまずは図を描いてみます。 (ホワイトボードに図を描く) リアルタイムOSに限らず、マルチタスク動作を行うOSでは複数のタスクが見掛け上平行して動くのですが、これを切り替えるための道具です。タスクを切り替えるためにはCPUの各種レジスタを一旦メモリの上に保存して、別のタスクの情報を復帰して動作を継続する…そんな動作を行っています。 (12) 具体的にどんな情報を保存するかというと、ぶっちゃけた話CPUの全てのレジスタということになります。 ちょっと見づらいかもしれませんが、H8では7本のレジスタとプログラムカウンタ、ARMでは15本のレジスタとステータスレジスタです。実はどちらも1本分レジスタが足りていませんが、スタックポインタはスタックポインタで、別の場所に保存しているので全部保存しています。 H8版では綺麗にER0レジスタ〜ER6レジスタが並んでいますが、ARM版ではちょっと変わった並びになっています。これについては、後で触れます。 (13) ディスパッチャを書く上で把握しておく必要があるのは、CPUの特徴です。 H8は古いだけあって非常にシンプルです。ここにかかれている通り、あんまり細かいことを考えなくて良いので楽です。 ということは、ARMの場合… (14) 完全に真逆です。 先ほど触れなかった、CPUの動作モードの概念及び例外処理の方法というのはこの部分にかかってきます。 プログラムが動作しているだけでもUSR/SYS、非特権/特権モードの意識は必要ですし、各種例外処理に応じたSVC, IRQその他の動作モードがあります。 また、この動作モードに応じて一部のレジスタが切り替わってしまうため、どのモードで動いているかを常に意識しておく必要があるだけでなく、どうやってレジスタを保存するかを考えるというパズルに挑む必要があります。 で、この結果が(12)のコレです。 タスクコンテキストを復帰する際のPCはリンクレジスタに格納されますが、これがあちこちに散らばってしまうだけでなく、使用するスタックも違うという点が厄介です。 タスクコンテキストの管理方法には色々なやり方がありますが、KOZOSの場合、スタック上にレジスタを全部積んでそのスタックポインタを管理するという方法を取っているため、スタックポインタが散らばっているとちょっと困るのです。 これはソースを見ていただくのが実は一番早いのですが、簡単に書くと (図を書く) こんな感じでCPUの動作モードをばたばた切り替えています。もう少しスマートな方法もありそうな気がするのですが、自分の腕ではこれが限界でした。 この辺がどうにかなればどうにかなるさと思っていたのですが、次の問題も痛い物がありまして。 (15) オブジェクトサイズの問題。 KOZOS自体あんまり大きいものではないため、オブジェクトサイズは非常に小さいはずです。小さいはずなのですが…なぜかELFのファイルにはゴミがついていて、そのままではon-chipのメモリではどうにもなりません。 この辺りの理由は正直良く分かりませんが、Sレコードフォーマットにすれば必要な部分だけ切り出せるだろうということでそれを使用して回避しています。Sレコードの処理は酒井さんが作られたSH2用KOZOSのコードをそのままお借りしています。 (16) ライセンスの問題。 実は、デバイス周りのコードは以前μT-KernelをLPC2388ボードに移植した際に作ったコードを使い回しています。CPUボードの初期化は、別にOSが変わったからといって変える必要もありませんし。 諸事情により、実はμT-Kernelを移植したと言ってはいけないんですが、便宜上そうしておきます。 で、移植と言ってもオリジナルのソースコードに対する差分をpublic-domainの形で公開しているのですが、このpublic-domainな部分にμT-Kernelのライセンスがかかってこないことを確認する必要があったという話です。 こちらとしては、何でも使えるように緩めのライセンスと言うか丸投げしていたのですが、μT-Kernel側は移植しようとされようとμT-Kernelライセンスのままなので、下手をすればひさしを貸して母屋を則られる可能性もあります。 そんなコードをKOZOSに乗っけても問題ないのかと。 バカバカしい話かもしれませんが、これは念のためT-Engineフォーラムに確認を取って問題ないことを確認した上で、載せています。public-domainなんかにせず、適当に著作権を主張したパッチでも用意しときゃ良かったかなあと反省している部分でもあります。 杞憂なのかもしれませんが。 (17) 最後にまとめですが、機種の違いをうまく合わせるのが移植という作業です。つじつまさえあってしまえば、大体は動きます。もちろん、機種に応じたうまく使って性能を上げていくことも大事ではありますが、それはちょっと脇に置いといて。 ですので、移植元と移植先の違いをしっかり理解しないとどうにもなりません。 あと、LPC2388版のKOZOSのソースコードも公開しているので、お暇な方はダウンロードして遊んでみてください。 以上で、発表を終わります。