TMS320C28x は、メモリをプログラム・メモリとデータ・メモリの 2 つの連続した
ブロックとして扱います。
❏ プログラム・メモリには、実行可能なコード、初期化レコード、およびスイッ チ・テーブルが含まれます。
❏ データ・メモリには、外部変数、静的変数、およびシステム・スタックが含ま れます。
C/C++ プログラムによって生成されたコード・ブロックとデータ・ブロックは、適 切なメモリ空間の連続したブロックに配置されます。
注: リンカのメモリ・マップ定義
コンパイラではなくリンカがメモリ・マップを定義し、コードおよびデータをター ゲット・メモリに割り当てます。コンパイラは、使用できるメモリの型について、使 用できない位置(ホール)や入出力(I/O)または制御のために確保されている位置 については、何も想定していません。
コンパイラは、リンカがコードおよびデータを適切なメモリ空間に割り当てること が可能な再配置可能なコードを作成します。たとえば、リンカを使用して、グロー バル変数を高速な内部 RAM に割り当てたり、実行可能なコードを内部 ROM に割り 当てたりできます。各コード・ブロックまたはデータ・ブロックをそれぞれメモリ に割り当てることができますが、これは一般的な方法ではありません(この例外は メモリ・マップド I/O です。これを用いると、C ポインタ型で物理メモリ位置にアク セスできます)。
メモリ・モデル
7.1.1 セクション
コンパイラは、コードとデータが入った複数の再配置可能なブロックを作成します。
これらのブロックは セクションと呼ばれ、さまざまなシステム構成に整合するよう に、さ ま ざ ま な 方 法 で メ モ リ 内 に 割 り 振 ら れ ま す。セ ク シ ョ ン の 詳 細 は、
『TMS320C28x アセンブリ言語ツールユーザーズ・マニュアル』を参照してください。
セクションの基本型は 2 つあります。
❏ 初期化されたセクションには、データ・テーブルおよび実行可能なコードが含ま れます。C コンパイラは初期化されたセクション(.text、.cinit、.const、.econst、
.pinit、.switch)を作成します。
■ .text セクションは、定数と同様に実行可能なコードをすべて含む初期化され
たセクションです。
■ .cinit セクションと.pinit セクションは、変数および定数を初期化するための
テーブルを含みます。
■ .const セクションは、文字列定数や明示的に初期化される(const で修飾され
た)グローバル変数と静的変数の宣言および初期化を含む初期化されたセク ションです。
■ .econst セクションは、文字列定数や明示的に初期化され、far メモリに配置さ
れる(far const かラージ・メモリ・モデルの使用で修飾された)グローバル 変数と静的変数の宣言および初期化を含む初期化されたセクションです。
■ .switch セクションは、スイッチ文のためのテーブルを含む初期化されたセク
ションです。
❏ 初期化されないセクションは、メモリ(通常 RAM)にスペースを確保します。
プログラムは、実行時にこの空間を変数の作成と格納に使用できます。コンパイ
ラは、5 つの初期化されないセクション(.bss、.ebss、.stack、.sysmem、.esysmem)
を作成します。
■ .bss セクションは、グローバル変数および静的変数のためのスペースを確保
する初期化されないセクションです。プログラム起動時に、C ブート・ルー チンは(ROM 内に存在する).cinit セクションからデータをコピーし、.bss セ
メモリ・モデル
■ .sysmem セクションは、動的メモリ割り当てのためにスペースを確保する初
期化されないセクションです。確保された空間は、malloc 関数が使用しま す。malloc 関数を使用しない場合、セクションのサイズは 0 のままになりま す。
■ .esysmem セクションは、動的メモリ割り当てのためにスペースを確保する初
期化されないセクションです。確保された空間は、far malloc 関数が使用しま
す。far malloc 関数を使用しない場合、セクションのサイズは 0 のままになり
ます。
リンカは出力セクションを作成するために、さまざまなモジュールから個々のセク ションを取得し、同じ名前のセクションを結合させます。完全なプログラムは、こ れらの出力セクションから構成されています。これらの出力セクションは、システ ムの仕様に合わせて、アドレス空間の任意の場所に配置できます。
.text、.cinit、switch の各セクションは、通常 ROM または RAM のいずれかにリンク され、プログラム・メモリ(ページ 0)内に配置されなければなりません。.const セ クションは、ROM または RAM のいずれかにリンクされますが、データ・メモリ
(ページ 1)内に配置されなければなりません。.bss/.ebss、.stack、.sysmem/.esysmem の各セクションは、RAM にリンクされなければならず、データ・メモリ内に配置さ れなければなりません。次の表に、それぞれのセクションのタイプが必要とするメ モリの型およびページ宛先を示します。
セクション メモリの型 ページ
.text ROM または RAM 0
.cinit ROM または RAM 0
.pinit ROM または RAM 0
.switch ROM または RAM 0、1
.const ROM または RAM 1
.econst ROM または RAM 1
.bss RAM 1
.ebss RAM 1
.stack RAM 1
.sysmem RAM 1
.esysmem RAM 1
メモリ・モデル
7.1.2 C/C++ システム・スタック
C/C++ コンパイラは、スタックを使用して以下の作業を実行します。
❏ ローカル変数を割り当てる
❏ 関数に引数を渡す
❏ プロセッサ・ステータスを保存する
❏ 関数の戻りアドレスを保存する
❏ 一時的な結果を保存する
ランタイム・スタックは、下位のアドレスから上位のアドレスへと増大します。デ フォルトでは、このスタックは .stack セクションに割り当てられます(rts ファイル
boot.asm を参照)。コンパイラは、ハードウェア・スタック・ポインタ(SP)を使用
してスタックを管理します。
注: .stack セクションのリンク方法
.stack セクションは、データ・メモリの下位 64K にリンクする必要があります。SP
は 16 ビットのレジスタで、64K を超えるアドレスをアクセスすることができませ ん。
サイズが 63 ワードを超える(SP オフセット・アドレッシング・モードの最大値に 達する)フレームの場合、コンパイラはフレーム・ポインタ(FP)として XAR2 を 使います。関数を呼び出すと、新しいフレームがスタックの一番上に作成され、ロー カル変数と一時変数はそこから割り当てられます。FP がこのフレームの先頭を指し 示すことで、SP の使用では直接参照できないメモリ位置にアクセスできるようにな ります。
スタック・サイズはリンカによって設定されます。またリンカはグローバル・シン ボル __STACK_SIZE も作成し、このシンボルにスタック・サイズ(バイト数)を割 り当てます。デフォルトのスタック・サイズは、1K ワードです。スタック・サイズ
は -stack リンカ・コマンド・オプションを指定することにより、リンク時に変更で
メモリ・モデル
7.1.3 .const/.econst をプログラム・メモリに割り当てる方法
システム構成が .const/.econst などの初期化されたセクションのデータ・メモリへの 割り当てをサポートしない場合には、.const/.econst セクションをプログラム・メモリ にロードし、データ・メモリ内で実行させる必要があります。ブート時に、プログ ラム・メモリから .const/.econst セクションをデータ・メモリにコピーします。この 作業を実行する手順は次のとおりです。
ブート・ルーチンを変更します。
1) ソース・ライブラリから boot.asm を抽出します。
ar2000 -x rts.src boot.asm
2) boot.asm を編集し、CONST_COPY フラグを 1 に変更します。
CONST_COPY .set 1
3) boot.asm をアセンブルします。
cl2000 -v28 boot.asm
4) ブート・ルーチンをオブジェクト・ライブラリにアーカイブします。
ar2000 -r rts2800.lib boot.obj
.const セクションの場合、次のエントリを含むリンカ・コマンド・ファイルを使って
リンクします。
MEMORY{
PAGE 0 : PROG : ...
PAGE 1 : DATA : ...
}
SECTIONS {
...
.const : load = PROG PAGE 1, run = DATA PAGE 1 {
/* GET RUN ADDRESS */
__const_run = .;
/* MARK LOAD ADDRESS */
*(.c_mark)
/* ALLOCATE .const */
*(.const)
/* COMPUTE LENGTH */
__const_length = .- __const_run;
}
メモリ・モデル
同様に、.econst セクションの場合、次のエントリを含むリンカ・コマンド・ファイ
ルを使ってリンクします。
SECTIONS {
...
.econst : load = PROG PAGE 1, run = DATA PAGE 1 {
/* GET RUN ADDRESS */
_ _econst_run = .;
/* MARK LOAD ADDRESS */
*(.ec_mark)
/* ALLOCATE .econst */
*(.econst)
/* COMPUTE LENGTH */
_ _econst_length = - ._ _econst_run;
} ...
}
リンカ・コマンド・ファイル内で、PROG という名前をページ 0 上のメモリ領域の 名前と、DATA という名前をページ 1 上のメモリ領域の名前とそれぞれ置き換える ことができます。コマンド・ファイルの残りは、上記の名前を使う必要があります。
CONST_COPY を 1 に変更した場合、有効にされた boot.asm 内のコードは、このよ
うにこれらの名前を使用するリンカ・コマンド・ファイルに依存します。いずれか の名前を変更するには、boot.asm を編集し、同じように名前を変更します。
7.1.4 動的なメモリ割り当て
コンパイラ付属のランタイムサポート・ライブラリには、実行時にメモリを変数に 動的に割り当てることができる関数(malloc、calloc、realloc など)が含まれていま す。これは大きなメモリ・プール(ヒープ)を宣言し、かつこれらの関数を使用し てヒープからメモリを割り当てることにより行われます。動的な割り当ては、C 言 語の標準的なものではなく、標準ランタイムサポート関数により提供されます。
このメモリ・プール(ヒープ)は、リンカによって作成されます。またリンカはグ ローバル・シンボル __SYSMEM_SIZE も作成し、このシンボルにヒープ・サイズ