テクニカルTips
目次 > テクニカルTips
GCCはPCだけでなくメジャーな組込用CPUに対応しています。
JDEはディレクトリ構造と定義ファイルでコンパイラのバリエーションに対応する仕組みになっています。
- 定義ファイルのディレクトリ(フォルダ)は次のような階層構造になっています。
※[cpudef]より下のディレクトリには自由な名前を使うことができ、その名称がJDEの基本設定の名称として表示されます。
※[cpudef]が定義ファイルのルートディレクトリです。
[cpudef]の内容が異なると同じプロジェクトでも編集できない場合がありますので重要なプロジェクトを作成したときはバージョンアップ前に同じ階層で[cpudefxxx]という名前でコピーすることを推奨します。
※定義ファイル変更によるトラブルを避けるために新しい定義ファイルを[cpudef-vnnn]という名前で作成します。(Ver3.05以降)
-
CPUタイプの分類 : H8,MCS51,SH,Z80
CPUシリーズをここで分類します。例えばルネサスCPUシリーズの名称などを使います。
-
CPU型式の指定 : H8S2212U H8S2212U-A H8S2215 等
同じシリーズの異なった型式のCPUをここで分類します。同じ型式でも異なるCPUボードで外部メモリのサイズや割付が違うものはここで分けます。
-
構成の定義 : 00 01
同じCPU同じボードでメモリの割り当てやプログラムの起動方法が異なるものをここで定義します。例えばH8やSHのブート書込みではプログラムとデータを全て内蔵RAMに転送して実行しますし、ボードによっては外部メモリにプログラムやデータを置く場合があります。これらの違いをこの階層で分類して定義しておくことで、プロジェクトから簡単に再利用できるようになります。
※この階層はディレクトリ名ではなくディレクトリ中のxxxx.mapdefというファイルの名称が設定名として表示されます。
※ プロジェクトの保守性を向上するためVer5.0から定義ファイルはプロジェクトディレクトリにコピーして使用する方式に変更しました
CPUタイプインポートをしない限りプロジェクト構築時の定義ファイルはそのまま残ります。
(以下はVer5.0以前に関するトピックとなります)
標準の定義ファイルはバージョンアップや不具合修正のため変更されることがあり、インストーラは古い定義を新しい定義で上書きします。そのため古いバージョンで作ったプロジェクトが新しいバージョンのJDEではコンパイルできなかったり出来たプログラムが動作しない場合が発生することがあります。そのような問題を避けるためにバージョンアップの前に定義ファイルのバックアップをおこなうことを推奨します。
一番下のディレクトリには構成を定義する次のファイルがあります。

-
タイトルと構成の説明 xxxx.mapdef
mapdefという拡張子のファイルは構成のタイトルと構成の説明のためのファイルです。
ファイル名は構成の欄にタイトルとして表示され、ファイルの内容がその下に表示されます。
-
options.inc
常に必要な#define 行を記述します。
このファイルの内容はコンパイルオプションに組み込まれ全てのソースから参照されます。
-
crt0.s
構成で使用するスタートアップルーチンのソースです。
JDEのプロジェクト>スタートアップファイル の頁で参照・編集することができます。
-
lds.x
構成で使用するリンカスクリプトです。
JDEのプロジェクト>リンカスクリプト の頁で参照・編集することができます。
※その他のファイルはテンポラリファイルです。削除しても定義には影響有りません。
このディレクトリには次のようなファイルがあります

-
00 01 xx
構成毎の定義ディレクトリです。名称は任意でmapdefという拡張子のファイルがディレクトリの中に存在すると定義ディレクトリとみなされJDEから参照可能になります。
-
include
CPUに対応するヘッダファイルを入れるディレクトリです。
コンパイル時にこのディレクトリはincludeファイルのあるディレクトリと見なされます。
-
cpudef.ini
CPU毎のツール名、コンパイルオプションなどを定義するファイルです。
このファイルの内容はmakefile.tp1 makefile.tp2 から参照されます。
通信パラメータもこのファイルで定義します。
-
makefile.tp (Ver5.0以降)
Ver5.0から全てのソースを一つのmakefileで構築する方式に変更しました
このテンプレートと cpudef.ini をベースにmakefileを作成しプロジェクトの構築をおこないます。
-
makefile.tp1(Ver4.0以前)
コンパイルに使うmakefile作成用のテンプレートです。
このテンプレートと cpudef.ini をベースにmakefileを作成しプロジェクトの構築をおこないます。
-
makefile.tp2(Ver4.0以前)
makefile 作成用テンプレートです。
このテンプレートはcrt0.sをアセンブルするためのものです。
-
cputype.txt
CPUについての説明を記述します、このファイルはドキュメント用で動作には影響を与えません。
make はGCCでプロジェクトを構築する際の基本となるツールで、makefileはmakeへの指令となるファイルです。
基本的かつ多機能なツールなのでここではその内容についての説明はしません。
makefile についてこれから勉強しようとする方がいらっしゃいましたら 「makefile 使い方」というキーワードでググれば役に立つサイトが山のように見つかることでしょう。
-
JDEでのmakefileの作成とプロジェクト構築
プロジェクトの構築を実行するとJDEは次の順序でmakefileを使ってコンパイル・リンクをおこないます。
※Ver5.0以降
makefile.tpとcpudef.ini及びプロジェクトの設定から プロジェクトパスにmakefileを作成し、
makeを呼び出してオブジェクトファイルを作成後、リンクをおこないプログラムを構築して、ターゲットファイルへの変換をおこないます。
※Ver4.X以前
1.makefile.tp2とcpudef.ini及びプロジェクトの設定から スタートアップファイル(crt0.s)のある場所にmakefileを作成し、makeを呼び出してcrt0.sをアセンブルしcrt0.oを作ります。
2.makefile.tp1とcpudef.ini及びプロジェクトの設定から プロジェクトソースと同じ場所にmakefileを作成します。
3.makeを呼び出してオブジェクトファイル作成、リンクをおこないプログラムを構築した後、motファイルへの変換をおこないます。これらの一連の処理手続きはmakefile.tp1により決定されます。
※全バージョン共通
※makefileはJDEの プロジェクト > makefile 頁で参照することができます。プロジェクトの構築毎に新しい makefile
が作成されますのでこのファイルは参照専用となります。
リンカスクリプトは実行ファイルの形式やメモリの割り当てを指定する手順を記述したファイルです。
ワンチップCPUやCPUボードはそれぞれ固有のアドレスとサイズのROMとRAMを持っています。
それぞれのシステムに合わせたリンカスクリプトを用意して各ハードウェアに合ったメモリの割付を指定します。
-
ROMとRAM
リンカスクリプトを記述するときにまず意識しなければならないのがROMとRAMのサイズとアドレスです。
PC上のアプリケーションプログラムは全てがRAM領域に配置されるのが普通ですが、組込システムではROMとRAMをきちんと使い分けないとプログラムが正常に動作しません。
通常ROMにはコード(プログラムの実行部)、RAMにはデータを配置します。
RAMのサイズも限られている場合が多いのでデータがRAMに収まるよう確認する必要があります。
-
SECTIONS : セクション
セクションはリンクの基本となる論理単位です。
以下は多くのコンパイラで共通のセクションの例です。
.text : コードを格納するセクション
.data : 初期化されたデータを格納するセクション
.bss : 最初に0クリアして使うデータセクション
.stack : スタックエリア
GCCにはこの他にターゲットCPU毎に特有のセクションがあり、組込用の簡単なプログラムを作る場合も一定のセクションを記述しておかないとエラーになる場合があります。
詳細は各ターゲット用のリンカスクリプトを参照して下さい。
スタートアップルーチンはCPUがリセット起動するのに必要な初期化をするルーチンです。
PCではアプリケーションの開発者がスタートアップルーチンを意識することはありません、それはBIOSとして標準的に組み込まれているからです。
組込システムではROMやRAMが限られていてハードウェア毎に初期化すべき内容が異なるため、自分でスタートアップルーチンの面倒を見なければならない場合が多くなります。
-
スタックポインタの初期化
スタートアップルーチンの最初にすべき処理はスタックポインタの初期化です。
CPUがサブルーチンを呼び出したり割込が発生したときに処理中のレジスタやフラグの内容をスタックに保存し、それらの処理から戻るときにスタックから内容を復帰します。
ですから、スタックポインタの初期化がスタートアップルーチンの最初におこなうのが一般的です。
-
ハードウェアの初期化
スタートアップルーチンで次におこなう処理はハードウェアの初期化です。
組込用のCPUでは複数の端子機能、外部バス機能が用意されていてハードウェアに合わせてレジスタを設定する必要があります。
※簡単なシステムではハードウェアの初期化はメインルーチンを呼び出した後で行う場合もあります。
-
メモリのコピー、初期化
初期化変数の初期値はROMに保存しますが、実行時は変数として扱うためにRAMに配置しなければなりません。
スタートアップルーチンの中でROMの内容をRAMにコピーすることで初期化変数を実現します。
普通の変数はプログラム開始時にゼロクリアすることになっていますが、この処理もスタートアップルーチンの仕事です。
※初期化変数のセクション名は .data 、変数のセクション名は .bss です。
newlibライブラリのprintf関数,puts関数などが呼ばれた時は最終的にハードウェアに依存する入出力関数を呼び出します。
ROMモニタはソフトウェア割り込みを通じてこの入出力をサポートする機能を持っています、syscalls_newlib.Sはnewlibライブラリからモニタの入出力関数=USB経由で文字をやりとりする、を呼び出すために必要です。
puts関数やprintf関数を利用する場合は、プロジェクトに追加して下さい。
FlashROMを書き込む場合、書込中のFlashROMは通常のアクセスが出来なくなります。
FlashROMを書き換えるためにはすくなくとも書き換えのコードだけはRAMにおいて実行する必要があります。