« 2009年5月24日 - 2009年5月30日 | トップページ | 2009年6月7日 - 2009年6月13日 »

2009年5月31日 - 2009年6月6日の2件の記事

2009年6月 5日 (金)

Beagle Boardを動かしてみる

 話は少し前後するが、このあいだ手に入れたBeagle Boardの動作試験の報告である。ウェブ上には既に沢山の人の動作報告があがっているので、今さらの感もあるが、自分の備忘録を兼ねてまとめておく。いや、こいつはすごいマシーンだ。

Linuxの組み込みバージョンAngstromの立ち上がりまで(5/29/09)
 STM32の開発が一段落したので、懸案のBeagleBoardを触っている。足りなかった部品、UARTケーブルは、このあいだ既に作ってあり、ROMモニターが動くところまではテスト済みである。Beagle

 次のステップは、ここにLinuxやAndroidなどのOSをインストールすることである。例によって先人の経験をありがたく参考にさせてもらうことにする。お手本にするサイトは、既にここに決めてある。このサイトは前から評判になって目をつけていたところで、ここではLinuxの組み込みバージョン、Angstrom(オングストローム)のデモ版を動かすところまで丁寧に教えてくれる。本当に良い時代になったものだ。

 Beaglebootこのサイトの著者はちょうど私と同じソフト系の人で知識の層が似ており理解が早い。恐らく私より遥かに若いのだろう。UARTのフロー制御を「なし」にしないと動かないので苦労したというところで笑った。昔シリアルが全盛のときは、フロー制御をしない「フリーランニング」という結線があり、これは、シリアルのCTSとRTS、DSRとDTRをコネクターの中で結んでしまう。

 こうすると、片側がフロー制御を要求する機器であっても問題なくつながる(自分が要求したものが返るので)。もちろん本当のフロー制御はできない。上品な言い方ではないが「垂れ流し」とも言っていた。そうか、シリアルはもう誰も使っていないので、こういうことは忘れられているのだろう。年をとったことを実感する。

 それはとにかくこのOSのインストールにあたっての問題は、UNIX(Linux)マシンが手元にないことである。Linuxは10年ほど前、今の電子工作同様熱中し、家中のPCや会社のPCにインストールしまくっていたが、今はすっかり手元にない。

 へそ曲がり、天邪鬼な性格なので、みんなが騒ぐようになるとかえって熱が醒めてしまう。Linuxも企業が使うようになってシステムが巨大化し、何か開拓者精神のようなものが失われたような感じがして興味が薄れたこともある。

 BeagleのためにLinuxをインストールするのも何なので、前から残してあったKnoppixのCDでLinuxを立ち上げてみた。ところが、このKnoppixのCDが古く、途中でどこかのサイトにリソースを取りに行く途中で止まってしまう。日付を見たら4年も前のCDだ。

 これじゃあ、いくら何でも古すぎる。久しぶりにLinux関連のキーワードでサイトを探した。最新版のKnoppix(6.1)を落とし(600Mだけれど数分。いや便利になった)、CDに焼いて立ち上げてみた。

 いやあ、立ち上がりの早いの何の。あっという間にLinuxが動き出した。ほんと浦島太郎の気分である。こんなに早いのなら、これを実用としても十分使える。

 SDカードのフォーマットが少しややこしく(fdiskを間違えて、fdisk /dev/sdc1とやって大はまり。 昔もよくやった)、UNIXのコマンドがなかなか思い出せず苦労したが、長い名前のファイル名の入力も、Xの上の端末なので、コピー&ペーストで間違いなくできて、システムを入れたSDカードが完成した。この時点で夜中の3時。ここまで来たら、最後までやるしかない。BeagleBoardにビデオケーブルをつけ(ケーブルの方が重くてケーブルを動かすとボードがふらふらする)、通電する。Angstromterm

 おお、カーネルロードが始まった。流れるようにメッセージが続く。うむ、順調のようだ。よーし、Angstromのロゴがキャラクタ画面に出た。Loginプロンプトでユーザー名を聞かれて弱った。始め設定かと思って新しいユーザー名、パスワードを入れるが反応しない。夜が白み始めて頭がもうろうとしているので、よくわからない。やけっぱちでrootと入れたら動いた。

 ばかな話である。Linuxの初期設定のあたりをすっかり忘れている。最初はrootしかいないのだ。Xの方はどうだ。残念。画面はこのモードをサポートしないという表示でEnlightmentは動いていない。まあ、動いたことだけでもよしとしよう。部屋を片付けて店じまいする。

 次の日。グラフィック環境が動かない原因がわかった。まだ環境変数を設定していなかった。Angstromlogin グラフィックボードへの設定を、環境変数に設定すると、見事にLOGIN画面が出た。思わずキーボードを叩いてしまって、苦笑いする。USBにまだキーボードがつながっていない。USB-LANとセルフパワーのHUBをまだ買っていない。まあ、LOGIN画面まででたので大丈夫だろう。

 キーボードと、USB-LANアダプター、HUBをアマゾンに発注した。最近はPC用品を通販で買うことが多くなった。値段が安いのである。価格.comなどの安売りランキングを見て、秋葉原に行っても必ずしも同じ値段で買える訳ではない。しかし、アマゾンなどは、安売り通販ショップに伍して、負けていない。秋葉でうろうろするより安いことが多い。

あっけなくウェブブラウザーまで動いて拍子抜け(5/31/09)
 アマゾンからUSB関連の品物(エレコムワイヤレスキーボードTK-FDP001WH、コレガUSB-LAN  FEther USB-TXC)が届いた。早速BeagleBoardにつないでみた。HUBはまだ到着しないが、今使っているセルフパワーのHUB(エレコムU2H-TAP3420SWH)をこちらにつなぐ。こいつはUSB-UARTコネクターの抜き差しをスイッチで出来るように買ったものである。USBマウスは、ウェブでは不調と言われたEeePCにオマケについていたもの(Arvel MS35MBL)。

 ブートする。シリアルポート(COM1)に順調にメッセージが流れ、Angstromのロゴが出て無事に立ち上がったようだ。画面を切り替える。ソフトキーボードのログイン画面が出た。さあ、キーボードが入るか。おおお、ちゃんとパスワード入力がキーボードからできる。Enlightmentの画面に替った。マウスは?これも問題ない。

 なんだなんだ。何の問題もなく認識するではないか。ブートメッセージを見ていくと、キーボードの型番までしっかり出ている。昔のLinuxとは大違いだ。海外の情報を頼りに新しいI/Oディバイスを認識させるのが、インストールのときの大仕事だった。

 次は一番問題のLANだ。うまくいったので調子に乗って、動いたままUSB-LANを接続する。活線挿抜というやつだ。ほほう、何か動き始めたぞ。いかん。コンソールには eth0が設定されたが、downしているというメッセージが出た。ifconfig eth0とすると、IPアドレスが定義されていない。やれやれこれは自分でやれと言うことか。

 これが、ちょっと前までさんざん使っていたコマンドがもう思い出せない。gatewayはどこだ。pingを入れたがやっぱり外へでていかないぞ、とやっているうち、ifconfig eth0を入れてみたら、さっき定義したIPアドレスが変わっている。あれ、どうしたの。そうかDHCPが動いたのか。物は試しと、Elightmentのウェブブラウザーを立ち上げて見る。

 何と、何と、ネットがつながっている。Mogillaの初期画面が出た!いやあきれたものだ。何もしないで、全部つながってしまった。日本語フォントが入っていないので字化けしているが間違いない。余りにも簡単にイーサネットが動いてしまってあっけにとられるばかりだ。Beagleweb

 これは一体何なのだ。一区切りがついて考えた。BeagleBoardは明らかに今までの組み込みコンピューターとは違う。要するに、小さなボードで電子工作っぽいけれど、もう、ここまで来ると、これは電子工作ではない。ここはLinuxと変わらない。世界が全く違う。

 ハードに素人が立ち入る隙がもうないのだ。それにソフトウエアの規模が大きすぎる。ARM7あたりまでは、まだソースを追いかける気力があるが、このレベルでは無理だ。別の趣味に近い。

 これはこれで昔、Linuxにはまっていたから、がた老「AVR」研究所としては研究の意味はあるが、8ビットの石を工夫して機械にしているときの、わくわくする気持ちがない。
嬉しいことに、このあいだのSDカードのLPCMプレーヤーは、周りの複数の人から発注を受けて量産を考えなければいけなくなった。はじめてのプリント基板制作に挑戦しようかとも考えているが、電池ホルダーが難物だ。これの自作はちょっと大変だが、物を作る喜びは、こちらの方が大きい。

 BeagleBoardは、ケースを考えたり、日本語フォントのインストール、それとウェブサーバーとしての能力をテストする課題などが残っているが、これはもう電子工作とは別の次元の話だ。まあ、がた老AVR研究所としては、BeagleBoardは余技としておこう。本業はあくまでもAVRクラスだ(最近はARMばっかりだけど)。

| | コメント (0) | トラックバック (0)

2009年6月 1日 (月)

ダブルバッファーでUSB仮想UARTの内部速度が2Mbps

しゃれた実装を考えたが挫折(5/28/09)
 SysTickタイマーで1ms単位の経過時間が測れるようになったので、勇躍、STM32基板のUSB仮想UARTの高速化にとりかかった。これまでにわかっていることは、UARTの速度が遅いときは問題ないが、早くなってくるとエンドポイントの送信終了の割込みがユーザープログラムがデータを移している最中に入り、このときのデータサイズが実際のデータと不整合が生じてデータが欠落する。

 これはSTマイクロが提供するSTM32F(Cortex-M3)用のVCPデモプログラムに最初からあった問題で、STマイクロのフォーラムで去年話題になり議論されていた。少なくとも私の知る限りまだ解決していないはずである。SysTickを使って改修されたコードがアップされたが、その後本人が動かないとして取り下げている。この解決を当研究所がやろうというのである。もしうまく行けば鼻が高い。

 方式はダブルバッファー方式である。前のDACのデコードと同じような考え方だ。ひとつのバッファーをユーザーの送信関数の書き込み用とし、ここに送信データを入れていく。送信関数ではエンドポイントに直接書き込まない。ここで書き込むと、書き込み終了の割り込みがどこで起きるかわからないからである。もうひとつのバッファーは、割込みルーチンが既に書き込み処理をしたデータが入っている。

 書き込み終了の割込みがかかり、割込みルーチンに制御が渡ったときに、バッファーをスイッチして、今度は送信関数が書き溜めていたデータをエンドポイントに書き込む。さきほど送り終わったバッファーが今度は送信関数が新たに書き込むバッファーとなる。これで、データ書き込みと送り出しの衝突を避けることができる。

 最初、コードを少なくするため、2組必要なバッファー配列とカウンターをポインター変数にし、そのアドレスをスイッチして動くようなスマートな方式でコードを組んだ。
バッファーに送信バイトを送り込むとして、

 * ( バッファーアドレス +  * カウンター++ )=  送信バイト;

みたいなプロっぽいコードである。バッファーアドレスとカウンターポインターを取り替えるだけで、main.cの送信関数USB_Putc()はダブルバッファーであることを知らないで済む。いやコーディング技術も格段に進歩したものだ、と、得意になって完成させた。ロジックはそう難しいものではない。気をつけないといけないところは、バッファーを切り替えるときに、ユーザープログラムの実行と重ならないように、フラグを立てて守るということである。今度は、割込みルーチンが見えているので、ユーザー側は、そのフラグを見て待てばよい。

 と、これが全くうんともすんとも言わないのである。どうもさっきのステートメントのところで暴走している。表記に間違いはないはずだ。何度もウェブなどで確かめる。うーむ、何か勘違いがあるのだろうか。プログラムはまさしく考えたようには動かない。書いたように動くだけだ。いずれにしても、ポインターを使ったコーディングは一歩間違えば、とんでもないところにデータを書き込み、簡単に暴走してしまう。

 色々いじったが好転しない。悩んだ挙句、この方法をとりあえずあきらめ、普通の配列を使い、愚直に2組のバッファーを別々に操作するルーチンに切り替えた。さあ、これでどうだ。これなら暴走しようがない。もう問題ないはずだ。

 ありゃりゃあ、これでも動かない。ええー、どこが悪いんだ? シングルバッファーに戻すと何事もなく動く。わからない。このあたりでGDBが使えれば良いのだが、今のままでは、USBを使っているので初期化の段階で、HardFaultに落ちてしまいメインループに来ない。環境を大きく換えないと使えない。別のUARTで変数を出してデバッグする手もあるが、どちらも手間がかかる。

ダブルバッファーが動いた!しかしこれで良いのか(5/29/09)Ws000000
 開発が暗礁に乗り上げている。マラソンや登山と同じだ。この苦しみが歓喜の材料なのだが、その最中はそれどころではない。大げさに言えば人生が暗い。今まで生きてきたことすべてが意味のない時間だったような気分になる。

 BeagleBoardのために久しぶりにモニターを取り替え、1920x1080のワイドディスプレイになって開発環境は一変し(エディターと端末が同時に見られる)、快適になったのだが、気分は優れない。救いは、このあいだの第三のファーム書き込み手法ROMのフラッシュローダーが思いのほか使い勝手が良く、プログラムの修正、ビルド、ファーム書き込みのサイクルが飛躍的に早くなったことである。AVRなみの開発環境である。Eclipseは編集とビルドだけにしか使っていないが、これはこれで便利だ。

 それはともかく、ダブルバッファーが動かない。基本的なところを少しづつ確認していくしかない。何回目かのコードレビューの最中に、ふっと気がついた。送信関数は律義にバッファーにデータを溜め込み、一杯になれば、割込みルーチンがバッEclipeファーを切り替えるのを待っている。では誰がUSBのエンドポイントに書き込むのだ。あ、あー、ここだ。エンドポイントに書き込む処理は、エンドポイントに書いた後の割込みルーチンにしかない。ポインターの暴走でもなんでもない。元から動かない。

 何と言うお馬鹿なコードだ。これでは永遠に送れない。しかし、どうすれば良いのだろう。頭の中が混乱する。何か根本的な間違いがあるのかもしれないが、ロジック的には一度mainの初期化のところでエンドポイントにデータを書き込む呼び水のようなダミー処理をすれば良いのではないか。そうすれば次々に割り込みが連続し、うまくいくのではないか。

 やってみた。やっほー、動いたぞ。ダブルバッファーの仮想UARTモニターが前と同じように動き始めた。転送速度を測る。ややや、2Mbpsだ。素晴らしく早い。1KB送るのに数msしかかかっていない。そりゃそうだ。バッファーに1バイトづつ送るだけで60kbps近くあったのだから、その64倍だったら3Mbps近くあっても、おかしくない。

 もちろんこの速度は、単に内部でUSBドライバーが受け取った時の速さで、実際にホスト(PC)との仮想UARTでの転送速度ではない。しかし少なくとも内部では安定的にメガビットのオーダーでデータが送れたことになる。

 肝心のデータ欠落をチェックするために、同じ文字でなく、"0123456789"の文字列を送ってみる。うむ、全く欠落はない。きれいに数列が画面上に並ぶ。1字の落ちもない。いやあ、至福の瞬間である。今までの暗い気持ちが吹き飛び、天下をとった気分になる(相当中毒が進んでいる)。

 しかし、ロジックとしては不満がある。今の状態は、データがなくてもエンドポイントに立て続けに書き込む処理が動いているはずだ。今は単なるモニタープログラムなので関係ないが、別のSmpvcd仕事をするときはCPUリソースを無駄に使っていることになり効率が悪い。

 というので、エンドポイントの割込みルーチンにデータがなければ処理をやめるようにし(割込みが止まる)、送信関数には、バッファーが何もないときのデータ送信では、ダミーのエンドポイント書き込みを入れるようにしたが、こいつはまた全く動かない。

やっと満足できるコードになった(5/31/09)
 速度が2MbpsまでになったUSB仮想UARTだが不満が残っている。呼び水方式で、USBのエンドポイントにデータを送るところまでは良かったが、これでは送信していないときも延々とUSBドライバーは0データを送り続ける。

 送信データがないときはこの繰り返しを止め、データが来たときに再開するロジックを色々考えて試してみるが、ことごとく失敗する。奇怪なことに、メインルーチンの初期化でダミーの書き込みをすると上手く行くのに、送信関数の中でやると先に行かない。

 この間の差は時間だけだ。余りやりたくなかったがタイマーを入れて調整することにした。しかし全く変わりがない。何か変だ。このタイマー(元々の雑誌のソースに入っていたもの)は

   Delay( int i) { while(i)  i--; }

という簡単なコードだが、iをいくら増やしても変わりがない。コンパイラーの最適化を疑ったが、i--は立派な処理だ。無効になるわけがない。それにこの関数は、前から使っていたはずだ。

 しかし、やっぱりおかしい。念のため、コマンドを新設してこいつの待ち時間をSysTickの時間で測ってみた。うひゃー、全部0で帰ってくる。何と言うことだ。コンパイラーがこのステップを取ってしまっているに違いない。

 AVRでやったように、ループにasm volatile("NOP");を入れる(これはアセンブラーコードでなくマクロだそうだ。従ってARMでも共通)。ちゃんと待ち時間遅れが作れた。やっぱりコンパイラーの仕業だ。 雑誌で動いていたのは開発環境IARとGNUの違いだろう。それにしても、i-- がどうして無駄なコードなのだ。理解に苦しむが文句を言っても始まらない。

 ところが、待ち時間を作ってもうまく行くときと行かないときがある。時間待ちはあくまでも対症療法だ。やはり基本から確実な方法を探すしかない。もういちどソースコードをひとつひとつ追いかけて手順を考えることにした。Beale

 BeagleBoardのセットアップ(次記事で紹介)で少し日をあけたのが良かったのだろう。良い方法を思いついた。これまで送信関数の方ばかりに注目して、何とかしようとあれこれ考えていた。しかし、割込みルーチン側で動作モードを設定していけばうまく行くことに気がついた。そうなのだ。送信関数は、いつどこで割込みを受けるかわからないのでデータカウントが変わる可能性がある。バッファーを制御するスイッチにもうひとつ「データなし」というステイタスを追加してプログラムを組み直した。祈る気持ちでテストする。やった。前と変わりなくデータが送信できた。

 CPUのオーバーヘッドが明らかに減っている。その証拠に先のループで待つウェイトルーチンの時間が早くなったのだ。すごい。はっきりと差がわかる。時間にして3%くらい早くなっている。やっとまともなコードになったと思う。

 ソースコードの公開は迷った。単に大量送信の時間が表示されるだけの、このままでは実用性0(ゼロ)のモニタープログラムである。まあ、これをベースに色々アプリケーションを考えれば役に立たないわけでもない。がた老「AVR」研究所の記念すべき、初の「ARM」プログラムソースでもある。

 人のソースを流用させてもらっているが、殆どのソースは雑誌からなので問題ないだろう。STマイクロのデモプログラムも、ソースリストに「責任取らないからね」という文言しかないので問題ないと判断した。Makefile、リンカースクリプトとスタートアップルーチンはこちらのお世話になった。この場を借りて御礼申し上げたい。

 ソースファイル一式(ライブラリ、リンカースクリプト、Makfile)をここにおきます。Eclipseのプロジェクトファイルですが、Eclipseがなくても動きます。また、実行させるだけなら、STM_VCPDフォルダーの中のstm_vcpd.hexをDfuか、フラッシュローダーで書き込めば動きます。

「STMVCPD_archive.lzh」をダウンロード

 コンパイルの簡単な手順は以下の通り。

・コンパイラー(CodeSourcery G++)をここからダウンロードする。(OSはEABI、Sourcery G++ Lite 2009q1-161を選ぶ。 5/31/09現在)
・解凍したフォルダの下のSTM_VCPDフォルダーにカレントディレクトリを置き、DOS窓でコンパイル(make all)する。 FWLibや、USBLibのディレクトリの位置は変えないこと。換える場合は、Makefileを修正する。

・また、gccの標準ライブラリとヘッダーファイルは、gccの入っているbinフォルダーと同列のarm-none-eabiフォルダーの中のlib\thumb2下のライブラリと、include下のヘッダーを使っている。正確にはMakefileを参照。

・解凍ファイルの中のFWLibや、USBLibはV1.0で、現在のV3と混在させると動かない可能性がある。
・出来上がったhexファイルをDfuか、フラッシュローダーでファームに書き込む。
・STM32の電源を入れ、PC側の端末プログラムでUSBのVCPに接続し、何かキーを入力すると、WelComeメッセージが出る。

| | コメント (12) | トラックバック (1)

« 2009年5月24日 - 2009年5月30日 | トップページ | 2009年6月7日 - 2009年6月13日 »