IgorPlug-USB for ATmega48


ソフトウエア USB その 2.

どっちか動けばいーや言うてたらどっちもすぐには動かなかったというオチがついたもう片方。 やっぱ天秤かけるようなことをしてはいかんのか ... は ともかく AVR による USB Low-speed device のソフトウエア実装で、 本家では AT90S2313 と ATmega8 で実装されている。 今のドキュメント上の回路図は ATtiny2313 と ATmega48/88/168 になっているのだが ... ATtiny2313 では実装例もあるのに、ATmega48/88 のほうはソース互換性がないなんて聞いてねえぞぅ。

注釈

元ソースが ATmega48 等で動かないのは、 ことに起因する。

とくに前者によって、 ビットセット/クリアするのに一時レジスタが必要になり、そのレジスタの push/pop が必要になり(レジスタ数も push/pop に掛ける時間の余裕もないのに) ... という具合に波及していく。

ここで、USB 側の割り込み禁止期間許容範囲はかなり狭く、 SYNC の最初の立ち下がりで USB の割り込みハンドラに移行、 そして SYNC の最後の 2 ビットまでに同期をとらなければならないのだが、 そのめには SYNC の立ち下がりから同期ビットに入るまで 6 ビット (48 サイクル) 以下でなければならない。

一方、USART の受信割り込みの冒頭にある割り込み禁止時間は現状で 15 サイクルだから、 33 サイクル以内に同期しなければならない。 ATmega8 で 4 サイクル余裕があったのが、ATmega48 で 1 サイクル足りなくなっている。... と思ったが、 最終的にどうなったか計算してない。 (ちなみに UART は割り込みハンドラに入る時に rjmp しておらず、 割り込み再許可までの時間を 2 サイクル前倒ししている。よーやる ...) ... ま、いいか。

ところで、 本家によれば UART 側は 57600bps ということになっているが、 ソース的には 115200bps 出るような分周比になっている。 ATmega8 って、このコードでも 57600bps になるんかな。 USB の受信ハンドラは受信中は全区間が割り込み禁止で、ぱっと見で約 100us ある。 115200bps (約 100us 毎) では USB 側が重負荷時にロクに動かないはずだが、さて。

ソース

USB ⇔ RS232 変換だけというにはとってももりだくさんなコードで、 ポートの上げ下げ読み書きから EEPROM やフラッシュの読みだしまでサポートしていることになっているが、 手を入れてないようなトコはテストなんぞほとんどしてないのであしからず。

とくに許容 EEPROM 最終アドレスは 0x07f のままで、0x100 にはなっていない。 いや、どーでもいい部分のわりに サイズが 1 バイト超えて書き換え部分がややこしくなったんで。

ハード

本家回路図と異なる点はない。
USB I/F for ATmega48

出力波形はというと、 ホスト側からのスルーレート制限済みの波形と比べても遜色ない綺麗なもの。
まあ FPGA よりもやや弱いバッファとはいえ 出力インピーダンス約 50ohm とほとんど整合しているとこに速度 1/10 というわけで。

ログ

もちろん詳細ログが取れる設定なまんま。
kernel: hub.c: port 5 connection change
kernel: hub.c: port 5, portstatus 301, change 1, 1.5 Mb/s
...
kernel: hub.c: new USB device 00:03.0-1.5, assigned address 20
kernel: usb-ohci.c: SUB URB:[2613] dev: 0,ep: 0-O,type:CTRL,flags:   0,len:0/0,stat:0(0) // setAddress するよ。
kernel: usb-ohci.c: cmd(8): 00 05 14 00 00 00 00 00
kernel: usb-ohci.c: RET URB:[2616] dev: 0,ep: 0-O,type:CTRL,flags:   0,len:0/0,stat:0(0) // おっけ〜。
kernel: usb-ohci.c: SUB URB:[2624] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/8,stat:0(0) // D.Desc. ちょうだい。
kernel: usb-ohci.c: RET URB:[2629] dev:20,ep: 0-I,type:CTRL,flags:   0,len:8/8,stat:0(0) // 先頭 8 バイトだけね。
kernel: usb-ohci.c: cmd(8): 80 06 00 01 00 00 08 00
kernel: usb-ohci.c: data(8/8): 12 01 01 01 00 00 00 08 stat:0
kernel: usb-ohci.c: SUB URB:[2629] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/18,stat:0(0) // D.Desc 全部よこせ!
kernel: usb-ohci.c: RET URB:[2630] dev:20,ep: 0-I,type:CTRL,flags:   0,len:18/18,stat:0(0)
kernel: usb-ohci.c: cmd(8): 80 06 00 01 00 00 12 00
kernel: usb-ohci.c: data(18/18): 12 01 01 01 00 00 00 08 eb 03 ff 21 03 00 01 02... stat:0 // ほいよ。
kernel: usb-ohci.c: SUB URB:[2630] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/8,stat:0(0)   // C.Desc. は?
kernel: usb-ohci.c: RET URB:[2634] dev:20,ep: 0-I,type:CTRL,flags:   0,len:8/8,stat:0(0)
kernel: usb-ohci.c: cmd(8): 80 06 00 02 00 00 08 00
kernel: usb-ohci.c: data(8/8): 09 02 19 00 01 01 00 80 stat:0                              // 例によって先頭だけね。
kernel: usb-ohci.c: SUB URB:[2634] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/25,stat:0(0)  // いいかげんにせえよ ...。
kernel: usb-ohci.c: RET URB:[263d] dev:20,ep: 0-I,type:CTRL,flags:   0,len:25/25,stat:0(0)
kernel: usb-ohci.c: cmd(8): 80 06 00 02 00 00 19 00
kernel: usb-ohci.c: data(25/25): 09 02 19 00 01 01 00 80 19 09 04 00 00 01 00 00... stat:0 // そんなこと言われても。はい。
kernel: usb.c: kmalloc IF d8425340, numif 1
kernel: usb-ohci.c: SUB URB:[263d] dev:20,ep: 0-O,type:CTRL,flags:   0,len:0/0,stat:0(0)   // setConfig. するよ。
kernel: usb-ohci.c: cmd(8): 00 09 01 00 00 00 00 00
kernel: usb-ohci.c: RET URB:[2640] dev:20,ep: 0-O,type:CTRL,flags:   0,len:0/0,stat:0(0)   // うん。
kernel: usb.c: new device strings: Mfr=1, Product=2, SerialNumber=0
kernel: usb-ohci.c: SUB URB:[2640] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/4,stat:0(0)   // 言語コード(Str.Desc.)くれ。
kernel: usb-ohci.c: RET URB:[2643] dev:20,ep: 0-I,type:CTRL,flags:   0,len:4/4,stat:0(0)
kernel: usb-ohci.c: cmd(8): 80 06 00 03 00 00 04 00
kernel: usb-ohci.c: data(4/4): 04 03 09 04 stat:0                                          //  0409 (米語) ね。
kernel: usb.c: USB device number 20 default language ID 0x409
kernel: usb-ohci.c: SUB URB:[2643] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/255,stat:0(0)  // 製造者名は?
kernel: usb-ohci.c: RET URB:[265b] dev:20,ep: 0-I,type:CTRL,flags:   0,len:82/255,stat:0(0)
kernel: usb-ohci.c: cmd(8): 80 06 01 03 09 04 ff 00
kernel: usb-ohci.c: data(82/255): 52 03 49 00 6e 00 67 00 2e 00 20 00 49 00 67 00... stat:0
kernel: Manufacturer: Ing. Igor Cesko http://www.cesko.host.sk
kernel: usb-ohci.c: SUB URB:[265b] dev:20,ep: 0-I,type:CTRL,flags:   0,len:0/255,stat:0(0)  // 製品名は?
kernel: usb-ohci.c: RET URB:[2671] dev:20,ep: 0-I,type:CTRL,flags:   0,len:78/255,stat:0(0)
kernel: usb-ohci.c: cmd(8): 80 06 02 03 09 04 ff 00
kernel: usb-ohci.c: data(78/255): 4e 03 41 00 56 00 52 00 33 00 30 00 39 00 3a 00... stat:0
kernel: Product: AVR309: USB to UART protocol converter                                     
kernel: usb.c: unhandled interfaces on device
kernel: usb.c: USB device 20 (vend/prod 0x3eb/0x21ff) is not claimed by any active driver.  // C.Desc. と名前から構成してみた。
kernel:   Length              = 18
kernel:   DescriptorType      = 01
kernel:   USB version         = 1.01
kernel:   Vendor:Product      = 03eb:21ff
kernel:   MaxPacketSize0      = 8
kernel:   NumConfigurations   = 1
kernel:   Device version      = 0.03
kernel:   Device Class:SubClass:Protocol = 00:00:00
kernel:     Per-interface classes
kernel: Configuration:
kernel:   bLength             =    9
kernel:   bDescriptorType     =   02
kernel:   wTotalLength        = 0019
kernel:   bNumInterfaces      =   01
kernel:   bConfigurationValue =   01
kernel:   iConfiguration      =   00
kernel:   bmAttributes        =   80
kernel:   MaxPower            =   50mA
kernel: 
kernel:   Interface: 0
kernel:   Alternate Setting:  0
kernel:     bLength             =    9
kernel:     bDescriptorType     =   04
kernel:     bInterfaceNumber    =   00
kernel:     bAlternateSetting   =   00
kernel:     bNumEndpoints       =   01
kernel:     bInterface Class:SubClass:Protocol =   00:00:00
kernel:     iInterface          =   00
kernel:     Endpoint:
kernel:       bLength             =    7
kernel:       bDescriptorType     =   05
kernel:       bEndpointAddress    =   81 (i/o)
kernel:       bmAttributes        =   00 (Control)
kernel:       wMaxPacketSize      = 0008
kernel:       bInterval           =   0a
kernel: usb.c: kusbd: /sbin/hotplug.murasaki add 20
murasaki.usb[23895]: device is added
murasaki.usb[23895]: vendor:0x3eb product:0x21ff Dclass:0x0 Dsubclass:0x0 Dprotocol:0x0 Iclass:0x0 Isubclass:0x0 Iprotocol:0x0
murasaki.usb[23895]: The device match nothing in mapfile
murasaki.usb[23895]: Please change MODULE in following line to appropriate module name, add it to /etc/murasaki/murasaki.usbmap
murasaki.usb[23895]: MODULE 0x0003 0x3eb 0x21ff 0 0 0x0 0x0 0x0 0x0 0x0 0x0 0x00000000

ホスト側

Linux kernel 2.6.11 から Igorplug USB 用のホストドライバが入った。
... が、手持ち 2.4.x なのでまだテストできず。

References


[日記へ] [目次へ]