Help us understand the problem. What is going on with this article?

USBデバイスをつくってみたい(1) シリアルポートのようなデバイス編

More than 5 years have passed since last update.

AVR-CDC

http://www.recursion.jp/avrcdc/cdc-ioj.html

  • 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_IOM88PH_"

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

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away