2011年6月10日金曜日

TOPPERSを触ってみる

以前から気になっているTOPPERSプロジェクト。以前にも少し触ってみたことはあるのだけれど、コンフィグレータがどうとか、静的APIがどうとか、初めて触るにはちょっとややこしいor面倒な部分が多くて挫折していた。う~ん、きっとコンフィグレータは後々良さが分かってくるんだろうけど、これまでになかった新しい何かを身につける・・・いや少なくとも乗り越えるにはちょっとしたパワーが要るんだなぁ。その点、FreeRTOSはカーネルソースコードも含めてコンパイル&リンクするだけでOSに必要な機能が使えたから簡単に取り組めたんだけどなぁ。ま、新しいものを素直に受け止められないのはオジサンになった証拠か。

でも今回はごにょごにょ言わずに何とか先に進めてみた。
ターゲットはcortex-m3(stellaris)だ。幸いcortex-m3向けの機種依存部分を提供してくださっている方がいたのでありがたくダウンロードさせていただいて、当面の評価を行おうと思う。

まず、TOPPER/ASPの最新版をダウンロードして展開。更に、cortex-m3依存部分も同じディレクトリに展開。doc/user.txtによると、やはりコンフィグレータcfgが必要らしい。が、ASPのフルパッケージに何故か入っていない。仕方ないので、またHPから探すと、今回はcfgのwindows向けバイナリが置いてあった。ソースも置いてあったけれど、目的はstellarisでtoppersを動かすことであって、コンフィグレータをビルドする方法とかはどうでもいい。で、ダウンロードしたcfg.exeはどこに置けばいいんだ?
とりあえず先に進むことにした。なるほど、他のオープンソース系と同じようにターゲットにあわせたconfigureスクリプトとmakeを行うのか。そして、configureスクリプトの実行はperlだと。そうか、shスクリプトはlinux系ユーザにはおなじみだけど、windowsユーザを考慮してまだ導入しやすいActivePerlなんかで対応できるようにしてるんだな、と勝手な推測。とりあえず、ActivePerlの最新版をダウンロードしてきてインストール、パスを通した後、コマンドプロンプトからperl ..\configure -T lm3s8962_gcc[ENTER]とタイプイン!何っ?エラー?PWDコマンドがないって?そりゃ、Windowsのcmd.exeにはPWDはありませんよ。ということは、ActivePerlはダメってこと?
う~ん、windows<オンリー>ユーザのためにperlを使うわけではないようだ。仕方ないのでActivePerlはソッコー消して、cygwinのbash上からperl/configureスクリプトを実行して事なきを得た。しかし、結局bash系の環境は必要なら何であえてperlを導入したのか分からない。shスクリプトのままじゃダメなの?perlは文字列処理が得意だから?

まぁ、いいや。とりあえずconfigureスクリプトは成功してmakefileができたようだ。そのままbashからおもむろにmake[ENTER]をバシッと。

またエラーですか。

今度はコンフィグレータcfgが無いと言っているようだ。cfgのあるべきパスは、../cfg/cfg/cfgですか。何ですか、そのパスは?まあよい、今回は素直にそのパスにダウンロードしたビルド済みcfg.exeを置いてみる。そして、再びmake[ENTER]をバシッと。

またまたエラーですか。

今度はTSKCTBXという識別子(たぶん構造体定義)が無いとおっしゃる。ハイハイ、どこか探してきますよ。というわけでソースツリーをgrep。しかし、TSKCTBXを定義している箇所が無い。いや、arch/m68k_gccの中に1つだけ発見した。でもなんかおかしいなぁ。名前から想像するに、TSKCTBXはタスク制御ブロックのようだけれど、その定義を発見したのはarch/以下。つまり、機種依存コードの中。こういう場合、タスク制御ブロックの定義って、機種依存ではなく、カーネル本体に含まれるべきなんでは?

困りました。TSKCTBX構造体を自力で定義せにゃならんのですか?と思っていたところ、偶然発見した。「CTBXはTSKCTBXに名前が変更されました。」

なんじゃそりゃ?

でCTBXで検索してみるとありました!やはり、機種依存部分のarch/arm_m_gcc/prc_config.hにありました。勝手にTSKCTBXに書き換えて、今度こそmake[ENTER]でサクッとコンパイル!

出ました。またエラーです。

今度は、hw_ints.hが見つからないと。この名前は見覚えがある。StellarisWareに含まれているヘッダファイルのようだ。includeサーチパスを見ると"LuminaryMicro_Driver"とか含まれてる。LuminaryはTIに買収されちまったよぉ~、StellarisWareに変わってパスも変更されたんだよぉ~。というわけで、makefileからインクルードパスの設定を変更して、などなど・・・。

どうやらダウンロードしたcortex-m3向け機種依存コードは、かなり古いもののようだ。実際、最終更新が2008年となっている。カーネル部分の更新について行けてないのか・・・。あきらめ半分でmake[ENTER]ポチっと。

お約束のエラーです。

今度は、INHINIB構造体にint_entryというメンバは存在しない、EXCINIB構造体にexc_entryというメンバは存在しない、という2つのエラー。INHINIB/EXCINIB構造体の定義を探してみると、いやint_entryとexc_entryはちゃんとFP型で宣言してある。FP型も定義してある。もしかしてこの部分はコンパイル時に読み込まれない(#if~#endifではじかれている?)可能性もあると思って、#errorとか適当なものを埋め込んでみるとちゃんとコンパイル時に#errorが報告されるのでこの定義を通っているようだ。では何故?・・・

分かりました。機種依存コードの中でint_entryとexc_entryを#defineで_kernel_int_entry/_kernel_exc_entryにリネームしてある。そうだ!思い出したゾ。

以前TOPPERSに取り組んでみてイヤになったのは、この#defineによるリネームのせいだ。コイツのせいで今回のようなコンパイルエラーが出て困ったんだった。こういうリネームをやられると、どの名前が本当の名前で、どこで定義されているのが実際に使われる名前なのかがまったく分からなくなる。しかも、int_entryのような単純な名前を入れ替えられると、今回のようにたまたま構造体のなかで使ったメンバに同名のものがあると、それもリネームされたり、されなかったりで、何が本当なのか訳が分からない。
どうしてこういう実装にしたのだろうか?結果的にこれがもっともスマートな解決方法なのかもしれないけど、私のように事情をよく知らない者がメンテなりポーティングする段になると、非常にメンテナンス性が悪くなると思うし、思わぬ不具合をはらみかねないと思うのだが。少なくとも#defineで名前の置き換えがされることを前提にしているシンボルなり関数があるのなら、その名前は置き換えられることがもっと区別しやすいような名前にすべきだと思う。今回のようにint_entryのようなありがちな名前だと、グローバル関数としてのvoid int_entry(void)をリネームしたいのか、INHINIB構造体中のint_entryメンバをリネームしたいのか判断できない。

で、結局この部分をどう解決すべきか?本当に手がかかるなぁ、ブツブツ・・・


[2011/6/10 18:45加筆]

その後の調査で分かったこと。

○#defineによる関数名のリネームは、ユーザが書くアプリケーション側の関数名との競合を避けるためらしい・・・
>>それなら敢えてリネームしなくても、ユーザー側が競合を回避すればいいだけではないか?
>>または、ユーザー側で使いそうな名前の関数をTOPPERS側で使わない方がよいのでは?実際、doc/user.txtにはtoppers_接頭辞を予約していると書いてあるんだから、一目でTOPPERSの「内部関数だな!」と分かる名前をつけることは、ソースコードの可読性を挙げるためにもむしろ有効な手法ではないか?
>>今回の場合は、Stellaris用の機種依存コード側でint_entryという名前をつけたこと自体が失敗だったのではないかと思われる(成果をダウンロードさせてもらっておきながら、なんとも勝手な言い分だろう>私)

で、とりあえず上に書いたint_entryとexc_entryの妙なリネームを回避するとサンプルをビルドすることができた!

0 件のコメント:

コメントを投稿