Previous Post | Top | Next Post |
TOC
基本のUSB AVRのATmega32u4と
AT90USB1286
を中心としたAVRチップに関して、ブートローダー関係を、1年半2年ぶりに見直し書きます。
開発環境
ATmega328P (2)の開発環境を再現すればOKです。
USB系のAVRで、変数名等の細かなところにとにかく疑問が出れば、/usr/lib/avr/include/
以下を見れば分かります。。
/usr/lib/avr/include/avr/iom32u4.h
– teensy2.0 (ATmega32u4)/usr/lib/avr/include/avr/iousb1286.h
– teensy2.0++ (AT90USB1286)
FUSEビットのSET
FUSEビットは、プログラム設定されると「0」で、プログラム解除されると「1」です。 不揮発メモリーのリセット状態が1なので、こうされている理屈は分かるのですが、通常のPIN信号電位等と逆で混乱します。
- プログラム設定(条件合致) = 対応ビット 0
- プログラム設定(条件不合致) = 対応ビット 1
電源投入時ちゃんとファームウエアーが立ち上がるには、BOOTRSTは1にして application reset (address 0x0000)としないといけません。 (BOOTRSTは0だと Reset vector = boot loader resetとなり、メモリー末尾に行きます。)
FUSEの設定変更(JTAG)
FUSEの設定変更は当然ですが要注意です。 よく考えずにJTAGをENABLEしたら、一部GPIOピンが動作しなくなって驚きました。
BOOT MODE (HWBE)のこと
USB系のAVRの起動の基本確認事項として、BOOTのモードの状況を確認します。
ARDUINO LEONARDO やTEENSY系の基板のPE2 (ALE,/HWBE)では、1K等で接地されています。だから、実際に出会うボードのリセットボタンが押された際のBOOT挙動は以下です。
- 通常PE2は接地電位なので、リセットを押したらHWBEヒューズがON(0)にされてると、ブートローダーの起動となる。
- 強引にPE2(ALE)をVCCに繋いだ状態で、リセットだとHWBEヒューズ設定によらず、アプリファームが起動する。(その間1Kに電気が5mAも流れますが。)
- HWBEがOFF(1)の場合、PE2によらず常にアプリファームが起動する。
ISP接続によるMCUのプログラミング
AVR-ISP II等を使うと、ブートローダーも何もない状態ででもISP接続でMCUに直接プログラム書き込みができます。
- http://ww1.microchip.com/downloads/en/Appnotes/doc2568.pdf
- http://ww1.microchip.com/downloads/en/AppNotes/doc1644.pdf
ブートローダーの書き換えにはこれを使います
確実ですが、接続が面倒でICピンを占領するので、定常的使用にはむきません。
TEENSY系でのISP接続でのブートローダー書き込み接続
TEENSY系はARDUINOのようなISP接続でのブートローダー書き込み専用コネクターはついていません. だから、AVRISP2から出ているケーブル端の以下のようなコネクター穴に、PIN-PINのアダプターを差し込みます。 (私の場合クリップケーブル端のデュポンコネクターの横穴はフラットケーブルの方向に向けてつけている。写真参照) 接続はこのPIN-PINのアダプター経由で連結したクリップをボード端の穴へ繋ぐのが簡単のようです。
つまり、私のアダプターは:
- female connector on flatcable end from AVRISP2 (hole view)
- male-male adapter PINs (top view) (used for connect to clip wires)
================= (RED LINE)
FLAT CABLE ====== YELLOW 2 - VCC * * 1 - MISO RED
FLAT CABLE ====== BLACK 4 - MOSI * * 3 - SCK GREEN
FLAT CABLE ====== BLUE 6 - GND * * 5 - RESET WHITE (w/yellow clip)
この接続先は以下です。
TEENSY 2.0 (TOP VIEW)
MINI
USB
+---+-----+---+
GND |* | | *|Vcc
PB0 |* | | *|PF0 ADC0
SCLK 3 GREEN ------ PB1 |@ | | *|PF1 ADC1
MOSI 4 BLACK ------ PB2 |@ +-----+ *|PF4 ADC4
MISO 1 RED -------- PB3 |@ * * *|PF5 ADC5
PB7 |* *|PF6 ADC6
PD0 |* *|PF7 ADC7
PD1 |* *|PB6 ADC13
PD2 |* *|PB5 ADC12
PD3 |* *|PB4 ADC11
PC6 |* *|PD7 ADC10
PC7 |* * @ @ @ * *|PD6 ADC9 (LED) -- low V for analog
+-------------+
^ ^ ^ ^ ^
PD5 ---+ | | | +---PD4 ADC8
VCC 2 YELLOW ----------------+ | |
GND 6 BLUE ------------------+ |
RST 5 WHITE --------------------+
TEENSY 2.0++ (TOP VIEW)
MINI
USB
+---+-----+---+
GND |* | | *|Vcc
PB7 |* | | *|PB6
PD0 |* | | *|PB5
PD1 |* +-----+ *|PB4
PD2 |* @|PB3 ---- RED 1 MISO
PD3 |* @|PB2 ---- BLACK 4 MOSI
PD4 |* @|PB1 ---- GREEN 3 SCLK
PD5 |* *|PB0
(LED) PD6 |* *|PE7
PD7 |* *|PE6
PE0 |* *|GND
PE1 |* *|AREF
PC0 |* *|PF0
PC1 |* *|PF1
PC2 |* *|PF2
PC3 |* *|PF3
PC4 |* *|PF4
PC5 |* *|PF5
PC6 |* *|PF6
PC7 |* @ @ @ *|PF7
+-------------+
^ ^ ^
| | |
VCC 2 YELLOW ----------------+ | |
GND 6 BLUE ------------------+ |
RST 5 WHITE --------------------+
ここで、ボードの横の配線取り回しの順番は時計回りで見ると両者同じですが、 コネクター側から見た順番が逆です。間違って繋ぐと、毎回IDが違うと言われて 正しくないが同じIDが読み出されるのでノイズ問題じゃないようで頭を抱え込みました。 後でつなぎ違いに気づいたときは、こわれそうにない間違いでほっとしましたが。。。
TEENSY系でのISP接続でのブートローダー書き込みプログラム
各種ブートローダーを、ISP接続でATmega32u4やAT90USB1286に導入しFUSE設定もする
スクリプトを作成しました。一式を、
https://github.com/osamuaoki/osamuaoki-hugo-proj の
中の005_teensy
以下に起きます。その中で./setup-teensy
とすると、作業環境が準備でるようにしました。
さて、まず./avrdude...
コマンドでavrdudeを使い、完全なチップの初期化のためにISP接続してFUSE設定とブートローダーの導入をします。
- TEENSY 2.0 (atmega32u4) には、自作の
nanoBoot.hex
を導入 (nanoBoot w/LED) - TEENSY 2.0++ (at90usb1286) には、QMKから落とした、
bootloader_at90usb128_1.0.1.hex
を導入
NOTE: 上記写真で、評価ボードに一見電源供給をしていないように見えますが、使用したAVR-ISP IIは以前書いたように改造済みですのでちゃんと電源は来ています。 改造しない純正品のままだと、別途USBケーブルを繋ぎ、それをUSB電源アダプターにでも繋ぐ必要があります。
ブートローダーによるMCUのプログラミング
通常のファームウエアー書き換えは、すでに書き込まれたブートローダーを使うのが便利です。
ブートローダー起動時にUSB接続されたデバイスがどういうデバイスとしてホストに認識されるかにより、USB AVRのブートローダーには基本3種類のケースがあります。
- CDC ブートローダー: シリアルデバイス
- Arduino Leonardo等で使用(いわゆるARDUINO UNOのようなシリアルインターフェース経由のファームウエアーの書き込み)
avrdude -c arduino
- DFU ブートローダー: DFUデバイス
- Arduino UNOで、USB-SERIAL変換機能を提供するサブMCUに使用、Atmel出荷時のデフォルト。
FLIP
というのは、このモードを利用するATMEL提供のWINDOWSホストのツール- FLIP USB DFU protocol version 1 (doc7618): Atmel mega AVR with USB series (Also 8051)
- FLIP USB DFU protocol version 2 (AVR4023): Atmel AVR XMEGA and UC3 series – 関係なし
- ホスト側:
dfu-programmer
が一番古くからあるLINUXホスト上のツール。DFU 1 - ホスト側:
avrdude -c flip1
でも動くはず
- HID ブートローダー: キーボードデバイス
- Teensy等で使用(プロプライエタリー)
- LUFAは少し大きいが、ソースが公開(GPL)
- ホスト側:
hid_bootloader_cli
(LUFA用, NanoBoot用) USB VID/PID = Atmel対応(LUFA, NanoBootも同様) - ホスト側:
teensy_loader_cli
(Official teensy用) USB VID/PID = pjrc.com対応
結論から言うと、MCUに入れるブートローダーとホスト側のツールは以下です:
- MCUに入れるブートローダー
- atmega32u4: 512 B に収まる nanoBoot w/ LEDの使用が推奨
- at90usb1286: 4096 B に収まる、私が手を加えたLUFA系HID ブートローダー (QMKのHID BOOTLOADERと似ているはず)
- ホスト側のツール
hid_bootloader_cli
- HID経由のUSB経由でのファームウエアの更新の際はプロンプトがあり、RESETを押しブートローダーを起動するように要求がありますます。
- PC側でターミナルを開き、
journalctl -f
かsudo dmesg --follow
等としてPCのカーネル挙動を観察しブートローダーとして立ち上がったデバイス認識の確認という対応でもできます。 - ブートローダーがここで作ったLED対応のnanoBootだとLEDがつくことでUSBデバイスが認識されたことが簡単に分かります。意外とコネクタの接触不良もあり、このLED機能良いです。
動作検証
基本、ファームウエアーを導入し動作させて確認するのが一番です。
- BLINKのファームウエアー("./setup-teensy"実行)
- シリアル接続モニタープログラム
TEENSY 2.0 の動作検証メモ
実験的にTEENSY2.0で確認したのは以下です。電圧印加にはVR等をPIN二つないでます。
- デジタル入力は、1.4Vぐらいが閾値の様でした。
- 内部プルアップをしないとPINの読みとり値は、当たり前ですが暴れます。
- 内部プルアップに対して、外部プルダウンは、10KΩだと1VでLOW、100KΩだと3.7VでHIGHでした。
- アナログも入力がつながってないと暴れます。LEDにつながっているD6は、ほぼ0Vでした。
手動配線キーボードの配線確認メモ
このあと触れるQMKを動かす用に準備した手動配線キーボードの配線確認をしました。
まず、基板上のLEDの動作を確認します。(avrmon: B D6 OH
)
過電流にならないように、LEDを消します。(avrmon: B D6 OL
)
キーボードのハンド配線の場合、トラブルしがちです。実際1つ断線がありました。
ダイオードの方向がCOL2ROW
の場合の待機状態は:
- ROW: OUTPUT with normally HIGH (avrmon:
B ?? OH
) - COL: INPUT with PULL-UP (avrmon:
B ?? IH
)
この状態では、スイッチを押しても入力変化(DC)はありません。
次に、COLUMN配線のチェックをするために、ひとまず全ROWをHIGH選択します。
- ROW: OUTPUT with normally HIGH (avrmon:
B ?? OL
for all rows)
この場合、同じCOLUMNのキーは区別できませんが、COLUMNに対応するBITがLOWになるので、スイッチ操作でスイッチの動作が確認できます。(DC)
私の場合、題6COLUMNが変化しませんでした。MCUボード上の対応ピンはMCUのPULL-UPが有効なので5Vきっちり出ますが、その先の電圧が0付近でばたばたしています。
問題ピンに繋がった配線をキーボードから切り離し電圧を測ってもまともに電圧が出ません。
どうも、C3の芋はんだか途中断線です。
次に、ROW配線のチェックをするために、ひとまず全ROWをLOW選択します。
そして、1つのROWだけをHIGH選択し対応するROWにあるキースイッチを押すとCOLUMN側に変化があることを確認します。 さらに、関係のないキースイッチを押してもCOLUMN側に変化がないことを確認します。
最後に、LEDの動作と明るさの確認をします。
各種ブートローダの状況確認メモ
Arduino系のブートローダー
Arduinoのブートローダー
ARDUINOは元々シリアル接続して書き換えます。USB-SERIAL変換接続が、ARDUINO UNOボードではFT232のような専用変換チップではなくサブMCUとなるATmega32u2に使われています。
キーボードプロジェクトを考えるので、シリアルに見えるArduinoのブートローダーあまり優先順位は高くありませんが、状況を確認します。
現在巷にあふれるARDUINOもどきは、FT232をUSBシリアル専用変換に使っていたARDUINO UNO の前世代の設計ベースで、FT232をよりやすいCH340に使っています。
こんなARDUINOもどきも含め、すべてのARDUINO UNOやARDUINO MINIのような、ATmega328P系のボードはシリアル通信でファームウエアーを書き換えるようになっています。 これはUSBを直接サポートするATmega32u4系のARDUINO MICRO, PRO MICRO、LEONARDOも同じプロトコルで、出荷時シリアル接続(CDC)のブートローダーが導入されています。
REPO:
- 本当のシリアルポートを使う328Pブートローダー: https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/optiboot (小さい)
- USBシリアルデバイスを使うUSB系AVRのCDCブートローダー https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/caterina (中身はLUFA, 4KB)
LUFAは現在 LUFA-170418-125-gd10535a4b
なので当時の11109と違い、LUFAの11109 以降を使うと、
32u4 Caterina はCaterinaをパッチしないとうまく動作しない
などと言う記事もありますが、それからだいぶ経つので2022年の最新版なら大丈夫かな。
ちなみに本物のUNOには、USB-SERIAL変換をするファームウエアーが導入されていたサブMCU(Atmega8u2) が搭載されています。 このサブMCU自体の書き換えにもちいるブートローダーはシリアル変換ファームウエアーとともにArduino Uno and Mega 2560 Firmwares for the ATmega8U2にあります。 これは通常のARDUINOの書き換えで書き込まれないようにブートローダーはDFUです。
Sparkfanの改造版Caterina (4KB) – CDC ブートローダー
- リセットのダブルクリックでのみ、アプリ書き込みモードに8秒間なる。
- リセットのシングルクリックは、即刻アプリのリセットに入る。
REPO:
- https://github.com/sparkfun/Arduino_Boards/tree/main/sparkfun/avr/bootloaders/caterina (2015年)
- https://github.com/jknofe/caterina (with LUFA-111009) (2017年)
Sparkfanの改造版Caterinaはいい感じのCDCですが、TeensyのLEDに対応するものがなかったので、リビルドはトライしていません。
Katiana (4KB) – CDC ブートローダー
googleで興味ある、フォーラムへのポスト を見つけました。 LUFAの2017ごろをベースに、Arduinoの改変を含め、USBシリアル番号等を含めた各種独自改造 をしています。 カウントダウンすることで、クロックのプリスケーリングを 1:1以外に設定することにも対応し、そえでも4KBに収まっ ているそうです。ただAtmega32u4専用だそうです。 GCC 5.4対応のPRは要チェックです。
REPO:
TeensyのLEDに対応するものがなかったので、リビルドはトライしていません。
LUFA (4KB each) – CDC, DFU, HID ブートローダー
LUFAはCDC, DFU, HID の3種類すべてのブートローダーを提供しています。
最新のLUFAベースで私がPRしたLUFAのブランチを、さらにBUILD用にパラメーター変更し 生成したHEXやビルドログもコミットしたLUFAのブランチを作りました。
ビルドは以下のような感じで終わります。これが実際のAVR上のメモリサイズのようです。(Hexファイルに普通のsizeコマンドすると少し大きな数字がでる。)
...
avr-size --mcu=atmega32u4 --format=avr BootloaderCDC.elf
AVR Memory Usage
----------------
Device: atmega32u4
Program: 3846 bytes (11.7% Full)
(.text + .data + .bootloader)
Data: 164 bytes (6.4% Full)
(.data + .bss + .noinit)
[INFO] : Finished building project "BootloaderCDC".
すべてのビルド結果をまとめると以下で、いずれも4KBのブート領域確保が必要でした。
Program | Data | board | mcu | bootloader | programmer |
---|---|---|---|---|---|
3846 | 164 | teensy2 | atmega32u4 | BootloaderCDC | avrdude -c arduino |
3882 | 133 | teensy2 | atmega32u4 | BootloaderDFU | dfu-programmer |
2118 | 86 | teensy2 | atmega32u4 | BootloaderHID | hid_bootloader_cli |
3790 | 164 | teensy2pp | at90usb1286 | BootloaderCDC | avrdude -c arduino |
3812 | 133 | teensy2pp | at90usb1286 | BootloaderDFU | dfu-programmer |
2124 | 86 | teensy2pp | at90usb1286 | BootloaderHID | hid_bootloader_cli |
ここで、最近のavrdude
はDFUもサポートしているので、dfu-programmer
とあるところはavrdude -c flip1
としても同じです。
比較的機能が少なく小さいHIDブートローダーでも、わずかではありますが2KBを越えているので、ブート専用領域に4KBを取っておく必要があります。
メモリーが少ないATmega32u4では下記のNanoBoot(512Bに収まる)を使います。
hid_bootloader_cli
LUFAのhid bootloaderに対応する、ホストPC側のプログラムです。
Debianでコンパイルするには、libusb-dev
パッケージが導入されている
必要があります。
nanoBoot改LED (512B) – HID ブートローダー
元々のnanoBoot は512 Byteに収まる小さな優れものBootloaderです。これは LUFA HIDブートローダーを徹底的にハンドオプティマイズしたものです。 ただし、オリジナルはCKDIV8と非設定限定で、LEDでの ブートローダーの起動確認もできませんでした。本物の Teensy 2.0 と同じFUSE設定では使えませんでした。それにつけても 非常に丁寧にコメントが書き込まれているアッセンブラーの 手動最適化手法が満載の素晴らしいコードとコメントでした。
自分が欲しい機能のCKDIV8対応と、LED点灯でのブートローダー の起動確認を何とか押し込むように、限られたスペースに押し込む パズル感覚のコーディングでしました。更にコード縮小をし、 sigprof さんが途中までしていた「String Descriptor」にも対応をしながら 512 Bに収まるようになりました。アップストリームにはまだマージ されていません。この導入には私がフォークしPRしている 私のnanoBootを参照ください。
すでに以前sigprof提案の アップロードサイズ制限はマージされているので、512Bに収まる範囲で かなり機能の良いbootloaderとなっていると思います。
これで中華コンパチ評価ボードを本物の Teensy 2.0 でも本物と同じユーザー向けのメモリー量を確保して使えます。
私のレポの、led branchに私のソースの最新版を、led-hex branchに最新版の コンパイル結果のHEXファイル集 までコミットしています。
各種ブートローダーの比較
QMKを導入すると、同時にAVR開発環境も整えられ、よさそうなブートローダーも拾ってきてくれます。
メモリーがタイトなatmega32u4は上記のnanoBootが良いと思いますが、AT90USB1286は余裕があるので選択肢があります。でも一筋縄ではいきませんでした。
- ISP経由でのプログラムは可能は確認済 (定常的使用にはコネクター設置が課題)
- nanoBoot移植は、PLL関係の変更だけではできません。どうもフラシュメモリーが8 bit変数を使っているところでオーバフローします。-> 断念
- 自分でコンパイルしたLUFA改のLEDブリンク付HIDブートローダー(4KB)。-> 推奨
- QMKのHIDはLED機能付だそうだが、ホストプログラムは分かったけど、肝心のファームウエアーのソースやHEXがどこにがあるのか?-> 断念
- DFUブートローダー (8KB) (QMK) https://github.com/qmk/qmk_firmware/tree/master/util -> 無駄に大きい
余談:DFU色々
DFUにはATmel専用みたいで古くからあるdfu-programmer
があります。
これ以外に、DFU 1.0 and DFU 1.1specifications対応でSTM32対応しているdfu-util
もあります。
どうも一番新しいfwupd
に入っていてDFU 1.0, DFU 1.1 にくわえ ST DfuSe vendor
extensionに対応しているdfu-tool
があります。この辺、基本AVRはdfu-programmer
でいきます。
ここで、DfuSe
が"DFU STによるVender Extension(ベンダー拡張)“の略と分かりちょっと納得。
STM32系のARMチップの際にでも他の2つは使ってみます。
Previous Post | Top | Next Post |