スパイス  組み込み制御装置の受注製作

Hitech-Cコンパイラを組み込み用に移植する
平成26年4月21日

 ダウンロード用雛形プログラムに下記の文書を追加しました。ダウンロード先:プログラムの雛形
 ・Hitech Cコンパイラの制約に関する箇条書き
 ・雛形を使用するときのソースプログラムの追加方法(差分検出プログラムによって変更点を見つけます)
C言語の開始処理
 やっとCコンパイラの移植作業の中心となるスタートアップ処理にたどり着きました。
ROM化によってスタートアップ処理の内容が変わる理由を説明していきます。
最初はデバッグ用のスタートアップ処理から始めます。この状態の開始処理は基本的にはOS向けの処理とほぼ同じになります。処理内容は下記のとおりです。
1.スタックポインタに初期値を設定する
2.割り込み処理アドレスに割り込み処理関数へのジャンプ命令を配置する。
3.初期値の無い(初期値がゼロである)変数の変数領域をゼロにクリアする。
(4.関数main()へジャンプする)
 このうち、3.はOS向けの開始処理でも同じで、1.と2.はOSが起動する前に行われている処理です。実装方法の違いはあるでしょうが、やっていることはほぼ同じです。そう考えるとデバッグ用の開始処理はOSの起動を省略したものと考えることが出来ます。これはデバッグ用の命令コード・データは全てがRAM上に配置されるという点でOSと同じ条件にあるためです。

対してROM化が前提の場合は、以前のブログ組み込みの準備で、下記を示しました。
1.スタックポインタに初期値を設定する
2.割り込み処理アドレスに割り込み処理関数へのジャンプ命令を配置する。
3.初期値のある(初期値が非ゼロの)変数の初期値を変数領域にコピーする。
4.初期値の無い(初期値がゼロである)変数の変数領域をゼロにクリアする。
(5.関数main()へジャンプする)

 ROM化による主要な変更点は3.のみです。この違いはデータの初期値の保管方法の違いからきています。OS向けやデバッグ用では、プログラムおよびデータは外部からRAMに読み込まれます。つまり、RAMに初期値を与えることが可能です。ところが、ROM化を前提に考えると不都合なことが起こります。初期値を与えるためにはROMに実装することが必要ですが、そうするとデータの変更が出来ません。ではRAMにデータを配置すると初期値は保障されないので別途に初期値を与える方法が必要になります。つまり、一つの変数に対して初期値を置くROMアドレスとそれにアクセスするRAMアドレスの二つが必要になります。 C言語が機能する前にROM上の初期値をRAM上の変数アドレスにコピーできれば、デバッグ用の環境と同じにできます。
 問題はこのような一つの変数に二つのアドレスを与えることが出来るかどうかです。ROM化対応を謳うCコンパイラは、何らかの方法でこの機能を実現している必要があります。このようなアドレスの2重化が必要なのは、プログラム自体がプログラムを書き換えない限りデータに限られます。一般的なCコンパイラはプログラムの中味を大きく4つのグループに分けて管理しています。一つ目はプログラムの命令コード(グループ名はcodeまたはtext)、二つ目は変数の中で初期値が0の変数(bss)、三つ目は変数の中で初期値が非0の変数(data)、最後はスタック変数(stack)です。C言語の非static ローカル変数はスタック変数です。static宣言のあるローカル変数とグローバル変数がdataおよびbssになります。どちらになるかは初期値が0かどうかで決まります。C言語の仕様から初期値を指定しないグローバル変数・static変数は初期値が0と見なされます。

   少しだけ補足説明
 ここでは”変数”と書いたので気がつき難いのですが、実際には”内容が固定の変数”も存在します。例えばprintf()系関数で使用される文字列部分(下記の青色部分)もdata領域に分類されます。比較的最近のコンパイラでは、このような変数をRAMにコピーする変数領域から外す処理をしているようですが、古いコンパイラでは一緒にRAMにコピーされます。その分メモリが無駄になりますが、ROM化は組み込み特有の要求ですので、すぐには対応出来なかったと思われます。
   prinf("%d\t %s\n", num, str);


 つまり、ROM化のためにはdataグループに関して初期値をおくアドレスと実際のアクセスを行うアドレスの2重化を行うことが必要です。
タイトル先頭へ 前へ 次へ タイトル末尾へ