初稿 2013/10/13
先月、発売されたLEGO社からEV3が発売された。
先行予約して入手したのだが、開発情報が全くない状態だったので、そのまま放置していた。
しかし、先日、アフレルから以下のような開発情報が公開された。
ホーム > 技術情報 > 外部機器との接続 > ネイティブLinuxプログラミング方法 (Ver0.3)
アフレルEV3開発情報ページ http://www.afrel.co.jp/archives/7301
この情報を元に、EV3の開発環境を整備していったのだが、このページの情報は以下のようなハマり処満載で、非常に苦労した。
おそらく、同じようなところで躓く人も多いと思うので、自分自身の覚書として書いたものを、ここに公開する。
EV3の開発はlinuxがベースとなる。
今回使用したlinuxのディストリビューションは、Ubuntuの長期サポート版(LTS)である以下のバージョンで、以下のCDイメージをインストールした。
ubuntu-ja–12.04.1-desktop-i386.iso
以下の機材を使用した。
lemovo ThinkPad X61s
最初に紹介した アフレルEV3開発情報ページ に書かれている手順に従って作業を進めると非常に効率が悪い。
以下に記載する作業手順は、我流ではあるが、できるだけ短時間に環境構築してサンプルプログラムを実行できるように工夫したので、本家のページに書かれている内容とは大きく異なっている。
判り難い場合は、本家のページを参照すること。
最初に、ツールチェーンとEV3のソースリストの入手に必要なツールのダウンロードとインストールを行う。
これは、これらのダウンロードに時間がかかるため、この作業を優先させるためである。
まず、最初に、更新されたパッケージのチェックを行い、git wgetをインストールする。
hdqrs@nerv:$ sudo apt-get update
hdqrs@nerv:$ sudo apt-get install git wget
以下のコマンドで、ツールチェーンをダウンロードする。
hdqrs@nerv:$ wget https://sourcery.mentor.com/GNUToolchain/package4571/public/arm-none-linux-gnueabi/arm–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
長さ: 77413954 (74M) [application/x-bzip2]
2013–10–12 13:38:35 (16.4 KB/s) - `arm–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2’ へ保存完了 77413954/77413954
このサイトは、回線が細いせいか、ダウンロードに1時間以上かかった。
アフレルEV3開発情報ページ の解説には、以下のように書いてあるがこれは間違い。
gitファイル名の最後の’s’が抜けているので、アカウントとパスワードを聞かれて、先に進めない。
Host$: git clone https://github.com/mindboards/ev3source.git
正解は、以下のように入力する。
hdqrs@nerv:$ git clone https://github.com/mindboards/ev3sources.git
hdqrs@nerv:$ du ev3sources/
1077720 ev3sources/
これも、こまごましたファイルをダウンロードしていくので、結構時間がかかる。
以下は、開発に必要なパッケージ類なので、まとめてインストールする。
hdqrs@nerv:$ sudo apt-get install git squashfs-tools u-boot-tools doxygen imagemagick libmagickcore-dev openjdk–7-jdk openjdk–7-jre-headless nfs-kernel-server
また、私の趣味で、Ubuntu のデフォルトディスクトップ環境が使いにくいので、lxdeをインストールした。それ以外にも、私が日常使用するツール類をインストールして環境を整えた。
hdqrs@nerv:$ sudo apt-get install beep lxde lxmenu-data flite vim-gtk geany markdown chromium-browser ibus-mozc mozc-utils-gui
一応、お約束なので、パッケージが最新の状態になるようにアップデート作業を行っておく。
hdqrs@nerv:$ sudo apt-get update
hdqrs@nerv:$ sudo apt-get upgrade
そして、不要になったパッケージ等を削除する。
hdqrs@nerv:$ sudo apt-get autoclean
hdqrs@nerv:$ sudo apt-get autoremove
事前にダウンロードしておいた以下のツールチェーンパッケージのインストール作業を行う。
arm–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
インストール用ディレクトリの作成する。
hdqrs@nerv:$ mkdir ~/CodeSourcery
ダウンロードしたファイルを展開する。
hdqrs@nerv:$ tar -jxvf arm–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C ~/CodeSourcery
展開されたファイルの名前を変更する。
hdqrs@nerv:$ mv ~/CodeSourcery/arm–2009q1/ ~/CodeSourcery/Sourcery_G++_Lite
lsコマンドでファイルが展開されているか確認する。
hdqrs@nerv:$ ls ./CodeSourcery/Sourcery_G++_Lite/
arm-none-linux-gnueabi bin lib libexec share
.bashrcにツールチェーンのPATHを追加するために、 エディタで、.bashrcを開き、ファイルの最後に次の行を追加する。
hdqrs@nerv:$: nano ~/.bashrc
export PATH=/CodeSourcery/Sourcery_G++_Lite/bin:$PATH
.bashrcで設定した内容が反映されるように、次の様に再度読み込みを行う。
hdqrs@nerv:$: source ~/.bashrc
パスが通っているかを次の様に、コンパイラを実行して確認する。
hdqrs@nerv:$ arm-none-linux-gnueabi-gcc -v
Using built-in specs.
Target: arm-none-linux-gnueabi
Configured with: /scratch/mitchell/builds/4.3-arm-none-linux-gnueabi-respin/src/gcc–4.3/configure –build=i686-pc-linux-gnu –host=i686-pc-linux-gnu –target=arm-none-linux-gnueabi –enable-threads –disable-libmudflap –disable-libssp –disable-libstdcxx-pch –with-gnu-as –with-gnu-ld –with-specs=‘%{funwind-tables|fno-unwind-tables|mabi=*|ffreestanding|nostdlib:;:-funwind-tables}’ –enable-languages=c,c++ –enable-shared –enable-symvers=gnu –enable-__cxa_atexit –with-pkgversion=’Sourcery G++ Lite 2009q1–203’ –with-bugurl=https://support.codesourcery.com/GNUToolchain/ –disable-nls –prefix=/opt/codesourcery –with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc –with-build-sysroot=/scratch/mitchell/builds/4.3-arm-none-linux-gnueabi-respin/lite/install/arm-none-linux-gnueabi/libc –with-gmp=/scratch/mitchell/builds/4.3-arm-none-linux-gnueabi-respin/lite/obj/host-libs–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr –with-mpfr=/scratch/mitchell/builds/4.3-arm-none-linux-gnueabi-respin/lite/obj/host-libs–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr –disable-libgomp –enable-poison-system-directories –with-build-time-tools=/scratch/mitchell/builds/4.3-arm-none-linux-gnueabi-respin/lite/install/arm-none-linux-gnueabi/bin –with-build-time-tools=/scratch/mitchell/builds/4.3-arm-none-linux-gnueabi-respin/lite/install/arm-none-linux-gnueabi/bin
Thread model: posix
gcc version 4.3.3 (Sourcery G++ Lite 2009q1–203)
ev3カーネルのソースリストのあるディレクトリで直接作業を行うわけには行かない。
そこで、ホームディレクトリの直下に作業用のprojectsディレクトリを作成する。
hdqrs@nerv:$ mkdir ~/projects
hdqrs@nerv:$ cd ~/projects/
gitでダウンロードしたev3カーネルのソースファイルを作業用ディレクトリコピーする。
hdqrs@nerv:/projects$ cp -a ~/ev3sources/* .
ev3カーネルビルド用のディレクトリに移動する。
hdqrs@nerv:/projects$ cd ~/projects/lms2012/open_first
hdqrs@nerv:/projects/lms2012/open_first$
以下のビルドの作業をまとめて行う。
ドキュメントの生成
ソースファイルのコメントなどからhtml形式のドキュメントを生成する。
u-bootのビルド
U-Bootをビルドする。
カーネルのビルド
EV3のカーネルをビルドする。
カーネルモジュールのビルド
EV3向けのカーネルモジュール(デバイスドライバ)のビルドを行う。
lms2012(仮想マシン)おより関連ライブラリのビルド
EV3の仮想マシンであるlms2012および、関連する共有ライブラリのビルドする。
lms2012上のアプリケーションのビルド
lms2012上で動作しているアプリケーションプログラムをビルド(バイトコード化)する。
hdqrs@nerv:/projects/lms2012/openfirst$ make doc
hdqrs@nerv:/projects/lms2012/openfirst$ make u-boot
hdqrs@nerv:/projects/lms2012/openfirst$ make kernel
hdqrs@nerv:/projects/lms2012/openfirst$ make modules
hdqrs@nerv:/projects/lms2012/openfirst$ make lms2012
hdqrs@nerv:/projects/lms2012/openfirst$ make programs
マイクロSDカードをUSBカードアダプタに差し、PCに接続する。今回は2GのマイクロSDカードを使用した。
その後、コンソール上でdmesgを実行し、割り当てられたデバイス名を確認した。
今回は、/dev/sdbに割り当てられたようだ。
hdqrs@nerv:~/projects/lms2012/open_first$ dmesg [13612.760160] usb 2-1: new high-speed USB device number 2 using ehci_hcd [13613.057168] Initializing USB Mass Storage driver... [13613.058419] scsi5 : usb-storage 2-1:1.0 [13613.058548] usbcore: registered new interface driver usb-storage [13613.058551] USB Mass Storage support registered. [13614.946148] scsi 5:0:0:0: Direct-Access Generic Storage Device 0.00 PQ: 0 ANSI: 2 [13614.950808] sd 5:0:0:0: [sdb] 3903488 512-byte logical blocks: (1.99 GB/1.86 GiB) [13614.950983] sd 5:0:0:0: Attached scsi generic sg1 type 0 [13614.951308] sd 5:0:0:0: [sdb] Write Protect is off [13614.951318] sd 5:0:0:0: [sdb] Mode Sense: 03 00 00 00 [13614.951803] sd 5:0:0:0: [sdb] No Caching mode page present [13614.951813] sd 5:0:0:0: [sdb] Assuming drive cache: write through [13614.958554] sd 5:0:0:0: [sdb] No Caching mode page present [13614.958564] sd 5:0:0:0: [sdb] Assuming drive cache: write through [13614.960788] sdb: sdb1 sdb2 [13614.963054] sd 5:0:0:0: [sdb] No Caching mode page present [13614.963064] sd 5:0:0:0: [sdb] Assuming drive cache: write through [13614.963069] sd 5:0:0:0: [sdb] Attached SCSI removable disk
http://www.afrel.co.jp/archives/7301 の解説には、スクリプトが用意されていて、それを実行すれば、パーティション分割、フォーマットが自動で行われるように書かれていたが、上手くいかなかった。 そこで、これらをすべて手作業で行う。
念のため、SDカードをアンマウントしておく。
hdqrs@nerv:/projects/lms2012/openfirst$ sudo umount /dev/sdb1 &> /dev/null
hdqrs@nerv:/projects/lms2012/openfirst$ sudo umount /dev/sdb2 &> /dev/null
fdiskの起動
hdqrs@nerv:/projects/lms2012/open_first$ sudo fdisk /dev/sdb
p コマンドで、SDカードの内容を確認する。
デバイス ブート 始点 終点 ブロック Id システム
/dev/sdb1 * 2048 104447 51200 b W95 FAT32
/dev/sdb2 104448 3903487 1899520 83 Linux
デバイス ブート 始点 終点 ブロック Id システム
/dev/sdb1 * 2048 104447 51200 b W95 FAT32
/dev/sdb2 104448 1128447 512000 83 Linux
第1パーティションをfat32形式でフォーマットする。
hdqrs@nerv:/projects/lms2012/openfirst$ sudo mkfs.msdos -n LMS2012 /dev/sdb1 &>> sdcard.err
hdqrs@nerv:/projects/lms2012/openfirst$ sudo mkfs.msdos -n LMS2012 /dev/sdb1 &> sdcard.err
第2パーティションをext3形式でフォーマットする。
hdqrs@nerv:/projects/lms2012/open_first$ sudo mkfs.ext3 -L LMS2012_EXT /dev/sdb2 &>> sdcard.err
アンマウントしてから、SDカードを外す。
hdqrs@nerv:/projects/lms2012/openfirst$ sudo umount /dev/sdb1 &> /dev/null
hdqrs@nerv:/projects/lms2012/openfirst$ sudo umount /dev/sdb2 &> /dev/null
再度、差し込むと、/media/のディレクトリ直下に、以下の2つの領域がマウントされる。
hdqrs@nerv:/projects/lms2012/open_first$ ls /media/
LMS2012 LMS2012_EXT
(1)SDカード上にカーネルとルートファイルシステムをコピーする。
これには、用意してあるコピー用スクリプトを使用する。
hdqrs@nerv:$ cd ~/projects/lms2012/open_first/ hdqrs@nerv:/projects/lms2012/open_first$ sudo ./update_sdcard.sh
(2)SDカードに新たに作成したファイルシステムで、lms2012というEV3の仮想マシンを起動しない様に設定を一部変更する。
hdqrs@nerv:$ sudo rm /media/LMS2012_EXT/etc/rc5.d/S99lms
(3)最後に、SDカードをumountして、SDカードをホストから取り出す。
hdqrs@nerv:$ sudo umount /media/LMS2012
hdqrs@nerv:$ sudo umount /media/LMS2012_EXT
これで、EV3のシステムを導入したSDカードの完成
アフレルEV3開発情報ページ には、C言語によって書かれた3本のサンプルが紹介されている。
しかし、そのままコピペしても、以下のようなコードなので、この状態では、コンパイルできない。
そこで、コンパイル&実行を確認したソースリストを以下に置いておく。
必要な場合は、ダウンロードして利用すること。
ev3sample.zipを展開し、/projects/lms2012ディレクトリの下に配置する。
~/projects/lms2012 ├── key-test │ └── source │ ├── Makefile │ ├── key │ └── key.c ├── led-test │ └── source │ ├── Makefile │ ├── led │ └── led.c └── motor-test └── source ├── Makefile ├── motor └── motor.c
LED点滅
サンプルの置いてあるディレクトリに移動し、コンパイルする。
hdqrs@nerv:$ cd ~/projects/lms2012
hdqrs@nerv:/projects/lms2012$ cd led-test/source/
hdqrs@nerv:/projects/lms2012/led-test/source$ make led
キー入力 サンプルの置いてあるディレクトリに移動し、コンパイルする。
hdqrs@nerv:$ cd ~/projects/lms2012
hdqrs@nerv:/projects/lms2012$ cd key-test/source/
hdqrs@nerv:/projects/lms2012/key-test/source$ make key
モーター制御 サンプルの置いてあるディレクトリに移動し、コンパイルする。
hdqrs@nerv:$ cd ~/projects/lms2012
hdqrs@nerv:/projects/lms2012$ cd motor-test/source/
hdqrs@nerv:/projects/lms2012/motor-test/source$ make motor
コンパイルして出来上がった実行ファイルは、EV3のファイルシステムの/home/rootにコピーする必要がある。
先程、作成したSDカード(EV3のルートファイルシステムをインストールしたもの)をホストPCに挿入し、再度マウントする。
そして、以下の手順でコピーする。
hdqrs@nerv:$sudo cp ~/projects/lms2012/led-test/source/led /media/LMS2012_EXT/home/root/ hdqrs@nerv:$sudo cp ~/projects/lms2012/key-test/source/key /media/LMS2012_EXT/home/root/ hdqrs@nerv:$sudo cp ~/projects/lms2012/motor-test/source/motor /media/LMS2012_EXT/home/root/
最後に、SDカードをumountして、SDカードをホストPCから取り出す。
hdqrs@nerv:$ sudo umount /media/LMS2012
hdqrs@nerv:$ sudo umount /media/LMS2012_EXT
EV3のルートファイルシステムをインストールしたSDカードをEV3に挿入し起動する。
そして、外部のネットワークと接続できるようになったら、telnetでloginする。
その後、以下のように、コマンドラインからサンプルの実行ファイルを起動する。
root@EV3:~# ./led
root@EV3:~# ./key
root@EV3:~# ./motor
アフレルEV3開発情報ページ には、カーネルモジュールをロードしたり、デバイスに実行権を付与するように書かれていた。
しかし、今回は、これらの操作をしなくても特に問題なく実行できた。
うまく動作しない場合は、これらの操作を実行してみること。
一連の作業を行い、linuxの環境で、EV3のデバイスをコントロールできることは確認できた。
しかし、実用的なアプリを作っていくには、謎が多いし、危険そうだ。
できれば、クロスコンパイルした実行ファイルの転送し、それをEV3内のランチャーから呼び出す方法が必要だと思う。そして、緊急停止する方法もなくてはならない。
また、クロスコンパイルした実行ファイルの転送方法も検討する必要がある。
NFS環境で、ファイルをやり取りする方法が紹介されているが、必要な時にftpでファイルをアップロードするだけでよいと思う。
EV3とホストPCの接続には、有線LAN、無線LAN、シリアルコンソールの種類が紹介されている。できれば、USBケーブル1本で接続できることが望ましい。
しかし、シリアルコンソールは、特別なコネクタ等の準備が必要となる。
できれば、イーサネットのクロスケーブルによる接続が可能か検討してみたい。
謎のディレクトリを発見。adk?
しかも、assembler.jarという名前のファイルが存在する。
│ ├── adk │ │ ├── apps.c │ │ ├── bmp │ │ ├── cmp │ │ ├── cnvlog │ │ │ └── cnvlog.c │ │ ├── lmsasm │ │ │ ├── DebugBytecodePrograms │ │ │ │ ├── compile.rc │ │ │ │ └── readme.txt │ │ │ ├── assembler.jar │ │ │ ├── assembler.logo │ │ │ ├── bytecodes.c │ │ │ ├── bytecodes.h │ │ │ ├── fileread.logo │ │ │ └── startup.logo │ │ ├── lmsbmp │ │ │ ├── bitmapconverter │ │ │ └── bitmapconverter.c │ │ ├── lmststasm │ │ │ ├── DebugBytecodePrograms │ │ │ │ ├── assemble.rc │ │ │ │ └── readme.txt │ │ │ └── bytecodeassembler.c │ │ └── tasm