USB-SPIブリッジの制作
何となくしっくりこない解決(2/12/08)
chaN氏のUSB-SPIブリッジを作ろうとして、このところ、はまっていた。
最初に作ったシリアルISPアダプタは順調で何の不自由もしていないのだが、AVRマニアのサイトではプログラムライターの話題が盛り上がっていて、やれ鶏卵問題(AVRライタに使うAVRは何で焼く?)だの、0.5ミリピッチのICをつけたの、速度が速くなったのだと、AVR関連のどのサイトに行ってもその制作記が載っている。
こういうものにこだわるのは、音楽を聴かずに周波数特性にこだわるオーディオファンを連想して余り関心がなかったのだが、秋月で、わずか¥100と聞いて思わず4ヶも買ってしまったTiny2313の使い道に困っていたのと、USBシリアル変換モジュールも予備があることなので作ってみることにした。ウェブサイトに、この秋月の変換モジュールを使った例が見当たらなかったのも作ろうとした動機のひとつである。
定番のブレッドボードで試作してみる。ブレッドボードはこうした試作には実に便利だ。ジャンパ線でなく単線をボードに密着させて配線すれば、かなり恒久的な装置にも使える。何より変更が簡単だ。ただ、一旦抜いてしまうと元のポイントへ戻すのが厄介になる。
今回はソースがあるのでプログラミングは必要ない。クロックとボーレートのところだけを直し、久しぶりのアセンブラーコンパイルである。ところがこれが通らない。エラーを見ると、予約語のORをシンボルに使おうとしてエラーになっている。何かいやな予感がしたのだが、いくつかのエラーはコードそのものに余り影響がなさそうなので、すべてコメント化し、とりあえず発振子(7.368Mhz)にあったファームが出来た。
このUSB-SPIブリッジの仕様書は何と英語しかない。英語はともかくどうも前提が省略されていて、今ひとつ何をやろうとしているのか理解しにくい。AVRSPという私も愛用させてもらっている書き込みソフトのUSB版だと思うが、モードが沢山あり、どのモードで書き込めば良いのか迷う。ソースコードを頼りに色々パラメータを入れて動かしてみるが、どれも冷たく「No spi bridge found」というメッセージで全くの門前払いである。
UARTのテストステートメントをいれるわけにはいかないので、早々とロジアナを出動させ信号を見る。モードによって多少違うが、PC側から話しかけたとき、正しく答えていないようでもあるし、ときたまターゲットの方に反転したデータを送り出したりしている。制御線の切り替えがあるはずなのだが、ロジアナで見たところでは動きは殆どない。ただ、制御線の論理を逆にすると少し動きが違ったりして、ますます混乱する。
USBシリアルの変換IC(FT232RL)はオリジナルのICとパッケージが違うだけで全く同じである。このブリッジは沢山の人が作っていて改良版もいろいろあるが、どの制作記でも制御線の反転に言及したサイトはない。研修講師の資料送付の締め切りが近づいてきて、お尻にそろそろ火がついてきたのだけど、何とも気になって2日間これにかかりきりだった。
配線に間違いがなく、ICも同じ、それでも動かないとなるとこれはこちらでアセンブルしたバイナリを疑うしかない。オリジナルのバイナリが10Mのクリスタルを使っているのを換算し、それに合わせたボーレートにしてAVRSPを動かしてみる。
何のことはない。オリジナルのバイナリはすんなり動いたのである。フューズビットの読み出し、プログラムの書き込み、何の問題もない。230Kbpsの速さなので書き込みは猛烈に速い。始めFTDI社のUSB変換ICのオプションを変えて動いたので、こいつが真犯人だと思ったが、デフォルトでも全く問題なく動いた。結局アセンブラーのコードがおかしかったのである。何ともしっくりこない解決だった。chaN氏の使ったアセンブラーはAVRstudioのと違うのだろうか。試しにファイル比較のソフトをウェブから落としてきて調べてみたら、確かに数ヶ所違いがある。ボーレートの変更にしては多すぎると思うのだが。
久しぶりに完全試合(2/17/08)
USB-SPIブリッジがブレッドボードで動いたので、今度は実装して、小さなケースに納める工作が待っている。研修講師の資料作成が思いのほか順調に進み休み前には、ほぼ目処がついたので、週末は工作に専念できた。まず、ミニルータを使って、基板の切り出し、上蓋のUSBソケットの穴あけをすませる。切り出しは楽だったが、穴をあけたあとの削りだしは、やはり支持工具がないと電動は難しいことがわかった。最後は平やすりで整形が必要であった。秋月の変換モジュールのピンヘッダーが高いのでぎりぎりまで切って、ジャンパーも短くする。
昨日の昼から配線を始める。ケースが小さいので実際の配線の前に部品配置を完全にやっておく必要がある。いわゆるアートワークである。シングルピンのICソケットは有用で、中に抵抗器をいれることが出来る。アートワークも何回もやると要領を覚えて楽になる。結構、綺麗にレイアウトが出来て自己満足する。
配線作業そのものは、昨夜2時間、今日、テニスから帰って2時間、家内の誕生日祝いに横浜中華街へ一家で夕食を食べに行き帰ってから1時間で完成した。どきどきしながらUSBソケットを差し込む。 ターゲットボードの電源がUSBから供給されLEDが点灯した。何か焦げる匂いがしないか一生懸命鼻を聞かす。頼りになる五感は今のところこれしかない。PCのDOS画面を出してコマンド(AVRsp)を送る。出た!正常にターゲットボードのMCU情報が表示された。 MCUを換えて見て違うメッセージを確認する。いやあ久しぶりのパーフェクトゲームである。気分は最高。これだから工作はやめられない。
しかし、ソフト的には納得がいかない結果なのである。あれからchaN氏のソースコードのオリジナルをAVRStudioのアセンブラに通してみてバイナリを比較してみたら全く同じであった。リストを変えたところは、CPUのクロックとシリアルのボーレートで、結果としてはひとつのプリスケール値になってコードに残るはずである。そこで試しにオリジナルと同じプリスケール値になるよう手持ちの発信子に合うボーレートにしてアセンブルしてコードを比較してみた。しかし全く同じにはならない。ただ、このまえの4行から変更行が1行に減った。
で、これを実際に動かしてみたら見事に動いたのである。???である。これ以上はアドレスとコードが併記されたアセンブルリストでもない限り解析は難しい。これはこれくらいにしておこう。何しろ動いているのだから。まだ、やらなければならないことが沢山ある。
丈夫になったのは良いけれど(2/22/08)
chaN氏にソフトUARTのソース流用の許諾をお願いしたら、2日もたたずに快諾を貰い、公開に向けての準備は整った。それは良いのだけれど、実は、I2Cスレーブのプログラムにはまだ不具合が残っている。最初のうちは快調にデータをLCDに出しているのだが、暫く送信を続けるとタイムアウトが起きてマスターまでハングアップさせてしまうのだ。
いずれ解明しなければとは思っていたのだが、こういう段々おかしくなるという不具合のトラブルシューティングは難しいもので、そのままになっていた。プログラムのトレースなどツールの完備したPCや大型機の世界でもこの種のバグは焦点を絞るのが難しく、昔から厄介なバグのひとつである。
ましてやマイコンの世界、シミュレーターはあっても時間がらみのシミュレーションは、その準備だけでも大変で、現実的にはほぼ不可能だし、トレースをとろうにも限られたメモリではいつ起きるか分からないハングアップに備えるには、それなりのプログラミングをする必要がある。もともと余命の少ないTiny26だ。下手にいじるとフラッシュの寿命が来て元も子もなくなってしまう。
と言って、このままではとても公開できるソースにならない。USB-SPIブリッジが意外に早く順調に動いたので(何となくしっくり来ないけど)、少し本腰を入れてデバッグを始めた。仕事が順調に捗って締め切りより5日も早く資料が仕上がったこともある。
まず、気になっていた1秒タイマが始終動きっぱなしの問題は、データシートを良く読んで、タイマのプリスケールの設定(制御レジスタTCCR1Bのビット0~3)を0にすればタイマが止まることがわかり、これを修正する。これで、通信が終わったあと割り込みをマスクするだけではハングしていた(原因不明だが)バグは解消した。今までは、必ずタイマを一回タイムアウトさせて次のタイマスタートを送信の開始にかけていた。それでも何回目かの送信でハングするのである。
この修正で元のバグも一緒に解消されるかと淡い期待がかかったが、それは甘かった。ハングするまでの時間は少し延びたが、相変わらず、10回前後の送信で、まず送信データが表示されなくなり、次のマスターからの送信でマスターもハングする。ハングする理由はわかっている。I2Cのスレーブ側の唯一の抵抗手段、クロック線(SCL)をLowにしたままにしてマスターが送信してくるのを待たせる手段、クロックストレッチがかかったままになり、マスターがデータを送れなくなるからである。
しかし、USIインタフェースを使うスレーブ側のソースにはSCLをLowにするステートメントは何処にもない。USIインタフェースのシフトレジスタが制御している。下手にSCLを強制的にLowを解除するようにしたら(簡単に出来るけど)、系全体がおかしくなって通信そのものが出来なくなる恐れがある。
タイミングチャートを作り、ソースを入念に追う。ソースは一応機能レベルを3段階にわけ、アプリケーションに近いプログラムでは全くI2Cのことを知らないでデータ受信が出来る構造にしてある。従ってプログラムは必然的に非同期で動いている。このあたりは時間の経過に気をつけないと、考えたようには動いてくれない。MCUのクロック(4000KHz)と、通信速度(100KHz)の差を十分考慮する必要がある。大差はあるようだけど、ソースはアセンブラでなくCだ。割込みのオーバヘッド(数十クロック)を考えると1/40の差はすぐ埋まってしまう。
通信の開始(スタートコンディション発行)から始めて、遂に怪しいところを見つけた。データが受信バッファに入り、アプリケーションがデータをLCD用のバッファに移すところで終了条件を聞いている。こいつはループになっていて必ず最初に終了条件を聞く。USIインタフェースは非同期に動いているので、もし、バッファに移す前に終了条件が送られてくると、バッファにデータが渡らない内に受信シーケンスが終わってしまう可能性がある。
これだ。こいつが最初にデータをとりこぼす原因だ。完全にデータを読み終わるまで、バッファ移動はしない構造に改めることにする。 I2Cには、マスタが送ってくるデータがいつ終わるかをスレーブが判定できないという問題があり、このプログラムでは、終了条件をひたすら待って、データ受信を終わらせている。スレーブからNACKを送って終わらせることも出来るが、これは上位のプロトコル(固定長か、レコード長を最初に送ってくる)が決まっていないと出来ない。
UARTのときもそうだったが、私にはどうも同時処理にこだわってプログラムの構造を複雑にしすぎる癖がある。長い間OSの元で開発してきたからCPUを専有するのに罪悪感があるのだ。昔は、複雑なロジックを作り長いループにしてしまって他の人に迷惑をかけてよく怒られた。マイコンがやるように、I/Oが終わるまで、ループして待つなどもってのほかだったのだ。
郷愁にふけっている場合ではない。早速、ベタに終了条件を待つ方式に変えてテストしてみる。おお、良さそうだ。やっと直ったか。これで公開しても大丈夫だな。それにしても手間をとらせたな、と機嫌よくテストを終わろうとして、最後に、念のため、最大サイズ(32文字)の連続テストをやってみる。
出た。画面をクリアする。あれ、クリアされない。しかし、次のデータを送信するとLCDには表示される。クリアなどの1文字コマンドだけが動かない。テスタを信号線に入れてみると、コマンドを送ったあと、さきのクロックストレッチが発生するが、1秒タイムアウトのおかげで初期状態にもどり、信号線はHighになって開放される。
やれやれ、1文字コマンドは効かなくなるが、丈夫なLCDドライバーにはなった。マスタをハングアップさせることはない。1文字コマンドが動かなくなるのはバッファがオーバフローして、どこかを破壊しているからだろう。まあ、これはぼちぼち調べるとする。
何度同じ間違いをするのか情けない(2/24/08)
1文字コマンドがうまく動かないのは、次の日ロジアナを持ち出して、余計なデータが送られていることを確認した。マスターのMega168はテストマシンということですべてやっつけコーディングで用をたしている。I2Cの場合はデータの送り方が厳密なので本当はまずいのだが、そうそう集中してコーディングは出来ない。
ありあわせの関数でデータを送るのをやめ、LCDドライバ用にちゃんとしたwrite関数にしたら、ピタリと症状はおさまった。これですべて想定した機能は動くようになった。少々乱暴なデータを送っても、今度は1秒タイムアウトですべてをリセットする機能がついているので安心である。残っているといえば、スレーブの電源を止めたときにI2Cそのものがハングすることだが、これは仕様の疑いもあるのでもう少し先送りする。
ただ、心残りは何故これまでのコマンド送出でハングし、修正によってうまく動いたのか理屈が通らないことである。動かない時との違いは、データの最終をあらわす改行記号(0x0D)が2つか1つかのところだけである。プログラムは読んだデータが改行ならば、これまでのデータを受け取り、それ以下は消してしまう。2つあることは何の関係もないはずなのである。
まあ、動いているのだから良しとしておこう。確定申告締め切りの時期が近づいてこまごまとした伝票の整理に飽きて気晴らしに、LEDを順番に点けて遊ぶ回路をブレッドボードで作り始めた。こういう手作業が何と言っても一番紛れる。
LEDだけでは面白くないので、点滅間隔をUARTから変えられるようにする。2313のピン配置は26とは全く違うので結構手間がかかる。回路組み立てに1時間、プログラム開発に1時間、軽く動くはずが、これがまた動かないのである。やれやれ。
送信は動いて初期メッセージを表示するが、キーボードからの受信が出来ない。LEDを挿入するが、受信のピン割り込みが起きていない。2313は26と違って261や861と同じようにピンチェンジ割込みを個別のピンに限定することが出来る。26でやったように送信のときの割込みのマスクや、割込み要求フラグを消して回る手間が省けて楽なのだが、レジスタの名前が違っていたりしてややこしい。データシートを隈なく読むが、動かない原因がわからない。気晴らしのつもりがかえってストレスが溜まってしまう。夜中も2時をすぎたので寝ることにする。
翌日、確定申告をやっとのことで下書きまですませたので、AVRに戻る。デバッグはこういう気分転換が効果的なようだ。ソースを最初から流してみてLEDのポート番号が実際と違うことに気づく。最初の石、26のピンアサインが頭にこびりついていて間違っていた。2313のピン番号は下から上に増えていくのである。
あわてて修正し動かしてみる。何のことはない。LEDはキーボードを押すと点灯するではないか。ちゃんと割込みがかかっている。ISPのUARTは正論理なので1を確認してデータを読みに行くはずだと次のステートメントを確認する。あっ、またビット5を1で比較している!!やれやれまた同じ失敗だ。何度同じ間違いをすれば済むのだろうか。これで3度目だ。しかも前と全く場所なのである。
また、弁解めくが、要するにLEDの番号違いというミスが重なったため、究明の方向が狂ってしまった。デバッグの時のひとつひとつの確認の大事さが身にしみる。
| 固定リンク
「AVR」カテゴリの記事
- ソフトI2Cはクロックストレッチまで手を出してあえなく沈没(2017.09.02)
- オシロのテストどころかソフト開発で大はまり(2017.07.26)
- 超音波方式の人感センサーI2C化と新しいオシロ(2017.06.29)
- motionの動体検知はRaspi3の電源が安定しない(2017.04.16)
- 赤外線学習リモコンはデータ再現で挫折したまま進まず(2016.07.21)
コメント