\documentstyle[a4j,12pt]{jarticle} \title{MULT-i でざいなぁずのぉと} \author{M・anon} \date{2002年8月11日} \begin{document} \maketitle MULT-iはP/ECE用$\mu$ITRON仕様準拠のリアルタイムカーネルです。本稿では、 MULT-i ver.0.1の制作にあたって、困ったこと、はまったこと、無意味に凝った こと、ver.0.2について考えていること、等々を述べます。他のカーネルの P/ECEへの移植や、読者が自分のカーネルを作ろうと思った時など、 ソースコードだけではわからない点について参考になれば幸いです。 本稿では、ソースコードと一緒に配布している、\verb|00README.TXT|で 述べられているような基本的なことについては特に説明をしません。 まだお読みでなければ、WWWで入手し、まずはそちらをお読みください。 配布元は\verb|http://www.geocities.com/anon6809m/|です。 \section{ことのはじめ} それは、確か /.jp の記事だったと思います。slashdotを御存知のかたなら ご存知とは思いますが、ニュースを伝える記事に、いろいろなコメントが 付くようになっているのがslashdotと他のありがちなニュースサイトの 違いであり魅力になっています。 で、P/ECEの発売発表と同時に明らかにされたのは、そのCPUでした。さっそく いく人かの物好きが仕様書を取り寄せ、Linuxを載せるにはアレだ、とかなんだ とかコメントが付き、その中に「載せるなら$\mu$ITRONでしょ」というのが ありました。 その後しばらく様子見していたんですけど、2001年の冬コミ準備でサークルの オフラインミーティングをやった時、既に買ったひとのP/ECEを見て、 「欲しいぃ ! ! 」とばかりに衝動買いしてしまいました。 買ってしばらくはBlackWingsをクリアしてみたりアルカリ電池でも一瞬で 消えるのに泣いてみたり、画像回転のデモを作って冬コミで見せびらかしたり してたんですが、とある日、某コンシューマ携帯ゲーム機用開発環境と P/ECEについて比較したウェブ頁で(これ書くために確認しに行ったら 消えてました\verb|(^^;|)P/ECEのカーネルについて「ITRON系?」とか、 とんでも\footnote{著者の故郷では「走る」ことを「とぶ」と言う。 ex.「とべ ! 」}8分なことが書いてあるではないですか。(2ちゃんねるの P/ECE関係のログを見てもITRONについての話が出てたりしてるようですが) ここで一発ITRONをのせてしまえ、とそれを見た私は発奮して(セロトニン? (笑))しまい、 前々から少しずつ調べていた本家カーネルの分析とコンパイラ周辺の 分析から得られた情報をもとに、一気にMULT-iを作り上げてしまった、 というのが、だいたいの「MULT-iができるまで」ということになります。 \section{Inside本家カーネル} P/ECEの未公開部分というのは、知ってる人は知ってるという話ではありますが、 やはり独自カーネルを書くとなると、いろいろと不安要素として問題に なってきます。例えば、とにかくデバッグするために何らかの出力が 欲しいけど、LCD以外にはてきとうな出力先が無くて、でも... とか。 (私はやりませんでしたが、いわゆる「拡張端子」にLEDを付けるとか、 カーネルを作るなら、とにかく単純で確実なデバッグ手段の確保を おすすめします) そんなわけで、独自カーネルとはいえ、いろいろと本家カーネルに 依存しないといけない部分が多くあります。そんなわけで、やはり 九州には足を向けて寝られません。 では、MULT-i ver.0.1が依存している本家カーネル関連の部分を説明しながら、 本家カーネルのInsideに迫ってみようと思います。 まず、制作メモの中に残されていた本家カーネルのメモリマップに ついてのメモを見てみます。 \begin{verbatim} [000000 〜 001FFF 8K 内部 RAM] (以下,システム 4K) 000000 〜 00001F ???? 000020 〜 0003FF カーネルサービステーブル 000400 〜 00051F トラップテーブル 000520 〜 000673 RAM に置くカーネルコードの置場 1 000674 〜 000D6F カーネルのワークエリア 000E00 〜 000E93 RAM に置くカーネルコードの置場 2 (以下,スタック 4K) 001000 〜 001FFF スタック ------------------------------------------------------------------------- 040000 〜 04FFFF 64K 内蔵 I/O ------------------------------------------------------------------------- 100000 〜 13FFFF 256K 外部 SRAM (ユーザ) ------------------------------------------------------------------------- [C00000 〜 C7FFFF 512K 外部 フラッシュROM] C00000 〜 C01FFF ブート・ブロック (※) C02000 〜 endmark カーネル C0C000 〜 C27FFF 112K フォント C28000 〜 C7FFFF ファイルシステム \end{verbatim} 本稿を読もうというかたなら、P/ECE初の商業本「P/ECEハンドブック」 は持っておられると思うので、それに載っているメモリマップと 対照させながら見てみてください(本体の側のにはSRAMの容量に誤植 があります。綴じ込み附録の側のほうは正しいので本体側のほうに 訂正を入れておきましょう)。実はもうひとつ、\verb|pceLCDTransDirect| のためのデータ形式ってネタもあったんですが、P/ECE本に載ってたので 没りました。 最も本家カーネルに依存している点は、やはりブート・ブロックだと 言えます。メモリマップ中にも\verb|※|マークが付いてますが、 電源投入、またはリセット直後のCPUが実行するコードであり、また、 方向ボタンの下とSELECTを押している場合には、いわゆる「緊急用 カーネル」として動作しているのがここのコードで、これがある おかげで、全く何もできない独自カーネルを載せてしまっても、 元のP/ECEに戻すことができます。 このへんのメモリへの配置をコンパイル時に調整しているのは、 \verb|pcekn.cm|というファイルで、\verb|makefile|を見ると わかりますが、これをlinkerに渡して\verb|.srf|ファイルを 生成しています。もしこれを変にいぢると、緊急用カーネルを 上書きしてしまうような\verb|.srf|ファイルが出来てしまいます。 気をつけましょう。 緊急用カーネルを起動しない場合、ブート・ブロックにあるコードは、 0xc02000〜にあるカーネルコードの先頭4バイトに書かれているアドレスに 飛びます。「ここまでは変更不可」と\verb|pcekn.c|に書かれている あたりの直前10行ぶんぐらいが、ここらへんの処理のために存在して います。 まず、\verb|static const PCETPENT entry_point[1]|が、先頭4バイトに 置かれることになるコードになり、そこにはその直後にある\verb|void BootEntry00( void )| のアドレスが書かれています。ブートブロックは\verb|BootEntry00|を呼び出し、 そこに書かれているインラインアセンブラのコードの通り、関数\verb|void BootEntry( void )| に処理が渡ります。と、このへんまで書いておけばあとは順を追って読めるでしょう。 \section{r8の罠} カーネルの分析と独自カーネルの制作にあたり、不要そうに見える処理は バッサリと切り捨てています。はじめてカーネルを使わずに動かしたプログラムは、 一見普通に動くのですが、時々止まることがありました。その止まり方が、 うまく動いている時はずっと動くのに、止まる時は動き出した直後に 止まる、というなんとも謎な挙動をしたのです。 いかにも「タイミング絡みで変なことが起きている」という感じに見えて、 LCD関係のコード(後述)とかをいろいろと触ったりしていたのですが、 ある時ふと、本家カーネルと比較してみて、\verb|BootEntry|の先頭の \verb|r8|の初期化を取っ払ってしまっているのが気になりました。これかな? と 思って\verb|r8|を0に初期化するようにしてみたところ、安定して動くように なった、ということがありました。 EPSONのC言語処理系のマニュアルとかを眺めてみると、\verb|r8|が特定の 値に設定されていることを前提に、\verb|r8|相対でのアドレッシングを使う ようなコードをコンパイラが吐くようになっているようです。特に、 \verb|-O|オプションによって変化するらしいのでよけいにはまっていた ような感じです。 \section{サービステーブル} MULT-iでは、いまのところ、本家カーネルがカーネルルーチンをアプリから 呼ぶために用意している、0x20〜0x3ffのメモリについては、使わずにあけてあります。 これ、自分でも忘れていて、これを書くためにソースに目を通していて思い出しました。 \section{LCD} とにかく、動いているかどうかの確認のために、場合によっては暴走する 場所を特定するためにも、最低限の画面表示が必要です。最近でこそ LCDCに関する情報も流れていますが、MULT-i制作当時は本家カーネルの コードを読んで、コマンド体系を推測するしか手がありませんでした。 そんなわけでMULT-iは、本家カーネルのLCD関連部分はほとんどそのまま 流用してます。 MULT-iの\verb|lcd.c|を、本家カーネルの\verb|lcd.c|と比較してもらうと わかると思いますが、2割〜3割程度削ってあります。使わないコードを 削ったつもりです。 他には、本家カーネルでは、速度を稼ぐためにLCD関係のルーチンの一部を 内部RAMに置くようになってます。フラッシュ操作のコードも、フラッシュ操作中は フラッシュにアクセスできないので内部RAMに置かれます。LCDのコードは、 単純に速度の問題なので、MULT-iでは普通にフラッシュに置くように 変更してあります。 あと、本家カーネルの\verb|lcd.c|の\verb|GetLCD|で、 \verb|LCDWK *wp = &lcdwk; //(LCDWK *)0x800;|となっているので、 一見決め打ちなのかな、と思いますが、v1.15のコメントにあるように、 決め打ちではありません。古いコードをコメントアウトで残してある だけのようです。   v0.2に手を付ける前に、LCDドライバを書こうかな、とも考えています。 デバッグのためにはテキストVRAMみたいな仕掛けがあると便利かな、とか 思うので。 \section{遅延ディスパッチ} 以下の文章中の$[x.y.z]$のような表現は仕様($\mu$ITRON4.0)書中の関連個所を 示しています。適宜参照しつつお読みください。 \subsection{遅延ディスパッチとは} 簡単なマルチタスクモニタを作っているうちはあまり問題になりませんが、 本格的な(RT)OSを作るとなるとすぐに、非常に大きな問題になるのが、 割込みハンドラとディスパッチが絡む、微妙なタイミングでの制御の 問題です。 以下、細かい議論になるので、ITRONに慣れていないかたは用語の 確認を$[3.1]$しておいてください。 あるRTOSベースのリアルタイムシステムを考えてみます。そのシステムでは、 優先度の異なる複数のタスクをサポートし、また、割込みハンドラから OSのサービスコールを呼び出して,起床待ち状態にあるタスクを起床させる ことができるようになっているとします。さらに、割込みハンドラは、 タスクのコンテキスト(スタック)を借りて動作することとします (Unixでは普通、割込みで即カーネルモードに遷移するので、この辺の 感覚は非常に違うと思います)。 さて、このシステムで次のような場合にどんなことが起きるでしょうか? \begin{enumerate} \item 低優先度のタスク{}bが実行中 \item 割込みが発生し割込みハンドラが起動される \item 割込みハンドラが、起床待ち状態にある高優先度のタスク{}aを 起床させるサービスコールを呼び出す \item OSのサービスコール処理ルーチンが、タスク{}aの起床処理をおこなう \item OSは、優先順位のより高いタスク{}aが実行可能状態になったので、 ディスパッチャを呼び出してタスク{}bのコンテキストを保存し、タスク{}aの コンテキストを復元して、タスク{}aにプロセッサを渡す \end{enumerate} ちょっと考えれば、割込みハンドラの、サービスコールを呼び出してから 以降の部分の処理が、タスク{}bにCPUが戻るまで実行されないことが わかると思います。これは、割込みハンドラの性質から考えて、 とてもまずいわけです。 仕様$[3.5.3]$では、ディスパッチャの優先順位が割込みハンドラより 低いこと、優先順位の高い処理があるのに、優先順位の低い処理をやっては いけないことが定められており、このような場合に適切な処理をすることが 求められています。 仕様書中の補足説明にあるように、この規則は$\mu$ITRON3.0までは、 割込みハンドラの終了までディスパッチャの起動が遅延される、という 「遅延ディスパッチの原則」と呼ばれていました。直感的に便利な 表現なので、本節でもこれを使いました。 $\mu$ITRON4.0では、研究成果からのフィードバックとして、割込みハンドラ から呼ばれたサービスコールの処理の実行は、割込みハンドラの終了まで 遅延させてよい$[3.6.2]$という「サービスコールの遅延実行」が 規定されています。 \subsection{TRON Chipでの実現} TRON Chipではこれを考慮した遅延割込み(DI)という機構が考えられました。 \verb|http://www.sakamura-lab.org/TRON/CHIP/1/1_8/122_124.htm| 坂村研サイトで見ることができるTRON Chip仕様のここのところの 「遅延割込み」と 図{}7 を見てみてください。 \subsection{MULT-iでのトリック} MULT-iでは、この遅延割込み機能に良く似た仕掛けを実現しています。 典型的なハードウェアの割込み処理機構は、一般に割込み要求レジスタ と呼ばれるレジスタが、割込み要求によってセットされ、割込みを受付けたら リセットする、という感じになっています。 なぜかP/ECEの本家カーネルでは、この役割をするレジスタが、 ソフトウェア側からも「要求あり」にセットできるという謎な設定で CPUを使うようになっています。 \verb|hard.c|の\verb|InitHard|の最後のほう、 \noindent\verb|bp[0x29f] = 0x06; // 割り込み要因フラグのみ RD/WR方式| \noindent というところです。データシートではS1C33209/221/222テクニカル マニュアルのFUNCTION PARTの{\newcounter{hoge}\setcounter{hoge}{2}\Roman{hoge}-5} ITC(割り込みコントローラ)のところにあります。 MULT-iも、一応本家カーネルにならって(というか、何処にどう影響が出るのか 皆目わからないので手が付けられない)、同じ設定で使用しています。   P/ECEのCPUには、割り込みレベルという概念があり、外部割り込みには割り込み 要因ごとに割り込みレベルという値を設定できます。PSR(プロセッサ状態レジスタ)の ILというフィールドの現在の値よりも大きい割り込みレベルの割り込みのみ、 CPUは受け付けます。 ソフトウェアから割り込み要求のセットができるので、割り込みレベル1 (0以外では一番低い)をディスパッチ専用に割り当て、ディスパッチが 必要になったらその割り込み要求をセットするようにすれば、割込みハンドラの 処理中(IL$>$1)なら割込みハンドラが終了してタスクに戻る(割り込みレベルが0になる) 時にディスパッチャが起動してディスパッチが起きる、というように、 うまく処理できるわけです。 ソースコードでは、\verb|mikernel.c|の、先頭にあるマクロ\verb|REQ_DSP|、 \verb|mi_start|関数中の\verb|/* 遅延ディスパッチのための仕掛け */|という コメントのあとにあるブロック、\verb|dispatch|関数(ディスパッチャ)のあたりが、 これに関連する部分ということになります。 \section{おわりに} \subsection{参考文献} 今まで書き忘れてたのですが、P/ECEのCDの中の「資料」というディレクトリの中にある テキストファイルは非常に参考になります。ぜひ読んでおきましょう。 以下、ITRON関係の参考文献を挙げておきます。   $\mu$ITRON4.0仕様 ITRON プロジェクトの頁\verb|http://www.ertl.ics.tut.ac.jp/ITRON/SPEC/mitron4-j.html| からPDFで拾えます(確認しようと思ったら www.itron.gr.jp が not found になるので高田研にあるほうを書いておきます)。 ふつ〜、最新版の4.01のほうでいいでしょう。 紙媒体で欲しい場合はTRON協会\verb|http://www.assoc.tron.org/data/spec/|から 印刷したのを買えますが、会員でないと¥5000もします(会員は¥3000)。kinko'sで PDFを出力するのとどっちが安いかな、とか考えてしまいますね。 TRON協会の話が出たのでTRON協会についてちと書いておきます。 基本的に法人によって構成されており、個人で会員にはなれません。 会費もけっこうします。ただし、ワーキンググループ(以下WG)への参加は 公開のWGだったら誰でも自由にできます。特にITRONに関しては公開WGがさかんにおこなわれて おり、個人の意見がフィードバックされているようです。また、ITRON については、セミナーも結構開催されてます。参加費がそこそこ手頃のなのも あったように思います。   $\mu$ITRON3.0標準ハンドブック改訂新版 \verb|http://www.personal-media.co.jp/book/tron/itron3new.html| $\mu$ITRON3.0の仕様です。「関数名や引数などが大きく変わりました。 (中略)現場からはかなりの怒りの声が上がっています。」なんていう 文章が、某「乳の詫び状」に載りましたけど、これをネタに中傷しようと するヤシはまず仕様をちゃんと比べてみてからにしてホスィ。 まぁ、冗談はさておき、結構高価いんですが(¥4000)、$\mu$ITRON4.0 では削られてしまったネットワーク機能とか色々と面白いので、書店で 買えるということも含めて、4.0の紙媒体版の代わりにこっちを買うという テもありかと思われます。   $\mu$ITRON4.0標準ガイドブック \verb|http://www.personal-media.co.jp/book/tron/191_2_c.html| ITRONの解説書の最新版です。ITRONを作ろう、とか思ったら、 とりあえず$^{\rm{TM}}$買っておいていいと思います。 C言語でふつ〜な手続き形のプログラミングができて、イベントドリブンも 齧ったことがある、という程度の前提は必要かと思いますが、 リアルタイムシステムのプログラミングの教科書としてもそこそこ使える と思います。   ITRON・$\mu$ITRON標準ハンドブック ITRON2と最初の$\mu$ITRONの仕様。現在品切・増刷未定ですが、PDFで 入手可能。 入手はPMCの頁\verb|http://www.personal-media.co.jp/book/tron/itron.html| から。 内容はかなり古いものですが、のちの$\mu$ITRONが、ITRON全体の後継として いろいろと大きな規格になってしまったのに対し、このころの$\mu$ITRONは、 フルセットでもかなり小さいので、勉強用には悪くないと個人的には思います。 とりあえず$^{\rm{TM}}$タダでPDFが読めますし。   実用 組込みOS構築技法 \verb|http://kyoritsu-pub.topica.ne.jp/bookhtml/0304/002472.html| ITRONの解説ではないRTOSの教科書。TRONのデンパは浴びたくないけど RTOSの勉強はしたい、とか思うんだったらぜひどうぞ。 あと、\verb|xxx_yyy()|という形のネーミング規則が嫌とか いう場合もどうぞ\verb|(^^;| \subsection{自分のカーネルを作ってみませんか?} MULT-iでは、$\mu$ITRON3.0のレベルRを目標にしたので、 あちこちで設計と実装がうまくいっていないところがあるとも 思います。独自カーネルに挑戦するだけなら、もっと手を抜ける ところがいろいろとあります。MULT-i ver.0.1のコードは、とにかく何らかの コードを実行できる最小限度のところまで、本家カーネルを読むにあたって 煩雑な部分は削ってありますので、機械語モニタ程度のシステムを載せるのであれば、 MULT-iのコードを流用すればすぐにできるでしょう。 本稿によって、ひとりでも、自作カーネルを作ってみよう、と思って 実行に移してくれるひとがいれば著者として幸いに思います。 \subsection{謝辞} TRONプロジェクトのプロジェクトリーダー坂村先生、ITRONプロジェクトの 高田先生、プロジェクトにかかわってこんにちのITRONをつくりあげられた 多くの研究者やエンジニアの皆様、そしてメーカーに感謝します。 また、なんだかんだ言われながらもP/ECEという遊べるおもちゃを企画し、 市場に送り出したAQUAPLUSに、iSmartのハード・ソフトをともに開発された 開発者のかたに、そしてP/ECEで遊んでいる皆様にも感謝を。 そして、いろいろと思い出させてくれた KS‘兄君’に国土交通大臣 \footnote{http://www.chikage.org}賞を。 \subsection{参考にしてます} P/ECE研究室 \verb| http://north.hokkai.net/~nsawa/| 自分は性格的に一発屋なので、コツコツとハードウェアのいじりかたを 研究されているNaoyuki Sawaさんには頭が上がりません。 どうやら独自カーネルへの道ということで研究を続けておられるようなので、 MULT-iがあっさりと追い越される日も近い... かも。   銀次郎のパーソナルページ\verb| http://www.eps.ddnn.jp/~gin/| ハードウェア改造とか。どっか参考にさせてもらった記憶があるんですけど... どこ だったか記憶が消し飛んでます\verb|m(__)m|   六波羅さんのスペース\verb| http://www2s.biglobe.ne.jp/~rokuhara/| フラッシュ換装ネタの技術情報をかなり参考にした... 記憶があります。   半年前の自分は他人だ、というのを痛感しました。やはり開発記録は ちゃんと付けなければ、といつも思うだけなんですよね。 \newpage \vspace*{150mm} {\bf おくづけ} \noindent      書名 : MULT-iでざいなぁずのぉと \noindent      著者 : M・anon \noindent     頒布者 : BBS電波温泉( http://www.interq.or.jp/earth/rsp/ ) \noindent   発行年月日 : 2002年8月11日 \noindent    版下出力 : 某プリンタ \noindent 印刷(コピー) : 何処かのコンビニ \noindent      製本 : 人力 \pagestyle{empty} \end{document}