連載
» 2006年12月19日 00時00分 公開

H8で学ぶマイコン開発入門(4):OSが起動する以前のスタートアップルーチン (2/4)

[山本 繁寿 ソフィアシステムズ,@IT MONOist]

スタートアップルーチン

 WindowsやLinuxなどのOSが搭載されたシステムでは、main関数の前後や周辺デバイスの制御は、OSが処理してくれます。これに対してOSが搭載されていない組み込みシステムの場合、OSが実行してくれる処理のすべてをプログラマが実装する必要があります。これらの処理を行うプログラムのことを、一般的にスタートアップルーチンと呼びます。スタートアップルーチンでは、最低限、以下の処理をプログラミングします。


  1. スタックの設定
  2. 割り込みベクタの設定
  3. ROM領域からRAM領域へ初期値データの転送
  4. 初期値を持たないデータのクリア(初期化)
  5. ハードウェアおよびCPU内蔵レジスタの初期化、割り込み許可
  6. アプリケーションプログラムの呼び出し

1.スタックの設定

 Cプログラムの自動変数(局所変数)は、変数が宣言された関数内部での計算やデータの保存、条件判定のためのフラグとして一時的に使われます。関数の仮引数や浮動小数点演算を行うためのテンポラリ領域なども一時的に使われ、さらにプログラムの書き方によりサイズや数が異なります。また、関数の戻り番地も常に値を保持している必要はありません。これら、一時的に使われる変数や作業領域などはコンパイラにより、スタックと呼ばれるRAM領域に割り付けられます(図1)。

スタック領域 図1 スタック領域

 プログラマは、アプリケーションプログラムで必要なスタック領域の大きさと、スタック領域の先頭アドレスをスタックポインタレジスタに適切に設定する必要があります。スタックを消費するものをまとめると、以下のようになります。

スタックを消費するもの

・自動変数
・複雑な計算をするためのテンポラリ領域:浮動小数点演算
・関数の戻り番地
・関数の仮引数
・割り込みの内部処理
・コンテキストの保存領域
・割り込み処理からの戻り番地
・割り込み関数内での自動変数、テンポラリ領域、関数の戻り番地/仮引数など

 スタック領域はコンパイラにより、読み書き可能なRAM内に配置されます。このため、スタートアップルーチンで細心の注意を払ってスタック領域を設定しないと、プログラムが暴走する原因になります。

 図2は、スタック領域の確保が十分ではなく、データ領域を破壊している例です。スタートアップルーチンで設定したスタックポインタが正常にスタック領域を指している間は問題ありません。しかし、スタックポインタがスタック領域の外側、この例ではデータ領域にまで侵入してくると、元データは破壊され、プログラムは動作異常を起こします。

スタック領域の確保が不十分でデータ領域を破壊する例 図2 スタック領域の確保が不十分でデータ領域を破壊する例

 また図3は、プログラム中で使っているポインタに問題があり、プログラムがスタックを破壊している例です。スタック領域に、関数の戻り番地が保存されているとします。この例ではプログラムポインタの使い方に問題があり、ポインタがスタック領域を指してしまいました。ポインタを使ってメモリからデータを取り出すだけなら、取り出したデータがおかしい値となるだけで、暴走する直接の原因にはならないかもしれません。しかし、ポインタでデータを書き込んでいる場合は、この例では本来あるべき関数の戻り番地が破壊されるため、プログラムは確実に暴走します。

プログラムポインタに問題がありスタック領域を破壊する例 図3 プログラムポインタに問題がありスタック領域を破壊する例

 このようにスタックの設定は、組み込みプログラムにとって非常に重要な要素です。

2.割り込みベクタの設定

 プログラム実行中に割り込みが発生すると、現在実行中のプログラムは中断され、プログラムカウンタは割り込み要因に対応するベクタを指します。割り込みベクタの記述方法や割り込み発生後の処理方法はマイコンにより異なります。本連載で使用するH8マイコンの場合、表1のベクタテーブルが割り当てられています。

H8のベクタテーブル 表1 H8のベクタテーブル

 H8マイコンの場合、割り込みが発生すると、以下の処理がマイコンにより実行されます。

  1. プログラムカウンタとコンディションコードレジスタ(CCR)をスタックに退避
  2. CCRの割り込みマスクビットを1にセット
  3. 割り込み要因に対応する割り込みハンドラのスタートアドレスを割り込みベクタテーブルから取り出して、割り込みハンドラに分岐

 プログラマの仕事は、割り込みハンドラのスタートアドレスを、ベクタテーブルに記述することです。H8/3048マイコンでは、割り込み例外処理を開始させる要因として、7種類の外部割り込み(NMI、IRQ0〜IRQ5)と内蔵周辺モジュールからの要求による30種類の割り込み内部要因があります。プログラマは、それぞれのベクタテーブルをプログラミングする必要があります。なお、割り込みハンドラ自体を記述することも、プログラマ側の責任であることはいうまでもありません。

Copyright © ITmedia, Inc. All Rights Reserved.