ぽよメモ

ファッション情報学徒の備忘録.

macOS Catalinaでavrdudeを使ってProMicroに書き込もうとするとprogrammer is not respondingというエラーが出る

はじめに

 これは2019/11/4現在の情報です.macOS10.15よりも新しいバージョンでは当てはまらない可能性があります.何か更新があれば,コメントを頂けると幸いです.

何が起きた?

 QMK Firmwareを知らない自作キーボード界隈は居ないと思いますが,ファームウェア

  1. Docker環境でビルド→avrdudeを直接叩いて書き込み
  2. make キーボード名:キーマップ名:avrdudeでビルド & 書き込み

のどちらの方法でも,ProMicroに大して書き込みが出来なくなってしまいました.具体的には下記の様なエラーが出ます(Docker環境でビルドしたhexファイルを書き込もうとしていました).

$ sudo avrdude -p atmega32u4 -c avr109 -P /dev/tty.usbmodem142101  -U flash:w:.build/choco60_pudding.hex

Connecting to programmer: .avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding

avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: ser_drain(): read error: Device not configured
avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
Found programmer: Id = ""; type =
    Software Version = .; Hardware Version = .
avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: error: buffered memory access not supported. Maybe it isn't
a butterfly/AVR109 but a AVR910 device?
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: error: programmer did not respond to command: leave prog mode
avrdude: ser_send(): write error: Device not configured
avrdude: ser_recv(): read error: Device not configured
avrdude: butterfly_recv(): programmer is not responding
avrdude: error: programmer did not respond to command: exit bootloader
avrdude: ser_close(): can't reset attributes for device: Device not configured

avrdude done.  Thank you.

最初はリセットスイッチの押し忘れ・タイミング外れなど色々と検討しましたが,最終的に下記のIssueにたどり着き,Catalinaの問題であることが分かりました.

github.com

純粋にOS側での問題があるらしく,QMK Firmwareやavrdude側でどうにかすることが難しい事が伝わってきます.が,コメントでVirtualBox経由だと上手くいったといった内容が見受けられるので,じゃあVagrantでビルド環境ごと隔離すれば良いじゃんと思い,試してみました.

環境

以下の様な環境で試しています.

手順

1. QMK Firmwareをクローン

 forkして使っている人や,既にローカルに持っている人はそれぞれ自分の環境に置き換えてください.最終的にローカルにリポジトリがあり,そのパスが分かれば良いです.ここでは適当にユーザのホームディレクトリ以下にcloneしたとして以降の手順を行います.

$ pwd
/Users/ユーザ名
$ git clone --recursive https://github.com/qmk/qmk_firmware

2. VagrantVirtualBoxのインストール

 Homebrew Caskでインストールします.Extension Packとバージョンを合わせる必要があります.もしVirtualBoxだけ先にインストールしており,Extension Packのインストールに失敗する場合,先にbrew cask upgrade virtualboxする必要があるかも知れません.

$ brew cask install \
    vagrant \
    virtualbox \
    virtualbox-extension-pack

Guest Additionsの自動更新プラグインをインストールします.

$ vagrant plugin install vagrant-vbguest

Guest Additionsを更新する

$ vagrant vbguest

僕はこの辺りで一度再起動を挟みました.

3. ProMicroデバイスの情報を確認

 USBケーブルでProMicro(を実装した自作キーボード)とMacを接続します.VirtualBoxではUSBデバイスを仮想環境から扱うために,パススルーを許可するデバイスホワイトリスト方式で許可する必要があります.そのためにプロダクトIDやベンダーIDを控える必要があります.VboxManageコマンドを使って確認します.

$ VBoxManage list usbhost
Host USB Devices:

UUID:               b8bdff28-b707-43f1-8340-51e9943f74f7
VendorId:           0x2341 (2341)
ProductId:          0x8037 (8037)
Revision:           1.0 (0100)
Port:               1
USB version/speed:  0/Full
Manufacturer:       Arduino LLC
Product:            Arduino Micro
Address:            p=0x8037;v=0x2341;s=0x000008828f96a793;l=0x14210000
Current State:      Busy

# 以下略

VendorIdとProductIdをメモります.次に,リセットスイッチを押して書き込み可能状態にします.このとき,ProductIdが変化するので,これもまたメモります.

$ VBoxManage list usbhost
Host USB Devices:

UUID:               b8bdff28-b707-43f1-8340-51e9943f74f7
VendorId:           0x2341 (2341)
ProductId:          0x0037 (0037)
Revision:           0.1 (0001)
Port:               1
USB version/speed:  0/Full
Manufacturer:       Arduino LLC
Product:            Arduino Micro
Address:            p=0x0037;v=0x2341;s=0x000008828f96a793;l=0x14210000
Current State:      Busy

# 以下略

これを次の手順でVagrantfileに記述します.

4. Vagrantfileを用意

適当なディレクトリ(ここでは$HOME/qmk_vagrantとする)に,以下の内容をVagrantfileとして配置します.

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|

  config.vm.box = "hashicorp/bionic64"
    
  config.vm.provider "virtualbox" do |v|
    # USBデバイスのパススルーを許可
    v.name = "VM to flash firmware into ProMicro"
    v.customize ["modifyvm", :id, "--usb", "on"]
    v.customize ["modifyvm", :id, "--usbehci", "on"]
    # 以下にパススルーを許可するデバイスの情報(vendoridとproductid)を書く
    # nameは単に識別のためなので特に気にしないで良い
    v.customize ["usbfilter", "add", "0",
                 "--target", :id,
                 "--name", "Arduino Micro (writable)",
                 "--vendorid", "2341",
                 "--productid", "0037",
                 "--remote", "no"]
    v.customize ["usbfilter", "add", "1",
                 "--target", :id,
                 "--name", "Arduino Micro",
                 "--vendorid", "2341",
                 "--productid", "8037",
                 "--remote", "no"]
  end

  # ここを環境に合わせて書き換える
  config.vm.synced_folder "/Users/ユーザ名/qmk_firmware", "/qmk_firmware"
  config.vbguest.auto_update = true

  # avrdudeとQMK Firmwareのビルドツール一式を揃える
  config.vm.provision "shell", privileged: false, inline: <<-SHELL 
    sudo apt-get update
    sudo apt-get install -y python3-pip avrdude
    /qmk_firmware/util/qmk_install.sh
   SHELL
end

5. ProMicroをMacから抜く

 USBケーブルで繋いでいたProMicroを抜きます.その方が安定しました.

 おそらくmacOS側でビジーだと,VirtualBoxのゲストOS内にうまくマウントできないのだと思います.

6. vagrant upで仮想環境を起動

 前の手順で用意したVagrantfileのあるディレクトリで以下のコマンドを実行します.

$ vagrant up

これで無事仮想環境が起動するのを待ちます.色々なインストールを含むので,多少時間がかかります.起動したらsshして仮想環境へ接続します.

$ vagrant ssh
# USBデバイスを確認
(guest) $ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

7. 再びUSBで接続し,書き込む

 再びUSBケーブルでMacとProMicroを接続します.以降の手順ではリセットスイッチを押す度にゲストOSが一瞬止まったように感じます.操作は反映されるので,焦って適当にコマンドを打たないようにしましょう.

 リセットスイッチを押して書き込み可能状態にしてlsusbしてみます.

(guest) $ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 003: ID 2341:0037 Arduino SA
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

/dev/ttyACM0が見えれば成功です.割とすぐ消えてしまうので,見えなくても焦らず再びリセットスイッチを押しましょう.

(guest) $ ls -l /dev/ttyACM0
ls: cannot access '/dev/ttyACM0': No such file or directory
# 1,2回見つからなくても何度か押せば見つかる
(guest) $ ls -l /dev/ttyACM0
crw-rw-rw- 1 root dialout 166, 0 Nov  3 15:30 /dev/ttyACM0

ここまで見えていればほぼ勝利です.ここから先は自分でavrdudeで書き込むのも,makeに任せるのもなんとかなります.

# /qmk_firmwareに移動
(guest) $ cd /qmk_firmware
# ファームウェアをビルドして書き込み
(guest) $ sudo make choco60:default:avrdude
QMK Firmware 0.7.54
Making choco60 with keymap default and target avrdude

avr-gcc (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Size before:
   text    data     bss     dec     hex filename
      0   16012       0   16012    3e8c .build/choco60_default.hex

Copying choco60_default.hex to qmk_firmware folder                                                  [OK]
Checking file size of choco60_default.hex                                                           [OK]
 * The firmware size is fine - 16012/28672 (55%, 12660 bytes free)
Detecting USB port, reset your controller now...................
# ここでリセットスイッチを押してしばらく待つ
Device /dev/ttyACM0 has appeared; assuming it is the controller.
Waiting for /dev/ttyACM0 to become writable.

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9587 (probably m32u4)
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 ".build/choco60_default.hex"
avrdude: input file .build/choco60_default.hex auto detected as Intel Hex
avrdude: writing flash (16012 bytes):

Writing | ################################################## | 100% 1.97s

avrdude: 16012 bytes of flash written
avrdude: verifying flash memory against .build/choco60_default.hex:
avrdude: load data flash data from input file .build/choco60_default.hex:
avrdude: input file .build/choco60_default.hex auto detected as Intel Hex
avrdude: input file .build/choco60_default.hex contains 16012 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 1.13s

avrdude: verifying ...
avrdude: 16012 bytes of flash verified

avrdude: safemode: Fuses OK (E:FB, H:D8, L:FF)

avrdude done.  Thank you.

手動でavrdudeコマンドを使って書き込む場合,以下の様にします.

$ sudo avrdude -p atmega32u4 -c avr109 -P /dev/ttyACM0 -U flash:w:hexファイルへのパス

直接 /dev/ttyACM0を指定するのですが,見つからない場合以下の様にエラーが出ます.

$ sudo avrdude -p atmega32u4 -c avr109 -P /dev/ttyACM0 -U flash:w:.build/choco60_pudding.hex
avrdude: ser_open(): can't open device "/dev/ttyACM0": No such file or directory

avrdude done.  Thank you.

リセットスイッチを押してからこのデバイスファイルが出現するまでラグがあるので,落ち着いて数回実行してください.

うまくいかないとき

 最初全くうまくいかなかったのですが,あるとき急に上手くいくようになったので正直これはかなり再現性の低い手順なのではないかと思っています.ただいくつかポイントはあるかなと思っています.

  1. macOS側でProMicroに触らない(ビジー状態にしない)
  2. vagrant upする前に一旦USB接続を切断し,ゲストOS起動後に接続し直す
  3. リセットスイッチを押してからは失敗しても2,3回やり直す
  4. とりあえず再起動する

正直macOS Catalinaにアップデートしない or WindowsLinux等の他のOSを使用する方が絶対良いと思います(真顔).

まとめ

この記事の手順は丸1日の試行錯誤を圧縮・整理した内容になっています.足りていない手順や余計な手順を含む可能性があることに留意してください.

 早く修正されることを祈っています.それでは良きキーボードライフを.