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配線を外す.

動作確認

  1. ドングルをPCのUSBポートに挿す
  2. ドングルにアプリが書き込まれていない場合,PC に UF2 ドライブが現れる
  3. UF2ドライブが現れたら,Bootloader書き込みは無事成功
  4. 現れない場合,次のトラブルシュートを試してみる

トラブルシュート

アプリ領域が書き込まれていると,PCに挿しただけではUF2書き込みモードにならない.

  1. 一度USBを抜く
  2. 再度,ドングルの中央ボタンを押した状態でUSBを挿す
  3. UF2書き込みモードになったら,アプリ領域に書き込みがあるがブートローダは正しくフラッシュされている
  4. それでも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 ローカルビルド を使う方法

ローカルビルドの詳細は省きますが,公式ドキュメントや先人が詳しく解説してくれています.

筆者はローカルビルドは初めてだったので,WSL+公式の方法で環境構築した.

ローカルビルドの手順メモ

zmk/app/boards/arm/raytac_mdbt50q_rxフォルダを追加し,ZMKモジュールと同じファイルをその中に追加.

さらに,その他のボード定義と同様に,同じ階層にboard.cmakeを用意.

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)
/zmk/app/boards/arm/raytac_mdbt50q_rx
.
├── Kconfig
├── Kconfig.board
├── Kconfig.defconfig
├── board.cmake
├── raytac_mdbt50q_rx.dts
└── raytac_mdbt50q_rx_defconfig

さらに方法1と同様のファイルを,zmk/app/boards/shields/<your_keyboard>フォルダに追加(下記例).

/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での投稿の反省として書いた.

https://x.com/BParound30/status/1990461497785626964?s=20

場合によってPCがBluetooth接続できなかったり,ファームリセット後の再ペアリングが面倒だったりで,ドングル運用を考えている方にとって,有用な記事になれば幸いです.

Discussion