Linux on an 8-bit micro? - Dmitry Grinberg
8bitマイクロでARMエミュレーターを実装してGNU/Linuxを動かした顛末が書かれている。
イントロ
初心者がマイクロコントローラーのフォーラムで、可愛いちっぽけな8bitマイクロでLinuxを動かせるかどうか質問するのはよくあることだ。大方は笑われるだけだ。Linuxフォーラムでも、Linuxの最低スペックは何かという質問がなされる。一般的な回答は、32bitアーキテクチャとMMUと、少なくともカーネルを載せるための1メガバイトのRAMだ。このプロジェクトは、そのようなありきたりな回答者を黙らせるためのものだ。右にみえる基盤のはATmega1284pだ。同じ物をATmega644aでも作って成功している。この基盤はこれ以外にプロセッサーを持たず、Linux 2.6.34をブートする。実は、完全なUbuntuスタックを動かすことだって可能だ。XやgnomeだってOKだ。時間さえあればの話だが。
RAM
確かに、完全なLinuxのインストールにはメガバイト級のRAMと32bit CPUとMMUが必要なのは事実だ。このプロジェクトではそれをすべて用意する。まず、RAMを何とかしよう。画像で分かるように、この基板には大昔の30ピンSIMMメモリーモジュールが載せられている。これは80286ベースのPCで使われていたものだ。このメモリはATmegaと繋がれている。筆者はスペック通りにアクセスしてリフレッシュもするコードを書いた(SDRAMはデータを失わないために定期的なリフレッシュを必要とするのだ)。どのくらい速いかって? リフレッシュ割り込みは62ミリ秒毎に発生し、1.5ミリ秒ほどかかる。そのため、CPU時間を3%ほど食う。RAMアクセスは、プログラミングを簡単にするため、一度に1バイトづつ行われる。結果として、最大帯域は毎秒300キロバイトほどだ。
ストレージ
RAMについては解決した。あとふたつ問題が残っている。ストレージはそれほど難しい問題ではない。SPIを使えばSDカードを使うのはとても簡単で、このプロジェクトでも採用した1GBのSDカードで問題なく動く。今回のファイルシステム(Ubuntu Jaunty)に限って言えば、512MBでも十分だ。ATmegaはハードウェアSPIモジュールを搭載しているが、どういうわけか、うまく動かない。そこで、筆者自らインターフェースにビッグバンを起こした[訳注:自力で書いた]。結果は十分に速い。約毎秒200KBほどだ。また、これはすばらしいおまけもついている。十分なピン数さえあれば、どんなマイクロコントローラーでも使えるのだ。ハードウェアモジュールは必要ない。
CPU
あと残っているのは、32bit CPUとMMUの要件だ。残念ながらAVRにはMMUはなく、8bitだ。この障害を克服するため、筆者はARMエミュレーターを書いた。ARMは筆者が最も得意とするアーキテクチャであり、簡単でエミュレーターも書きやすい。なぜ既存のエミュレーターを移植せずに自力で書いたのか? それは、他人のコードを移植するのは面白くないこと、それと既存のエミュレーターに8bit機への移植を容易にするよう考慮されて書かれたものが存在しないことだ。たとえば、AVRコンパイラーはintが16bitであるので、"(1 << 20)" のような簡単なコードさえ通らない。かわりに、"(1UL << 20)"を使わなければならない。他人の不慣れなコードベースで、intが使われているあらゆる箇所をしらみつぶしに探して書き換えるのは悲惨だ。それに、筆者は常にモジュール化されたARMエミュレーターを書きたいと思っていたのだ。そこで、自力で書いた。
その他の機能
基盤と外の世界とのやり取りは、一本のシリアルポートを介して行われる。現在、シリアルポートはPCに接続されているが、キーボードとキャラクターLCDを基盤に接続することも可能で、完全に独立機としても動作する。基盤にはLEDがふたつある。これはSDカードアクセスを知らせるためのものだ。一つは読み込み、ひとつは書き込み。基盤にはボタンもひとつある。一秒間押された場合、エミュレートCPUの実行速度をシリアルポートに吐くようになっている。AVRは24MHzに動作する(標準の20MHzより若干オーバークロックしている)
どのくらい速いのか?
uARMは速度の鬼というわけではない。bashプロンプト("init=/bin/bash" カーネルコマンドライン)を表示するのに二時間かかる。そこからUbuntuをブートし終わる("exec init"してログインする)までにさらに4時間かかる。Xを起動するのはさらに時間がかかる。エミュレートされたCPUの実行速度は、6.5KHzといったところだ。8bitマイクロで32bit CPUとMMUをエミュレートするのだから、仕方がないことだ。興味深いことに、ブートさえしてしまえば、システムは何とか使えることだ。コマンドをタイプして結果を得るまでに一分しかかからない。これはつまり、実際に、使うことができる。例えば、筆者は今日、SDカードをフォーマットするのに使った。これは最速というわけではないが、おそらく最も安価で、最も遅く、最も単純な手で組み立てた、部品数の最も少ない、ローエストエンドLinux PCと言えるだろう。基盤は手でワイヤーを使ってハンダ付けされている。プリント基板すら必要ない。
このあと、ARMエミュレーターの解説に入り、ソースコードも公開されているが、残念ながら自由なソフトウェアではない。非商用利用限定だ。これは自由原則0を満たさない。
動画もある。
SRAMにリフレッシュが必要とは初耳だったので原文を見たら
ReplyDelete> (SDRAM requires constant refreshing to avoid losing data).
SDRAMとSRAMは全然違うものですが。
1Uも16bitの可能性があるのではと思ったら原文は
> "(1UL << 20)"
わざとやってるんですか?
修正。
ReplyDelete手で書き写したため間違いぐらいありますて。
×基盤 ○基板
ReplyDeletebit-bangがビッグバンになってるのはbit-bangを知らなかったのかな…。ちょい意外。
ReplyDelete> GNU/Linuxを動かせる最低スペックはATmega
ReplyDeleteエミュレーションなのに ATmega が最低スペックな訳ないじゃん