【組込みOS開拓史 PART2】機能設計_起動 ①スタックポインタの初期化
まずは、起動に関する設計を行う。設計の対象は、マイコンの電源をONしてから、main関数がコールされるまでの処理だ。普段、仕事でやっている組込みよりも、さらに「下」の領域だ。「レジスタの操作をアセンブラで行う」という痛快なことをやる。
とりあえずスタックポインタの初期化からはじめる。
【起動シーケンス】
①電源ON
②リセット割込み
(リセット割込みベクタに登録済の関数start()がコールされる。)
※割込みベクタについては、別途、割込みの設計をする時に考える。
③割込みベクタ内でスタックポインタの初期化
④main関数へジャンプ
→ 以降のシーケンスは「機能設計_ブートローダ」に記載する。
【スタックポインタの初期化】
スタックポインタ:スタック領域の最上段*1のアドレスを格納するレジスタ。ここからスタック領域として使います!という目印としての役割を果たす。
・スタックポインタをどうやって設定するか?
→マイコンマニュアルによれば、「sp」というレジスタが用意されているらしい。関数をコールする際、何もしなくても、spが勝手にスタックポインタとしての役割を果たしてくれる。よって、僕がやるべきことは、spに対し、スタックポインタとしたいアドレスを代入することだけだ。
<スタックポインタの設定方法>
・レジスタ「sp」について
ER0~ER7:汎用レジスタ(32bit)
ER7という32bitのレジスタがスタックポインタのレジスタとして使えるらしい。上の表だと(SP)というのがどの領域かわかりにくい。*2
・レジスタへのアクセスについて
マニュアル「2.7 アドレッシングモードと実効アドレスの計算方法」を読むと以下のように書いてある。
他にもアクセス方法はあるが、今の所は直接アクセスの方法がわかればいい。ER7とかけば、ER7のレジスタにアクセスできるようだ。また、ER7にかんしては、spと言い換えができるらしい。*3
レジスタへの命令は以下のように書く。(『組込みOS入門』(以下『OS本』)より
mov.l #_stack,sp
- mov A B:A→Bへのデータ転送。(.lはlongワード型を表す。アドレスなので4バイト。)
- _stackは、stackをリンカスクリプトで定義している。_stackと記述することで、アドレスを表す。(別途記載する)
- #は、即値命令を表す。*4
・実際にどのアドレスから何バイトをスタック領域として使うべきか?
具体的なコードでいうと、stackをリンカスクリプトファイルのどこに書けばよいかという問題だ。スタック領域がどれだけのサイズになるかは、実行してみないと分からない。よって、『OS本』では、RAMの末端付近に配置している。
stack(rw) : o = 0xffff00, l = 0x000000 /* end of RAM */
o:開始アドアドレス
l:サイズ
・なんでアドレス「0xffff00」が末端付近だとわかるのか?
マニュアル「3.6 各動作モードのメモリマップ」および『OS本』 p.92に記されている。
【用語一覧】
・スタートアップ
:起動時に始めに実行される処理。リセットのベクタ内に書かれているorベクタからジャンプした先に書かれている。