開発の基本的な流れ

本章では、Armadilloを使った製品開発を行うために必要な一連の手順を順を追って説明します。

基本的な流れは、以下のようになります。

  1. アプリケーションプログラムを作成する
  2. Debian GNU/Linuxルートファイルシステムアーカイブを作成する
  3. 量産に向けた準備をする
  4. 製品出荷後のメンテナンスをする

まずは、製品の機能を特徴づけるアプリケーションプログラムの作成方法について説明します。 アプリケーションプログラムは、C言語で作成するものとします。 これまでにC言語での開発経験がある方でも、Linuxでの開発スタイルやクロス開発特有の問題など、注意すべき点がいくつかあります。

次に、Debian ユーザーランドのルートファイルシステムアーカイブを作成する方法について説明します。 ルートファイルシステムアーカイブに、オリジナルのアプリケーションプログラムや設定ファイルを追加する方法も、ここで紹介します。

一通りの開発が完了したら、量産に向けた準備を行います。 アットマークテクノでは、Armadilloを使った製品の量産をなるべく簡単に行えるよう、カスタマイズサービスを提供しています。

最後に、製品出荷後のメンテナンスについて気をつけなければならないことについて説明します。

本章では、Armadillo を使った場合の開発サイクルの全体像を掴んでもらうために、各手順の概要的な説明のみをおこないます。

8.1. アプリケーションプログラムの作成

本章では、C言語でアプリケーションプログラムのソースコードを作成し、コンパイル、実行する方法について説明します。

Linuxでのアプリケーション開発は初めてという方でも読み進められるように、まずホストである作業用PCでプログラムのコンパイルと実行をおこなう方法を説明します。 その後、作業用PCでターゲットとなるArmadillo用にプログラムをコンパイルし、Armadilloで実行する方法について説明します。

8.1.1. Hello World!

まずは、定番である「Hello World!」を表示するだけのアプリケーションプログラムを作成し、実行してみます。

以下に示す、図8.1「hello.c」を作成し、atmarkユーザーのホームディレクトリ(/home/atmark)に保存してください。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        printf("Hello World!\n");

        return EXIT_SUCCESS;
}

図8.1 hello.c


[注記]テキストエディタ

Linuxでの定番のテキストエディタといえばviやemacsですが、これらは操作を覚えるだけでも大変です。 Debian GNU/Linuxでは、Windowsでのメモ帳のように気軽に使えるテキストエディタとしてgeditというアプリケーションが標準でインストールされています。

geditは「アプリケーション」-「アクセサリ」-「テキスト・エディタ」メニューから起動することができます。 操作方法は、Windowsアプリケーションに似ているので、すぐに覚えることができるでしょう。

入力したソースコードが意図したとおりに動作するか、まずは、ホストとなる作業用PC上で実行して確認します。

ソースコードをコンパイルするには、端末を起動して、以下のコマンドを実行してください。

[ATDE ~]$ gcc hello.c -o hello

図8.2 hello.cをコンパイルするコマンド


Linuxでは、Cコンパイラとしてgcc(GNU C Compiler)を使用します。 gccの引数にソースコードのファイル名を与えて実行すると、コンパイル、アセンブル、リンクの一連の処理を自動で行い、実行ファイルを出力します。 -oオプションに続いて指定した引数で、実行ファイルの名前を指定することができます[46]

なお、コンパイル、アセンブル、リンクの一連の処理を行い、実行ファイルを生成することを、「ビルドする」と表現します。

実行ファイルは、カレントディレクトリにhelloというファイル名で作成されます。 カレントディレクトリにあるファイルを実行するには、「./」を付けて相対パスでファイル名を指定します。

[ATDE ~]$ ./hello
Hello World!

図8.3 helloの実行結果


エラーやワーニングなくコンパイルでき、意図したとおりに実行結果が表示されたでしょうか? 何か問題があれば、ソースコードを修正して、問題がなくなるまでコンパイル、実行を繰り返してください。

ホスト上で問題なく実行できたら、ターゲットとなるArmadillo用にクロスコンパイルします。

[ATDE ~]$ arm-linux-gnueabihf-gcc hello.c -o hello

図8.4 hello.cをクロスコンパイルするコマンド


Armadillo(ARM)用にコンパイルするときは、arm-linux-gnueabihf-gccという名前のクロスコンパイラを使用します。

クロスコンパイラでコンパイルしたものは、ARM用のバイナリとなっているため、もちろんホストでは実行できません。

[ATDE ~]$ ./hello
/lib/ld-linux-armhf.so.3: No such file or directory

図8.5 クロスコンパイルしたhelloの実行結果(ATDE上)


[ティップ]ファイル形式の簡単な見分け方

fileコマンドを使用すると、作成された実行ファイルがi386(x86)用なのか、ARM用なのかを簡単に見分ける事ができます。

i386用の実行ファイルをfileコマンドで調べると、以下のように「80386」と表示されます。

[ATDE ~]$ file hello
hello: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically
linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=84cc
e45ccca0ec56f0cbd2b36b299bdd484a3d94, not stripped

ARM用のバイナリでは、「ARM」と表示されます。

[ATDE ~]$ file hello
hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically li
nked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=f
e0cc3af441ae9b586159ad8a9ced593a3c1c506, not stripped

ターゲット上で実行するために、Armadilloに実行ファイルをコピーします。 Armadilloに実行ファイルをコピーする方法には様々なものがありますが、ネットワーク(Ethernet)経由で転送する方法が手間が少なくて良いでしょう。

ここでは、scp コマンドを使用することにします。

標準状態のArmadilloではSSH Serverが動作していないので、まずはArmadilloにopenssh-serverをインストールします。

[armadillo ~]# apt-get update && apt-get install openssh-server

図8.6 openssh-serverのインストール


次に scp コマンドを実行して、Armadilloにファイルを転送します。

scp では、リモートマシン上のファイルを次のように表現します。

"ユーザー名@IPアドレス:/ディレクトリ名/ディレクトリ名/.../ファイル名"

今回はローカルマシン上の "hello" というファイルを、リモートマシン上の atmark ユーザーのホームディレクトリ(/home/atmark/以下)にコピーすることにします。

[ATDE ~]$ scp ./hello atmark@<ArmadilloのIPアドレス>:~/
The authenticity of host '192.168.0.2 (192.168.0.2)' can't be established.
ECDSA key fingerprint is SHA256:lrhNjYNWnytCglh881CuT5Vlgwmlq/G4UiqVDfTvohE.
Are you sure you want to continue connecting (yes/no)? yes  1
Warning: Permanently added '192.168.0.2' (ECDSA) to the list of known hosts.
atmark@<ArmadilloのIPアドレス>'s password:  2
hello                                         100% 8376     1.6MB/s   00:00

図8.7 Armadilloへのファイル転送


1

"yes" と入力

2

Armadillo の atmark ユーザーのパスワードを入力[47]

[ティップ]同じコマンドを入力する手間を省く

一度入力したことがあるコマンドを繰り返し入力するのは、大変面倒です。

シェルには、一度入力したコマンドを記憶しておくヒストリー機能が備わっています。

↑キーで、それまでに入力したコマンドを表示します。

また、Ctrl-rでそれまでに入力したコマンドを遡って検索できます。

例えば、Ctrl-rに続いて、scと入力すると、「sc」を含む以前入力したコマンドを検索して表示します。 表示されたコマンドを実行するには、そのままEnterキーを入力してください。

[ATDE ~]$
(reverse-i-search)`sc': scp ./hello atmark@172.16.2.156:~/

転送した実行ファイルをArmadilloで実行してみます。

[armadillo ~]# /home/atmark/hello
Hello World!

図8.8 クロスコンパイルしたhelloの実行結果


[ティップ]

Linuxでプログラムを実行しようとした時、「Permission denied」というエラーが表示されることがあります。 これは、実行ファイルに実行権限がないことを意味しています。 Linuxシステムでは、ファイル一つ一つに、どのユーザーに対して読み、書き、実行する権限を与えるか、指定することができます。

ファイルの権限を変更するにはchmodコマンドを使用します。 +xオプションを付けてchmodコマンドを実行すると、ファイルに実行権限を付けることができます。

[armadillo ~]# chmod +x /home/atmark/hello

図8.9 実行権限を付与する


このように、Armadillo上で動作させるアプリケーションも、最初はホスト上でビルド、実行を繰り返してあらかたのバグを取り除いてから、ターゲットとなる Armadilloで動作確認するというのが、アプリケーション開発の基本的な流れになります。

8.1.2. ライブラリとヘッダファイル

ATDEを使ってシステムを構築するメリットの一つに、豊富なライブラリが利用可能である点が挙げられます。

本章では、ライブラリを使ったアプリケーションプログラムの作成方法について説明します。

[ティップ]

必要なヘッダファイルの名前や、共有ライブラリのファイル名がわかっている場合は、Debian プロジェクトサイトの「パッケージの内容を検索」からファイルの含まれるパッケージの名前を探す事ができます。

また、パッケージの部分的な名前が分っている場合は apt-cache search コマンドを使って必要なパッケージを探す事もできます。

例として、算術演算ライブラリに含まれるsin関数を使用します。 sin関数はdouble型の引数を一つとり、その正弦の値を返す関数です。 引数はラジアンで指定します。

double sin(double x);

図8.10 sin関数のプロトタイプ


[ティップ]関数の定義を調べる

Linuxシステムでは、オンラインマニュアルでシステムコールとシステムライブラリに含まれる関数の定義を調べることができます。 オンラインマニュアルには、関数定義の他、関数が定義されているヘッダファイル、動作の詳細や戻り値などの情報が記載されています。 オンラインマニュアルを調べるには、manコマンドを使用します。

sin関数を調べるには、以下のコマンドを実行してください。

[ATDE ~]$ man sin

sin関数を使用したサンプルプログラムを以下に示します。 math.hは、sin関数を定義しているヘッダファイルです。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char *argv[])
{
        double x = 0.5;

        printf("sin(%g) = %g\n", x, sin(x));

        return EXIT_SUCCESS;
}

図8.11 sin.c


sin.cをhello.cと同様にコンパイルすると、sinが未定義というエラーになります。

[ATDE ~]$ gcc sin.c -o sin
/tmp/ccQ0sxun.o: 関数 `main' 内:
sin.c:(.text+0x30): `sin' に対する定義されていない参照です
collect2: error: ld returned 1 exit status

図8.12 sin.cをコンパイルするコマンド


Linuxシステムでは、ライブラリはlibライブラリ名という名前になっています。 算術演算ライブラリの場合、libmです。 ビルド時にライブラリをリンクするには、-lライブラリ名オプションを指定します。

[ATDE ~]$ gcc sin.c -lm -o sin

図8.13 sin.cをコンパイルするコマンド(-lmオプション付き)


実行結果は以下のようになります。

[ATDE ~]$ ./sin
sin(0.5) = 0.479426

図8.14 sinの実行結果


Armadillo用にクロスコンパイルするには、hello.cの例と同様にコンパイラにクロスコンパイラを用いるだけです。

[ATDE ~]$ arm-linux-gnueabihf-gcc sin.c -lm -o sin

図8.15 sin.cをクロスコンパイルするコマンド


実行ファイルをArmadilloにscpで転送し、実行結果を確認してください。

[armadillo ~]# /home/atmark/sin
sin(0.5) = 0.479426

図8.16 sinの実行結果(Armadillo上)


ATDEでは、gccを用いてコンパイルを行った場合、インクルードパスは/usr/includeとなります。 「#include <ヘッダファイル名>」というディレクティブでヘッダファイルをインクルードした場合、インクルードパスにあるヘッダファイルを使用します。

クロスコンパイル用に、コンパイラとしてarm-linux-gnueabihf-gccを用いた場合のインクルードパスは、/usr/arm-linux-gnueabi/includeとなります。 gccを用いた場合とは、参照するヘッダファイルが異なる事に注意してください。

また、ホスト用のライブラリは、/lib/i386-linux-gnuディレクトリにあります。 算術演算ライブラリの場合、/lib/i386-linux-gnu/libm.so.6[48]です。

ARM用のライブラリは、/usr/arm-linux-gnueabihf/libディレクトリにあります。 ライブラリを使用するプログラムをターゲットで動かす場合には、実行ファイルだけでなく、ライブラリファイルもターゲット上の適切なパスに配置されている必要があります。

[ティップ]

Armadillo-640でDebianから供給されるライブラリを利用する場合、基本的にはライブラリファイルの配置場所を気にする必要はありません。

Armadillo-640およびATDE7に同名のDebianパッケージをインストールすることで、自動的にライブラリファイルが適切なパスに配置されます。

例えば、libmの場合は、次のようにDebianパッケージをArmadillo-640、ATDE7にインストールします。

[armadillo ~]# apt-get update && apt-get install libc6  1

1

Armadillo-640に libc6 (ライブラリ本体)をインストール

[ATDE ~]$ sudo apt-get update
[ATDE ~]$ sudo apt-get install libc6  1
[ATDE ~]$ sudo apt-get install libc6-dev  2
[ATDE ~]$ sudo apt-get install libc6-dev-armhf-cross  3

1

ATDE7に libc6 (ライブラリ本体)をインストール

2

ATDE7に libc6-dev (ネイティブ開発用パッケージ)をインストール

3

ATDE7に libc6-dev-armhf-cross (クロス開発用パッケージ)をインストール

libc6は、システム上のほぼ全てのプログラムが使用するため、すでにArmadillo-640およびATDE7にはインストール済みとなっています。 そのため、今回の例ではライブラリをインストールするという手順は省略しています。

8.1.3. make

プログラムをビルドする際、毎回gccコマンドを入力するのは手間がかかります。 makeを使うことで、複雑なビルド手順を自動化することができます。

makeは、makefileと呼ばれる設定ファイルにプログラムをビルドするルールを記述しておくと、それに従って次に行うべき手順を見つけ出し、必要なコマンドだけを実行してくれるツールです。

makefileには、以下の形式でルールを記述します。

ターゲット: 依存ファイル1 依存ファイル2
        コマンド1
        コマンド2

図8.17 makefileのルール


makefileには、複数のルールを記述することができます。 1つのルールは必ず1つのターゲットを持ちます。 このターゲットが、そのルールで生成されるファイルとなります。 ルールには、ターゲットを生成するために必要な依存ファイルと、ターゲットを生成するためのコマンドを記述します。

依存ファイルは「<ターゲット>:」の後にスペース区切りで記述します。 また、コマンドは、ターゲットの次の行から行頭のタブ(スペースではなく)に続いて記述します。 依存ファイルとコマンドは、0個以上記述することができます。 つまり、依存ファイルやコマンドがない場合もあります。

また、makefileでは変数を使用することができます。 「変数名 = 値」という形式で定義し、$(変数名)で参照します。 基本的に、変数の値は文字列として扱われます。

sin.cをビルドするmakefileは以下のようになります。 sin.cと同じディレクトリに、Makefile(Mは大文字です)という名前で保存してください。

CC = gcc
CFLAGS = -Wall -Wextra -O2
LDFLAGS = -lm

TARGET = sin

all: $(TARGET)

sin: sin.o
        $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@

clean:
        $(RM) *~ *.o $(TARGET)

%.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $<

図8.18 sin.cをビルドするMakefile


makeコマンドを引数を指定せずに実行した場合、makeはカレントディレクトリにあるGNUmakefile、makefile、Makefileという名前のファイルを順番に検索し、最初に見つけたファイルをmakefileとして認識します。

makefileを認識後、makeはmakefileで一番最初に記述されたルールに従って処理を行います。 図8.18「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 $@」が実行されます。 $^も特殊な変数で、依存ファイルを意味します[49]。 これを展開すると、「gcc -lm sin.o -o sin」となります。libmとsin.oをリンクして、実行ファイルsinを生成します。

sinが生成されると、allターゲットに対するルールが適用されます。 しかし、allターゲットに対応するコマンドはないので、何も行われません。 当然、allという名前のファイルも生成されません。 そのため、allターゲットに対する処理はmakeコマンドを実行するたび、毎回行われることになります。

実際の実行結果は、以下のようになります。

[ATDE ~]$ ls
Makefile  sin.c
[ATDE ~]$ make
gcc -Wall -Wextra -O2 -c -o sin.o sin.c
sin.c: In function ‘main’:
sin.c:5:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
 int main(int argc, char *argv[])

sin.c:5:26: warning: unused parameter ‘argv’ [-Wunused-parameter]
 int main(int argc, char *argv[])^~~~

gcc -lm sin.o  -o sin
[ATDE ~]$ ls
Makefile  sin  sin.c  sin.o

図8.19 makeコマンドの実行結果


makeコマンドを実行すると、まず、sin.cのコンパイルが行われます。 このとき、警告オプションの影響で、使用していない変数(argcとargv)があるという警告が表示されています。 警告だけでエラーは出ていないので、オブジェクトファイルsin.oが生成され、それを元に実行ファイルsinが生成されています。

ここで、再度makeコマンドを実行しても何も行われません。 makeは、ターゲットと依存ファイルが変更された時刻を比較して、ターゲットの変更時刻が依存ファイルの変更時刻よりも新しい場合、ターゲットを再生成する必要はないと判断して、ターゲットに対応するコマンドを実行しません。 ターゲットがないか、ターゲットよりも依存ファイルが新しい場合のみターゲットの生成をおこないます。

[ATDE ~]$ make
make: `all' に対して行うべき事はありません.

図8.20 makeコマンドの再実行結果


makeコマンドには、引数にターゲット名を指定することもできます。 図8.18「sin.cをビルドするMakefile」では、cleanターゲットを引数として渡すと、生成したファイルを削除します。

[ATDE ~]$ ls
Makefile  sin  sin.c  sin.o
[ATDE ~]$ make clean
rm -f *~ *.o sin
[ATDE ~]$ ls
Makefile  sin.c

図8.21 make cleanの実行結果


最後に、makefileをクロスコンパイルに対応させる方法を紹介します。 ホスト用にビルドするか、クロス用にするかは、コンパイラにgccを使うか、arm-linux-gnueabi-gccを使うかの違いだけで対応できることを利用します。

CROSS := arm-linux-gnueabihf

ifneq ($(CROSS),)
CROSS_PREFIX := $(CROSS)-
endif

CC = $(CROSS_PREFIX)gcc
CFLAGS = -Wall -Wextra -O2
LDFLAGS = -lm

TARGET = sin

all: $(TARGET)

sin: sin.o
        $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@

clean:
        $(RM) *~ *.o $(TARGET)

%.o: %.c
        $(CC) $(CFLAGS) -c -o $@ $<

図8.22 sin.cをビルドするMakefile(クロスコンパイル対応版)


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を使用して、クロスコンパイルとホスト用コンパイルの両方に対応することができます。

8.2. Debian GNU/Linuxルートファイルシステムアーカイブの作成

Armadillo を一度起動した後にルートファイルシステム上には、使い方によってはsshの秘密鍵や、動作ログ、シェルのコマンド履歴、ハードウェアのUUIDに紐付く設定ファイル等が生成されています。 そのまま、他のArmadillo にルートファイルシステムをコピーした場合は、鍵の流出やUUIDの不一致による動作の相違が起きる可能性があります。 そのため、量産等に使用するルートファイルシステムは新規に at-debian-builder を使って構築します。

本章では、at-debian-builder を使用してDebian GNU/Linuxルートファイルシステムアーカイブを作成する方法と オリジナルのアプリケーションプログラムや設定ファイルを追加する方法について説明します。

8.2.1. at-debian-builderの取得

at-debian-builderは、以下のURLからダウンロードすることができます。

基本的には、最新バージョンのソースコードを使用するようにしてください。 本章の例では、以下のバージョンを使用します。

表8.1 使用するat-debian-builderのバージョン

対象 バージョン ダウンロードURL

at-debian-builder

v1.2.0

https://download.atmark-techno.com/armadillo-640/at-debian-builder/at-debian-builder-v1.2.0.tar.gz


ファイルの取得にはwgetコマンドを使います。

[ATDE ~]$ wget https://download.atmark-techno.com/armadillo-640/at-debian-builder/at-debian-builder-v1.2.0.tar.gz
[ATDE ~]$ ls
at-debian-builder-v1.2.0.tar.gz

図8.23 ソースアーカイブの取得


アーカイブの展開にはtarコマンドを使います。

[ATDE ~]$ tar xzvf at-debian-builder-v1.2.0.tar.gz
[ATDE ~]$ ls
at-debian-builder-v1.2.0  at-debian-builder-v1.2.0.tar.gz
[ATDE ~/at-debian-builder-v1.2.0]$ ls
a600_resources  aiotg3_resources  aiotg3l_resources  ax1_resources  build.sh

図8.24 アーカイブの展開


これで、ルートファイルシステムアーカイブを作成する準備が整いました。

ここで build.sh を実行すると、標準状態のルートファイルシステムアーカイブを作成することができますが、今は実行しません。

8.2.2. ルートファイルシステムのカスタマイズ

組み込み機器の場合、プロダクト固有のアプリケーションプログラムは、必ずと言っていいほど存在すると思います。 ここでは、プロダクト固有のアプリケーションプログラムをルートファイルシステムアーカイブに追加する方法を紹介します。

at-debian-builder では、製品名_resouces内のファイルを変更し、build.shを実行することで、ルートファイルシステムをカスタマイズすることができます。 Armadillo-640の場合は、a600_resources内のファイルを修正していきます。

8.2.2.1. ファイルやディレクトリを追加する

a600_resources 以下にファイルやディレクトリを追加すると、そのファイルやディレクトリはそのままルートファイルシステムに配置されます。 a600_resourcesディレクトリはルートファイルシステム上のルートディレクトリ( / )に対応しており、a600_resourcesディレクトリ直下に配置されたファイルは、ルートファイルシステム上のルートディレクトリ直下に配置されます。

ただし、最初から a600_resources 以下に配置されている resources ディレクトリは例外で、ルートファイルシステム上に配置されません。 resources ディレクトリ以下には、ルートファイルシステムアーカイブの作成の際に使用するスクリプトやインストールするパッケージ情報などが格納されています。

例として、「アプリケーションプログラムの作成」「ライブラリとヘッダファイル」で作成した、アプリケーションプログラム sinを追加します。

ルートファイルシステム上の /usr/local/bin ディレクトリに sin を配置する場合は、次のようにします。

[ATDE ~/at-debian-builder-v1.2.0]$ ls a600_resources
resources
[ATDE ~/at-debian-builder-v1.2.0]$ mkdir -p a600_resources/usr/local/bin
[ATDE ~/at-debian-builder-v1.2.0]$ cp ~/sin a600_resources/usr/local/bin
[ATDE ~/at-debian-builder-v1.2.0]$ ls a600_resources/usr/local/bin
sin

図8.25 /usr/local/bin へのアプリケーションプログラムの追加


[ティップ]

mkdir コマンドを -p オプションを付けて実行すると、dir1/dir2/dir3 のような複数の階層からなるディレクトリをまとめて作成することができます。

[ATDE ~]$ mkdir -p dir1/dir2/dir3
[ATDE ~]$ ls dir1
dir2
[ATDE ~]$ ls dir1/dir2
dir3

8.2.2.2. Debianパッケージを追加する

Debianパッケージを追加するには、a600_resources/resources/packagesファイルにDebianパッケージの名称を追記します。 パッケージ名は1行に1つ書くことができます。 パッケージ名は、Armadilloで動作確認をする際に"apt-get install"の引数に与えた正しい名前で記載します。

例えば、libc6 の場合は

[armadillo ~]# apt-get update && apt-get install libc6

のようにしてインストールするので、次のように追記します。

[ATDE ~/at-debian-builder-v1.2.0]$ vi a600_resources/resources/packages
# List of packaes will install in the debootstrap chroot environment.
# A line start with # is comment. Separate packages name with new-line or space.

#Init
systemd
systemd-sysv

#Utils
sudo
locales
sed
less
expect
cu
vim-tiny
dosfstools
util-linux
rsyslog
bash-completion
man
dialog

#Device
i2c-tools
evtest

#Network
iptables
net-tools
wget
iputils-ping
iputils-arping
dnsutils
openssh-client
ifupdown
iptables-persistent

#Base Libs
libglib2.0-0

#sin Libs  1
libc6  2

図8.26 a600_resources/resources/packagesの修正


1

"#" で始まる行はコメントとして認識されます。

2

libc6 を追記します。

誤ったパッケージ名を指定した場合は、ビルドログに以下のようなエラーメッセージが表示されて当該のパッケージが含まれないアーカイブが生成されてしまいます。 例えば、libc6 を追記する際に、誤って libc としてしまった場合、ビルドログに次のエラーメッセージが表示されます。

E: Unable to locate package libc

図8.27 誤ったパッケージ名を指定した場合に起きるエラーメッセージ


[ティップ]

パッケージに依存する他のパッケージは明記しなくても、apt によって自動的にインストールされます。また、aptやdpkg等の Debian GNU/Linux の根幹となるパッケージも自動的にインストールされます。

例えば、「アプリケーションプログラムの作成」「ライブラリとヘッダファイル」で作成した sin で利用している libm は libc6 に含まれていますが、libc6 は明記しなくてもインストールされます。[50]

[警告]

openssh-server のような「パッケージのインストールの際に、自動的に秘密鍵を生成する」パッケージは、基本的にpackagesには追加せず、Armadillo を起動した後に "apt-get install" を使って個別にインストールしてください。

openssh-server を packages に追加した場合、構築したルートファイルシステムアーカイブを書き込んだ全ての Armadillo に、単一の公開鍵を使ってログインすることができてしまいます。もし、意図的に、複数の Armadillo で同一の秘密鍵を利用したい場合、脆弱性となり得ることを理解して適切な対策をとった上で利用してください。

8.2.3. ルートファイルシステムアーカイブのビルド

ルートファイルシステムアーカイブを作成するには、次のコマンドを実行します。

[ATDE ~/at-debian-builder-v1.2.0]$ sudo ./build.sh a600

図8.28 ルートファイルシステムアーカイブのビルド


生成されたルートファイルシステムアーカイブは「イメージファイルの更新」で使用するので、わかりやすいように ~/images ディレクトリを作成して、その中に移動しておきます。

[ATDE ~/at-debian-builder-v1.2.0]$ mkdir -p ~/images
[ATDE ~/at-debian-builder-v1.2.0]$ ls debian-stretch*
debian-stretch-armhf-a600-20190410.tar.gz  1
[ATDE ~/at-debian-builder-v1.2.0]$ mv debian-stretch* ~/images
[ATDE ~/at-debian-builder-v1.2.0]$ ls ~/images
debian-stretch-armhf-a600-20190410.tar.gz

1

at-debian-builder で作成されたルートファイルシステムアーカイブのファイル名は debian-stretch-armhf-a600-作成日.tar.gz となります。

8.3. イメージファイルの更新

前章ではルートファイルシステムアーカイブを作成しました。 ここでは、そのルートファイルシステムアーカイブをArmadilloに書き込み、正しく動作するか確認していきます。

8.3.1. インストールディスクの作成

まずは、ルートファイルシステムアーカイブをArmadilloに書き込むために、インストールディスクを作成します。

インストールディスクとは、Armadilloの動作に必要なソフトウェアを一挙に更新することができるブートディスクfootnote[Armadillo-640では特定のイメージが書き込まれたmicroSDカード]のことです。

インストールディスクは make-install-disk-image を使って作成できます。

8.3.1.1. make-install-disk-image の取得

make-install-disk-imageは、以下のURLからダウンロードすることができます。

基本的には、最新バージョンのソースコードを使用するようにしてください。 本章の例では、以下のバージョンを使用します。

表8.2 使用するmake-install-disk-imageのバージョン


wgetコマンドでアーカイブを取得し、tarコマンドでアーカイブを展開します。

[ATDE ~]$ wget https://download.atmark-techno.com/armadillo-640/make-install-disk-image/make-install-disk-image-v1.0.0.tar.gz
[ATDE ~]$ tar xzvf make-install-disk-image-v1.0.0.tar.gz

8.3.1.2. Armadilloに書き込むイメージファイルの準備

インストールディスク作成する前に、Armadilloに書き込むイメージファイルの準備をします。 必要なのは次の4つのファイルです。

  • ブートローダーイメージ
  • Linuxカーネルイメージ
  • DTB(Device Tree Blob)
  • ルートファイルシステムアーカイブ

ルートファイルシステムアーカイブは「ルートファイルシステムアーカイブのビルド」で作成しました。 他のファイルついても、ユーザーがカスタマイズして作成することができますが、今回は"Armadillo サイト"でダウンロードすることができる標準イメージを使用します。

使用するイメージファイルは次のとおりです。

表8.3 使用するイメージファイル

対象 バージョン ダウンロードURL

ブートローダーイメージ

v4

https://download.atmark-techno.com/armadillo-640/image/u-boot-a600-v2018.03-at4.imx

Linuxカーネルイメージ

v11

https://download.atmark-techno.com/armadillo-640/image/uImage-a600-v4.14-at11

DTB(Device Tree Blob)

v11

https://download.atmark-techno.com/armadillo-640/image/armadillo-640-v4.14-at11.dtb

ルートファイルシステムアーカイブ

v20190326 ベース

なし(「ルートファイルシステムアーカイブのビルド」で作成)


~/images ディレクトリに移動してから、イメージファイルをダウンロードします。

[ATDE ~]$ cd ~/images
[ATDE ~/images]$ wget https://download.atmark-techno.com/armadillo-640/image/u-boot-a600-v2018.03-at4.imx
[ATDE ~/images]$ wget https://download.atmark-techno.com/armadillo-640/image/uImage-a600-v4.14-at11
[ATDE ~/images]$ wget https://download.atmark-techno.com/armadillo-640/image/armadillo-640-v4.14-at11.dtb
[ATDE ~/images]$ ls
armadillo-640-v4.14-at11.dtb               u-boot-a600-v2018.03-at4.imx
debian-stretch-armhf-a600-20190410.tar.gz  uImage-a600-v4.14-at11

8.3.1.3. インストールディスクイメージのビルド

いよいよ make-install-disk-image を使ってインストールディスクイメージを作成します。

まずは make-install-disk-image-v1.0.0 ディレクトリに移動します。 make-install-disk-image-v1.0.0 ディレクトリの中には、build.shというスクリプトとcore ディレクトリがあります。

[ATDE ~]$ cd ~/make-install-disk-image-v1.0.0
[ATDE ~/make-install-disk-image-v1.0.0]$ ls
build.sh  core

次のようにして build.sh を実行するとインストールディスクイメージを作成することができます。 ビルドに成功すると "install-disk-sd-a640-日付.img" が生成されます。

[ATDE ~/make-install-disk-image-v1.0.0]$ sudo ./build.sh \
a640 \
~/images/u-boot-a600-v2018.03-at4.imx \
~/images/uImage-a600-v4.14-at11 \
~/images/armadillo-640-v4.14-at11.dtb \
~/images/debian-stretch-armhf-a600-20190410.tar.gz
[ATDE ~/make-install-disk-image-v1.0.0]$ ls
build.sh  core  install-disk-sd-a640-20190410.img

図8.29 インストールディスクイメージのビルド


[ティップ]

sudo を付けずに build.sh を実行すると、sudo を付けるよう指示するメッセージが表示されます。

[ATDE ~/make-install-disk-image-v1.0.0]$ ./build.sh
ERROR: Please run script with sudo

また、引数を指定せずに build.sh を実行すると、ヘルプが表示されます。

[ATDE ~/make-install-disk-image-v1.0.0]$ sudo ./build.sh
Install Disk Image Build Script v1.0.0

Usage:
  sudo ./build.sh BOARD UBOOT KERNEL DTB USERLAND

  BOARD: a640
  UBOOT: u-boot image
  KERNEL: uImage
  DTB: Device Tree Blob image
  USERLAND: Debian userland archive

Example:
  sudo ./build.sh a640 u-boot-a600-v2018.03-at4.imx uImage-a600-v4.14-at11 armadillo-640-v4.14-at11.dtb debian-stretch-armhf-a600-20190326.tar.gz

8.3.1.4. インストールディスクの作成

インストールディスクイメージをmicroSDカードに書き込むことで、インストールディスクを作成できます。

手順を簡単にするため、ATDEに microSDカード 以外のストレージを接続しないでください。

microSDカードを ATDE に接続してください。 接続方法についての詳細は「取り外し可能デバイスの使用」を参照してください。

microSDカード以外のストレージが接続されていなければ、microSDカードには /dev/mmcblk0 もしくは /dev/sdb のデバイスファイルが割り当てられます。 microSDカード以外のストレージが接続されていた場合は、ATDEがストレージを認識した順番に依存して、microSDカードに /dev/mmcblk1 や /dev/sdc などのデバイスファイルが割り当てられます。

microSDカードに /dev/sdb が割り当てられた場合は、次のようになります。

[ATDE ~/make-install-disk-image-v1.0.0]$ ls /dev/mmcblk0
ls: '/dev/mmcblk0' にアクセスできません: そのようなファイルやディレクトリはありません
[ATDE ~/make-install-disk-image-v1.0.0]$ ls /dev/sdb
/dev/sdb

dd コマンドでインストールディスクイメージをmicroSDカードに書き込むことで、インストールディスクを作成します。

[ATDE ~/make-install-disk-image-v1.0.0]$ sudo umount /dev/sdb[0-9]  1
[ATDE ~/make-install-disk-image-v1.0.0]$ sudo dd \
if=install-disk-sd-a640-20190410.img \  2
of=/dev/sdb \  3
conv=fsync
604160+0 レコード入力
604160+0 レコード出力
309329920 バイト (309 MB) コピーされました、 108.641 秒、 2.8 MB/秒

図8.30 インストールディスクの作成


1

microSDカードを接続した際に自動で全てのパーティションがマウントされるため、一旦アンマウントします。

2

入力ファイルに「インストールディスクイメージのビルド」で作成したインストールディスクイメージを指定します。

3

出力デバイスにmicroSDカードに割り当てられたデバイスファイルを指定します。

dd コマンドが終了したら、インストールディスク作成完了です。

8.3.2. インストールの実行

  1. Armadilloの電源が切断されていることを確認します。接続されていた場合は、電源を切断してください。
  2. USBシリアル変換アダプタのスライドスイッチを確認します。スライドスイッチが図8.31「スライドスイッチの設定」の 1 側に設定されている事を確認してください。

    images/usb-serial-slide-switch.svg

    図8.31 スライドスイッチの設定


  3. インストールディスクを使用してSDブートを行います。JP1とJP2を共にジャンパでショートし、インストールディスクをArmadilloに接続してください。
  4. Armadillo に電源を投入するとmicroSDカードからブートローダーが起動し、次に示すログが表示されます。

    U-Boot 2018.03-at1 installer+ (Apr 04 2018 - 21:17:22 +0900)
    
    CPU:   Freescale i.MX6ULL rev1.0 at 396 MHz
    Reset cause: POR
    DRAM:  512 MiB
    MMC:   FSL_SDHC: 0, FSL_SDHC: 1
    In:    serial
    Out:   serial
    Err:   serial
    Net:   FEC
    Warning: FEC (eth0) using random MAC address - 5a:fd:55:1c:bb:91
    
    =>
  5. 次のように"boot"コマンドを実行するとインストールが始まり、自動的にeMMCが書き換えられます。

    => boot
    3345800 bytes read in 204 ms (15.6 MiB/s)
    23185 bytes read in 53 ms (426.8 KiB/s)
    ## Booting kernel from Legacy Image at 82000000 ...
       Image Name:   Linux-4.14-at1
       Image Type:   ARM Linux Kernel Image (uncompressed)
       Data Size:    3345736 Bytes = 3.2 MiB
       Load Address: 82000000
       Entry Point:  82000000
       Verifying Checksum ... OK
    ## Flattened Device Tree blob at 83000000
       Booting using the fdt blob at 0x83000000
       Loading Kernel Image ... OK
       Loading Device Tree to 9eeff000, end 9ef07a90 ... OK
    
    Starting kernel ...
    : (省略)
    *+*+* Install Start!! *+*+*
  6. 以下のようにメッセージが表示されるとインストール完了です。電源を切断してください。

    *+*+* Install Completed!! *+*+*

8.3.3. インストール後の動作確認

インストールが完了したら、「ルートファイルシステムのカスタマイズ」で行った変更が正しく反映されているか確認します。 ここまでの手順で間違いがなければ、/usr/local/bin ディレクトリに sin が配置されており、sin を実行することができるはずです。

まずはArmadilloを再度起動し、rootユーザーでログインしてください。

次に以下のコマンドを実行して、/usr/local/bin/sin が存在するか、実行できるかを確認します。

[armadillo ~]# ls /usr/local/bin/sin
/usr/local/bin/sin
[armadillo ~]# /usr/local/bin/sin
sin(0.5) = 0.479426

図8.32 インストール後の動作確認


図8.32「インストール後の動作確認」のようになれば問題ありません。

8.4. 量産に向けた準備

これまでに、製品独自のアプリケーションプログラムを作成し、それをルートファイルシステムに取り込み、さらにインストールディスクを作成して、Armadilloに書き込むという一連の開発の流れについて説明してきました。 十分にテストして、システムとして動作することが確認できれば、製品として出荷する準備は整ったことになります。

本章では、製品の量産化前に行うべきことについて説明します。

8.4.1. ライセンスに関する注意事項

Armadilloで使用しているソフトウェアは、その大半がオープンソースソフトウェアです。 オープンソースソフトウェアの中には、GPLのようにそのソースコードを公開することが義務付けられているものがあります。 製品化を行う前に、使用しているソフトウェアがどのようなライセンスを持っているのか、確認する必要があります。

Linuxカーネルには、GPLが適用されます。 そのため、Linuxカーネルを使用したシステムを販売する際には、システムで使用しているLinuxカーネルのソースコードをエンドユーザーが入手できる手段を提供しなければなりません。

なお、LinuxカーネルはGPLですが、アプリケーションプログラムからシステムコールを介してその機能を使用する分にはアプリケーションプログラムはGPLの影響を受けません。

8.5. 製品出荷後のメンテナンス

本章では、製品化後に気をつけるべき点について説明します。

8.5.1. ソフトウェアアップデートへの対応

Armadillo用のブートローダー、Linuxカーネル、Debian ユーザーランドは、機能追加やバグ修正などで随時アップデートがおこなわれます。 これらのアップデートが行われた際、ユーザーの製品で使用しているソフトウェアもアップデートする必要があるかもしれません。 製品出荷後でもソフトウェアをアップデートできるよう、手順や仕組みを準備しておくのが無難です。

8.5.2. ハードウェアの変更通知

ソフトウェアだけでなく、ハードウェアの変更がある場合もあります。ハードウェアの変更には、エラッタの修正や使用部品の変更、基板の改版などが含まれます。

ユーザー登録を行っておくと、このような変更が行われた際に送られる通知を受け取ることができます。



[46] 実行ファイル名を指定しない場合、実行ファイル名はa.outとなります。

[47] デフォルトでは "atmark"

[48] /lib/i386-linux-gnu/libm.so.6は/lib/i386-linux-gnu/libm-2.24.so へのシンボリックであり、これがライブラリの実体です。ライブラリのバージョンが変わっても、コンパイルオプションなどを変更しないで済むようにこのような仕組みになっています。

[49] 依存ファイルが複数指定された場合、$^はそれらすべてを意味するのに対して、$<は最初の一つだけを意味します。

[50] libm6 はutil-linux, bash, wgetなど様々なパッケージから利用されています。