いろいろ苦労させられたので、記録に残しておきます。技術的な内容も含みますが、
それが参考になるかどうかは分かりません。
(日付は連続していますが)毎日付けていたわけではないので、内容は不正確です。
最初の方は書いてなかったので記憶で補完しています。
公開するにあたって読み直したら、いろいろ突っ込みたいところがあったので、
コメントを入れてみました。<hr>の間の、日付の入っていない部分です。
uClinuxの移植作業が落ち着いてきたので、実機でテストする方法を考える。
考えるまでも無く、カーネルをRAMにダウンロード→実行するしかないだろうという結論に達する。
uClinuxの作業が一段楽したので↑の続きを考える。
基本方針として、ローダーを用意することにしたので、どこから調達するか決
める。
てな物がまとまる。
ソースは絶対に必要、それ以外は状況をみてというところ。
でも、RS232Cで1Mbyteをダウンロードするのは避けたいので、
ネットワーク経由のダウンロードも必須に近い物がある。
全部満たせるのはRedBootぐらい?
検索してみても、以外に使えそうな物がない。要求が厳しすぎるのが原因なんだけど。
選択肢としては、
日立のモニタは、ASM38が必要、SREC以外読めない(転送サイズが倍以上になるので不可)、
という部分が引っかかるので、候補から落とす。機能的には十分なんだけど。
自分で作る場合は、ネットワークサポートが問題になりそう。
tftpをしゃべってくれればいいので、最後の手段としてudp/ipプロトコル処理と
neのドライバを、uClinuxのソースからもらえば良いんだけど。
いちばん簡単そうなのは、RedBootかな。
eCosのサポートCPUにH8/300Hが入っていないのが気になるけど。
RedBootを第一、だめなら自作な方向で進むことにする。
正式サポートは無くても、世界のどこかで移植している人がいるかもしれないので探してみる。
uClinuxが移植されているんだから、eCosもどこかに転がっているだろうと
思いつつ探していると、ecos-disucsの記事が引っかかる。
移植しようと思っている人はいるらしい。その後の議論でRedHatの人が
否定的な発言をしているのが少し気になる。
とりあえずeCosの最新版ソースとドキュメントを拾ってくる。
ドキュメントを読んでみる。日本語訳は古すぎるので、参考程度にとどめた方がよさそう。
探しても見つからない。ということで移植を試みてみることにする。
さらにドキュメントを読んでみる。日本語の方はまったく参考にならない。
英語の方にはそれなりに書いてあるみたい。
検索してみても、日本語で参考になりそうな情報はまったく引っかからない。
まあ、SHのHALを参考にすればいいか。
ということで、苦労の道を歩み始めることになりました。
このころは、2月末ぐらいには出来るかななどと劇甘なことを考えていましたが・・・。
MLの議論を読むかぎり、問題というのは、h8300-hitachi-hms-gccのc++サポートのことらしい。
確かに使っている例は見たことがないので、不安といえば不安。
でも、c++ → RTLのトランスレーターは他のアーキテクチャと同じ物なはずだし、
h8300のバックエンドは、uClinuxのコンパイル出来るぐらいに安定しているので、
特に問題は無いような気がする。
ということで、念のために実体の無いHALを作ってコンパイルを通してみることにする。
うまくいったら、中身を作って行けば、最終的にH8/300のHALが完成。
SHのHALをざっと見てみる、SH3/4がターゲットらしい、
SH1/2ならそれなりに参考にできそうなんだけど。
あまり参考にならないので、他のHALも調べてみる。
mn10030が似ているような気がする、データシートがないので詳しいことは不明。
松下はデータシートをWEBで公開していないのかな?
とりあえずmn10030に下敷きになってもらうことにする。
mn10030のディレクトリをh8300としてコピーして、中身の名前もそれに合わせて変える。
ターゲット名はh8300h_simにする。ついでに中身を#if 0で殺していく
一通り直ったので、cdlのコンパイラオプションをH8/300H用に書き換えて、
コンパイルしてみることにする。他にも直さないといけないのかもしれないけど、
よく分からないのでとりあえずそのまま。
で、どうやってコンパイルすればいいの?
一発目のはまりです。
そんなこともわからんくせに移植するなといわれそうですが。
コンパイルするには、ecos/host/tools/configtool/standalone/common/ にある ecosconfigというユーティリティでソースツリーを作ってから、 makeする。ということが分かった。そんなのドキュメントに無かったぞーと思って検索したら、 最後の方に少し書いてあった。Windowsのユーティリティはたくさん書いてあったのに。
使い方 ecosconfig --srcdir=$HOME/ecos/packages コマンド らしい。 コンパイルは ecosconfig --srcdir=$HOME/ecos/packages new h8300h_sim ecosconfig --srcdir=$HOME/ecos/packages tree make
とりあえずコンパイル方法はわかったので、ecosconfigをいじってみる。
listコマンドでターゲットの一覧を出力させてもh8300h_simが出てこない。
ディレクトリを追加しただけでは出てこないらしい。
うーんとうなっていると、ecos.dbと言う実にあやしいファイルを見つける。
ここに追加しないとecosconfigは認識してくれないらしい。
ということで関係する部分を適当に追加してみる。
何度も文句をいわれながら何とか認識してもらえたので、ソースツリーを作ってもらう。
これは一発でOK
makeも通った。libmで怒られたけど。ということで、コンパイラの問題はなさそう。
それほど深みにはまらずに抜け出すことに成功しました。
ちなみにここでmakeが通るのは当然の結果です。なんせリンクしていないので。
確かこの時はbuild finishedだけでOKと判断しました。無知とは恐ろしい物です。
もっとも、この時点でELF問題にぶち当たっていたら、
このまま闇に葬られていたことは確実なので、何が幸いするかわかりません。
穴埋め開始。
単純に置き換えるだけでよさそうな部分を埋めていく。
コンテキストの切り替えと、雑用関数が完成。
割り込みまわりに手をつける。さすがに単純に置き換えるわけには行かないので、
少し考える。
基本的な考え方はuClinuxの割り込みと同じなのでそれほど難しくは無いんだけど、
リアルタイムOSなので、速度・サイズの両面から詰めていく。
昨日の続き、それなりに満足。uClinuxにも入れてみようかなと思ってみたり。
ライセンスが違うので、単純に持っていくのはまずいかも。
割り込みプライオリティの制御が出てくる、なくても問題はないらしいけど、
サポートはあるのでSHのコードをベースにして入れてみる。
やっぱり周辺回路は似てるなーと思う。
SCIのドライバ。FIFOなしはSHと同じHWなので、アドレスだけ#ifdefで切り替えて、
と思っていたら、アーキテクチャ別に持たないといけないらしい。
仕方がないのでSHのソースをコピーして適当に直す。
で、H8/300対応が大体終わったはずなので、cdlを直していく。うーん、よくわからん。
cdlの修正中。
ecosconfigに嫌われまくり・・・。coreはいてくれるし。
エラーの山じゃなくてソースツリーを作ってください。お願いします。
といっても通じるわけが無く。
通るようになった。
cdlは良く分からん。
二個目のはまりです。直後に襲ってくる事態に比べたら、かわいいもんです。
cdlの書式などはeCosのドキュメントに書いてあるんですが、
ターゲット依存の部分の説明に重点が置かれているので(当たり前)、
アーキテクチャがらみの部分は良く分かりません。
ひょっとしたら読み方が悪いだけで、きちんと書いてあるのかもしれません。
HALごとの差はほとんど無いので、
他のアーキテクチャのcdlをぱくりまくって何とかなりました。
ということで、cdlの書き方はいまだに良く分からないままです。
日本語ドキュメントがほしいですね。
makeも通った。何もしないとライブラリが出来るだけなのか。RTOSだからそんなもんか。
long longでOut of rangeのワーニングが出てる。なんで?あとで見ておこう。
RedBootを作ってみるか。どうやって作るんだ?RedBootのドキュメントにあった。
ecosconfig --srcdir=$HOME/ecos/packages new <target> redboot
ということらしい。作ってみる。
う、Confrict食らった。cdlが間違えてるみたい。
直してOK。ソースツリーが出来た。
一日空いた。もったいない。
出来上がったRedBootのソースツリーをコンパイルしてみる。
long longのワーニングはなさそう。RedBootで使っていないところが引っかかるのかな?
いっぱいUnresolved Symbolが出た。全部大文字のシンボルはマクロの定義漏れとしても、
なんでこんなにいっぱい…。Duplicate Symbolも出てる。
とりあえずマクロの定義漏れを修正。ソースツリーは再構築しないとだめなのかな?
念のために作り直してmake。
やっぱり定義済みのシンボルがエラーにされているみたい。なんで。
ということで泥沼の始まりです。
ちなみにソースツリーは、インクルードファイルに手を入れるか、
コンフィグレーションを変更した時に再構築が必要になります。
ただしWindows環境ではどうなるか分かりません。多分同じだと思いますが。
Duplicate Symbolは__attribute__((weak))が使えないのが原因らしい。
gccを直さないといけないので、とりあえず放置。
謎のUnresolv Symbolの原因追求。
nmで見る限り、.oと.aではきちんと定義されているので、リンク時の問題らしい。
makefileかldscriptの指定がまずいのかな?
どっちも自動生成か。追っかけるのが面倒。
makefileでは.oの指定はしないのか。ということはldscript?
読みにくい。こんな書き方あり?
よく分からないので、他のアーキテクチャのRedBootを作って比べてみることにする。
使えるコンパイラは、
makeしたら、i386-PC-gccがないとかいってくるので、
make ccommand_prefix=""
でmakeする。
何事も無く完成。ということはH8/300H環境がまずい?
出来上がったPCとh8300h_simのバイナリ・.o・.aを比較してみる。
nmの結果に目立った差は無い。objdumpで見てみると…セクション名が違う
.debug〜セクションがないのはCOFFだから関係ないとしても、
それ以外にもセクション名が違う部分が何箇所かあって、
h8300h_simの方は途中で切れているように見える…。
ひょっとしてCOFFのオブジェクトフォーマットではリンクできない?
という結論に達する。
そういえば、出来上がったバイナリの名前がredboot.elfだ・・・。
泥沼第一幕終了。
objdumpの結果を張っておかなかったのが悔やまれます。
objdumpは24日以降何回か使っていますが、
セクション名がCOFFの制限に引っかかっているのは全然気がつきませんでした。
やっぱり一回ぐらい「linker&Loader」を読んでおきたいとつくづく思いました。
ちなみに一番最後の部分は真実です。全然気がつきませんでした。
ま、良くあることですね。というのは動いている今だから言えることですが。
「ELF環境じゃないとコンパイルできない」問題は、H8/300Hでは致命的なので、
回避するべく努力する。
weakはCOFFでも問題なく使えるはずなので(uClibcで使ってるけど問題なし)、
セクション名を短くすれば何とかなりそう。
が、セクション名も自動生成されているらしい、全然追いかけきれない。
2月が終わってしまう。当初の予定では完成しているつもりだったのに。
いろいろ試すも、うまくいかない。というかあちこち直さないと無理らしい。
バリアントの部分だけで吸収しきれる問題ではなさそう。
どうしよう。
ここで無理やりCOFFに対応させても世の中の流れがELFになっているので、
COFFに対応させる労力が無駄になる。という結論に達したので、
h8300-elfな環境に移行して、そこでeCos/RedBootを作ることにする。
ということで、gcc/binutils/gdbのスナップショットを取ってきて、
h8300-hitachi-elfなクロス環境を作成する。これでコンパイルできるようになるはず。
ということで、COFFを捨ててしまいました。
uClinuxも2.4はELFが必須なので、特に問題はないでしょう。
ちなみに2.0のカーネルははhmsのままで行くつもりです。て、ここに書くことか?
ちなみに、ここでコンパイラを切り替えたことが、更なる悲劇を生みます。
出来上がったh8300-hitachi-elf環境を試す。
makeしてみる。weak宣言でエラーが出る。ワーニングじゃないの?
メッセージから行くと(日本語だとかえってわかりにくい気がする)
ヘッダのインクルードを止めればいいのか。
直してmake。通った。
gdbで読んでみる。サイズがおかしいような気が…。
objdumpしてみる。空のバイナリが出来ている。なんで?
.oと.aをobjdumpで見てみる。問題なし。ということはリンカ?
target.ldをチェックしてみる。0byte。なんで?
まずはcppにtarget.ldの元を食わせてみる。OK。
makeの時と同じ条件で試してみる。だめ。
オプション指定?
とりあえず、gcc-2.95.3をELFなコンパイラにしてみる。よさそう。
cppの問題らしいので、追いかけてみる。
-MDを指定するとうまくいかない?ヘルプに載ってないし。
ふと思い立ったので、コンパイラ問題の詳細を聞くために、
MLで移植を考えた人に現状を聞いてみる。最初に聞いておけばよかったような気もする。
uclinux.orgからメールが来た。ということでuClinuxをいじる。
eCosは一回休み。
一回じゃなくて三回になってしまった。ということでeCosに復帰。
cpp問題を調べる。
なんとなく思いついて、コンパイルオプションから-MDをはずしてみる。
よさそう。
cppがおかしいのかな?スナップショットだから何があるか分からないな。
質問の結果、移植作業は行っていないらしい。
コンパイラ問題もCOFFとELFの問題ではないらしい。
動きそうになってきたところで、いつぞやのlong longのワーニングを調べる。
ソースを見てみると、long longに定数を代入しているだけ。定数式が範囲外ということか?
16進16桁なのであふれるはずは無いと思って、少し試してみる。
9 桁目で怒られた。まさかと思って、sizeof(long long)の結果を拾ってみる。4 …。
ということは、sizeof(int)==sizeof(long)==sizeof(long long)か?
ANSIには違反していないはずだけど、sizeof(int)==sizeof(long long)
に許せない物を感じる。
第一eCosの型定義で64bit長の型が必要なので、このままでは動かすことが出来ない。
weakの問題もあるので、gccに手を入れることにする。まずは、変更箇所を確認するため、
「Using&Porting GCC」を読む。
泥沼が続きます。一歩進むと次にはまってしまう状態です。
sizeof(long long)==4は意外な盲点でした。ちなみに、sizeof(double)も4です。
gccのターゲットの中でも特殊な方らしく、
h8300を入れても三つしかありません(dsp16xx/h8300/mn10020)。
ここまできてしまうと手段を選ぶのも面倒なので、安易にgccに手を入れてしまいます。
もっとも、他の手段で逃げてもややこしくなるので、根本的な解決法はこれしかないんですが。
コンパイラを切り替えたことで発生したcppの問題は、
この時点では逃げていますが結局直すことになってしまいます。
GCCの修正続き。特に変な改造はいらないらしい。
gcc/config/h8300.hの定義を変更すれば良いいみたい。
weakのほうは修正が入っている。ELF対応に合わせて入れた?ということで、
long longを64bitに再定義して終わり。
H8/300の場合64bit長の型を定義するとえらいことになりそうなので、
target_flagによって32bit/64bitを切り替えるようにしてみる。
直してmake。問題なし。
テストプログラムをコンパイルしてみる。muldi3とdivdi3が未定義エラー。
libgcc.aがまともに出来ていない?nmで見てみる。_muldi3.oで定義されているシンボルが、
なぜか_mulsi3になっている。どこかでシンボル名をすりかえているらしい。
どこで切り替えているか分からないので、cppを通した結果を眺めてみる。
libgcc2.hで#defineされていた。どうやらLONG_LONG_TYPEは、
式ではなく定数にしないといけなくなったらしい。
「Using&Porting GCC」の内容が古くなってきているのか。最新版の日本語訳がほしい。
面倒なので常に64bitにしてしまう。もう一度作り直してテスト。うまくいった。
ということで、RedBootを作り直してみる。
動かすためにはgdbのシミュレータにSCIサポートを入れなければ…ということで、
5.0用のパッチを当てる。inc/decのバグは直っているようなので、
未実装命令と、内臓I/Oのシミュレーションを突っ込む。できた。
gdbに読ませて動かしてみる。動いているらしい…。がシリアル側に何も出てこない。
何も出てこない原因を調べる。RedBootはHALのDiag用入出力関数を呼んでいるらしい。
SHのHALを見てみると、Diagで使えるSCIのドライバがあった。
面倒なのでそっくりコピーさせてもらう。
他のところも少しずつ直してコンパイルを通す。出来た。
動かしてみる。お、起動メッセージが出た、感動。コンソールからの入力もOK。
ヘルプを出してみる。コマンド実行もOK。dumpしてみる。止まった…。
もう一回試してみる…やっぱり止まる。少しトレースしてみる。
なんてことは無いループから抜けられなくなってる。割り込み?
ブレークを仕掛けて追いかける。割り込みはかかってないらしい。
シンボル名から行くと割り算を繰り返している。RedBootのソースから該当個所を探す。
バイナリ→文字列変換でwhileの終了条件が成立しなくなっているらしい。
どうも割り算の結果が合わなくなっているような気がする。
RedBootだと大きすぎて分かりにくいので、テストプログラムを書いてみる。
やっぱり割り算を間違えている。アセンブラソースを見る限りは間違っていないので、
割り算関数がおかしい?
i386で同じプログラムをコンパイルしてみる。同じようなコードが生成されているので
動かしてみる。当然正しい答えが返ってくる。割り算関数の方はだいぶ違っているようなので、
単純な比較は無理そう。
問題の_divdi3.oをobjdumpで逆アセンブルしてみる。うーん、
気のせいでなければer0とer1が引数になっているような気がする。
i386の方も見てみる。スタックから8バイト取り出している。ということはこれでいいのか。
libgcc2.Cを読んでみる。引数の型はDWtypeということらしい。定義を探す。あった。
typedef int DItype __attribute__ ((mode (DI)));が実体で、DWtypeに#defineされている。
でも、なんでintなのに8byteになるんだ?attributeの指定に意味があるのかな? 調べてみるか。
調べてみた。やっぱりattributeの指定に意味が合った。modeで指定したサイズを持つらしい。
DIというのが良く分からないけど、RTLのDImodeと同じ意味なのかな?
とすると、DIは8バイトになるので、
H8/300Hの_divdi3で4バイトになっているのがおかしいということになる。
またlibgcc2.hの#defineで置き換えられているかもしれないので、
cppの結果をあたってみた方がよさそう。
cppの結果を読んでみる。
__divdi3(SItype u, SItype v)
・・・。計算が合わないわけだ・・・。が、#defineしているところが見つからない。
あった、コンパイルオプションで-DDI=SIが指定されている。これをはずせばいいのか。
で、このオプションはどこで指定されているんだ?
gcc/config/h8300/t-h8300で定義されているのを発見。はずしてみる。
こう何回もgccを再構築していると速いマシンがほしくなってくる。
できた。テストプログラムを動かしてみる。おお、答えがあっている(当たり前)。
RedBootも作ってみる。問題なく起動。
お、アドレスの表示がまともになっている。
dumpもOK。
loadは、相手の準備ができていないから無理か。
一応完成ということになるのかな。
ということで、めでたく泥沼脱出に成功しました。良かった良かった。
どう考えてもeCosの移植より、それ以外の修正に手間がかかっています。
特にlibgccの所は、「Using&Porting GCC」にも書かれていないので、
気が付くまでにえらい時間がかかりました。
gccは日本語化されているので、最新ドキュメントの日本語訳が早くほしいですね。
(英語版は読むのに時間がかかるので)
念のためにcvs updateしてから、H8/300H版を再構築してみる。問題なし。
RedBootのコードを読む限りでは、eCosはアーキテクチャ依存性を吸収する
ライブラリ集として使われているような気がする。
ということで、eCosそのものの動作試験をやってみる。
ecosconfig --srcdir=$HOME/ecos/packages h8300h_sim ecoscondig --srcdir=$HOME/ecos/packages tree make
で、標準的?なeCosのカーネルができるはず。
あ、libmでおこられた。そうか、sizeof(double)==4問題か。とりあえずremove。
できた。exampleのプログラムをこれと一緒にリンクすればいいのか。
makefileを直して、makeしてみる。RedBoot_Versionがないとかいわれた。なんで?
あれ、何故かredboot_main.oがくっついている。cdl間違えてる?
objdumpで見るとくっついてないのに。うーむ。
げ、redbootのディレクトリにできてるライブラリをリンクしてる。makefileを間違えた。
直した。あれ、まだエラーが消えない。調べる。cppの問題にぶち当たっているくさい。
これはまじめに直さないとまずそう。
cppが出力をはかなくなる問題の調査、gdbで追いかけてみる。
あれ、h8300-hitachi-elf-cppはただのドライバだったのか。知らなかった。
ということでcpp0をgdbで地道に追いかける。
うーん、-MDってObsoluteなのかな、--helpで出てこないし。
-MFじゃだめなのかな?試してみるか。だめみたい。素直に調べることにする。
わかった、出力禁止されてる。直してみるか。うん、よさそう。
でも、これが正式仕様になったら、結構困りそうな気がする。
ついでにweakのエラーも調べてみる。
うーん、ただ単にエラーチェックを強化されただけに見えるな、
externしたシンボルを、weak付で再定義すると出るのか。
ソースの書き方の問題なので、そのままにしておこう。
直したcppで全部作り直す。できた。
サンプルとリンク。できた。
helloを動かしてみる。メッセージが出てきた、動いた。と思ったらおちた。
変なアドレスにジャンプしているみたい。割り込みかな?
テストの続き、落ちた時にpcが0になっている。
タイミングからいって、割り込みくさいんだけど。落ち方は、
コンテキストスイッチみたいだし。
原因が絞りきれない。
サンプルが動きつつある。
割り込みがかかると死ぬ問題は、単に割り込みハンドラのインストールが
失敗していただけだった。コンテキストスイッチはOK?とりあえず直して見る。
割り込みは正常に処理されるようになった、んが、途中で落ちるのが直らない。
割込み処理には複数回入っているので、やっぱりコンテキストスイッチがおかしい?
追いかけた結果、コンテキストスイッチは無関係だった。きちんと切り替わってた。
まあ、効率無視でuClinuxと同じ方法を使ったので、動かないほうがおかしいんだけど。
でも、割り込みハンドラの挙動が怪しいのは確か。追いかけた結果、
HAL_INTERRUPT_STACK_PENDING_DSRで落ちてる。
ということは、dsrテーブルのセットアップがまずい?見た所良さそうなんだけど、
ん、spが壊れてる。er3に待避してるんだけど
cyg_interrupt_call_pending_DSRsから帰ってきたところで壊れてる。
これってcaller savedだっけ?
ちょうどよくgccのソースがあったので確認、er0-er3が関数呼出しで破壊される
ことになっている。今までer2までだと思ってた。
仕方がないので、レジスタの割り当てを変えてみる。とりあえずなおったっぽい。
他のサンプルも試してみる。
うーん、timerが動いていないような気が、じゃなくって動いていない。
タイマ割り込みから、schedulerの周期処理は呼ばれているので、普通に考え
れば、その先で起こす処理が走っていないのでは、と言う結論になる。
で、探してみてもそれらしい部分が見つからない。なんで?
cyg_thread_delayから戻ってこなくなる現象を追求するため、 気合を入れてカーネルの中を追いかける。トレースで追いかけるのは限界
実体は、Cyg_Thread::delay。処理は、
先にスリープしてるので今ひとつ分かりにくい。でも、要求が衝突することを考えると、
この方が簡単なのか。奥が深い。
などと感想を書いてもしかたないので、先に進む。
で、戻らなくなるのは、タイムアウトしても起床要求が飛んでこないので、
時間経過待ちから抜けられないのが原因であることはほぼ確定。
と実にシンプル。inline関数になっている。CYGFUN_KERNEL_THREADS_TIMER
を定義しないと使えないみたい。コンフィグレーションが違うだけだったら間抜け。
とりあえずさらに進む。タイマの実体は、Cyg_ThreadTimer。
時間管理は、親クラスのCyg_Alarmが面倒を見ている。
Cyg_Alarmは、時計とイベントカウンタを抽象化しているだけか。
トリガがかかると、指定した関数をコールバックしてくれる。
Cyg_Alarmコンストラクタで結びつける時計 or カウンタを指定するようになっている。
Cyg_ThreadTimerは当然時計。時間切れでalarmが呼ばれるようになってる。
ということは、この時計が動いていないということになる。
時計は、システムグローバルの時計使っている。スレッド毎にnewしたらえらいことになるから?
で、alarmの方は単純に起こしているだけ。やっぱりここにたどりつけていない説が有力。
ということで、Cyg_Clockを調べる。イベントカウンタを継承している。
タイマ割り込みイベントのカウンタという扱いらしい。なるほど。
ということは時間経過の処理は、カウンタが持っているのか。カウンタもあたってみるか。
カウンタはCyg_Count。条件はリストで複数持てるようになってる。結構凝った作り。
タイマを共通で使うことを考えると、条件一個じゃ使い物にならないか。
イベントが発生したらtickを呼べば良いらしい。回数指定はPending分の補正用ということかな。
時計の場合は割り込みでここを呼んでいろ。
ここで、時間経過をチェックしてコールバックしている。。ちなみにコールバック
はC言語手順。
だいぶ長くなってしまった、スレッドをたたき起こす処理の終端までたどり着いたので、
割り込み周りを調べてみる。
時計の実体は、*Cyg_Clock::real_time_clock。
ポインタということは…、どこで初期化してるんだ?
あった、Cyg_RealTimeClock::Cyg_RealTimeClockで初期化している。
rtcというグローバルなインスタンスがあるので、これで初期化されているのか。
なんでrtcを直接使わないのか気になる。コンフィグレーションの都合?
tickはCyg_RealTimeClock::dsrで呼ばれてる。ここの割り込みがきていることは確認済み。
ということは、tickに渡しているイベント回数が0になってる?どこで数えてるんだろう。
Cyg_Interrupt::post_dsrか。昨日追っかけた時にpost_dsrは呼ばれていたので、
interrupt_endのintrが腐ってない限り数えているはず。
この値がpost_dsrのthisになるので、運がよければ腐っていても動いてしまうのか。
ということは、HALのinterrupt_entryがあやしいような気がする。
うむ、渡しているのは、hal_interrupt_objectで、この中身は、
HAL_INTERRUPT_ATTACHしたときにthisで初期化されるはず、ということで定義をチェックする。
isrのインストールは問題ないので、hal_interrupt_objectsも正常に初期化されているはず。
これは、実際に動かしてみないと無理か。
で、追いかけてみる。うーむ、きっちり動いてる、時間切れでwakeupしている。
という事はスケジューラーがそのスレッドを無視しているのか?
スケジューラーは動いてるから気にしていなかったんだけど。
さらに追いかける。hal_thread_switch_contextで切り替わった瞬間に割り込みが入って、
そこから抜けられなくなっているみたい。ということはスケジューラーも無罪か。
割り込みがかかりっぱなしになってるのかな?
タイマのレジスタをダンプしてみる。わかった、8TCSRのCMIAが落ちていない。
それでコンテキストスイッチの瞬間で割り込み許可になって抜けられなくなるのか。
ということは、hal_interrupt_acknowledgeがおかしいのか。
うーむ、テーブルがずれてる。これじゃクリア出来るわけがない。
ということで直した。ばっちり。割り込み周期が長すぎる気がするけど。
しかし、全然関係ないところを調べてしまったな。勉強になったけど。
ぽつぽつ修正。ほぼ完成かな?と言えるところまで来たので、ソースを整理する。
で、ディレクトリを掃除して、コンフィグレーションからテストすることにする。
う・・・。掃除しすぎてしまった。packages/hal/h8300の下をきれいさっぱり消
してしまった・・・。
かなり前のバックアップを発見。日付と内容から一通り書きおわった頃のものらしい。
これより新しいのはなさそう。ここから最新版を復元することにする。
日記の記述を記憶で補完して修正。ついでにcdlで不自然な部分を修正。
eCosカーネルがなんとか動きそうなところまでたどりつく。
動くんだけど、どこかで0番地にジャンプしてる状態。同じことを繰り返してないか?
復元作業続き。ドキュメントはPDFよりHTMLのほうがわかりやすいことに気がつく。
ということで、こっちを読みながらCYGHAL_DBG*のcdlを修正。
無理やり通していた部分がきれいになった。
RedBootが動かない・・・。コンソールの初期化で落ちる。
わかった、hal_platform_initで、hal_if_initを呼ばないといけないらしい。
動くようになった、あれ、ベクタテーブルをダンプしても0しか出てこない。
gdbでダンプしてみる。やっぱり0しか入っていない。0にジャンプするのは、こ
れが原因か?でも、なんでベクタテーブルが読まれないんだろう。
objdmpで見てみる。あ、ALLOCが立ってない、だから読んでもらえないのか。
セクション属性に"a"をつける。読まれた。
eCosカーネルの動作もOK。やっぱりタイマの割り込み周期がおかしいような気がする
(異常に長い)。
タイマ割り込みの周期を調べる。どうやら1tickの周期は決まっていないらし い。
をcdlに定義することになっているらしい。でも、CYGNUM_HAL_RTC_NUMERATORは
どういう意味があるんだろう。
よくわからないので、他のHALを参考にして1tick=10msに設定してみる。CPUの実力からすれば
5msでも耐えられるはずなので、余裕でしょう。
テストする。短くなった、こんなものだろう。ということで、今度こそ一応完成。
再び悲劇が起きないうちに公開してしまうことに決定。
ということで、書きかけの紹介ページを完成させる。
コンパイル環境からして人柱状態なので、説明もシンプルにする。
英語ページはどうしようかな。また適当に訳して出すか。
かなりいいかげんな英語ページを作成。意味が通じるのか?
どうでもいいようなことで、ecos.dbを眺めていたら、SCIのドライバ(devsの方)
を登録していないことに気がつく。あう、ということで修正。
いつぞや質問した人に、「出来たよ〜」なメールを送る。その時RedHatに連絡したほうが
よくない?と言われていたのを思い出したので、RedHatにコンタクトを取って
見ることにする。
Officialを漁ったら、FAQに
Contributeの方法が書いてあった。適当なことを書いてメールを送る。
あ、文字コードがeuc-jpになってる。直した。
RedBootでloadするためには[x-z]modemが必要、ということでcuを捨てて
minicomへの移行を試みる。
minicom -p <pty名>で疑似端末も開けるらしい。と思ったらマスタ側だけ?
新しいバージョンを探してみる。2.0はスレーブも開けるようになっている。
と思ったら、/dev/pts/?だけらしい。
仕方がないので、gdb側で、/dev/ptmxを使うように直す。単純に開けばいいのかな?
だめだ、スレーブ側が開けない。manにも載ってない。
googleで探す。NEWS-OSの例が引っかかった。
fd=open("/dev/ptmx",O_RDWR);
grantpt(fd);
unlockpt(fd);
ということらしい。試してみる。よさそう。何やってるか解らないのがなんだけど。
redhatから返事が来た。マージしてもらえそう。
そのために誓約書?を送らないといけないみたい。
gccの問題についていろいろ話し合う。aliasのエラーとcppは
バグ報告を出すことにする。
ターゲット固有の問題に関しては、提案を出してみる。
通らなかったら、パッチをeCosのアーカイブに入れてもらうしかなさそう。
と思ったら、cppの問題は修正されていた。しかし、こんな直し方でいいの?
LONG_LONG_TYPE_SIZEを64bitにするパッチと、
昔作ったnormal modeのパッチを送ってみる。
ChangeLogには、一時期64bitになっていたようなことが書いてあったのが気になる。
aliasのエラーはレポートを送る。PR #6074
偶然binutils-2.12のリリースを知る。アナウンスがなかったので、
全然気がつかなかった。試した限りは問題なさそう。
ふと思い立ったので、aliasのエラーを調べる。
2回handle_alias_attributeが呼ばれているのが気になるので、
そのへんから当たってみる。
c++モードがだめなので、cc1plusに固有な部分がだめなのはわかってるんだけど、
ということで、どこから呼ばれているか当たってみる。
decl_attribute → handle_.*_attributeになっているので、decl_attribute
からたどってみる。
cplus_decl_attributeにたどりついた。C++のときだけ使っているので、これ
のような気がする。
調べてみる。何か違う。backtraceを取って見る。
duplicate_delcsからも呼ばれてる。
よくわからなくなってきたので、gcc-3.0.3のソースと比べてみる。
3.0.3の方は、duplicate_declsでdecl_attributeは呼んでいない。
duplicate_declsで、各宣言のattributeを一個にまとめているらしい。
ということは、ここでdecls_attributeを呼ぶのがそもそもおかしいんでは。
エラーメッセージからいっても、宣言が2回あるといっているので、
ためしにとってみる。
問題なし。ということで原因は、duplicate_declsでdecl_attributeを呼んでいたせいらしい。
パッチを送る。PR出して、パッチも送るのはなんか間抜け。
その他メールを送ったりパッチを更新して、gccの作業が終わる。
やっとRedBootのチェックに戻れる。
ということでloadをチェック。ymodemはネゴ出来なかった。
誓約書を送る。料金は意外に安かった。
パッチを受け取ったメールが届いた。今の所好意的。
問題はPR出してるやつなんだけど。
uClibcをいじっていたので、RedBootは進展なし。
ネゴ出来ないのは、タイミングが実時間にあっていないからでは?と思う。
メールのやりとりがメインになってる。
uclinux-devで、uClinuxをターゲットにした、H8/Sのボードを作る話を見つける。
面白そうなので問い合わせてみる。$199というのが少し引っかかるが。
RedBootの方はあいかわらず進展なし。少し探った限りは、
そもそも通信出来ていないのでは?疑惑があり。SCIエミュレーションがおかしい?
ということで、SCIエミュレーションを探ってみる。
1byteごとの読み込みを1kbyte読んでバッファリングに変更する。うーん、変化なし。
データを見るかぎり、読めてはいるらしい。ということは、RDRをセットする所か?
む、これだと連続して送られたときデータが捨てられてしまう。
これか!ということで修正。
通るようになった。んが、えらく遅い、BRRの設定を間違えているみたい。
cdlが間違っていて、ボーレートジェネレータのクロックがえらい数字になっている。
直してまともな数字になった。
う〜ん、シンボルを間違えてもエラーにならないのか。注意しないと。
うむ、4月になってしまった。
ダウンロード出来るようにはなった。が遅いのはあいかわらず。
BRRの値はまともなので、本物で見てみないとわからん。
sbとの相性が悪いだけかもしれないが。
作りかけのgdb_stubを入れてみるか。そのあとRAMターゲットのサポートかな。
昨日は何もできなかった。
秋月のH8/3068ボードが再入荷したらしい。通販に問い合わせたら在庫ありと言われた。
のでボードと電源を発注。
現金書留を送ろうと思ったら、WEBにも載っているので、そっちから頼んでみる。
また何もできなかった。困ったものだ。
秋月ボードが送られてきたらしい。受取は明日。RedBoot(というかeCos)
の改造を急がないと。
などと思いながら、sourceforge.jpにuClinux-H8のプロジェクトを作る。
eCos/RedBootも実機で動いたらプロジェクトに入れよう。
秋月ボードが届いた。ので組み立てる。サンプルが動いた。
ボードを作るよりも、それ以外ではまりまくり。
eCosのターゲット追加作業を開始。ターゲットなので、たいした手間は無いはず。
出来た、一瞬でおわってしまった。コンパイル出来たので、あとは明日。
昨日の続き。
RedBootを作ろうとしたら、CYGSEM_HAL_ROM_MONITORが
定義されていないといわれてしまう。何それ?。
ROMターゲットのとき必要らしい。実体はいらないようなので、宣言だけ入れる。
うーむ、RAMが足りない。食いつぶしているところを探す。
RedBootのワークが結構食ってる。ここを削るのは面倒なのでとりあえず後回し。
vector.Sが妙に食ってる。む、スタックに4Kもとられてる。最低1Kらしいので、
1Kにしてみる。なんとか足りたらしい。久々に味わった苦労。
出来たので、実機に焼いてみる。40Kもあると結構時間がかかる。
書きおわったので、電源ON。シミュレータでテストしてあるので、
初期化でこけなければ動くはず・・・動いた。ということでいろいろ試す。
あれ、メモリが見えない。カニも見えない。なんで?
回路図を見てみる。CSで制御してるのか。そういえばCS出力設定いるんだっけ?
データシートを確認。やっぱりリセット後は出力されていない。やられた。
初期化処理をミスって2回無駄に書き込んだ。あと95回か。
あれ、カニが見えない。何か初期化がいるのか?調べてみよう。
とりあえず適当なプログラムをダウンロード・・・出来ない。タイムアウトが短すぎ?
ダウンロード出来ないのは、タイムアウト時間おかしいのが原因らしい。
のでディレイ処理を調べる。基本的にはCPUに合わせて作るものらしい。
ということで作ってみる。1μ単位らしい。
出来た、けどおかしい。計算を間違えているのかな?
タイミングは、時間の計算を一桁間違えていたらしい。間抜けすぎ。
ダウンロードは通るようになった、けどメモリが見えていないらしい。
とりあえず、データシートを読み直してみる…う、ROM有効な場合は、
アドレスバス死んでる?
うーむ、下のほうも初期状態ではでは出力されていないのか。真面目にデータ
シートを読んだほうがいいかな。
気を取り直して修正。テストプログラムを読ませてダンプしてみる。OK。
goしてみる。動いた!
ということでパッチを整理して更新。日付が変わってるし。
CYG_HAL_STARTUP == RAMのためのコンフィグレーションを作成。
動いた。ということで、フラッシュの書き込みから当分開放される。
昨日作ったパッチは作りそこねていたようなので、これを公開しておこう。
残りはネットワークということで、少し調べる。
ドライバは、dp83902aを使えばいいらしい。
MIとMDかきれいに別れていて、MDの部分はeCos HALのAPIを使っているので、
手を入れる部分はかなり少ないみたい。
気になるのは、直接扱っているターゲットがいないことか。
まあ、何とかなるでしょう。
ネットワークのところで、ディレイを使っているので、タイミングを合わせておく。
うーん、NAKが帰ってくる。なんでかな?
タイマの時間に関係なくループを抜けているような気がする。
ループはきちんと回ってる。でもおかしい。
うーん、RAMとROMで時間が違う。
ふと気になったので、実行速度を計算してみる。
DRAMなので4cycle×8bitバスなので2回アクセス。なのでスピードは1/4。
間に合ってないような気がすごくする。
正確なステップ数を求めるためにアセンブラで書いてみる。
分解能10μなら追いつくはず。
・・・やっぱりあわない。
タイマーのカウント数から時間を求めてみる。5%ぐらいずれてるけど、
まああってる。実測値とあわないだけらしい。
何回か図ると、適度にぶれるので、時間は取れていると思うんだけど。
ここまで来ると、考えられることはただ一つ。
カウンタを読んでいる間、クロック入力が禁止される。
TCNTのアクセスタイミングが書いてないのでよくわからないけど、
内蔵I/Oは3ステートでアクセス出来るようなので、
2ー3のタイミングでカウントアップしないように、
禁止している可能性が高そう。
ということで、タイマーのカウントから経過時間を求めるのをやめて、
適当な間隔でコンペアマッチを起こして、それをつかまえることにしてみる。
うん、よさそう。あとは、間隔の調整かな。
16uSec単位にしてみる。ばっちり。時間待ちはこれで終わりにする。
で、時間を合わせるとYMODEMのダウンロードがうまくいかなくなるので調べる。
タイムアウト時間をいろいろいじってみる。変わらず。
NAKが帰っているので、エラーで戻っている場所を探す。
CRCの2バイト目が受けられないらしい。オーバーラン?
らしい。RDRFが立ったところで、時間待ちを抜けるようにしてみる。変わらす。
成功・エラー・成功・エラー…の繰り返しなので、
受信処理が間に合わないわけではないらしい。
ACKを返してから、次の受信が始まるまでが遅い?ようにみえる。
get_hdrの直前でACKを返してみる。通った。
しかし…そんなに遅いのかな?
気を取り直して、ネットワークを入れる。でかい。
出来たので起動。カニが見えないと言われる。うーむ。
どうやら、初期化処理が呼ばれていないらしい…
なんで?このへんはよくわからん。
初期化テーブルが空になってる。あれ、ドライバがリンクされていない。
どうやら、パッケージを手動で追加しないといけないらしい。
勝手に入るのと、入らないのと、区別がよくわからない。
cdlとecos.dbの書き方だとは思うんだけど。
初期化にたどりついた。MACアドレスが読めていない。
Jumper Modeの場合はMACアドレスは自力で読まないといけないらしい。
プラットホーム依存の初期化で読み込む。読めた。
が、その先で凍る。BOOTPのパケットが飛んでいないので、そのへんだろう。
dpのデバッグレベルを最大にする。なぜか動く。なんで?
でも、パケットは飛んでいないみたい。
よくわからん。
なんとなくデータの出力が早すぎのような気がするので、ディレイを入れてみる。
あたり、はまらなくなった、でもパケットが飛んでいる様子はない。
根本が間違っているような気がする。
別におかしいところは見つからない。
一個だけ // Enable all interruptsというコメントが気になったので、
コメントアウトしてみる。
む、TxのLEDが光った。TxEventに回った。ということはこれか?
もう少しテストしてみよう。
直ったようなので、固まった原因は、これらしい。
でも、パケットは飛ぶけどキャプチャ出来ないので、変なデータが飛んでるような気がする。
変なデータが飛んでるような気がする。ということなので、
送信データの処理をもう一回チェックする。
デバッグプリントを見るかぎり、送信するデータは問題ないので、
カニに書き込んだあとだろうと見当をつけてみる。
データは、DP_OUT_DATAマクロで書き込んでいる。
でもって書き込みアドレスがdp->data。
ん、初期化するコードを書いた記憶が…無い。
そのへんで初期化して…無い。これが原因?
ns_dp83902a_plf_initで初期化してみる。出来たので動かしてみる。
反応はまとも。でもIPアドレスは取れない。
dhcpサーバーのログを見てみる。リクエストは届いている、
BOOTPは設定しないと蹴られるらしい。
dhcpd.confを修正、もう一回起動。お!、IPアドレスがもらえた。
PINGを打ってみる。返事が来るのできちんと動いているらしい。
よさそうなので、telnetでつないでみる。お、つながった。
tftpdを設定して、loadを試す。ばっちり。
デバッグプリントがうるさいので、全部止める。
試行錯誤の結果も全部元に戻す。
もう一回ためす。大丈夫みたい。
祝 ネットワークサポート完成。
環境の都合により、uClinuxは一時中断して、eCosをいじる。
ということで、GDB stubまわりのデバッグ。
STUBサポート付きのRedBootを作ってみる。問題なくできる。
GDBから接続…出来ない。うーん、接続シーケンスがよくわかっていないので、
どこから追いかければいいのか…。
RedBootの入力処理で、GDBのパケットをチェックしているので、
そこから追いかけてみる。
パケットのヘッダを検出すると、例外処理を起動してstubに制御が回っているらしい。
パケットの処理は共通部分の処理なので、ここに飛んでいないような気がする。
ので、追ってみる。
うーむ、割り込みのほうに回っている。あ、ベクタ番号の計算が間違ってる。
よく動いているな。全部同じところに飛ぶから平気なのか。
直した、例外処理に入ったけどつながらない。なんで?
昨日の続き。
SCIエミュレーションがくさった版のGDBだったらしい。新しいGDBで接続に成功。
メモリの読み書きもOK。なんだけど、プログラムが実行出来ない。
コマンドは受け付けているけど、そっちに飛んでいかない。
あいかわらずよくわからないので、追いかける。
例外処理から抜けることで、読み込んだプログラムに飛んでいくらしい。
ここで、レジスタを書き換えてすり替えているのか。
どうやらPCの書換に失敗しているのが原因らしい。
レジスタのインデックスが間違っていた。これだ。
ブレイクポイントも動いた。シングルステップも良さそう。と思ったら、
rtsがおかしい。戻りアドレスが拾えていない。
スタックポインタの値がそもそも拾えていなかった。拾えるようにしたら直った。
しかし、コンテキストスイッチまわりまで直す羽目になるとは。
ついでにメモり消費量を押さえるべく努力する。stubで5Kぐらいまで押さえた。
コンフィグレーションによっては、もう少し減るはずなので、まあ実用範囲内かな。
CTRL-Cのサポートをチェックしていなかったので、チェックする。
コードは動いてるんだけど、なぜかすり替えたtrapが実行されないので、
うまく戻ってこれない。シミュレータの割込み処理のせいだと思うんだけど。
本物で試すか。
ついでなので、WDTのドライバも入れてしまう。これも本物でテストするか。
実機に焼いてみる。問題なし。 だいたい終わりかな?
昨日の続き。
しばらく更新することもなくなるかな。
そういえばGCC3.1はいつ出るんだ、5月になってるけど。
久々に書いてる。
GCCは1ヶ月遅れぐらい?3月25日版とあまり変わっているように見えない。
GCC関係の記述を修正する。パッチは特に変えるところは無いかな?
と思ったけど、libgccの部分を少しきれいにする。
出来たので、RedBootをコンパイルしてみる。問題なし。
ということで、GCC3.1関連の更新。
次回更新は、2.0公開後になったりして。
またまた久々。
>次回更新は、2.0公開後になったりして。
ということになりました。予想より早かったのでそんなに間は空いてませんが。
(多分)最終版のパッチを公開。マージされるまでの期間限定。
eCos関係の作業はとりあえず完了したので、ここの更新も終わりかな。
4ヵ月ぶりです。
前回から、ほとんど変更はありません。
試験的にIDEサポートが入ったぐらいです。
SourceForge.JP
ヘ引っ越す事にしました。
と言う事で、ここにおいてあるドキュメントは、全てObsoluteになります。
検索で飛んで来れるので、消す事はありませんが、一切更新しません。
最新情報は、SourceForgeから拾ってください。よろしくお願いします。