できるCCS⑥ [ ビルド編 ]

プロジェクトの取り込み・作成はできましたか?
今回はプロジェクトのビルド方法や、ビルドを行う際に必要となる各種ファイルについて解説します。

そもそもビルドとは

そもそもビルドとは何でしょうか?
一言でいえば、「CやC++等のプログラミング言語で記述したプログラムをターゲットボード上で“実行可能な”イメージファイル(Out File)に変換する作業」のことをいいます。
ここで “実行可能な” という意味を少し考えてみましょう。マイコンやアプリケーションプロセッサはそれぞれ特有のマシン語で動作しています(個々のマシン語は、そのデバイス特有のバイナリの数値の羅列で表現されています)。

ポイント1 : C/C++やアセンブリ言語で記述したプログラムは、マシン語に変換しないとデバイス上では動作しない

さて、マシン語に変換されたプログラムはどこで動作するのでしょうか?
当然、対象のデバイス上で…ということになるのですが、より厳密に言えば、「対象のデバイスがアクセス可能なアドレスに配置されているメモリ上で動作する」ということになります。

ポイント2 : マシン語に変換されたプログラムは、その配置先を定義しないと動作することができない

このように、アプリケーションをビルドする際には、少なくとも上記のポイントを解決する必要があります。

TI社ではこれらのポイントを解決するために、各デバイス毎に「ツール・チェーン」を無償で提供しています。ツールチェーンは、主にC/C++コンパイラ、アセンブラ、リンカで構成されています:

  • C/C++コンパイラは、CやC++で記述されたプログラムをマシン語(オブジェクト)に変換
    →ポイント1を解決します
  • アセンブラは、アセンブリ言語で記述されたプログラムをマシン語(オブジェクト)に変換
    →ポイント1を解決します
  • リンカは、与えられたメモリに関する情報を元に、C/C++コンパイラやアセンブラで生成されたオブジェクトの配置先を決定し、最終的に実行ファイルを生成
    →ポイント2を解決します

イメージを見てみましょう。

プロジェクトをビルドするには

それでは作成したプロジェクトをビルドする手順をみていきましょう。

ビルドしたいプロジェクトを選択後、「Project → Build Project」または「Build」ボタンをクリックするとビルドを開始します。

ビルドが完了すると、その結果がConsoleウィンドウに表示されます。
また、エラーや警告がある場合はProblemsウィンドウに詳細が表示されます。

ビルド手順は以上となります。意外と簡単でしたね。ボタンひとつで終わる作業ですが、この裏で行われているいろいろな工程を意識するとより理解が進むでしょう。

さて、ビルドした実行イメージファイルはどこへ行ったのか…気になりませんか?
それはOut Fileとして特定の場所に生成されています。一般的に、実行イメージファイルのことをOut Fileと呼びます。次項ではこのOut Fileについてご紹介していきます。

Out Fileとは

Out Fileには、コンパイルされたプログラムのデータや、シンボル情報(コンパイルオプションによる)、そしてそれらのメモリ配置情報等が含まれており、CCSはそれを解釈しながらエミュレータを介してターゲットボード上にあるデバイスの内部RAMや外部RAMにプログラムをロードすることになります。

ビルドすると、プロジェクトの直下に「ビルドコンフィギュレーション名」のディレクトリが生成されるのが確認できますでしょうか?Out Fileはその中に生成されます。
例えば、Debugビルドコンフィギュレーションでビルドすると、/Debugフォルダに生成されることになります。

Map Fileとは

ビルド後のDebugフォルダには様々なファイルが生成されますが、その中でも重要なMap Fileについてご紹介いたします。

Map Fileはシステムに存在するメモリの先頭アドレスや容量、各セクション(セクションについて説明は後述します)の配置先などが記述されているファイルです。

Link Command Fileとは

Map Fileでは各種メモリの容量やデータの配置が設定されているとご紹介しましたが、これは一体だれが決めたのでしょうか… ここでLink Command Fileの登場です。

Link Command Fileとは、システム上の「どのメモリ」に「何のセクション(コードやデータ)」をマッピングするか自由に設定することができるファイルのことです。
組み込みの世界では、メモリやCPUリソースが限られていますので、ユーザはプログラムの中の何のデータをどこのメモリに配置するのかを意識することが非常に重要になります。
CCSではその設定をLink Command Fileで行うのです。

プロジェクト内に拡張子*.cmdのファイルが見えますでしょうか?そちらがLink Command Fileです。
以下がLink Command Fileを開いた画面になりますが、「MEMORYディレクティブ」では、システムに存在するメモリがどこのアドレスからどれくらい存在するのかを定義しています。一方、SECTIONSディレクティブは、プログラムの各種セクションをどのメモリに配置するのかを定義しています。

セクションとは

先程から「セクション」という言葉が出てきますので、ここで少し解説をしておきます。

ビルド時、リンカはプログラムやデータをいくつかのブロックに分けてOut Fileを生成します。
このブロック1つ1つを「セクション」と呼びます。
セクション毎に格納される内容は異なり、リンカに依存するところがあるかもしれませんが、主に以下の表のようになります。

ユーザ独自のセクションを作成するには#pragmaを使用することで可能です。例えば、あるグローバル変数に対してセクションを割り当てるには以下のようにDATA_SECTIONを使用します。

  • ソースコードへの追加
    • プログラムのセクション指定
       「#pragma CODE_SECTION(関数名,  ”.セクション名”)」
    • 変数のセクション指定
       「#pragma DATA_SECTION(変数名,  ”.セクション名”)」
  • Link Command Fileへのコードの追加
    • 「SECTIONS {  .セクション名  >  指定メモリ名  }」

まとめ

今回は、ビルド方法と、それに関連するファイルについての概要をご紹介いたしました。
さらなる詳細については、お使いのデバイスに対応するCompiler User's GuideおよびAssembly Language Tools Guideをご確認ください。これらのドキュメントについては、 こちらをご参照ください。

次回はデバッグにあたって必要なビルドコンフィグレーションやTarget Configuration Fileの設定を解説させていただいた後、いよいよデバッグを行っていきます。どうぞお楽しみに。

できるCCSはコチラから