読者です 読者をやめる 読者になる 読者になる

あるごリズム備忘録

学んだことの記録と日記

組み込みOS(第6回)

ステップ6の内容

前回ステップで、転送したELF形式ファイルを解析し、セグメント情報を読み取り、とりあえず内容を表示することだけはできた。今回のステップでは、読み取った情報をもとに、ファイル内容ををRAM上にコピーし、エントリーポイントに処理を渡すプログラムを実装する。

エントリ・ポイント

実行を開始するアドレスのこと。ELFヘッダの中には、エントリ・ポイントを保持するために割り当てられた領域がある。

関数へのポインタ

ELF形式ファイルから読み取ったエントリポイントのアドレスは、関数へのポインタとして変数に持っておく。関数へのポインタ f は次のように宣言できるらしい。

[返り値の型] (*f)( [引数] );

コード中に次のように書くと、f にポインタが渡されている関数が呼び出される。

f([引数]);

疑問点

runコマンドの動作

ブート・ローダのrunコマンドは、1回目は必ず失敗する。2回目はうまくいく。
理由はわからなかった。
アドレスを表示させてみたところ、一度目のコマンド実行時は、エントリーポイントのアドレスが0になっているが、2度目は正常にアドレスが入っている。しかし、1回目と2回目のコマンド実行の間に何か処理が入っているわけではないので、原因がわからない。

OS側のmain関数

OSのコマンド”exit”で、os側のmain関数はreturn されるが、その後の処理がどこに渡されるかがわからない。書籍のままのコードだとexitにあとフリーズする。これはおそらくリンカ・スクリプトの無限ループのため、この部分を丸々削除するとブート・ローダに処理が戻るはずだと考えた。しかし実際は、1回目のexitコマンドでは再びOSが起動し、2回目はブート・ローダに処理が戻った。原因が特定できなかった。


12ステップで作る組込みOS自作入門

12ステップで作る組込みOS自作入門

組み込みOS(第5回)

ステップ5の内容

ステップ4までで、とりあえずファイルの転送まではできるようになった。ここからは、転送したELF形式ファイルをRAM上に展開できるようにする。ステップ5では、展開はせず、ELFの解析プログラムまでを作成する。

マジック・ナンバ

ELF形式ファイルの先頭にある16バイトの領域に配置されている数値データのこと。様々な識別情報が書かれており、特に最初の4バイトは、「0x7f 0x45 0x4c 0x46」となっていて、これによってELF形式であることが判別できる。

「セクションと」と「セグメント」

セクション

リンカが、複数のオブジェクト・ファイルをリンクして一つの実行形式ファイルにする際に使用する。それぞれのオブジェクト・ファイルのセクションに従って、同じ種類のデータは、実行形式ファイルにおいて、同じデータ領域(.textとか)にまとめられる。

セグメント

ローダは、実行形式ファイルの内容を、書かれているセグメント情報にしたがって、セグメント単位でメモリ上に展開する。

疑問点

リンカについて

リンカ・スクリプト(ld.scr)は、リンカそのものではなく、リンカへの指示が書かれたファイルであることを理解できた。しかし、そうなるとリンカ本体はどれになるのかまだ理解できてない。


12ステップで作る組込みOS自作入門

12ステップで作る組込みOS自作入門

組み込みOS(第4回)

ステップ4の内容

今までは、プログラムの書き換えのたびに直接ROMを書き換えてきたが、ROMの書き換え回数には上限があるため、この方法を変更する。ROMにはブート・ローダーを書き込んでおき、起動のたびに、シリアル経由でプログラムをダウンロードし、RAMに展開する。この方法なら、ブート・トーダーを完成させてしまえば、プログラム本体を修正するたびにROMの書き換えを行わなくてすむ。
今回は、XMODEMプロトコルによって、ファイルを転送するところまでやる。

XMODEM

シリアル経由でのファイル転送プロトコル。古くからある(パソコン通信時代に流行ったらしい。)
プロトコルの実装」という響きのワクワク感。

シリアル受信用のライブラリ

今後はH8側でも受信を行うので、そのためのライブラリを実装する。

エコーバック

シリアル通信を行うときのエコーバックはどこに書かれているんだろうかという疑問は以前から持っていた。シリアルドライバで行ってしまうこともあるらしいが、今回、ドライバは送受信に専念するという意味でライブラリの中に書いた。

ファイル転送手順

kz_xmodemを使う方法

書籍で標準で使われている転送ツールではなく、kz_xmodemを使用すると、操作手順が少なくて楽。
(参考サイト: http://blog.livedoor.jp/noanoa07/archives/1994090.html

$ kz_xmodem [送りたいファイル名] /dev/tty.usbserial-FT0UMQ8C

(その後普通に通信)

$ sudo cu -l /dev/tty.usbserial-FT0UMQ8C
書籍通りやる方法(macの場合)

多少操作が増えても、せっかく実装したloadコマンドを使いたい場合は次のようにする。

kzload> load
$ ~+ lsx [送りたいファイル名]

(あとは待つだけ)

ABI(Application Binary Interface)

スタックポインタには、レジスタER7が使われている。だから、ジャンプ命令jrsやリターン命令rtsでは、引数を指定しなくても、勝手にER7が使われている。これはコンパイラが自動で行っているが、多くの場合、ABI(Application Binary Interface)という規格でCPUごとに決められている。したがって、CPUのABIをサポートしているなら、違うコンパイラコンパイルしたオブジェクトファイルでもリンクして正常に動作することができる。

スタートアップの無限ループ

スタートアップ(starup.s)の最後にある

1:
	bra 1b

このbraは戻り先を覚えない簡易的なジャンプ命令のようなもの。引数の1bは、「この命令より前にある”1:”というラベルの内最も近いもの」という意味である。つまり、直前にそのラベルがあるので、無限ループを表す。これ以前のスタックmain()へのジャンプの後、つまりmain()から戻ってきたとき、おかしな動作をして暴走しないようにする対策になっている。

疑問点

ファイル転送のに関して

lsxと、実装したXMODEMに関するプログラムの役割の範囲がよくわからない。
lsxはひたすらプロトコルのルール通りにビットデータを投げてきて、実装したプログラムは、それを意味のある形で上手く受け取っている?
さらに、kz_xmodemを使用した場合は、実装部分に関しては丸々使わないことになるのでは・・・と思っているけど、その認識はあっているのだろうか。 

ABIに関して

対象CPUのためにどのABIを使うのかというコンパイラの設定は、どこでやっているのかがわからない。Makefileの項目のどれかがその設定なんだろうか。


12ステップで作る組込みOS自作入門

12ステップで作る組込みOS自作入門

組み込みOS(第3回)

ステップ3の内容

ステップ2まではできなかった静的変数の書き換えを可能にするため、各ファイルを修正する。

変数の種類

変数にには「静的変数」と「自動変数」という種類がある。これらは、プログラムで宣言された位置によって種類が決まり、割り当てられるメモリ領域も異なる。

静的変数

関数の外で宣言される。初期値がないものはROMのデータ領域に置かれ、あるものはROMのBSS領域に置かれる。

自動変数

関数の内側で宣言される。RAM上に置かれる。

静的変数の書き換え対応

静的変数は、ROMに置かれるが、これだと内容の変更ができないので変数として使用できない。この対策として、マイコンの電源を入れた直後、ROMのデータ領域の内容を、RAMにコピーして、プログラムの変数からはそのコピー先にアクセスするように設定した。コピーはmain.cの最初で行い、設定はリンカ・スクリプトで行う。このような一連の処理を、「
VA≠PAにする」というらしい。

PA(ロード・アドレス/物理アドレス

静的変数の初期値が配置されるアドレス

VA(リンク・アドレス/仮想アドレス)

プログラムから静的変数を使うときにアクセスするアドレス

ELF形式

コンパイラが生成する実行形式ファイルのフォーマット。linuxにおいては、readelfコマンドで解析することができ、メモリのセクション情報や、各シンボルが割り当てられている番地などが確認できる。初期値のない静的変数が、BSS領域に置かれている事などもここで確認する事ができる。
(本の環境と異なる部分)
macでは、readdlfコマンドが使えないので、インストールする必要があった。

% brew install binutils

使用するときは、readelfではなく、greadeflとする。

% greadelf -a kzload.elf

その他

疑問が2つほど残った

  • リンクとは、プログラム中の関数や変数などのシンボルに対して、メモリを割り当ててやる作業という認識あっているのか?
  • リンカの実体は、リンカスクリプトなのか?


12ステップまで、3月中にやりきりたい。なんとしても時間を作り出して確保する。


12ステップで作る組込みOS自作入門

12ステップで作る組込みOS自作入門

組み込みOS(第2回)

 ステップ2の内容は、シリアルコントローラのレジスタによる設定、標準ライブラリ風関数の実装が主な内容だった。今回気になったのは「分周」と「ボーレート」の関係くらい。
 
 まず分周とは、CPUのクロック周波数をnで割ってほしい周波数を作ることらしい(n:分周比)。そして、この作った周波数をシリアルモジュールに供給する。
メインクロックを分周するnをBRRに設定すると思っていたんだけど違うらしい。どうもBRRの値とボーレートの対応表がマニュアルにマイコンごとに用意されていて、それを見て設定すれば良いらしい。
 マニュアルを見ると、表の他にBBR値の計算式も書かれていた。確かに歩調同期方式の式でBBRは64になる。ただし、(64*2^(2n-1))と−1の部分の意味がわからない。64*2^(2n-1))は設定するシリアル通信で使うビット長とかで違うのかもしれない。ビット長8なら8になるとかだったら理解できる。
 クロック同期方式と歩調同期方式の違いもよくわからなかった。この辺も確かに理解したい部分ではあるんだけど、この辺にかかりっきりになってしまうと進まない。この本で一番やりたいのは、メモリ管理とかスレッドの部分なので、あまりここで時間は使わないようにしたい。少し調べて、その時理解できなくても、「具体的にどこが」わからないかを記録しておけば(数学ガール的にいうと「分からないの最前線」)、最低限またあとで考えることができるからよしとしたい。


(蛇足)
 第1回の記事からだいぶ間が空いてしまった。期末試験その他いろいろあったが、時間を作れなかったわけではないので結局いいわけ。とにかく、本を進める過程で書き残し続けることはやめたくないので、今回はかなり雑な文章になってしまったが形に残すことを優先した。時間があれば書き直したい。


12ステップで作る組込みOS自作入門

12ステップで作る組込みOS自作入門

組み込みOS(第1回)

『12ステップで作る組み込みOS自作入門』という本を購入した。


以前から気になってはいたが、なかなか手を出さずにいたら存在を忘れてしまっていた。
再び購入意欲が高まった理由は、今期の大学のOSに関する講義があったこと、そしてバイト先(組み込み系の会社)に置いてあるのを見かけて思い出したから。
また、自分の中で不足しているかつ、欲しい知識として、アプリケーション層未満の階層での知識がある。
これは単純に自分の興味がそそられる部分でもあるし、将来的にもその方向で進んで行きたいという思いが最近大きくなっているからだ。
(あとこの動画を見たのも結構大きい。本当に楽しそうに話すので感動した。)


このような直接何かを作り出さない活動に、今のタイミングで時間を使うはどうかという考えが無いわけではないけど(「もっと実践的にカタチのあるものを作ってやりながら学び、実績を作るほうがいいかもしれない・・・」等)、「知りたい!やりたい!」と直感的に思えたタイミングでやるのが、経験的に一番吸収が良いので今すぐやる。
12ステップ、約500ページで少ない量ではないが、最後までさっさとやり遂げてしまいたいと思う。


ここから本題。
今回は初めてなのでステップ1の環境構築をやる。
現在まともに使えるPCがMacBookPro (Retina 13-inch、Early 2015)しかないのでこれを使う。
環境を作る手順は以下のサイトを参考にさせてもらった。
blog.livedoor.jp
書籍ではmacに関することは書かれていないので非常にありがたかった。


購入したケーブル等はすべて同じものを購入して問題なく使えた。
手順もほぼ同じように進めることができた。
ただし、ブログを書かれた方と使用しているgccの種類と設定等が違うようで、ブログには書かれていないエラーが発生したので少し言及する。


binutilsをビルドするとき

clang: error: unsupported option ‘-print-multi-os-directory'

という表示がされた。
調べてみたところ、このオプション‘-print-multi-os-directory'はコンパイル完了後に設定などをただ表示してくれるだけの機能なので、とりあえず無視したが、結果的に今のところは問題ない。
macgccLLVMでホントのgccじゃない(?)から云々・・・みたいなことが関係していそうだが、進めることを優先したいのでまた今度考えることにする。


以上、トラブルはこの程度で思っていいたよりもスムーズに、ステップ1は終わった。
新しく知ったことは、このブログに書くことを目標にこれから進めて行きたい。



12ステップで作る組込みOS自作入門

12ステップで作る組込みOS自作入門

「なぜ、あなたの仕事は終わらないのか」の感想

 この本はICPCでスポンサー企業の方からいただいたものだ。もとから気になっていたので、ありがたかったが、なかなか読む時間を作れず、昨日やっと読み終えた。いくつか印象に残った点があるのでここに記録しておく。


最初の2割の時間で仕事の8割終わらせる
 筆者はこのフレーズを本の中で何度も強調していた。目的は2つ。1つ目は、実際に取り掛かって難易度を認識し、かかる時間の見積もること。2つ目は、後半に心理的余裕を持たせて仕事のクオリティを上げること。(早く提出することではない!)1つ目に関しては、心から納得できた。ちょうど前回のゲーム作成において、取り掛かって初めて必要な仕事と時間が見えてくるということを実感していたからだ。2つ目は当然といえば当然である。わかっているけど難しいことだ。ただ、これも習慣の問題で、本の中で書かれていたように、同じ習慣は66日続けないと定着しないらしが、これは逆に言えばたった2か月さえ頑張れば自分のモノにできるということだ。

目的があれば勉強はたやすい
 別の言い方をすれば、「勉強のための勉強はするな」といこと。理由は簡単で、そんなものは続かないので身にならない。逆に、それが必要な場面になれば、「勉強」でなく自然と「調べる」。そして目的をたっせいするために、細かいことなど気にしないで、どんどん前進できる。これに関しても、自分が何度も体験してきたことだから納得できる。例えばPythonPHPを触ってみたことなど、もちろん無駄ではなかったと思いたいけど、必死になる明確な目的がないからから体には残らない。逆に、今やってるゲーム作りや、夏のインターンでのマイコンの作品などは、目の前に必ず形にしなければならないものが見えていたから自然と貪欲に努力できていた。

「まず作ってみる」が、世界を変える。
 これもゲームの企画や開発の初期段階でで、散々感じたことだ。アイディアは最低限動くものがあれば判断がしやすい。面白くなるかどうかの確信は、話だけの時よりもずっとしやすい。採用、不採用に関わらずとにかく判断が早くなる。また、先ほどの繰り返しになってしまうが、「モックアップ」が初期段階で存在しないと、必要な仕事が最初見つけずらいので、最後に焦ってたくさんの仕事をやることになってしまう。

朝が最強
 この理由に筆者が挙げていたのは、邪魔(LINE,メールなど)が入りずらいこと、そして外部要因の締め切りができることだった。1点目はいいとして、2点目については特に共感した。自分で決めた内部的要因などは簡単に破ってしまう。一方で外部要因に関しては、精神的にかなりの強制力がある。筆者の場合、それは家族が起きてくることらしいが、自分が体験したのは、人との締め切りである。これだと朝に限ったことだけではなくなるが、外部要因が効果的である点は同じだ。ただ、朝は早くにやると、講義の開始など確かに外部からの締め切りが多いので試してみたい。夜だと、いつまでもダラダラと続けてしまう。
 
 このように見ていくと、ここ2か月ほどでのチームでのゲーム作りから学ぶことは多かったのだなと改めて感じた。最近は、少し怠け気味なところがあったので、この本でまた気持ちが引き締まった。
 最近はこの手の自己啓発本を読みたいと思うことは少なくなっていた。以前は結構読んでいたが、多くの場合、読んでも何も変わらないと感じていたからだ。だが、今回は自分の経験と照らし合わせなながら、「あそこでああ考えたのは間違っていなかったんだな。」と答え合わせのような感覚で読んでいた。そのおかげで自分の、ぼんやりとした考えに自信が持てた。そして、これは特に自分が変わらなくてもたくさん読んでいたころからだが、自己啓発本のいいところは「元気が出る」ことだ。これは馬鹿にできない。何をするにしても、元気でなければ何かをやり始めるだけのの自信が出ない。自信なんていう根拠のないものは、こういう本によって「なんか行けそうな気がする」という気持ちになって獲得するものだと思う。以前岡田斗司夫が、自己啓発本のこのような効果について評価しているのを見て、当時は「自己啓発本なんて意味ないんだな」などと思ったが、今ならわかる。「元気が出る」のは本当に重要だ。だから、この本の最後の部分にある筆者の精神論的な熱い話も、自分には意味のあるものだった。なにせ元気が出る。

なぜ、あなたの仕事は終わらないのか スピードは最強の武器である

なぜ、あなたの仕事は終わらないのか スピードは最強の武器である