「12ステップで作る組み込みOS自作入門」環境構築した
「12ステップで作る組み込みOS自作入門」始めてはや数日。 6章まで終わってようやく折り返し地点。 環境構築がいろいろ大変だったのでその記録をしていく。 基本的には書籍とサポートページを行ったり来たりしながら環境構築をすすめる。
概要
VirtualBox + Vagrant で仮想環境を使って開発環境を構築していく。
- ホスト Linux Mint 19.2 Tina
- ゲスト VirtualBox Ubuntu 16.4 32bit
わざわざ仮想化せんでもええやん。ただ環境構築はミスって不可逆的な変更でいろいろ汚してしまった時、気持ちが辛くなる。仮想化することで、間違ったらいつでも捨てることができると自分に言い聞かせ、作業の心理的安全性を確保する。
ええんや! メモリもCPUも資源は潤沢なんやから! これが富豪的ソフトウェア開発や!
ホストにはエディタとセルフコンパイラとシリアル接続。そして Git でバージョン管理。
ゲストにはセルフコンパイラとクロスコンパイラをインストール。
VirtualBox の設定で、ゲストにUSBシリアル変換アダプタからの接続をバイパスすることはできたけど、あまりメリットがなかった(後述)。
64bit OS だといろいろ不都合があるので 32bit OS を使う。
具体的には GCC ビルド時にパッチを当てる必要がある。gcc3.4.6だとコンパイル時に負数の即値があると警告が出てくる。警告であってエラーではないので、もしかしたら動作に問題はないのかもしれない(そこまで詳しく調査してない)が、ビルド時に警告を無視し続けるのは精神衛生上あまりよろしくないので、64bit を避ける。
たぶん、64bitOS ならGCCも新しいバージョンにすればいいんだけど、書籍との環境を変えすぎると、問題が起こったときに原因の切り分けがとても大変になるので、なるべく書籍での環境に合わせる。
ゲストOS設定
VirtualBox + Vagrant 設定を作っていく。
まず vagrant-vbguest プラグイン導入。これがないと起動直後の共有フォルダ同期でコケる。
できたらゲスト OS を Vagrant Cloud からダウンロードする。
Vagrant box ubuntu/xenial32 - Vagrant Cloud
vagrant init ubuntu/xenial32 vagrant up
これでダウンロードが始まるのでしばらく待つ。無事起動したら、Vagrantfile
に共有フォルダ設定を追記する。
設定ファイルではホストゲスト間の共有フォルダを設定していく。ホスト OS の Vagrantfile
と同じディレクトリにある workspace
ディレクトリをゲスト OS と共有する。ソースファイル編集の作業は主にこの共有フォルダ内で行う。ちなみにこの設定は46行目あたりにあった。
config.vm.synced_folder "./workspace", "/home/vagrant/workspace"
設定したら vagrant reload
してゲスト OS を再起動。
セルフコンパイラは最新でOK。いつの間にか入っていた。
クロスコンパイラの構築
binutils と gcc の tar を取ってきて解凍。
- GCC Releases - GNU Project - Free Software Foundation (FSF)
- Binutils - GNU Project - Free Software Foundation
書籍のサポートページによると、クロスコンパイラに関しては最新ではないほうがいいらしい。なので、書籍にて検証済みのバージョンを使用する。
binutils
書籍の手順に従ってインストール。./configure
時のオプションに --disable-werror
がないと make install
でコケる。
gcc
インストール前にパッチを当てる。パッチはサポートページから入手。パッチコマンドで当てる。
書籍の手順にしたがってソースコードを修正し ./configure
して make
して sudo make install
する。これでインストールはOK。
ビルド後の後片付け
両方のインストール後は使用したファイルをそのままにしてはいけない。
GCC のディレクトリが、なぜかあとで vagrant reload
または vagrant up
したときに、起動直後の rsync でエラーを起こしてしまう。そしてホストゲスト間のフォルダ同期に失敗してしまう。
対策は、gcc
フォルダを削除する。あるいは、Vagrant 設定ファイルがあるディレクトリ以下からどこか別の場所に移動する。
これだけで何事もなかったように動く。
なんで GCC の解凍後のディレクトリが rsync を邪魔するのかはわからん。沼が深そうなので、調査は一旦後回し。
シリアル接続
バイナリイメージ作成はゲストOSでやって、マイコンボードとの通信はホストOSでやる。
今回使ったのは USBシリアル変換コード。秋月電子で買った。ドライバの追加なしでいきなり使えた。
接続するとコマンドで /dev/ttyUSB0
が出てるのが確認できる。
ただしこのままでは通信できない。/dev/ttyUSB0
には一般ユーザのアクセス権がないため。なので権限設定をしていく。
とりあえず接続できるようにするには chmod 666 /dev/ttyUSB0
でいい。しかしこれだと、USB 接続を外すたびに権限がリセットされる。なので接続ごとに毎回設定をするようにする。
lsusb
コマンドでベンダ ID とプロダクト ID を見る。そして /etc/udev/rules.d/50-usb-serial.rules
に追記する。
以下の記事を参考にした。
これで USB を挿し直しても無事に権限設定ができている。
ぶっちゃけ、なんで ttyUSB0
でなんで 0
なのかはわからん。1
かもしれないし 2
かもしれないけど、それを確認するコマンドもわからん。とりあえず ttyUSB0
で決め打ちして動いてるからOKとした。あとで調べる。
そして Hello, World! へ……
シリアル通信は ckermit で行う。初見ではボードに電源をつないでも何も反応がなかったので、本当に動いているのか不安だったけど、ちゃんと動いていた。
kermit の設定は書籍に従う。自分の環境だと set carrier-watch off
をつけないとうまくいかなかった。
kermit 設定は ~/.kermrc
に記述すればいい。
# ckermit デフォルト設定 set line /dev/ttyUSB0 # 接続先 # 接続設定 set speed 9600 # ボーレート set terminal bytesize 8 # ビット set stop-bits 1 # ストップビット set parity none # パリティ set carrier-watch off # キャリア検出 set flow-control none # フロー制御 # 4章以降で必要(後述) # lrzsz を利用したファイルの送受信プロトコル設定 set protocol xmodem rx {rx -b} {sx %s} {sx -b %s} rx rx
以下の記事を参考にした。
- 組込み開発の常識!?C-Kermitの使い方を調べたメモ | Futurismo
- tools/kermit - NORK's "HOW TO..." Wiki ç¥ãã¦ãã®ãã¯ãWikiã
- Kermit 95 - The SET TERMINAL Command
これで kermit 起動後は connect
で接続できる。
書籍1章に従って正しくプログラムを転送できているなら、これでリセットボタンを押すごとに Hello, World! を受信できる。
たまに出力される文字列が化けて出てくることがある。そんなときは、とりあえず USB シリアルケーブルの USB-PC 間を一度抜き挿しすると直る。
ゲストOSにUSBシリアル接続をバイパスする場合
最終的には見送ったが、ゲストにUSBをバイパスする方法もある
VirtualBox のゲスト OS 設定画面でシリアルポートのパスに /dev/ttyUSB0
を設定。これでゲストOSの /dev/ttyS0
に接続することでシリアル通信ができる。
……はずなのだけど、なぜか自分の環境では受信できたりできなかったり、画面上の文字列表示がずれてたりで、うまくできなかった。これがバイパス設定を見送った主な理由。
他にも単純な問題はある。ホストOSのデバイスをゲストOSに常にバイパスする設定だと、USBが挿さっていない状態でゲストOSを起動すると常にエラーが起きる。これがはっきり言って面倒くさい。
このふたつの理由から、USBシリアルはホストから通信したほうが手間かからずにいいな、となった。
2章以降での問題と解決など
3章以降でのリンカスクリプトの修正について
Google グループ によると、書籍3章のリンカスクリプトは厳密な記述ではないらしく、根本的な解決方が紹介されていた。なので適用した。
さらに、
www.slideshare.net
51ページ以降にて、ビルド時の問題とその解決方法が載っている(GCC 4.7)。このコードの変更も適用した。
4章以降でのファイル転送のオプション変更
4章以降、シリアル通信でファイル転送を行うようになる。
そのとき kermit で接続するなら lxzsz を追加にインストールして送受信するのだけど、その設定コマンドは書籍から以下のように変更している。
set protocol xmodem rx {rx -b} {sx %s} {sx -b %s} rx rx
-a
オプションから -b
オプションへ変更している。man ページによると -a
オプションは ascii モードで、-b
オプションは binary モードで送信する。この違いは何かというと、-a
モードでは改行コードの LF が CRLF に変換されてしまう。
これだと4章でのテキストファイル送信時に、ローカルでのファイルダンプと送信済みファイルのダンプが一致しない。送信過程で LF が CRLF に変換されてしまうため。ちなみに改行コードを CRLF で送信すると CRCRLF になる。そのため binary モードで送信するよう、オプションを変更している。
感想
こんな感じの設定で6章まで来た。お疲れ様でした。
この環境でこれまで問題なかったので、たぶんこの先も大丈夫じゃないかな……。
残り半分。頑張っていきましょう。
とか言っている間に、最後まで終わりました。非常に有意義な時間を過ごせました。感想はまた別の記事で。
学習中にコミットしていたリポジトリはこちら。
お疲れさまでした。