やったこと
今日から3日間特別講義です。
今日はその1日目で、僕はOS開発ゼミに参加しました。
ベアメタル開発のテーマで、はじめに事前学習の進捗を確認し、その後各々開発を開始しました。
僕はベアメタルのRaspberry piでLチカできるところまで行っていたので、この日はUARTの実装からはじめました。
8:30から開発を開始しましたが、10:00までに,一文字’H’の出力ができるようになりました。
低レイヤー開発をあまりやったことはなかったですが、キャンプまでのLチカでマニュアルの読み方などを講師のtnさん作の資料で追体験しながら学んでいたので、マニュアルを読んで、適切なアドレスのメモリに入れて、、という作業を実装するだけで、あまりここまでには苦労しませんでした。
ここからが長かった。'H'
は出せるのですが、"Hello,World\n"
を出そうとfor
ループを仕組むと、
1 | HeeeeellllloWrrlddHelloo |
のように、確かに出そうとしている文字ではあるが明らかに正しく書けていない文字が出力されるようになりました。
はじめに疑ったのはFIFOの空き待ちの不具合でした。
FIFOがNot Fullであることを1 Byte毎に確認して送っていたはずでしたが、それのアドレスやビットシフトの数が違うことが考えられるなと思いました。
しかし、それらは何度確認しても正しかったのです。
ただのfor loopをまさか間違えるはずもないですし、(実際Macで動かして確認しましたし)何だろうと思っていました。
午後になって、JTAGデバッガを接続しました。
が、ここで出力したkernel.elf
に、gdbからdebug symbolが見つからないと怒られてしまいました。-g
はつけているはずで、何も検討がつきません。
その後、tnさんがうまくビルドできたソースをもらって手元でビルドしてみると、そこからはきちんとシンボルが出ています。
そこで、それらのファイルとdiffして確認していくことにしました。
僕はCMakeを使い慣れていないので、CMakeLists.txt
のミスだと思っていましたが、tnさんのファイル群のそれを私のものに差し替えてもまともにビルドはできるまま。
これのせいではなさそうでした。
そんなこんなで講義終了の22:00を迎えました。
ここまで、4時間ほど、デバッガをつなぐためのデバッグに時間を食っていました。 最悪です。
部屋に戻って、続きをしました。
明日以降の講義の時間はもっと創造的なことに使いたかったので、何としてでもこれを夜のうちに潰したかったんです。
それでもなかなかうまくいかず、最後にダメ元で、リンカスクリプトを差し替えました。
「Symbol、出てるやん…」
意味わかんないです。
すぐにそれをdiffして、差異のあるところを一つづつ順番に直しながら、どこでsymbolが出るようになるか検証しました。
結果、以下のdiffのせいでした。
1 | < .stack : { |
いや、スペース二個ですやん!? こいつのせいで4時間とはまじでありえない。
明日からはこういうしょーもないのにかからないことを祈ります。
その後、無事にデバッガを接続でき、「え? ちゃんとFIFO待ってるやん?」となって、試しにUSB-Serial変換アダプタを再び繋いでみたら、ちゃんとHello,Worldになってましたとさ。
あのバグもメモリレイアウトがおかしかったことに起因してたのかもしれません。
とほほ、、
学んだこと、みたこと
私はこんなしょうもないバグに積んでいたわけですが、私の右側では、同テーマの方が、rustでの実装にチャレンジされていました。僕はむさ苦しいCコードで書いていたわけですが、同じものをあんなにも美しく実装されるとRustやりたさが出てきました。
僕もキャンプ後Rustをやろうと思いました。
それでは もう遅いので寝ます。 おやすみなさい。