EV3 事始め

初稿 2013/10/13

はじめに

先月、発売されたLEGO社からEV3が発売された。 先行予約して入手したのだが、開発情報が全くない状態だったので、そのまま放置していた。
しかし、先日、アフレルから以下のような開発情報が公開された。

ホーム > 技術情報 > 外部機器との接続 > ネイティブLinuxプログラミング方法 (Ver0.3)

アフレルEV3開発情報ページ http://www.afrel.co.jp/archives/7301

この情報を元に、EV3の開発環境を整備していったのだが、このページの情報は以下のようなハマり処満載で、非常に苦労した。

おそらく、同じようなところで躓く人も多いと思うので、自分自身の覚書として書いたものを、ここに公開する。

開発環境

OS

EV3の開発はlinuxがベースとなる。
今回使用したlinuxのディストリビューションは、Ubuntuの長期サポート版(LTS)である以下のバージョンで、以下のCDイメージをインストールした。

ubuntu-ja–12.04.1-desktop-i386.iso

ハードウェア

以下の機材を使用した。

lemovo ThinkPad X61s

作業手順について

最初に紹介した アフレルEV3開発情報ページ に書かれている手順に従って作業を進めると非常に効率が悪い。
以下に記載する作業手順は、我流ではあるが、できるだけ短時間に環境構築してサンプルプログラムを実行できるように工夫したので、本家のページに書かれている内容とは大きく異なっている。
判り難い場合は、本家のページを参照すること。

  1. ソース類の入手に必要なパッケージの入手
  2. ツールチェーンのダウンロード
  3. ev3カーネルのソースコード入手
  4. 開発に必要なパッケージ類のインストール
  5. ツールチェーンのインストール
  6. ev3カーネルの構築作業のための準備
  7. ev3カーネルのビルド
  8. ev3カーネルのインストール
    1. マイクロSDカードのデバイス名の確認
    2. fdiskによるパーティションの分割
    3. SDカードへのEV3システムの導入
  9. C言語によるサンプルプログラム
    1. サンプルソースの配置
    2. サンプルのコンパイル
    3. システムへの実行ファイルのコピー
    4. サンプルプログラムの実行

ソース類の入手に必要なパッケージの入手

最初に、ツールチェーンと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カーネルのソースコード入手

アフレル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

  1. インストール用ディレクトリの作成する。

    hdqrs@nerv:$ mkdir ~/CodeSourcery

  2. ダウンロードしたファイルを展開する。

    hdqrs@nerv:$ tar -jxvf arm–2009q1–203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C ~/CodeSourcery

  3. 展開されたファイルの名前を変更する。

    hdqrs@nerv:$ mv ~/CodeSourcery/arm–2009q1/ ~/CodeSourcery/Sourcery_G++_Lite

  4. lsコマンドでファイルが展開されているか確認する。

    hdqrs@nerv:$ ls ./CodeSourcery/Sourcery_G++_Lite/
    arm-none-linux-gnueabi bin lib libexec share

  5. .bashrcにツールチェーンのPATHを追加するために、 エディタで、.bashrcを開き、ファイルの最後に次の行を追加する。

    hdqrs@nerv:$: nano ~/.bashrc
    export PATH=/CodeSourcery/Sourcery_G++_Lite/bin:$PATH

  6. .bashrcで設定した内容が反映されるように、次の様に再度読み込みを行う。

    hdqrs@nerv:$: source ~/.bashrc

  7. パスが通っているかを次の様に、コンパイラを実行して確認する。

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カーネルの構築作業のための準備

ev3カーネルのソースリストのあるディレクトリで直接作業を行うわけには行かない。
そこで、ホームディレクトリの直下に作業用のprojectsディレクトリを作成する。

hdqrs@nerv:$ mkdir ~/projects
hdqrs@nerv:$ cd ~/projects/

gitでダウンロードしたev3カーネルのソースファイルを作業用ディレクトリコピーする。

hdqrs@nerv:/projects$ cp -a ~/ev3sources/* .

ev3カーネルのビルド

ev3カーネルビルド用のディレクトリに移動する。

hdqrs@nerv:/projects$ cd ~/projects/lms2012/open_first
hdqrs@nerv:/projects/lms2012/open_first$

以下のビルドの作業をまとめて行う。

  1. ドキュメントの生成

    ソースファイルのコメントなどからhtml形式のドキュメントを生成する。

  2. u-bootのビルド

    U-Bootをビルドする。

  3. カーネルのビルド

    EV3のカーネルをビルドする。

  4. カーネルモジュールのビルド

    EV3向けのカーネルモジュール(デバイスドライバ)のビルドを行う。

  5. lms2012(仮想マシン)おより関連ライブラリのビルド

    EV3の仮想マシンであるlms2012および、関連する共有ライブラリのビルドする。

  6. lms2012上のアプリケーションのビルド

    lms2012上で動作しているアプリケーションプログラムをビルド(バイトコード化)する。

hdqrs@nerv:/projects/lms2012/openfirst$ make doc
hdqrs@nerv:/projects/lms2012/open
first$ make u-boot
hdqrs@nerv:/projects/lms2012/openfirst$ make kernel
hdqrs@nerv:/projects/lms2012/open
first$ make modules
hdqrs@nerv:/projects/lms2012/openfirst$ make lms2012
hdqrs@nerv:/projects/lms2012/open
first$ make programs

ev3カーネルのインストール

マイクロSDカードのデバイス名の確認

マイクロ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

fdiskによるパーティションの分割

http://www.afrel.co.jp/archives/7301 の解説には、スクリプトが用意されていて、それを実行すれば、パーティション分割、フォーマットが自動で行われるように書かれていたが、上手くいかなかった。 そこで、これらをすべて手作業で行う。

  1. 念のため、SDカードをアンマウントしておく。

    hdqrs@nerv:/projects/lms2012/openfirst$ sudo umount /dev/sdb1 &> /dev/null
    hdqrs@nerv:/projects/lms2012/open
    first$ sudo umount /dev/sdb2 &> /dev/null

  2. fdiskの起動
    hdqrs@nerv:/projects/lms2012/open_first$ sudo fdisk /dev/sdb

  3. パーティションの分割作業
    1. p コマンドで、SDカードの内容を確認する。

      デバイス ブート 始点 終点 ブロック Id システム
      /dev/sdb1 * 2048 104447 51200 b W95 FAT32
      /dev/sdb2 104448 3903487 1899520 83 Linux

    2. トラブルの原因となるので、すべてのパーティションをdコマンドで削除する。
      • dコマンドで、全パーティションを削除する。
    3. fat32パーティション作成
      • nコマンドで、第1パーティションに容量50MBの領域を確保する。
      • tコマンドで、第1パーティションのシステムタイプを 1 から b \tW95 FAT32. に変更する。
      • aコマンドで、第1パーティションをアクティブにする。
    4. linuxパーティション作成
      • nコマンドで、第2パーティションに容量500MBの領域を確保する。
      • tコマンドで、第2パーティションのシステムタイプを 83 \tLinux. に変更する。
    5. 分割内容の確認
      • pコマンドで、設定した内容を確認する。

      デバイス ブート 始点 終点 ブロック Id システム
      /dev/sdb1 * 2048 104447 51200 b W95 FAT32
      /dev/sdb2 104448 1128447 512000 83 Linux

    6. 設定した内容をSDカードに書き込む
      • wコマンドを実行すると、設定した内容がハードディスクに書き込まれる。
        これで、パーティショニングは完了
      • qコマンドを実行すると、パーティションの情報が更新されないので、注意すること。

フォーマット作業

  1. 第1パーティションをfat32形式でフォーマットする。

    hdqrs@nerv:/projects/lms2012/openfirst$ sudo mkfs.msdos -n LMS2012 /dev/sdb1 &>> sdcard.err
    hdqrs@nerv:/projects/lms2012/open
    first$ sudo mkfs.msdos -n LMS2012 /dev/sdb1 &> sdcard.err

  2. 第2パーティションをext3形式でフォーマットする。

    hdqrs@nerv:/projects/lms2012/open_first$ sudo mkfs.ext3 -L LMS2012_EXT /dev/sdb2 &>> sdcard.err

  3. アンマウントしてから、SDカードを外す。

    hdqrs@nerv:/projects/lms2012/openfirst$ sudo umount /dev/sdb1 &> /dev/null
    hdqrs@nerv:/projects/lms2012/open
    first$ sudo umount /dev/sdb2 &> /dev/null

  4. 再度、差し込むと、/media/のディレクトリ直下に、以下の2つの領域がマウントされる。

    hdqrs@nerv:/projects/lms2012/open_first$ ls /media/
    LMS2012 LMS2012_EXT

SDカードへのEV3システムの導入

(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カードの完成

C言語によるサンプルプログラム

アフレルEV3開発情報ページ には、C言語によって書かれた3本のサンプルが紹介されている。
しかし、そのままコピペしても、以下のようなコードなので、この状態では、コンパイルできない。

そこで、コンパイル&実行を確認したソースリストを以下に置いておく。
必要な場合は、ダウンロードして利用すること。

ev3sample.zip

サンプルソースの配置

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

サンプルのコンパイル

システムへの実行ファイルのコピー

コンパイルして出来上がった実行ファイルは、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開発情報ページ には、カーネルモジュールをロードしたり、デバイスに実行権を付与するように書かれていた。
しかし、今回は、これらの操作をしなくても特に問題なく実行できた。
うまく動作しない場合は、これらの操作を実行してみること。


Notes

一連の作業を行い、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