組込み開発再入門(2) – リンカスクリプト

組込み開発再入門(1)で適当なリンカスクリプトを書いた。
これをブラシュアップしつつもうちょっと理解してみようと思う。

スポンサーリンク

セクション

とりあえずセクションという概念を理解しなければリンカースクリプトは理解できない。よく使われるセクションについて調べてみた。

.text セクション

プログラムの実行コード(機械語)を格納する。ROM領域に格納する。

.data セクション

変数の初期値を格納する。ROM領域に格納しておく。実行時にRAM領域にコピーすることで書き換え可能にする。

.bss セクション

未初期化のデータを格納する。RAM領域に格納する。

.rodata セクション

文字列定数や const で修飾された値が変わらないデータを格納する。

.stack セクション

スタック領域。H8マイコンのスタック領域は下方伸長なのでRAMの一番最後に格納する。ローカル変数の値などを格納する。

割り込み

H8マイコンはベクタ割り込み方式というのを採用している。割り込み発生時に割り込みベクタテーブルを参照し、そこに登録された割り込みハンドラにジャンプする仕組みになっている。
割り込みベクタの位置はメモリの先頭アドレス 0x000000 から 0x0000FF の 256 バイト分である。主要なベクタアドレスは以下の通り。

割り込み要因 割り込み番号 ベクタアドレス
リセット 0 0x000000
NMI 7 0x00001c
トラップ命令 8〜11 0x000020〜0x00002c
外部割り込み 12〜17 0x000030〜0x000044

メモリマップや割り込み要因と割り込み番号についての詳細は各マイコンのハードウェアマニュアルを参照すること。

ここで大事なことは、電源投入時 (リセットピンが High になったとき) 0x000000 に書かれているアドレスに処理が飛ぶということ。

再びリンカスクリプト

適当に書いてみたリンカスクリプトの SECTIONS を見てみる。
リンカスクリプトの SECTIONS はメモリの配置を決めている。

SECTIONS
{
    . = 0x0;
    .vectors : {
        LONG(ABSOLUTE(_start))
    }
    . = 0x00100;
    .text : {
        *(.text)
    }
}

. はロケーションカウンタといって、メモリのアドレスを指し示す。
ということで、

. = 0x0

は メモリアドレス 0x00000 から書き始めろという指示になる。

    .vectors : {
        LONG(ABSOLUTE(_start))
    }

ここでベクタテーブルの開始アドレス 0x00000 に _start のアドレスを書いている。_start は何かというと、アセンブラで記述したラベル (関数) である。アセンブラのソースコードを見ると、この関数 _start は .text セクションに記述されている。

    . = 0x00100;
    .text : {
        *(.text)
    }

となっていることから、_start が置かれている .text セクションはアドレス 0x00100 から書き始められているということがわかる。

ということで、処理の流れは以下のようになる。

  1. 電源が投入されるとリセット割り込みが発生し、0x00000 を見に行く
  2. 0x00000 に書かれているアドレス 0x00100 へジャンプする
  3. 0x00100 に格納されている機械語 (アセンブラで書いた _start 関数) が実行される

とりあえずここまで。
ブラッシュアップしてないじゃん。というつっこみは無しで。

スポンサーリンク

フォローする