2007-09

にっき

2007-08

開発日記


ぱどさんからの情報

>ところでAVR-USBのスループット向上ですがホストとデバイス間にHi-SpeedUSBハブを挿んでみてはいかがでしょう?

>ホストからはHSのハブに転送させてハブにHSからLSにTTさせてみると速くなったりしませんでしょうか。

  • 確かに速くなりました。
  • コントロール転送が15kB/秒になります。(SiSと比べて2倍、intel、VIAと比べて8倍速くなった)
  • ホストコントローラの種類に拠らず速くなります。
  • LowSpeedバルク転送がうまくいきません。原因はまだわかりません。


  • HSハブをPC(EHCIホスト)とAVRの間に挟むことで、どうやらマイクロフレーム(125μS単位でのトランザクション:スプリットトランザクション?)が使用可能になるようです。

これは美味しいかも


USBハブ実験

AVR-CDC改(最小限のCDCでエコーバックのみを行うもの)を試してみた。

  • USB1.1ハブに繋いだ場合はCOM3:になり、teratermでエコーバック出来た。
  • USB2.0ハブに繋いだ場合はCOM5:になり、teratermで接続は出来るもののエコーバックが帰ってこない。
  • やはりLowSpeedバルクが殺されているような気がする。
    • ってやっぱりSnoopyを動かして試さなきゃ!

AVR_term

ここまで作った。

bash ./checksize main.bin
ROM: 1696 bytes (data=6)
RAM: 95 bytes
  • コントロール転送のみを使う。
  • エンドポイントなし。
  • EEPROMのread/writeを削除したモニタをそのまま残す。
  • 最大4バイトの送信データを送信し、最大7バイトの受信データを受け取る。
  • PC側では簡単な送受テストを動作。


  • サイズ的には余裕のよっちゃん、なのでigorさんのと同じようにirdaとか追加できそう。
  • monitに仕込んでおいたポート内容のダンプ機能がデバッグに思いのほか役立った。

ToDo

  • 受信FIFOの正しい扱い 済み
  • 送信FIFOのFULLチェック 済み
  • 受信割り込みでの割り込み許可ポイント 今のところポーリングで受信しているので不要
  • ボーレート設定 済み
  • 送受テストばかりしてないでterminalとして動作させる 済み
  • 仮想com:のエコーバックを使用してcomポートに見せかける

USBtoシリアルが出来た。

  • これでやっと、昔作ってずっと放置していたAKI-Z80やらSuper-AKI をUSB接続出来るぞ、っと。
  • ジャンク箱をあさって、Z80なボードを掘り出した。

/ATMEL_AVR/upload/aki80.jpg

  • なんか、珍しい石英ガラス窓付きのチップが載っているぞ!
  • これが、おとぎ話に出てくる紫外線消去型EP-ROMってやつか?

どうする、おい

  • ROMライター持ってないぞ。

ここからさらに強引な展開

  • AVRでROMライターを作る。
    • いまさらROMライターかよ。
  • 多ピン品種のAVRで27C256っぽいROMの真似をする。
    • ATMEGA644-DIP40があれば可能だ。
    • しかし、本末転倒ではないか?
    • ATMEGA644-DIP40があればZ80なんかいらんだろ?

部品が乗る前の写真(秋月) http://img.akizukidenshi.com/images/org/k-123.jpg

  • もちろん、EPROMは載っていない。あとで載せたものだ。
  • いまさらZ80アセンブラかよ。
    • (LSI−Cってのも昔あったけれど、雑誌付録にいつも付いていてフリーなやつはLSI−C86のほうだ)
  • これ1枚買うのも結構高かったよ(現在も入手できる。3000円)
  • 今なら迷わずATMEGA644-DIP40を3個買う。

仮想COMエコーバックポートに対応中

ここまで書いた。

  • CommEmuDrvをDLしてインストール。
  • COM5:とCOM9:を仮想ポートペア(エコーバック対)として作成。
  • AVRterm.exeを改造したcomm.exe で、COM9を開く。
  • COM9:から受け取ったデータはAVRに流す。
  • AVRからの受信データをCOM9:に流す。
    こうすることで、COM5:に接続したteratermは、AVRのシリアルポートに繋がったことと等価になる(予定)
  • 一応書いてみた。
  • 一応動いたが・・・ごにょごにょ・・・反応が2V、じゃなかった鈍い。
  • キーをバタバタ打った後で1秒くらい置いて、ドカドカっと文字が帰ってくる。

なんで?

  • どうやらAVR側はシロだ。
  • AVRと交信せずに、WIN32内で完結するエコーバックを書いて回しても反応は同じ。
  • ところがWriteFile(Ex)せずに直接printfする場合はすんなりと速い。
  • COM9:に対するWriteFile(Ex)が発生すると長時間(0.5秒くらい)待たされているような感じだ。
  • これは同一ファイルハンドルCOM9を使ったReadFileExとWriteFileが競合するパターンのようだ。
  • 単体テストのときはうまく回避する術を見つけたような気がしたのだが・・・(気がしただけだったのか?)

この、どうしようもない閉塞感は何なんだ・・・

  • AKI−H8/3048Fとそのライターボードをジャンク箱から発掘。
  • USBにつなげてやろうと思った。
  • あれ?何これ?12Vいるやん。
  • 200mAだと?大飯食いめ!
  • とりあえず通電してみた。動かない。なんで?FLASH消えたのか?
  • まあよい、開発環境は残っているかな?うーんWin95以前かな?だめだこりゃ。
  • RS232Cが25PIN DーSUBだ(PC98仕様)

というか最密充填両面印刷で700ページもあるHITACHIのマニュアルは何なんだろう。

  • たしかに機能てんこ盛り。
  • いちいちアセンブラでコーディングしろと・・・。
  • 複雑すぎるんだよなー。このH8は。その割遅い。
  • 手間掛かりすぎるんだよなー。12V要るし。
  • まあ、当時ワンチップで128KのFLASHが乗っているマイコンは他になかったような気がするが。
  • もう、いまさら使おうとは思わないんだよなー。
  • AVRに繋ぐのめんどくせーなー。やめよっかなー。

日の丸マイコンが凋落の日々となった理由の一端がすこしわかったような気がする。

  • だせーんだよ。何もかもが。

そう、いまさらH8を復活させて何か作ろうというわけではない。

  • 単に動態保存したいだけなんだ。
  • ビンテージパソコンコレクターと同じだな。
  • あと、コンパイラー揃えるの面倒だなー。AVRだけでいいやもう。

仮想COMエコーバックポートにて、手詰まり

手詰まりとなった。

  • AVRとは接続しない状態で、COMポートをオープンし、1バイトづつ文字を読み書きする。
  • すなわち、ごく単純な無手順ターミナルすら作れないという謎現象だ。
  • 突き詰めていったところ、WriteFile()でCOMに書き込むと、それが反対側のCOMポート(teraterm)に表示されるまでに0.5秒くらいのラグが出来るのだ。
  • ReadFileもスレッドも一切使わない状態でもそうなる。
  • OVERLAPPEDをやめてもそうなる。
  • 送信文字数が1バイトだろうが100バイトだろうが、0.5秒後にしか出現しない。
  • さらにたちがわるいのは、その期間内のReadFileが一切ブロックされることだ。

これがCommEmuDrv作成の仮想COMにだけそうなるのか、リアルのCOMでそうなるのかもまだ分からない。

  • teraterm同士を仮想COMで繋いで手打ちする限りはラグは起きない。
  • プログラムを使わずにコマンドライン上から
    C:> copy file.txt COM5
    などとしても同様の現象に見舞われ、さらに悪いことにファイルの先頭しか送信されない。
    • ちなみに受信側はteraterm


激しく謎すぎてWIN32のCOMx:はようわからん・・・・。


ComEmulDrvへの対応を断念した。

症状:

  • COMポートに送信(writeFile)して、0.5秒くらいのラグがあって文字が(teraterm側に)表示される問題。
  • 受信はまったく問題ない。
  • あと、問題は、空白の0.5秒の間にteratermで打った文字がぜんぜん受信できずに捨てられることだ。
  • まったく原因がつかめない。

じゃあteraterm同士では大丈夫なのか?

  • 試してみた。
  • ポートの方向によって、だめなときがある。
    • わりと、最後の1文字が0.5秒遅れで出たり、もう1文字書いたときに遅れて出たりする。
    • これはどちらかというとWindowsのカーネルのタイムスライスがおかしいんじゃぁ?
  • teratermでは文字が捨てられることはなさそう。
  • リアルRS232Cポートではこのようになるというのは聞いたことない。
    • ComEmulDrvの癖なのかもしれない。
    • ソースを見たが、よく分からない。
    • Google先生にも聞いてみたが、使用例はごく少ないらしく、症例を発見できず。

Win32上でのComm関係でかれこれ3日くらい悩んだがもうあきらめよう。


H8/3048F(季節柄秋なので、秋の月、秋月)のその後

  • 25PINのパラレルコネクタは使わないっぽいので外して、そこにUSBのBコネクタ を実装してみた。
  • H8/3048F本体基板の3端子レギュレータを外して、USBの+5を直接H8の5Vに繋いだ。(本来はH8/3048F本体基板に12Vが印加される仕様)
  • USB盗電システム成功。H8モニタ起動OK。
  • ついでに、ATtiny2313を実装。
  • 部品は100Ω×2、1.5kΩ×1、12MHzXtal、0.1μFパスコン、AVRチップ、とたったこれだけで製作。
  • 何を省略したかというと減圧レギュレータ、Xtalの負荷コンデンサ。
  • AVRは5V動作。
  • これで何の問題もなくAVR_Monit入りのAVR_termが起動した。

まだ、USBシリアルからH8には繋いでいない。

  • というのは、H8/3048F本体基板のRS232Cは、リアルRS232CのTxD、RxDなので、レベル変換とインバータが必要だからだ。
  • H8/3048F本体基板上のADM232を外して直結すればいいのだが、あんまり触りたくない。(配線が細いので・・・)

さらにAKI80接続した。

  • 実はレベルコンバータが面倒だったので、いきなりZ80 SIOのほうに接続してみた。
    #d 8000
    8000 ff ff ff ff 0000 00 00 ff ff ff ff 0 00 00 00
    8010 ff ff f df 00 00 00 0 ff ff ff fd 00 00 00 00
    8020 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
    8030 ff ff ff ff 00 00 00 0 ff ff ff ff 00 00 0000
    8040 00 00 00 00 f ff ff ff 00 00 00 01 f ff ff ff
    8050 00 0040 00 ff ff ff ff 00 0 00 00 ff ff f ff
    8060 00 00 00 00 ff ff ffff 00 0 00 00 ff ff ff ff
    800 00 00 00 00 ff ff ffff 00 00 00 00 ff ff f ff
    8080 ff f ff ff 00 00 00 00 ff f ff ff00 00 00 00
    80a0 ff f ff ff 00 0000 00 ff f ff ff 00 0 00 00
    8b0 ff ff ff f 00 0000 00 ff ff ffff 00 00 0 00
    80c0 0 00 00 0 ff ff ff ff 0000 0000 ff ff ff ff
    80d0 00 0 00 00 ff f ff ff 0000 00 0 ff ff ff ff
    0e0 00 0 00 00 ff f ff ff 0000 00 00 ff f ff ff
    0f0 00 00 0000 ff ff f ff 00 00 00 0 ff f ff ff

惨敗。受信欠落多すぎ。

AVRの負け。

Z80の勝ち。


直ったぜ!

#d 8000
8000 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
8010 ff ff ff df 00 00 00 00 ff ff ff fd 00 00 00 00
8020 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
8030 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
8040 00 00 00 00 ff ff ff ff 00 00 00 01 ff ff ff ff
8050 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff
8060 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff
8070 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff
8080 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
8090 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
80a0 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
80b0 ff ff ff ff 00 00 00 00 ff ff ff ff 00 00 00 00
80c0 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff
80d0 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff
80e0 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff
80f0 00 00 00 00 ff ff ff ff 00 00 00 00 ff ff ff ff

ハイスピードハブを挟んだだけで直った。

  • ワンダフル!
  • ボーレートは38400bps
  • RS232C受信がポーリングによるものなので、直結だと開放タイミングがうまく確保できないのだろう。
  • 割り込み受信にするしかない?

モニタはこんな奴が入っていた。


H8には勝った。

  • 秋月H8/3048Fのマザーボード(兼ライターボード)に乗っていたIC NEC2003 の空きピンを利用してインバータ兼レベルコンバーターを実装。
  • 2003はダーリントン接続の2Trが8個入っている。
  • まるでLEDドライバーみたいなやつ。
  • これをRS232CのTxDにつないで、出力をプルアップしたのちAVRのRxDに繋ぐ。
  • 逆も同様。
  • どうやらRS232Cから直結するとうまく行かない。
  • RS232Cラインがー10Vに振れたときに逆流ダイオードに引っかかって死亡。
  • 3kオームを入れてとりあえずOK。

結果

  • H8は19200BPSのモニターが起動する。
  • AVRも19200に合わせてAVR_termを起動。
  • 今回はハイスピードハブがなくても受信文字欠落は無かった。

OK。出来上がり。

現在のステータス

  • AVR_term経由でAKI-80との接続に成功。(38400BPS)
    • ただし、ハイスピードハブを挟まないと受信文字欠落が生じる。
  • AVR_term経由でH8/3048Fとの接続に成功。(19200BPS)
    • RS232CからAVRへは余ったダーリントンでインバート接続した。
    • ハイスピードハブを挟まなくてもOK。

H8を勉強中

H8のブートモードのおさらい。

ブートモード、ユーザープログラムモードともに、VPPに12Vを印加。
ブートモードではさらにMD2にも12Vを印加。

  • ホストは00を何回か送る。
  • H8はそれを見てボーレートを調整する。
  • H8は調整できたら00をエコーバックする。
  • ホストは00を受け取ったら、次に55を送る。
  • H8は55に対してAAを返す。
  • ホストは、HI,LOの順に転送プログラムサイズを送る。
  • ホストは、転送プログラム本体を送る。
  • H8は、それぞれをバイトごとにエコーバックする。
  • 転送が終わったら、H8はFLASHを全消去する。
  • 全消去が済んだらAAを返す。消去に失敗するとFFを返し、停止する。
  • H8は転送されたユーザープログラム(FF300もしくはFFF300からサイズ最大C00バイト)を実行する。
    • FFF300 はモード6のとき(16MB)FF300はモード5,7のとき(1MB空間)

以上。

これらを実行してくれるツールがh8write.c なのだが、AVR_termに組み込むのは無理。

  • というのは、AVR_termには1バイト単位でのsend/recvをサポートしている論理層がないのだ。
  • 基本的にポーリングで(キー入力処理/AVRとの交信/文字表示)のループを回しているだけなのだ。
  • こいつをバイト志向のインターフェースにするには、AVRとの交信を別スレッドで回して、そのスレッドとメインスレッドのインターフェースをバイト志向のFIFOなりPIPEに改造しなければならない。(今はそうなっていない)

PuTTYを試す。

  • PuTTYはフリーなssh / telnetクライアント。
  • serialもサポートされている。
  • Windows / Linux と動作範囲は広い。
  • なぜだかわからないが PuTTYだと、ComEmulDrvとの相性が良い。
    不思議だ。
  • 不思議なことにOVERLAPPED引数エリアをReadFile() WriteFile() 直前に毎回ゼロクリアしている。
  • そんなことWIN32HELPに書いてないぞ。
  • やってみたが・・・今一つだ。
  • むしろ、readfileのthreadでsleep(1)しているのが悪いらしい。

自分が馬鹿であることに気づいた(もっと早く気づけよ)

  • Sleep(1mS)が悪い、と書いたが、実はそうではなくて。
  • ReadFile( ... OVERLAPPED &ovl );でIO_PENDINGじゃないときは、既に読み込み完になっている。
  • そのときはGetOverlappedResultとかWaitForなんとかとかは、一切不要で。
  • すでに受信できてるわけ。
  • なのに、そのデータを捨てちゃだめだよなー。>アホ。

どうりで、teratermからのuploadをReadFileスレッドでぜんぜん受信できないわけだ。

  • Sleep(1)を外すと、「のほほん」タイムが省略されて、常にIO_PENDING状態になり、
  • たまたま受信できていたわけ。

最近の思うところ

OLIMEXのこれが欲しいんだな。

  • made in ブルガリーだが、どう考えてもH8の20MHzに対してクロック比3倍、CPI比4倍、 計12倍は軽く速い
  • SH−2と比べてもこっちのほうが良さげ。消費電力でもSHより少ない。
  • フラッシュ512K、RAM42KBと、十分な容量。
  • おまけにUSB FullSpeed内蔵だな。
  • ARMなのでコンパイラには不自由しないし、アセンブラで書いても速い。

こうなってくると、もうるねさすなんかいらないという感じ。

  • というか秋月さん、H8はもういいからこんなナイスなボード売って。(OLIMEXのデッドコピーじゃないやつね)
    • 意訳:CPIの悪いコストパフォーマンスの悪いH8はもう保守品種にしてしまっていい。
    • USBとかLANは欲しい。あとは適度にクールなCPUを安く載せて。
    • EzUSB FX2はいくらHiSpeedでも(8051だから)嫌だ。


じゃあ何かい?。今までのAVRとH8は回り道だったってこと?


MIPSも面白いかも。

こっちはOLIMEXじゃないけれど、100BaseTが4ポートとシリアルとUSBが付いて3800円だ。

MIPSの175MHz、8M RAM 2M FLASHだ。OLIMEXを超えている。

しかも、Buffaloだぜ。普通のパソコンショップに売ってるし。

改造するなら、ジャンクで入手すべきだが。

  • ひとつ注意しておくと、USBはデバイスではなくてホストだ。
  • だが、Linux化出来るので、各種ドライバーは揃うわけで、楽だろ。

下手に実用品として使おうとしないこと(たとえばWebサーバーとかFTPサーバーとかインターネットに晒すとか)

  • 実用品なら玄箱買っとけ。あっちはRAMがこの16倍はある。
  • 実用品じゃなくて、マイコンボードと考えると、なんなんだろうこの高機能っぷりは!175Mhzのボードなんて1万円でも買えないぜ。しかもLinux動いてるし。
  • EtherNetのハブ(もしくはルーター)+αとして実用に使うは善し。+αの部分はあまり多くを望まないこと。

Win32 Commポートリベンジ!

  • なんかほんとにteraterm-->ComEmulDrv-->自作Comm通信は相性が悪いようだ。
  • 症状としては、Commに対するReadFileとWriteFileの発行(オーバーラップも含め)が重なるだけでダメダメになる。
  • teratermの代わりにPuTTYだと、割といい感じ。
  • なぜだかわからない。
  • 文字欠けの問題は、Commに対するReadFileとWriteFileの発行(オーバーラップも含め)が重ならないようにセマフォとかMutexで制御することで回避は出来るが、送信が起きると受信文字が妙に遅れてくる問題はそのままのようだ。
  • ちなみにWriteFileせずにconsole printするような(半二重通信)アプリにすると、どちらのtermでも快調だ。

Win32のCommはほんとにようわからん。


結局のところ、半二重でよいからとっととやっつけてしまおう的なソリューションを取ることにした。

要はh8write.cが動けば(AVR tiny2313経由でH8/3048Fに書ければ)いいというそれだけなのだ。

  • だから、文字欠けさえなければ、応答が遅かろうがどうでもよい。
  • h8write.cのやりかたが、けっこう投槍的なので、真似しようかと。(ERROR_IO_PENDINGなんか見てないし)

結果、成功。

  • わざわざWIN32用の無手順端末を書いた。
  • 投槍的にはせずに、普通に書いてみた。
  • RS232C受信文字があるかどうかをポーリングする関数ClearCommError()を使って、結局スレッドは用いなかった。
  • さらに、無手順端末モードの他にエコーバックサーバーモードを追加した。
  • 2つのtermを立ち上げ、片方をエコーバックサーバーにして、もう片方を無手順端末にする。

ばっちりだ。

  • 無手順端末でなくteratermを使ったときだけ、応答が遅い現象が起きる。
  • PuTTYでは起きないので、teratermだけ本物のRS232Cポートを仮定した何かのエラーチェックがあるのではないか???
  • ComEmulDrvのCOMポートに対して、GetCommProperties()を発行すると、COMPROP構造体がオールゼロのままで何も情報を返さないので、やはり実在COMポートとは異なるようだ。