AVR-CDC
- AVRをシリアルポートへの読み書きによって制御できるデバイス。
- 各ポートのON/OFF、Digital/Analogの読み込みなど。
- パソコンとの接続はUSBケーブル。電源もUSB。
- AVRのソフトウエアでUSBプロトコルを処理するのでUSB用のchipが不要。部品がとても少ない。
- AVR
- クリスタル
- コンデンサ3個
- 抵抗3本
- ダイオード2個
- BLINK(1)みたいな"USBデバイス"が自作できる!!
- Arduinoでいいのではないか
- 2-3000円ぐらいするのが負けている感
- 完成品なのが負けている感
- USB-シリアル変換の部品が高くついている感
- うちにあったのは88pと20MHzのxtalなのでこれを使いたい
コード修正
cdcio.2009-07-15/mega48/defaultの中のファイルをちょっと変える。
- Makefile
- MCU = atmega88p
- F_CPU 12000000UL → 20000000UL
- mega48/main.c
- "#if AVR_IOMX8_H" → "#if AVR_IOMX8_H || AVR_IOM88P_H"
make
% PATH=$PATH:/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin
cdcio.2009-07-15/mega48/default% make
avr-gcc -I".." -I"../../usbdrv" -mmcu=atmega88p -Wall -gdwarf-2 -DF_CPU=20000000UL -Os -fsigned-char -MD -MP -MT main.o -MF dep/main.o.d -c ../main.c
avr-gcc -I".." -I"../../usbdrv" -mmcu=atmega88p -mmcu=atmega88p -Wall -gdwarf-2 -DF_CPU=20000000UL -Os -fsigned-char -MD -MP -MT usbdrvasm.o -MF dep/usbdrvasm.o.d -x assembler-with-cpp -Wa,-gdwarf2 -c ../../usbdrv/usbdrvasm.S
avr-gcc -I".." -I"../../usbdrv" -mmcu=atmega88p -Wall -gdwarf-2 -DF_CPU=20000000UL -Os -fsigned-char -MD -MP -MT oddebug.o -MF dep/oddebug.o.d -c ../../usbdrv/oddebug.c
avr-gcc -I".." -I"../../usbdrv" -mmcu=atmega88p -Wall -gdwarf-2 -DF_CPU=20000000UL -Os -fsigned-char -MD -MP -MT usbdrv.o -MF dep/usbdrv.o.d -c ../../usbdrv/usbdrv.c
avr-gcc -mmcu=atmega88p main.o usbdrvasm.o oddebug.o usbdrv.o -o cdcio.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature cdcio.elf cdcio.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex cdcio.elf cdcio.eep || exit 0
avr-objdump -h -S cdcio.elf > cdcio.lss
fuse
どんな設定にすればいいのか。Readme.txtに書いてある。
Fuse bits
ext H-L
ATmega48/88/168 FF CE-FF
SPIEN=0, WDTON=0, CKOPT(mega8)=0,
Crystal: Ex.8MHz/PLL(45,461), BOD: 1.8-2.7V
-
ext=0xFF
bit3-7は未使用なので0xFFも0x07も同じ。 -
H=0xCE
bit7:RSTDISBL = 1 RESETピン有効
bit6:DWEN = 1 デバッグWIRE不許可
bit5:SPIEN = 0 直列プログラミング許可
bit4:WDTON = 0 WDTは常時有効
bit3:EESAVE = 1 EEPROMは未保護
bit2:BODLEVEL2 = 1
bit1:BODLEVEL1 = 1
bit0:BODLEVEL0 = 0 => 1.8Vでリセット -
L=0xFF -> 0xF7
bit3210=1111は12MHzの設定。
ほかは
http://qiita.com/takeru@github/items/b6bd851ed8727d6c8862
と一緒なので0xF7にする。
bit7:CKDIV8 = 1 8分周しない
bit6:CKOUT = 1 クロック出力しない
bit5:SUT1 = 1
bit4:SUT0 = 1 => 遅い起動(=安定)
bit3:CKSEL3 = 0
bit2:CKSEL2 = 1
bit1:CKSEL1 = 1 => 0.4-20MHz 全振幅発振器
bit0:CKSEL0 = 1 => 外部クリスタル -
まとめ ext=0x07 H=CE L=F7
% avrdude -C /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf -P /dev/tty.usbserial-A9005bvI -c avrisp -p m88p -b 19200 -U lfuse:w:0xF7:m -U hfuse:w:0xCE:m
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.06s
avrdude: Device signature = 0x1e930f
avrdude: reading input file "0xF7"
avrdude: writing lfuse (1 bytes):
Writing | ################################################## | 100% 0.06s
avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xF7:
avrdude: load data lfuse data from input file 0xF7:
avrdude: input file 0xF7 contains 1 bytes
avrdude: reading on-chip lfuse data:
Reading | ################################################## | 100% 0.02s
avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: reading input file "0xCE"
avrdude: writing hfuse (1 bytes):
Writing | ################################################## | 100% 0.02s
avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xCE:
avrdude: load data hfuse data from input file 0xCE:
avrdude: input file 0xCE contains 1 bytes
avrdude: reading on-chip hfuse data:
Reading | ################################################## | 100% 0.02s
avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: safemode: Fuses OK
avrdude done. Thank you.
hex書き込み
% avrdude -C /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf -P /dev/tty.usbserial-A9005bvI -c avrisp -p m88p -b 19200 -U flash:w:cdcio.hex
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.06s
avrdude: Device signature = 0x1e930f
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "cdcio.hex"
avrdude: input file cdcio.hex auto detected as Intel Hex
avrdude: writing flash (3686 bytes):
Writing | ################################################## | 100% 6.47s
avrdude: 3686 bytes of flash written
avrdude: verifying flash memory against cdcio.hex:
avrdude: load data flash data from input file cdcio.hex:
avrdude: input file cdcio.hex auto detected as Intel Hex
avrdude: input file cdcio.hex contains 3686 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 4.27s
avrdude: verifying ...
avrdude: 3686 bytes of flash verified
avrdude: safemode: Fuses OK
avrdude done. Thank you.
だめ
"コンソール"に
2014/05/15 13:42:16.000 kernel[0]: USBF: 87733. 18 The IOUSBFamily is having trouble enumerating a USB device that has been plugged in. It will keep retrying. (Port 4 of Hub at 0x1d110000)
2014/05/15 13:42:16.000 kernel[0]: USBF: 87733. 18 The IOUSBFamily was not able to enumerate a device.
こんなログが繰り返しでている。なにかだめっぽい。
ビルド済みのcdcio88.hexでやってみる
クリスタルは12MHzに変更。fuseもL=0xFFで、全てデフォルトの設定。
2014/05/15 14:21:35.000 kernel[0]: AppleUSBCDCACMData: Version number - 4.2.1b5, Input buffers 8, Output buffers 16
2014/05/15 14:21:35.000 kernel[0]: AppleUSBCDC: Version number - 4.2.1b5
2014/05/15 14:21:35.645 UserEventAgent[289]: add service for USB-PIO
OKっぽい反応。
% ls -l /dev/tty.*
crw-rw-rw- 1 root wheel 18, 0 5 14 01:01 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw- 1 root wheel 18, 2 5 14 01:01 /dev/tty.Bluetooth-Modem
crw-rw-rw- 1 root wheel 18, 42 5 15 14:26 /dev/tty.usbserial-A9005bvI
% ls -l /dev/tty.*
crw-rw-rw- 1 root wheel 18, 0 5 14 01:01 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw- 1 root wheel 18, 2 5 14 01:01 /dev/tty.Bluetooth-Modem
crw-rw-rw- 1 root wheel 18, 56 5 15 14:30 /dev/tty.usbmodem1d1141
crw-rw-rw- 1 root wheel 18, 42 5 15 14:26 /dev/tty.usbserial-A9005bvI
接続すると、"/dev/tty.usbmodem1d1141"というのが増える。
しかし、コマンドには反応なし。
screen /dev/cu.usbmodem1d1141 9600
とか
screen /dev/tty.usbmodem1d1141 19200
して"@"を送っても反応しない。
ドライバ入れ替え
「AppleUSBCDC tty」で検索すると
http://www.omiya-giken.com/?page_id=1196
が見つかった。
(入れ替える前)
# kextstat | grep USBCDC
183 0 0xffffff7f8264d000 0x4000 0x4000 com.apple.driver.AppleUSBCDC (4.2.1b5) <35 4 3>
184 0 0xffffff7f826c8000 0x4000 0x4000 com.apple.driver.AppleUSBCDCACMControl (4.2.1b5) <35 4 3>
185 0 0xffffff7f826cc000 0x7000 0x7000 com.apple.driver.AppleUSBCDCACMData (4.2.1b5) <119 35 5 4 3>
(入れ替えた後)
% kextstat | grep USBCDC
189 0 0xffffff7f8264d000 0x3000 0x3000 com.apple.driver.AppleUSBCDC (3.1.4) <119 35 5 4 3>
190 0 0xffffff7f826c8000 0x7000 0x7000 com.apple.driver.AppleUSBCDCACMControl (3.1.4) <119 35 5 4 3>
191 0 0xffffff7f826cf000 0x9000 0x9000 com.apple.driver.AppleUSBCDCACMData (3.1.4) <119 35 5 4 3>
192 0 0xffffff7f826d8000 0x5000 0x5000 com.apple.driver.AppleUSBCDCECMData (4.2.1b5) <41 35 5 4 3 1>
結局だめ。元に戻した。
Macのドライバが悪いの? → ハブでした。
Raspberry PI + ハブでOK.
MacBook Airの直接接続でOK.
ハードの組み合わせでOK/NGがある。
iMac Direct : OK
iMac + Hub(U2H-TM410BWH) : NG
MacbookAir Direct : OK
Raspberry PI + Hub(U2H-TM410BWH) : OK
http://www.recursion.jp/avrcdc/faqj.html
ここにちゃんと書いてありました。
USB2.0のポートにUSB2.0のハブをつけてAVR-CDCはうまく動かない。
直接接続 or USB1.1のハブを挟むといいらしい。
でも、Raspberry PIはハブ経由でOK直接はNGだ。
信号の電圧の違いだったりするのか、ソフトウエア的な問題なのか?よくわからないなあ。
lsusb -v
...
Bus 001 Device 006: ID 16c0:05e1 VOTI CDC-ACM class devices (modems)
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 2 Communications
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x16c0 VOTI
idProduct 0x05e1 CDC-ACM class devices (modems)
bcdDevice 1.00
iManufacturer 1
iProduct 2
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 67
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 1.10
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
CDC Call Management:
bmCapabilities 0x03
call management
use DataInterface
bDataInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 255
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 0
ソフトウエア
とりあえず、動くハードウエアがわかったのでソフトウエア側を進める。
- 何も変えずにmega88でmake 88pに書き込み → OK
- 最新のv-usb + mega88でmake → OK
- 最新のv-usb + mega88pでmake → OK
- 最新のv-usb + mega88p + 20MHzでmake → OK
規格外
host側が/dev/tty*を読み書きするだけなのでお手軽なのだがハブやポートの組み合わせで動かないというのはなんだかなあ。
- http://www.recursion.jp/avrcdc/indexj.html
- 「Low-Speed での 3つのエンドポイント生成とバルク転送は規格外の動作となる」
- 「ロースピードのバルク転送モードは新 OS では動かせなくなりつつあります。USB 技術の実験材料として楽しんだ後は、HID モードで使うか、コントローラ内蔵マイコンに移行してください。」
- http://vusb.wikidot.com/usb-device-classes
- "Consumes ca. 90% or more of the AVR's CPU time because bulk endpoints are polled aggressively by the host. Real-time applications on the AVR are close to impossible."
- https://github.com/larskanis/libusb
- LIBUSB is a Ruby binding that gives Ruby programmers access to arbitrary USB devices.
HIDを試してみよう。
まとめ
- 遠回りしたけどUSBデバイスをつくることに成功
- 規格外なので動いたり動かなかったりするのがいまいち
- HID+Ruby+libusbを試してみたい
つづき→ http://qiita.com/takeru@github/items/42873e1a7e0aef830eea