ZMKドングルでXiao以外のモジュールを使用するときのあれこれ
用意するもの
-
ハードウェア
- nRF52840 搭載のハードウェアモジュール(技適認証済みのもの)
- デバッグアダプタ(今回はST-LINK)
- SWD配線用のジャンパー線(SWDIO, SWCLK, GND, VDD)
-
ソフトウェア
- Bootloader(HEXファイル)
- ZMKファームウェア(UF2ファイル)
- MSYS MINGW64 (Windows11環境)
- ST-LINK のドライバ(開発環境にインストール)
- OpenOCD(ST-LINK利用時)
以下詳細
ドングルの選定
nRF52840 SoC使用のもので技適付きのものから選ぶ.
今回選んだのはこれ:nRF52840 MDBT50Q 開発用USBドングル
Type-Cコネクタのものもある:nRF52840 MDBT50Q 開発用USBドングル(Type-Cコネクタ)
上記2つがおすすめな理由:
- 技適認証を得ている.
- 国内(SWITCH SCIENCE)で買える.
- オープンソースな UF2 Bootloader でサポート対象(非対象だと結構面倒).
- すでにZMKのボード定義がある(公式ではないが,ZMKモジュールとして).
その他デバイス
上記で買ったもの(Type-Aコネクタ型)は,UF2 Bootloader が書き込まれていない → ファームをDnDできない.
Bootloaderを書き込むために,AmazonでST-LINK V2の互換品を探す.
例えばコレ:ST-LINK V2 互換品
Type-Cコネクタ型は,試していない(PCにType-Cポートがない).
書き込みファイル
Adafruit_nRF52_Bootloader から,最新リリースのBootloaderをダウンロード.
raytac_mdbt50q_rx_bootloader-0.9.2_s140_6.1.1.hex
また,ZMKの Keyboard Dongleに従って生成した,ドングル用のファームウェアも用意する.
分割キーボードの場合,例えば
<your_keyboard>_left.uf2<your_keyboard>_right.uf2<your_keyboard>_dongle.uf2
Bootloader書き込みの後で用意しても良い.
ドングル側のZMKファーム作成方法は後述
書き込みソフト
筆者はWindows11を利用しているので,ターミナルとしてMSYS2 MINGW64を選択した.
今回はST-LINKを利用するので,ST-LINKのドライバを入手する.
SWD(Serial Wire Debug)経由でHEXファイルを書き込むために,OpenOCDをインストールする.
pacman -S mingw-w64-x86_64-openocd
Bootloader書き込み
SWD配線
ドングルのハウジングを開いて,ジャンピングワイヤでST-LINKとSWD接続する.
SWDの配線は,データシート通りに行う.
OpenOCD
ST-LINKをPCのUSBポートに挿す(ドライバインストール済みとする).
ターミナル(MSYS2 MINGW64)で
openocd -f interface/stlink-v2.cfg -f target/nrf52.cfg
-> Listening on port 4444 telnet connections
別のターミナルで
telnet localhost 4444
telnet経由で下記を順に実行する.
> init
> reset halt
> program full/path/of/raytac_mdbt50q_rx_bootloader-0.9.2_s140_6.1.1.hex verify reset
> shutdown
ST-LINKをPCから取り出して,ドングルとのSWD配線を外す.
動作確認
- ドングルをPCのUSBポートに挿す
- ドングルにアプリが書き込まれていない場合,PC に UF2 ドライブが現れる
- UF2ドライブが現れたら,Bootloader書き込みは無事成功
- 現れない場合,次のトラブルシュートを試してみる
トラブルシュート
アプリ領域が書き込まれていると,PCに挿しただけではUF2書き込みモードにならない.
- 一度USBを抜く
- 再度,ドングルの中央ボタンを押した状態でUSBを挿す
- UF2書き込みモードになったら,アプリ領域に書き込みがあるがブートローダは正しくフラッシュされている
- それでもUF2書き込みモードにならなかったら,以下の手順を試して,フラッシュ領域を消去する
telnet経由でhexファイルを書き込む前に,フラッシュメモリを消去する.
> init
> reset halt
> flash erase_address 0x00000000 0x100000
> program full/path/of/raytac_mdbt50q_rx_bootloader-0.9.2_s140_6.1.1.hex verify reset
> shutdown
その他情報
JLinkを用いて,nrfjprogで書き込む際は,こちらが参考になりそう.
Raytac BLEドングル MDBT50Q-RX にブートローダを書き込む
ドングル側のファームウェア
方法1 Github Actions を使う方法
モジュールとして作ってくれている人がいました!
ZMK Raytac USB Dongle Module
READMEのインストラクションに従ってビルドしてみてください.
方法2 ローカルビルド を使う方法
ローカルビルドの詳細は省きますが,公式ドキュメントや先人が詳しく解説してくれています.
- ZMK Firmware/Development/Local Toolchain/Setup/Container
- zmk-workspaceで簡単にZMKファームウェアをローカルビルドする
- WSL+dockerでZMKのローカルビルド環境を構築する
- zmkを使った自作キーボード製作入門 番外編 WindowsでZMKファームウェアをビルドする環境を作る。ローカル環境でビルドが完結すると嬉しいから。
筆者はローカルビルドは初めてだったので,WSL+公式の方法で環境構築した.
ローカルビルドの手順メモ
zmk/app/boards/arm/raytac_mdbt50q_rxフォルダを追加し,ZMKモジュールと同じファイルをその中に追加.
さらに,その他のボード定義と同様に,同じ階層にboard.cmakeを用意.
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
include(${ZEPHYR_BASE}/boards/common/uf2.board.cmake)
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
.
├── Kconfig
├── Kconfig.board
├── Kconfig.defconfig
├── board.cmake
├── raytac_mdbt50q_rx.dts
└── raytac_mdbt50q_rx_defconfig
さらに方法1と同様のファイルを,zmk/app/boards/shields/<your_keyboard>フォルダに追加(下記例).
.
├── Kconfig.defconfig
├── Kconfig.shield
├── <your_keyboard>.dtsi
├── <your_keyboard>.keymap
├── <your_keyboard>_dongle.conf
├── <your_keyboard>_dongle.overlay
├── <your_keyboard>_l.conf
├── <your_keyboard>_l.overlay
├── <your_keyboard>_peripheral.dtsi
├── <your_keyboard>_r.conf
└── <your_keyboard>_r.overlay
あとはドキュメントに従って,UF2ファイルを生成する.
west build -p -d build/your_keyboard/dongle -b raytac_mdbt50q_rx -- -DSHIELD=your_keyboard_dongle
west build -p -d build/your_keyboard/left -b seeeduino_xiao_ble -- -DSHIELD=your_keyboard_left
west build -p -d build/your_keyboard/right -b seeeduino_xiao_ble -- -DSHIELD=your_keyboard_right
UF2ファイルができるので,いったんコンテナからWindowsにコピーする.
docker cp <container name>:/workspaces/zmk/app/build/your_keyboard/dongle/zephyr/zmk.uf2 C:\path\to\windows\local\dongle.uf2
ZMKファームウェア書き込み
あとは通常のZMKファームウェア書き込み手順に従って,ドングル(センター)と左右キーボード(ペリフェラル)にUF2ファイルをDnDする.
つまずいたところ
今回初めての試みとして
- Xiao nRF52840 以外のSoC
- MSYS2の導入
- オープンBootloaderの書き込み
- ZMKローカルビルド
といろいろ手を出したせいで,思った以上につまずきながらの開発となった.
Xiao nRF52840 以外のSoC
ドングルに使用されているボードの定義ファイルを,最初別のものと勘違いしていた.
最初に見ていたのは,zephyr/boards/arm/nrf52840dongle_nrf52840/のフォルダで,これを利用するためにもローカルビルドは必須と思いこんだ.
実際,このファイルを修正して使うのも手段としてはありと思うが,途中でオープンになっているモジュールを見つけたのでそちらに切り替えた.
MSYS2の導入
ターミナル,どれがええねん問題.
今回のはBootloaderがサポート対象でファイルダウンロードすればOKだったが,別件で非対象のものをビルドするのにCMake,makeコマンドが必要で,導入しやさの観点(主観)でMSYS2を選んだ.OpenOCDを導入するのもMSYS2の方が安定するらしい(生成AI調べ).
MSYS2は必要なライブラリを改めてパスに通す必要があり,それすら知らなかったので,「え,Pythonどこ行った?」などが普通に起こり,環境構築でつまずいた.
オープンBootloaderの書き込み
これはわらかないものをわからないまま使ったので,つまずいてすらいない.
全て生成AIの奴隷となってコマンド入力しただけだが,フラッシュメモリ消去→UF2書き込みモードに立ち上がりまでできていたので深堀りしないことにした.
(さすがにflash erase_adressするときは,メモリマップを探した)
ZMKローカルビルド
ZMK公式手順に従ったのだが,zmkフォルダの外にzmk-configなどを作って,それをworkspaceにマウントして使う,というのが良くわからずできなかった.
とりあえずzmkフォルダ内にソースを放り込んでビルドしたので,時間があれば公式手順でもちゃんとやりたい.
おわりに
この記事は,以下のXでの投稿の反省として書いた.
場合によってPCがBluetooth接続できなかったり,ファームリセット後の再ペアリングが面倒だったりで,ドングル運用を考えている方にとって,有用な記事になれば幸いです.
Discussion