まずは、製品の機能を特徴づけるアプリケーションプログラムの作成方法について説明します。アプリケーションプログラムは、C言語で作成するものとします。これまでにC言語での開発経験がある方でも、Linuxでの開発スタイルやクロス開発特有の問題など、注意すべき点がいくつかあります。
次に、Atmark Distと呼ばれるアットマーク社製品用の開発ディストリビューションを用いて、ユーザーランドのルートファイルシステムを作成する方法について説明します。ここでは、Armadilloの標準と同じルートファイルシステムのイメージファイルを作成し、それをArmadilloに書き込む方法を紹介します。
続いて、標準のルートファイルシステムをカスタマイズする方法について説明します。ユーザーランドに、作成したオリジナルのアプリケーションプログラムや設定ファイルを追加する方法を紹介します。
一通りの開発が完了したら、量産に向けた準備を行います。アットマークテクノでは、Armadilloを使った製品の量産をなるべく簡単に行えるよう、カスタマイズサービスを提供しています。
本章では、Armadillo を使った場合の開発サイクルの全体像を掴んでもらうために、各手順の概要的な説明のみをおこないます。詳細な説明は、第2部でおこないますので、そちらをご参照ください。
本章では、C言語でアプリケーションプログラムのソースコードを作成し、コンパイル、実行する方法について説明します。
Linuxでのアプリケーション開発は初めてという方でも読み進められるように、まずホストである作業用PCでプログラムのコンパイルと実行をおこなう方法を説明します。その後、作業用PCでターゲットとなるArmadillo用にプログラムをコンパイルし、Armadilloで実行する方法について説明します。
まずは、定番である「Hello World!」を表示するだけのアプリケーションプログラムを作成し、実行してみます。
以下に示す、図7.1「hello.c」を作成し、atmarkユーザーのホームディレクトリ(/home/atmark
)に保存してください。
| テキストエディタ |
---|
Linuxでの定番のテキストエディタといえばviやemacsですが、これらは操作を覚えるだけでも大変です。Debian GNU/Linuxでは、Windowsでのメモ帳のように気軽に使えるテキストエディタとしてgeditというアプリケーションが標準でインストールされています。 geditは「アプリケーション」-「アクセサリ」-「テキスト・エディタ」メニューから起動することができます。操作方法は、Windowsアプリケーションに似ているので、すぐに覚えることができるでしょう。 |
入力したソースコードが意図したとおりに動作するか、まずは、ホストとなる作業用PC上で実行して確認します。
ソースコードをコンパイルするには、端末を起動して、以下のコマンドを実行してください。
Linuxでは、Cコンパイラとしてgcc(GNU C Compiler)を使用します。gccの引数にソースコードのファイル名を与えて実行すると、コンパイル、アセンブル、リンクの一連の処理を自動で行い、実行ファイルを出力します。-o
オプションに続いて指定した引数で、実行ファイルの名前を指定することができます[]。
なお、コンパイル、アセンブル、リンクの一連の処理を行い、実行ファイルを生成することを、「ビルドする」と表現します。
実行ファイルは、カレントディレクトリにhello
というファイル名で作成されます。カレントディレクトリにあるファイルを実行するには、「./
」を付けて相対パスでファイル名を指定します。
エラーやワーニングなくコンパイルでき、意図したとおりに実行結果が表示されたでしょうか?何か問題があれば、ソースコードを修正して、問題がなくなるまでコンパイル、実行を繰り返してください。
ホスト上で問題なく実行できたら、ターゲットとなるArmadillo用にクロスコンパイルします。
Armadillo(ARM)用にコンパイルするときは、arm-linux-gnueabi-gccという名前のクロスコンパイラを使用します。
クロスコンパイラでコンパイルしたものは、ARM用のバイナリとなっているため、もちろんホストでは実行できません。
| ファイル形式の簡単な見分け方 |
---|
fileコマンドを使用すると、作成された実行ファイルがamd64(x86)用なのか、ARM用なのかを簡単に見分ける事ができます。 amd64用の実行ファイルをfileコマンドで調べると、以下のように「x86-64」と表示されます。 [ATDE ~]$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.26,
BuildID[sha1]=0xdecb54e8721f8b0ca4d2b28e47460a0b41e8eb18, not
stripped
ARM用のバイナリでは、「ARM」と表示されます。 [ATDE ~]$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.26,
BuildID[sha1]=0x5006625cc66e41bd277140ffa89f862d6df0c637, not
stripped
|
ターゲット上で実行するために、Armadilloに実行ファイルを転送します。
Armadilloの標準イメージでは、FTPサーバーが自動で起動しており、pub
ディレクトリに書き込みが可能になっていますので、転送にはFTPを使用することにします。
ATDE側のFTPクライアントして、lftpを使用します。ArmadilloにFTPでファイルを転送するために、以下のコマンドを実行してください。
| 同じコマンドを入力する手間を省く |
---|
一度入力したことがあるコマンドを繰り返し入力するのは、大変面倒です。 シェルには、一度入力したコマンドを記憶しておくヒストリー機能が備わっています。 ↑キーで、それまでに入力したコマンドを表示します。 また、Ctrl+rでそれまでに入力したコマンドを遡って検索できます。[] 例えば、Ctrl+rに続いて、lfと入力すると、「lf」を含む以前入力したコマンドを検索して表示します。表示されたコマンドを実行するには、そのままEnterキーを入力してください。 [ATDE ~]$
(reverse-i-search)`lf': lftp 172.16.25.11 -e "cd pub;rm hello;put hello;quit"
|
転送した実行ファイルをArmadilloで実行してみます。FTPのpub
ディレクトリに転送したファイルは、Armadilloの/home/ftp/pub
ディレクトリに保存されます。
「Permission denied」というエラーが表示されました。これは、転送した実行ファイルの実行権限がないことを意味しています。Linuxシステムでは、ファイル一つ一つに、どのユーザーに対して読み、書き、実行する権限を与えるか、指定することができます。
ファイルの権限を変更するにはchmodコマンドを使用します。+x
オプションを付けてchmodコマンドを実行すると、ファイルに実行権限を付けることができます。
今度は、無事に「Hello World!」という実行結果を確認できました。
このように、Armadillo上で動作させるアプリケーションも、最初はホスト上でビルド、実行を繰り返してあらかたのバグを取り除いてから、ターゲットとなる Armadilloで動作確認するというのが、アプリケーション開発の基本的な流れになります。
ATDEを使ってシステムを構築するメリットの一つに、豊富なライブラリが利用可能である点が挙げられます。
本章では、ライブラリを使ったアプリケーションプログラムの作成方法について説明します。
例として、算術演算ライブラリに含まれるsin関数を使用します。sin関数はdouble型の引数を一つとり、その正弦の値を返す関数です。引数はラジアンで指定します。
| 関数の定義を調べる |
---|
Linuxシステムでは、オンラインマニュアルでシステムコールとシステムライブラリに含まれる関数の定義を調べることができます。オンラインマニュアルには、関数定義の他、関数が定義されているヘッダファイル、動作の詳細や戻り値などの情報が記載されています。オンラインマニュアルを調べるには、manコマンドを使用します。 sin関数を調べるには、以下のコマンドを実行してください。 [ATDE ~]$ man sin
|
sin関数を使用したサンプルプログラムを以下に示します。math.h
は、sin関数を定義しているヘッダファイルです。
sin.c
をhello.c
と同様にコンパイルすると、sinが未定義というエラーになります。
Linuxシステムでは、ライブラリはlibライブラリ名
という名前になっています。算術演算ライブラリの場合、libmです。ビルド時にライブラリをリンクするには、-l
ライブラリ名
オプションを指定します。
実行結果は以下のようになります。
Armadillo用にクロスコンパイルするには、hello.c
の例と同様にコンパイラにクロスコンパイラを用いるだけです。
実行ファイルをArmadilloにFTPで転送し、実行結果を確認してください。
ATDEでは、gccを用いてコンパイルを行った場合、インクルードパスは/usr/include
となります。「#include <ヘッダファイル名
>」というディレクティブでヘッダファイルをインクルードした場合、インクルードパスにあるヘッダファイルを使用します。
クロスコンパイル用に、コンパイラとしてarm-linux-gnueabi-gccを用いた場合のインクルードパスは、/usr/arm-linux-gnueabi/include
となります。gccを用いた場合とは、参照するヘッダファイルが異なる事に注意してください。
また、ホスト用のライブラリは、/usr/lib
ディレクトリにあります。算術演算ライブラリの場合、/usr/lib/x86_64-linux-gnu/libm.so
[]です。
ARM用のライブラリは、/usr/arm-linux-gnueabi/lib
ディレクトリにあります。ライブラリを使用するプログラムをターゲットで動かす場合には、/usr/arm-linux-gnueabi/lib
ディレクトリにあるライブラリファイルを実行ファイルと共にターゲットにコピーしなければなりません。
Armadilloの標準イメージでは、算術演算ライブラリは/usr/lib/libm.so.6
[]にあるため、今回の例ではライブラリをコピーするという手順は省略しています。
プログラムをビルドする際、毎回gccコマンドを入力するのは手間がかかります。makeを使うことで、複雑なビルド手順を自動化することができます。
makeは、makefileと呼ばれる設定ファイルにプログラムをビルドするルールを記述しておくと、それに従って次に行うべき手順を見つけ出し、必要なコマンドだけを実行してくれるツールです。
makefileには、以下の形式でルールを記述します。
makefileには、複数のルールを記述することができます。1つのルールは必ず1つのターゲットを持ちます。このターゲットが、そのルールで生成されるファイルとなります。ルールには、ターゲットを生成するために必要な依存ファイルと、ターゲットを生成するためのコマンドを記述します。
依存ファイルは「<ターゲット>:」の後にスペース区切りで記述します。また、コマンドは、ターゲットの次の行から行頭のタブ(スペースではなく)に続いて記述します。依存ファイルとコマンドは、0個以上記述することができます。つまり、依存ファイルやコマンドがない場合もあります。
また、makefileでは変数を使用することができます。「変数名 = 値」という形式で定義し、$(変数名)で参照します。基本的に、変数の値は文字列として扱われます。
sin.c
をビルドするmakefileは以下のようになります。sin.c
と同じディレクトリに、Makefile
(Mは大文字です)という名前で保存してください。
makeコマンドを引数を指定せずに実行した場合、makeはカレントディレクトリにあるGNUmakefile
、makefile
、Makefile
という名前のファイルを順番に検索し、最初に見つけたファイルをmakefileとして認識します。
makefileを認識後、makeはmakefileで一番最初に記述されたルールに従って処理を行います。図7.17「sin.cをビルドするMakefile」の場合、一番最初のルールは「all: $(TARGET)」です。これは、変数を展開すると「all: sin」となり、「allターゲットを生成するにはsin
ファイルが必要である」というルールになります。
allを作成するにはsin
が必要ですので、makeは「sin: sin.o」というルールに従ってsin
を生成しようと試みます。このように、makeはルールに従って、最初のターゲットに必要なファイルを芋づる式に生成します。
「sin: sin.o」というルールは、「sin
を生成するには、sin.o
が必要」という意味になります。sin.o
には「%.o: %.c」というルールが適用されます。これは、特殊なルールの書き方ですが、「.oで終わるターゲットを生成するには、.cで終わるファイルが必要」という意味になります。.oと.cの前は、同じ文字列です。即ち、「sin.o
を生成するには、sin.c
が必要」ということになります。
sin.c
は、既にあるファイルなので、ここでようやくコマンドが実行されます。%.oに対応するコマンドは、「$(CC) $(CFLAGS) -c -o $@ $<」です。CCやCFLAGSは、Makefile
の最初で定義されている変数です。$@や$<は特殊な変数で、それぞれターゲット名と依存ファイル名を意味します。そのため、このコマンドを展開すると、「gcc -Wall -Wextra -O2 -c -o sin.o sin.c」となります。
gccに見慣れないオプションが付いていますね。-Wall
と-Wextra
は、警告オプションです。ソースコードにバグを誘発しそうな構文があれば、コンパイル時に警告メッセージを表示してくれます。gccでコンパイルを行う場合は、必ず警告オプションを付けておき、警告メッセージが出ないようなソースコードを記述することを習慣付けておくことで、C言語の構文が原因のバグを未然に防ぐことができます。
-O2
は、最適化オプションです。gccでは、いくつかの最適化レベルを指定することができます。-O2
を指定した場合、コードサイズと実行速度をどちらも犠牲にしないような最適化を行います。
-c
オプションが付いている場合、gccはコンパイルとアセンブルまでしか行わず、リンク処理を行いません。この時、出力ファイルはアセンブラが出力したオブジェクトファイルになります。
sin.c
からsin.o
が生成されると、次はsinターゲットに対応した「$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@」が実行されます。$^も特殊な変数で、依存ファイルを意味します[]。これを展開すると、「gcc -lm sin.o -o sin」となります。libmとsin.o
をリンクして、実行ファイルsin
を生成します。
sin
が生成されると、allターゲットに対するルールが適用されます。しかし、allターゲットに対応するコマンドはないので、何も行われません。当然、allという名前のファイルも生成されません。そのため、allターゲットに対する処理はmakeコマンドを実行するたび、毎回行われることになります。
実際の実行結果は、以下のようになります。
makeコマンドを実行すると、まず、sin.c
のコンパイルが行われます。このとき、警告オプションの影響で、使用していない変数(argcとargv)があるという警告が表示されています。警告だけでエラーは出ていないので、オブジェクトファイルsin.o
が生成され、それを元に実行ファイルsin
が生成されています。
ここで、再度makeコマンドを実行しても何も行われません。makeは、ターゲットと依存ファイルが変更された時刻を比較して、ターゲットの変更時刻が依存ファイルの変更時刻よりも新しい場合、ターゲットを再生成する必要はないと判断して、ターゲットに対応するコマンドを実行しません。ターゲットがないか、ターゲットよりも依存ファイルが新しい場合のみターゲットの生成をおこないます。
makeコマンドには、引数にターゲット名を指定することもできます。図7.17「sin.cをビルドするMakefile」では、cleanターゲットを引数として渡すと、生成したファイルを削除します。
最後に、makefileをクロスコンパイルに対応させる方法を紹介します。ホスト用にビルドするか、クロス用にするかは、コンパイラにgccを使うか、arm-linux-gnueabi-gccを使うかの違いだけで対応できることを利用します。
Makefile
をこのように修正すると、引数なしでmakeコマンドを実行するとクロスコンパイルをおこない、「make CROSS=」として実行するとホスト用にコンパイルします。
Makefile
の先頭で、CROSS変数にarm-linux-gnueabiを代入して定義しています。「ifneq ($(CROSS),)」は、CROSS変数が空でなければ次の処理を実行することを意味します。CROSS変数には値が代入されているので、次の処理が実行され、CROSS_PREFIX変数が定義されます。CC変数には、gccの前にCROSS_PREFIX変数の値をつけた文字列を代入します。そのため、CCの値はarm-linux-gnueabi-gccとなり、クロスコンパイルが行われます。
makeコマンドは、引数で変数を定義でき、そのようにして定義した変数はmakefile中で定義する変数よりも優先される機能があります。そのため、「make CROSS=」というように、CROSS変数を空文字列で定義すると、CROSS_PREFIXも定義されません。そのため、CCの値はgccとなりホスト用のコンパイルが行われます。
このように、同じソースコード、同じmakefileを使用して、クロスコンパイルとホスト用コンパイルの両方に対応することができます。
7.2. Atmark Distを使ったルートファイルシステムの作成
Atmark Distは、アットマークテクノ独自のソースコードベースの開発ディストリビューションです[]。Atmark Distを使うと、ユーザーランドのルートファイルシステムとカーネルのイメージファイルを簡単に作成することができます。
Atmark Distには、様々なアプリケーションプログラムとライブラリのソースコードが含まれています。一方で、Linuxカーネルは対象となる製品毎に適切なソースコードが異なるために、Atmark Distには含まれていません。製品毎に適切なカーネルソースコードを追加して使用します。
Atmark Distでは、対象となる製品毎にどのような機能を含めるかの設定をおこなうことができます。製品のことを「プロダクト」、設定のことを「コンフィギュレーション」と呼びます。Atmark Distには、Armadilloの開発セット用のプロダクトが含まれています。この開発セット用のプロダクトを元にして、ユーザー独自のプロダクトを追加することもできます。
本章では、Atmark Distにユーザー独自のプロダクトを追加し、ルートファイルシステムとカーネルのイメージファイルを作成し、イメージファイルをターゲットとなるArmadillo のフラッシュメモリに書き込む方法について説明します。
アットマークテクノが配布しているAtmark DistとLinuxカーネルのソースコードは、以下のURLからダウンロードすることができます。
表7.1 Atmark DistとLinuxカーネルソースコードのダウンロードURL
基本的には、最新バージョンのソースコードを使用するようにしてください。本章の例では、以下のバージョンを使用します。
表7.2 使用するAtmark DistとLinuxカーネルソースコードのバージョン
ファイルの取得にはwgetコマンドを使います。
アーカイブの展開にはtarコマンドを使います。
以降の操作を分かりやすくするため、atmark-dist-20151026
ディレクトリにatmark-dist
という名前でシンボリックリンク[]を張ります。シンボリックリンクを作成するには、lnコマンドに-s
オプションを付けて使用します。
Atmark Distが使用するLinuxカーネルを指定するために、atmark-dist
ディレクトリにLinuxカーネルソースディレクトリへのシンボリックリンクを張ります。
| 注意: linux-3.x はそのまま入力 |
---|
「linux-3.x 」は、省略表記ではありません。置き換えなどをせずにそのまま入力してください。 |
Atmark Distでは、製品固有の設定やファイルは製品(プロダクト)毎のディレクトリにまとめて、管理しています。このディレクトリのことを、プロダクトディレクトリといいます。アットマークテクノ製品の場合、開発セット用の標準イメージに対応するプロダクトディレクトリが、製品毎に用意されています。
Armadilloを使って独自の製品を作る場合、ベースとなるArmadillo用のプロダクトディレクトリをコピーして使用することで、基本的な設定を引き継ぐことができカスタマイズが容易になります。今回は、Armadillo-420ベーシックモデル開発セット用のプロダクトディレクトリをコピーして使用することにします。独自プロダクトの名前は、my-productとします。以下のコマンドを入力し、my-product
というプロダクトディレクトリを作成してください。
7.2.4. ルートファイルシステムのビルドとイメージファイルの作成
コンフィギュレーションの設定が完了したら、ルートファイルシステムとカーネルをビルドします。Atmark Distでは、ビルドと共に、それらをArmadilloのフラッシュメモリに書き込める形式に変換します。このファイルを、イメージファイル又は、単にイメージといいます。
Atmark Distでビルドとイメージの作成を開始するには、makeコマンドを引数なしで実行します。
makeが完了すると、atmark-dist/images
ディレクトリにイメージファイルができています。
romfs.img
がユーザーランドのルートファイルシステムの、linux.binがカーネル
のイメージファイルです。末尾に.gzが付いているファイルは、それぞれを圧縮したものです。通常は、圧縮されたイメージファイルをArmadilloに書き込みます。
前章で作成したイメージファイルを、Armadilloのフラッシュメモリに書き込みます。
Armadilloでは、フラッシュメモリをいくつかの領域(リージョン)に分割して使用しています。カーネルイメージはカーネル領域に、ユーザーランドのルートファイルシステムイメージはユーザーランド領域にそれぞれ書き込みます。
ここでは、Hermit-Atブートローダーのtftpdl機能を使用して、ネットワーク経由で書き込む方法を紹介します。Armadilloのフラッシュメモリにイメージファイルを書き込む方法はいくつかありますが、ATDEとArmadilloがネットワーク接続できている環境であれば、tftpdlによる書き込みが手軽で高速です。その他の書き込み方法については、「Armadillo-400シリーズ ソフトウェアマニュアル」を参照してください。
tftpdlは、TFTPプロトコルを使用してTFTPサーバーからファイルをダウンロードし、フラッシュメモリの書き換えを行う機能です。ATDE5では標準でTFTPサーバーが動作しており、すぐに使うことができます。以下のコマンドを実行して、イメージファイルをTFTPサーバーが使用するディレクトリにコピーしてください。
tftpdl機能は、Hermit-Atブートローダーの保守モードで使用することができます。
保守モードで起動するために、一度Armadilloの電源を切り、SW1(タクトスイッチ)を押しながら電源を投入してください。保守モードでHermit-Atが起動すると、Armadilloのシリアルインターフェース1に以下のプロンプトが表示されます。
以下のコマンドを実行することで、tftpdl機能を使用して、カーネルにlinux.bin.gz
を、ユーザーランドにromfs.img.gz
を書き込みます。イメージファイルは、カーネルかユーザーランドのどちらか一方だけ指定することもできます。
フラッシュメモリへの書き込みが完了したら、Armadilloの電源を入れ直すことで書き込んだイメージで起動します。
これまでに、製品独自のアプリケーションプログラムを作成し、それをAtmark Distに統合してルートファイルシステムとカーネルをビルドし、イメージファイルを作成、そして、Armadilloに書き込むという一連の開発の流れについて説明してきました。十分にテストして、システムとして動作することが確認できれば、製品として出荷する準備は整ったことになります。
本章では、製品の量産化前に行うべきことについて説明します。
開発段階では、通常、Armadilloの開発セットを使用します。開発セットには開発に必要な周辺機器一式が含まれているので便利ですが、量産時には不要なものもあります。Armadilloは量産用にボード単体の量産モデルも販売しています。
また、アットマークテクノでは、ユーザー独自のイメージファイルの書き込みや梱包といったカスタマイズを、Armadilloにおこなって納品するという、カスタマイズサービスを提供しています。カスタマイズサービスを利用すると、ユーザーはイメージファイルと作業内容を指示するだけで、ユーザー用にカスタマイズされたArmadilloを購入することができます。
カスタマイズサービスでは以下のサービスを提供しています。
表7.4 カスタマイズサービスの種類
サービス | 内容
|
---|
コネクタ実装指定サービス | 標準コネクタの実装/非実装の指定や、指定コネクタの実装など |
ROM イメージ書き込みサービス | 基板への指定のイメージファイル書き込み |
梱包指定サービス | 個装箱への封入や、指定シールの貼付などの梱包 |
ケーシングサービス | ケースへの基板を組み込み |
オプション品指定サービス | ACアダプタやケーブルなど、開発用モデル添付の標準オプション品を指定 |
その他カスタマイズサービスに関する詳しい内容については、弊社営業部までお問い合わせください。
Armadilloで使用しているソフトウェアは、その大半がオープンソースソフトウェアです。オープンソースソフトウェアの中には、GPLのようにそのソースコードを公開することが義務付けられているものがあります。製品化を行う前に、使用しているソフトウェアがどのようなライセンスを持っているのか、確認する必要があります。
Linuxカーネルには、GPLが適用されます。そのため、Linuxカーネルを使用したシステムを販売する際には、システムで使用しているLinuxカーネルのソースコードをエンドユーザーが入手できる手段を提供しなければなりません。
なお、LinuxカーネルはGPLですが、アプリケーションプログラムからシステムコールを介してその機能を使用する分にはアプリケーションプログラムはGPLの影響を受けません。
BusyBoxも同様にGPLが適用されるソフトウェアです。