Linux から MINI EZ-USB を使う


モノはオプティマイズさんとこのこれ。 チップに AN2131SC を使ったものと AN2135SC を使ったものの 2 種類あるが、買ったのは AN2135 版のほう。 将来こいつのデータバスに SL-811HS をはっつけることを考えているが、どーなるやら。

製作

部品数激少でハンダ付け所用時間 10 分弱、しかして足すことの AN2135 の目視チェック 30 分。あぅ。
MINI EZ-USB
... クリスタルのハーネスと AN2135 のランドが危うく接触するとこやった。AN2135 のピン間 (0.8mm) の 1/3 くらいしか開いてない。 0.8mm 間隔なりのハンダ付けしてる (← つまりいいかげん) から、0.2mm 級の精度なんてねーって。

本家の「回路、製作」を読み返したら

「クリスタルとチップのピンの位置が近いためショートしやすい」
と、ちゃんと書いてあったし、読んでもいたんだが、 この「チップ」、クリスタルのすぐ下にあるチップ抵抗のことかと最初誤読していた。

チップといえば、これは 22pF と 0.1uF の二種類のチップコンデンサを使う。 ラベルなんか書いてないのでバラけたらおしまいである。 ふつー少ないほうの 22pF を先に付けてしまうんだろーが、 クリスタルの裏側という手のこんだトコなので先にすることもできず、 ちと緊張を強いられた。テープから外さなきゃいいんだけど、 0.1uF を順繰りに貼っつけていった結果、「0.1uF が 2 個だけのったテープ」というモノが出来て ちょいびびった。いや、もちろんメモはしてあったんだけど。
切実に LCR メータ欲しいと思った ...。

この基板、ケースに止めるための穴が開いてない。 コネクタが一方にしかなく、USB コネクタがあって力がかかることを考えると裸で使わざるをえない。 同時に買った FX2 USB 2.0 も開いてないのですべて開いてないのかと思ったら、 残るカメレオン USB と EZ FPGA には開いているらしい。

端子ピン配置

本家に一覧がないのでメモ。2135 からは BKPT, WAKEUP# 以外のすべてが配線されている。
Side A (部品面) Side B (ハンダ面)
1 FRD# (PA5) FWR# (PA4)
2 PC0/RxD0 D7 (PB7)
3 PC1/TxD0 D6 (PB6)
4 PC2/INT0# D5 (PB5)
5 PC3/INT1# D4 (PB4)
6 PC4/T0# D3 (PB3)
7 PC5/T1# D2 (PB2)
8 PC6 (WR#) D1 (PB1)
9 PC7 (RD#) D0 (PB0)
10 SDA SCL
11 CLK24 Vcc (3.3V)
12 Vbus (5V) Vbus (5V)
13 GND GND

ん、BKPT はどーでもいいが WAKEUP# は欲しかったかも。 なお、カメレオン USB 上の AN2135 では PC4 〜 PC7 を CPLD の JTAG 用に占有、 PC0 〜 PC3 が CPLD 向け GPIO になっている。

コンパイラ等の準備

sdccas31. アセンブラは sdcc にも asx8051 てのが付属し、ふつーはこちらを使うが Ezusb2131 のサンプルが as31 を必要としたので入れた。

sdcc は Debian にも入っているが、サンプルやらなんやらぜんぜん足りないので sdcc 2.3.0 のソースだけは拾ってもっておく。 この場合、nightly snapshot にはサンプルなどは入ってないので持って来ても意味はない。 as31 のほうは、ソースから適当に。

1st ローダの準備

Linux ホストから EZ-USB にファームを流し込むためのローダ。 EZ-USB の初期化用 I2C EEPROM を EZ-USB 経由で書き込むためのローダはまた別で、 その手の 2nd ローダとしては こういうのがある。 EEPROM 繋げてないので使ったことはないが。

1st ローダ一覧:

前二者は 213x 用、最後のは FX2 でも使えるらしい。 ただ、FX2 では fx2_programmer を使ったほうがいいかもしれない。モニタ(デバッガ)を兼ねて便利。4 つとも usbdevfs を必要とするので、事前に
# mount -t usbdevfs none /proc/bus/usb 
しておく。

ローダ機能がオマケの usbstress は別として、使い勝手は fxload が良かったが、 物事が軌道に乗るまでは Ezusb2131 のお世話になった。 Ezusb2131 は 「EZ-USB デバイスが Linux から見える」というステップと「Linux から EZ-USB デバイスへ書き込む」というステップが 完全に分離しているのでトラブルを追いやすい。逆に言えば、ファームを書き込むたびにベンダ ID やデバイス ID が ころころかわる EZ-USB では Ezusb2131 のようにデバイスを登録してしまうタイプだと 書き込むたびにデバイスの切り離し/再接続が発生して煩い。 ... とくに音が。認識しなおすたびにピポッと鳴るわけで ... (^^;

Ezusb2131 の注意事項として二つ:

Ezusb2131 はそのままでは書き込める HEX ファイルのレコードが 16バイトまでの制限がある。 sdcc が吐く hex ファイル相手ならこのままでいいが、世のファームバイナリでは 16 バイトを越えるレコードを持つものがある。 ま、ezusb2131.c を 1 箇所書き換えるだけだが:

 - #define MAX_IHEX_RECORD_LEN 16  /* intel hex 
 + #define MAX_IHEX_RECORD_LEN 32  /* intel hex 

もうひとつ。生の (unconfigured な) EZ-USB を Ezusb2131 デバイスとして登録する関係で、 EZ-USB デバイスそのものにみえるデバイスのドライバがホストに入っていてはならない。 具体的には dabusb がこれにあたる。中身は EZ-USB なオーディオデバイスだが、こいつに認識してもらっては困るので dabusb.o は外す。

もちろん fxload とかを使う場合でも dabusb は外しておいたほうが無難だと思うし、 Ezusb2131 の README にも「外せ」って書いてある。けど、最初のうちはわざわざ dabusb をいれておいた。 Ezusb2131 入れる前でも dabusb が入ってればちゃんと MINI EZ-USB 繋ぐと認識してくれる。 これでカードが正常動作してることを確認した。

サンプルファームと動作テスト、その 1.

Ezusb2131 から led2.hex を使う。 この led2.hex は port B の bit4 に 0.8Hz の方形波を出す。 AN2135SC では port B が使えないので、適当にどこかに変えてから。

% zcat Ezusb2131-1.0.tar.gz | tar -xv
% cd Exusb2131
% make
% Examples/MarkII
% as31 led2.asm
% su root
# insmod ../../exusb2131.o
# cat led2.hex > /proc/bus/usb/001/002
"/proc/bus/usb/" のあとのバス番号、デバイス番号は環境による。

port C の bit5 に割り当てたので、 MINI EZ-USB 端子の A7 〜 A13 間に LED 付けておいたところ点滅してくれた。 ただ予想より周期が遅い。100msec の待ちが H と L で合わせて 5 つ入れたつもりだったが、 0.5Hz な点滅になっているよーな気がする ...。

補足その 1、Ezusb の Examples 内の時間測定コード
でまあ、バグっとったわけだが。

Wait1msec 関数の内部で 10 cycles x 1200 = 1msec とカウントしている。 12MHz で動いているとみていて、ひじょーにもっともらしいのだが ──
EZ USB は 水晶 (or セラロック) 12MHz を使って内部 24MHz 動作、4 クロック/サイクル動作なので命令サイクルは 6MHz ですな。 てけとーにこんな感じで:

***************
*** 111,121 ****
  Wait100msec:
          mov     r0, #100
  Wait1msec:                      ; A delay loop
!         mov     dptr,#-1200
  More:   inc     dptr            ; 3 cycles
          mov     a,dpl           ; + 2
          orl     a,dph           ; + 2
!         jnz     More            ; + 3 = 10 cycles x 1200 = 1msec
          djnz    r0, Wait1msec   ; 
          ret
  
--- 108,118 ----
  Wait100msec:
          mov     r0, #100
  Wait1msec:                      ; A delay loop
!         mov     dptr,#-600
  More:   inc     dptr            ; 3 cycles
          mov     a,dpl           ; + 2
          orl     a,dph           ; + 2
!         jnz     More            ; + 3 = 10 cycles x 600 x 4clk/cycle / 24Mclk/s  = 1msec
          djnz    r0, Wait1msec   ; 
          ret

これ、Examples/MarkII/ 下でも Examples/Waldo/ 下でも同じコードなので、たぶん他にも潜在的に同等のコードがあるだろう。 命令サイクルが 12MHz てことは内部クロック 48MHz てことで、 ... Ezusb"2131" を主張しながら FX2 用になってんのね。FX 以降用?

補足その 2、 fxload の場合
fxload を使う場合は HEX ファイル作ってから (insmod exusb2131 〜 cat のかわりに)、
# fxload  -D /proc/bus/usb/001/002 -t an21 -I led2.hex
とする。"-t an21" (AN213x タイプのロード動作を指定) は無くても動くことになっているし、 初回 (電源投入直後) のロードでは動くが、二度目以降 (一度以上ロードしたところへの上書き) は 自動判別がアテにならんこともあるみたいなのでつけている。

Ezusb では切断/再接続が頻繁におきるため、デバイス番号がテストのたびに変わっていくが、 fxload では物理的に切断しないかぎりおんなじ番号なので入力は楽。
... なことは楽なんだが、もう一声、できればロード先デバイスを自動的に識別していただきたい。 "/proc/bus/usb/001/002" などとうちこむのは見た目よりも面倒なんだぞぅ。 このパス文字列、あまり completion が効かない場所にあるから。

サンプルファームと動作テスト、その 2.

usbstress 使って USB な通信テスト。 gcc 3.3.1 では make できなかった。直すのめんどーなので gcc 2.95 を使う。

% zcat usbstress-0.3.tar.gz | tar -xv
% cd usbstress-0.3
% CC=gcc-2.95 ./configure
% CC=gcc-2.95 make
% su root
# ./usbstress -v -t c
# ./usbstress -v -t b
# ./usbstress -v -t r
usbstress は usbstress 向けの ID を持った USB デバイスを /proc/bus/usb から自力で探し出すため、 デバイスを指定しなくても動く。また、unconfigured な EZ-USB を見付けると firmware.ihx をロードしてくれる (ロードするだけで usbstress 的テストには入らない)。名前固定だが、けっこ便利。

動かしてみると、 -t で指定するところの c (コントロールの転送)、b (バルクのピンポンな転送)、ab (バルクの窓枠シフト的転送)、 については動くんだが、i (アイソクロナス転送) がエラー出まくった。

480 バイトのパケットリクエストに対し、448 バイトしかホストが受け取れてない。 ... どこかでバッファの計算しくったんだろーな。

# ./usbstress -v -p sz=448 -t i
などとして、パケットサイズを 448 以下にしてやるとちゃんと動いた。

ちなみに、この firmware.ihx の性能はというと、TP240 相手のバルク通信で 150kB/s、 Athlon XP 1700+ な PC 相手のバルク通信で 250kB/s ほど。 遅いようにみえるがアイソクロナス転送で 1MB/s 出るので USB SIE の能力限界ではないらしい。 ま、いちいち返事を待ってるしな。

アセンブラなんで下地にするには辛いが、こういうリファレンスもないといかんだろってことで。

次!

MINI EZ-USB が動いたところで FX2 の動作テストに行ってみよ〜

補記: EEPROM への書き込み

2nd ローダ使ってみたのでメモ。

上記 URL から ezhid-0.8 を拾ってきて build.

まず EEEPROM への読み書き用 firm を流し込む:

# fxload  -D /proc/bus/usb/001/002 -t an21 -I i2c_firm.ihx
すると eeprom.pl で読み書きできるようになる:
# eeprom.pl -d /proc/bus/usb/001/002 -r -a 0x0200 -l 2
eeprom.pl では I2C EEPROM は I2C アドレスの 1 にあることが仮定される (EZ USB は、この位置の EEPROM からブートする)。 違うアドレスのやつについては、 ハードコードになってるので
$i2c_wired_address
を適当に書き換える。

ブート用 firm は、ふつーに build したものから:

create_ezhid_e2.pl < i2c_firm.ihx > i2c_firm2.ihx
として作る。... が、i2c_dirm って EEPROM ブートに対応してないかも。なんか動いてくんない。
[日記へ] [目次へ]