hoboNicolaライブラリ1.6.2版について

XIAO RP2040 + ch9350_xiao_rev02

 概要

hoboNicolaライブラリ1.6.2版の更新内容、ビルド方法などについて。

  • キーボードインタフェース用のCH9350Lを使ったアダプターのサポート。従来からのminiUHS (MAX3421EE)用とライブラリファイルは共通とし、メインスケッチ(inoファイル)を分けた。
  • RP2040 を載せた Adafruit KB2040XIAO RP2040 をhoboNicolaアダプターのマイコンボードとして使えるようにした。
  • XIAO nRF52840(BLE) をhoboNicolaアダプターのマイコンボードとして使えるようにした。このとき、コアライブラリとしてスイッチサイエンスのISP1807MBと同じ Adafruit nRF52 BSPを使うことで、BLE関係のコードを共通にした。
  • 各マイコンボードの相違(マイコン、LED構成、SPI用GPIOなど)をライブラリ側で吸収するための修正やスリープ関係の見直しを行った。

ソース一式のダウンロード

ソース一式のダウンロードは、hoboNicolaのダウンロードページから。今回のファイル名は、hoboNicolaLibrary162.zip とした。

1.6.2版の更新点など

CH9350L を使ったキーボードインタフェースボードへの対応

XIAO RP2040 + ch9350_xiao_rev02

前回の投稿に載せた、hoboNicola CH9350L ボードに対応するためのプログラム( src/hobo_nicola_ch9350if/hobo_nicola_ch9350if.cpp および .h  ) を追加した。先に公開したArduino用のライブラリ(ch9350ifLibrary)と中身はほぼ同じだが、hoboNicolaライブラリを直す過程で変更を入れやすいよう、こちらの src 内に包含した。

CH9350Lを使ったボードを使うときには、メインスケッチとしてexamples/ch9350_hobo_nicola/ch9350_hobo_nicola.ino を使ってビルドする。従来からのMAX3421EEを搭載した mini USB Host Shield(miniUHS)を使うときは、従来と同じく usb_hobo_nicola.inoを使う。

マイコンボード依存コードの分離

1.6.1版までは、マイコンボード依存部分をまとめた device_setup.h を usb_hobo_nicola.inoと同じフォルダに格納していたが、ch9350L用のスケッチでも使うことになったので、srcフォルダに hobo_board_config.cpp および.h として追加した。device_setup.hは廃止。

このファイルには、SAMD21やAVRの省電流のための初期化処理やボードごとのLEDの相違を吸収するためのマクロ定義、ディジタルポートの初期設定などが書いてある。

XIAO nRF52840 + ch9350_xiao_rev01

各ボードごとのLEDの扱い方

今回のバージョンでは7種類のマイコンボードに対応したが、各ボードのLEDの種類や接続方法はまちまちである。LED を使う場面でいちいち #ifdef ディレクティブを書くのも面倒なので、ライブラリ内で LED1とLED2およびBLE_LED という3つのマクロ定義にまとめた。LED1がnicolaモードかどうかを示し、LED2はエラー提示用。BLE_LEDはBLE接続時に点滅させるためのもので、nRF52840コア以外は使わない。

WS2812系のNeoPixelしか搭載していないボードについては、Adafruit_NeoPixelライブラリを使って、色指定で点灯させるようにしLED1とLED2の代わりにした。そのあたりの操作は、hobo_led.cpp を参照。

マイコン
ボード
ふつうのLED NeoPixel RGB LED
( アノードコモン)
Pro Micro
および
Leonardo
LED1 = LED_BUILTIN_RX
LED2 = LED_BUILTIN_TX
なし なし
Adafruit
QTPy-m0
なし LED1 = 緑
LED2 = 赤
電源制御可能
なし
Seeed Studio
XIAO-m0
LED1= LED_BUILTIN
LED2 = PIN_LED2
なし なし
Switch Science
ISP1807MB
LED1 = PIN_LED1
LED2 = 別途用意
BLE_LED= 別途用意
なし なし
Seeed Studio
XIAO-nRF52840
なし なし LED1=D13
LED2=D11
BLE_LED=D12
Adafruit
KB2040
なし LED1=緑
LED2=赤
電源制御無し
なし
Seeed Studio
XIAO-RP2040
 なし 使わない
電源制御可能
LED1=GPIO16
LED2=GPIO17
(BLE_LED=BPIO25)

LED1= LED_BUILTIN という表記の右辺側は、各ボードの構成を記述した pins_arduino.h や variant.h 内に定義されているマクロを表しており、D13やGPIO16という表記は、LEDを操作するときに使うディジタルピンあるいはGPIO番号を表している。

残念なのがISP1807MBで、ボードには赤色のLEDが一つ載っているだけである。ブレッドボードなどに自前でLEDを載せて対応することはできるので「別途用意」とした。

NeoPixel LEDを搭載しているボードのうち、WS2812の電源ピンがGPIOポートに接続されているものは「電源制御可能」とした。上記では、XIAO-RP2040とQTPy-m0が該当したとえばスリープ時にNeoPixelの電源をオフにすることができる。KB2040のNeoPixelの電源ピンは+3.3V直結なので常時オンになっており、消灯中も0.3mA程度消費しているようだ。前にも書いたかもしれないが、+3.3V電源でもWS2812は動くようである。

ビルドに使ったライブラリなど

ボードごとのコアライブラリ(BSP)は以下のとおり。

マイコン BSP 備考
ATMega32U4 Arduino AVR Boards 1.8.3

SparkFun AVR Boards 1.1.13

(必須)
ATSAMD21 Arduino SAMD Boards 1.8.13

Adafruit SAMD Boards 1.7.10

(必須)

※1

nRF52840 Adafruit nRF52  1.3.0 ※2
RP2040 Raspberry Pi Pico/RP2040  2.3.2 Arduino-Picoコア。

※1 XIAO-m0のビルドのために、若干の追加修正を実施。以前の投稿を参照
※2 XIAO-nRF52840のビルドのために、若干の追加修正を実施 (後ほど詳しく)。

ライブラリとしては、Adafruit_TinyUSB_Library 1.14.1  を導入して利用した。このライブラリを導入するとき、Adafruit_NeoPixelライブラリも入れますか? と聞かれたので「はい」と応えたら 1.10.5が導入された。NeoPixelのコントロールのためこちらも必須。

KB2040 + ch9350_promicro_rev01

UHSライブラリの修正

以前のバージョンでは、USB Host Shield Library 2.0 を導入しておく必要があったが、現在のhoboNicolaでは必要なファイルを src/UHSLib2.0内 に包含しているので、別途ライブラリとして導入する必要はない。今回は、XIAO-RP2040およびKB2040と、XIAO nRF52840をMAX3421EEベースのminiUHS に接続するための修正を行った。

RP2040用の追加(avrpins.h)

RP2040 (Arduino-Picoコア)では、ポートの設定や操作はArduinoライブラリの pinMode()やdigitalWrite()、 digitalRead() で行うようにした。Arduino-Picoコアでは、ディジタルピン番号からGPIO番号に変換する処理などがないのでAVRのArduinoに比べるとオーバーヘッドも小さい。

XIAO nRF52840用の追加(avrpins.h)

ポートの操作を行う定義(MAKE_PIN)については、ISP1807と共通とし、各ピンの定義のみを追加した。

共通部分 (usbhost.h)

usbhost.h 内に、新たに対応を追加したマイコンボードの定義を追加した。

実際のところ、各ボード用のSPIライブラリはハードウェアSPIをサポートしているので、MISO, MOSI, SCKについての定義は役に立っていない。

スリープ関係

メインスケッチ(usb_hobo_nicola.ino および ch9350_hobo_nicola.ino ) 内のスリープ関係の処理を若干修正した。いずれも、void loop() 内に記述。

hoboNicolaアダプターは、ホスト側(おもにPC)のUSBがサスペンド状態になったことを、TinyUSBライブラリの USBDevice.suspended() または ArduinoライブラリのUSBDevice.IsSuspended() をテストすることで検出し、スリープを開始する。このとき、設定項目にある K : KEYBOARD SUSPEND (従来のPSEUDO SUSPEND から変更) が有効ならば、アダプターに接続されているキーボードもサスペンドしようとする。キーボードのサスペンドは、MAX3421Eならば SOFKAENAB ビットの操作によって、CH9350LならばRESETをアクティブにすることで実施する (CH9350LのRESETをアクティブ化すると、キーボードに対するSOFの送出が停止し、結果として多くのキーボードはサスペンド状態になる)。

ただ、ずっとスリープしたままではアダプターに接続しているキーボードを叩いてスリープから復帰させることができないので、定期的(MAX3421EEならば約1秒ごと、CH9350Lならば約2秒ごと)にスリープから復帰してキーボードを復活させ、キー入力の有無を調べる。キー入力があれば USBDevice.remoteWakeup() またはUSBDevice.wakeupHost() というライブラリAPIを使ってホスト側に復帰要求を出すようにしている。

1.6.2版では、スリープ状態が30分間持続した場合、もはやキーボードで復帰する気はないんだろうと判断して、キーボードの復活とキー入力の調査を行わないようにした。なお、そのような場合でもホストが何らかの要因(マウスや電源スイッチ操作とか)で復帰した場合には、!USBDevice.suspended() を検出してアダプターは通常動作に復帰する。

※ RP2040の場合、スリープ中に USBDevice.remoteWakeup() を実行すると、その後のサスペンド状態の検出が怪しくなり、PCが復帰してもアダプターはスリープ状態のままになってしまう。その理由が追えていないので、RP2040を使った構成ではキーボードによるサスペンドからの復帰はできないようにしてある。また、RP2040のスリープについては、Pico SDKの sleep_ms() をつかうようにしてみたが、あまり省電流でもない(まだ研究不足)。

MSC Notifyについて

AVR以外のマイコンボードでは、1.6.1版からhoboNicolaアダプターが作成する小さなドライブ (ボリュームラベル : hoboNicola) 内のファイルをPC側から操作することで、IME状態を通知できるようにした (observe_ime .exe 1.1.0版が必要)。その目的は、ScrLock LEDによる状態通知を回避するため。

1.6.2版より設定項目の、M : MSC NOTIFY (TINYUSB) が有効になっている場合にのみ、hoboNicolaドライブを作成するようにした。有効から無効、または、無効から有効に状態を変更したとき、マイコンをリセットして初期化からやり直すようにした。

なお、nRF52840コアを用いるマイコンの場合、このリセット処理が今のところうまくいかないので、hoboNicolaアダプターが接続されているときは常にドライブが作成される。

RP2040のサポート

ProMicro型のAdafruit KB2040 と Seeed StudioのXIAOシリーズの一つ XIAO-RP2040での動作を確認した。各ハードウェアやRP2040のことなど。

Adafruit KB2040

Adafruit KB2040

KB2040はProMicro型なのだが、両側には片側13個のパッドがある。写真の一番左側のパッドには、USBのD+とD- が引き出されているので、たとえばキーボード基板に直付けして自前のUSBコネクタに配線するようなことができる。D+およびD- と、RP2040のUSB_D+、USB_D- ピンの間にはそれぞれ27Ωの抵抗が入っているので、そのままUSBコネクタに接続することができる。

プログラムから利用できるオンボードLEDとして NeoPixel LED (WS2812B)が実装されている。このWS2812Bの電源は、+3.3Vに直結されているので、プログラムからオフにすることはできない。

その他の特徴としてはI2Cデバイスを接続するためのJST SH 4ピンコネクタ ( STEMMA QT) や、スケッチやデータを格納するための8MBytes のQSPIフラッシュメモリが実装されている。

XIAO-RP2040

Seeed XIAO-RP2040

XIAO-RP2040 は他のXIAOシリーズと同様に肝心の部分は金属製のカバーに覆われている。オンボードのQSPIフラッシュは、Raspberry Pi Picoと同じく2MBytes。

LEDとしては、NeoPixel LED(WS2812系)とアノードコモンのRGB LEDが載っていて、NexPixelの電源はGPIO11でオン/オフできる。RGB LEDのカソード側は、RGBともに異なるGPIOに接続されているので、ふつうのLEDが3つ並んでいるのと同じように扱うことができる。

BOOTSELスイッチとRESETスイッチ

RP2040を使ったたいていのボードには、プッシュボタン型のBOOTSELスイッチとRESETスイッチが載っている。RESETは文字通りCPUをリセットするためのもの。

BOOTSELはDFUモードを開始するときに使うものだが、Arduino IDEで使うときは仮想シリアル(CDC)のtouch1200操作でDFUモードを開始し、ビルド済のスケッチを転送できるのでふだんはまず使わない。スケッチを動かしているときにBOOTSELを単独で押しても目に見える影響はないようだ。

BOOTSELを押した状態でRESETをオン/オフし、それからBOOTSELを離してやると、UF2ブートローダーが開始してPCのExplorerに以下のような RPI-RP2ドライブ が現れる。

RPI-RP2ドライブ

このドライブにUF2フォーマットされたファームウェアファイルをドロップしてやると、ブートローダーが中身を解析してQSPIフラッシュ内の所定の位置に格納してくれる。格納後には自動的にリセットがかかり転送したファームウェア(スケッチ)が開始する。

hoboNicolaのようなUSBデバイスを開発していると、ときとしてPCからUSBデバイスとして認識されなくなってしまい、Arduino IDEからCOMポートが見えなくなってスケッチが転送できないことがある。

USBデバイスが認識されません

そういうときには、BOOTSEL + RESET操作を使ってブートローダーモードとし、ユーザー名/AppData/Temp/arduino_build_xxxxx フォルダ内にできている スケッチ名.ino.uf2 ファイルをドライブにドロップしてやればよい。うまく転送できると自動的にリセットがかかってスケッチが開始する(当然、問題点を修正したあとだが)。

Raspberry Pi Foundation謹製のRaspberry Pi PICO(RP2040ブレイクアウトボード)には、RESETボタンがついていない。そのためブートローダーモードに入るには、BOOTSELを押したままUSBケーブルを抜き差しするしかない。RESETボタンを備えたボードについての解説でもそんなふうに書いてあったりするが、ボタンスイッチがあるならそちらを使った方がいいでしょう。

Arduino IDEでのビルド

Arduino IDEでRP2040 (あるいは Raspberry Pi Pico) 用のプログラムをビルドするにあたり、コアパッケージあるいはBSP(Board Support Package) としてArduino公式の Arduino Mbed Core for RP2040 を使うか Earle F. Philhower, III氏による Raspberry Pi Pico Arduino core (Arduino-Pico)  を使うかで迷うところ。

Arduino-Picoは、今回使った XIAO-RP2040とKB2040 のいずれもを variantとしてサポートしており、公式版に比べてより従来からのArduino BSPに近い印象だった。その上、QSPIフラッシュを使ったEEPROM(エミュレーション)ライブラリもちゃんとサポートしており、スケッチを入れ替えても書き込んだ内容が保持される。そのあたりの理由で、Arduino-Picoを使うことにした。このパッケージも頻繁に更新されてるようだが、今回は2.3.3版を使ってビルドおよび動作確認を行った。

Adafruit KB2040 のチュートリアルを見ると、Arduino-Pico (earlephilhowerコア) を導入するところから話が始まっているが、XIAO-RP2040の公式のBSPは、1.xx版はArduino-Picoベース、2.xx版はArduino Mbed Coreベースになっている(以下のライブラリマネージャのバージョン表記を参照)。

Arduino IDE ライブラリマネージャ Seeed XIAO RP2040

ライブラリマネージャでなんとなく更新してしまうと、まるでベースの異なるパッケージに入れ替わってしまうことになり、あまり素晴らしくないので、Seeed StudioのBSPは使わないことにし、Arduino-Picoコアで進めることにした。

Arduino-Picoのセットアップ

Arduino IDEの環境設定/追加のボードマネージャのURL: に、 https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json  を追加してあれば、ツール/ボードマネージャの入力フィールドに RP2040と入力することで Raspberry Pi Pico/RP2040 by Earle F. Philhower, III が表示される。バージョン2.3.3 でビルドとhoboNicolaの動作を確認した。

Arduino IDE ボードマネージャ

ビルド時の設定

Arduino IDEの ツール/ボード で Raspberry Pi RP2040 Boards (2.3.3) を選ぶとサポートするボード名がずらっと表示されるので、Adafruit KB2040 または、Seeed XAIO RP2040を選択する(なぜか、XIAOではなくXAIOと書いてある)。

Flash Size: として、Sketchが1MBになるようにする (KB2040ならば Sketch: 1MB,  FS: 7MB、XIAOならば Sketch: 1MB,  FS: 1MB) 。hoboNicolaをビルドしてもスケッチサイズは100KBにも満たないので最小値とした。今回のhoboNicolaではあまったフラッシュを ファイルシステムとしては使わないのだが、そのうち使うかもしれません。

CPU Speed:50MHzとする。初期値の133MHzでもいいのだが、コアクロックを下げるとそれだけ消費電流も小さくなるので。

USB Stack: は、Adafruit TinyUSB を選択する。現状のhoboNicolaライブラリは、AVR以外はAdafruit TinyUSBライブラリに依存している。

シリアルポート: については、接続中のRP2040ボードが見えているはずなのでそれを選択する。

その他の設定は、初期値のままとしている。

XIAO nRF52840(BLE) のサポート

XIAOシリーズ最初のBLE対応製品で値段も手頃($10 USD 前後)だから技適マークが付き次第欲しいと思っていた。

Seeed XIAO-nRF52840

以前対応した同じnRF52840コアのスイッチサイエンス ISP1807 Micro Board のビルドは  Adafruit nRF52 BSP ( Arduino Core for Adafruit Bluefruit nRF52 Boards ) に依存しており、USBデバイスとしての機能はAdafruit TinyUSBライブラリを、BLEキーボードとしての機能はnRF52 Bluefruit ライブラリを利用している。XIAO nRF52840への対応も同じようにした。

XIAO nRF52シリーズ用BSPについて

RP2040と同様にSeeed Stduioが用意してくれているBSPは、バージョンによって中身が大きく違っている。Arduino IDEのボードマネージャを開いて “Seeed nRF52″を検索するとこれを書いている時点では(インストール済の2.7.2も含めて)3つのバージョンが表示される。

Arduino IDE ボードマネージャ

これらのうち、2.6.1版と2.7.2版はRP2040と同じくArduino Mbed CoreベースのBSPで、1.0.0版のみが Adafruit nRF52 BSPをベースにしたものだった。nRF52 Bluefruit ライブラリを利用するために1.0.0版を使うことも考えたが、残念なことにAdafruit_TinyUSB ライブラリが含まれておらず、USBスタックとしてTinyUSBを指定することも考慮されていなかった。しょうがないので、Adafruit nRF52 BSPに対して必要な項目を追加したり編集したりすることで、ISP1807と同じコアおよびライブラリを利用できるようにした。

追記 BSPがAdafruitベースになった

2023年の9月に XIAO nRF52840をビルドしようとしたところ、状況が変わっており、Adafruit nRF52 BSPをforkしたものが用意されていた。BSPの中身は、 https://github.com/Seeed-Studio/Adafruit_nRF52_Arduino に公開されている。

Seeed nRF52 BSP

Arduino IDEのボードマネージャでは、1.1.4版をインストールできたので、これを使ってビルドしたところ、なんの問題もなくビルド、アダプターへのアップロード、そしてキーボード入力まで実行することができた。

ビルドにあたっては、以下のライブラリが使用された。

Adafruit_TinyUSB_Libraryは、この時点での最新バージョンを別途取得しているが、その他は nRF52 BSPとともにインストールされた。

Adafruit_nRF52_Arduino については、この時点で1.5.0版がリリースされており、おそらくSeeedのものより進んでいるようである。

Adafruit nRF52と統合されたので、以前に書いた以降の作業は不要となった。せっかくなので残しておきますけど。

Adafruit nRF52 BSPでXIAO nRF52840をビルドする準備

※ Seeed nRF Boards 1.1.4 以降を使う場合、このセクションに書いてある処置は不要です。

まずは、Seeed Stduio nRF52 BSP (1.0.0)版をArduino IDEにインストールする。インストールにより …\Arduino15\packages\Seeeduino\hardware\nrf52\1.0.0 が出来るので、その中からいくつかのフォルダやファイルを …\Arduino15\packages\adafruit\hardware\nrf52\1.3.0 にコピーしていくという手順になる。

variants内フォルダのコピー

Seeed側のvariants 内の Seeed_XIAO_nRF52840 フォルダを、そっくり adafruit側の variantsフォルダ配下にコピー

このとき、variant.h 内の LED_STATE_ON の論理が逆になっていることに気がついた。 #define LED_STATE_ON 1 // State when LED is litted となっているが、正しくは、1 を書くと消灯で0で点灯なので、 #define LED_STATE_ON 0 に修正した。このマクロは、Adafruitのwiring_digital.c 内の void ledOn(uint32_t pin); などで使われている (hoboNicolaでは使ってない)。

boards.txtへの追記

adafruit側の 1.3.0/boards.txt に、以下を追加(Seeed のboards.txtからコピペ)。

リンカースクリプトのコピー

Seeed側の cores/nRF5/linker/nrf52840_s140_v7.ld を、Adafruit側の cores/nRF5/linker/ 内にコピー。ここでNordic softDeviceのバージョンが変わっていることに気がついた。スイッチサイエンスのISP1807MBではs140_v6 だが、Seeed nRF52は s140_v7になっている。

softdevice APIのコピー

Seeed側の cores/nRF5/nordic/softdevice/s140_nrf52_7.3.0_API  フォルダを、Adafruit側の cores/nRF5/nordic/softdevice/ 配下にコピーする。このフォルダには、Nordic Semiconductor社が提供する softDevice APIのヘッダファイルが含まれている。ファイルに記載されているライセンスを読む限り、そっくりそのままコピーして使う分には問題ないと判断した。

Arduino IDE

Arduino IDE nRF52

ここまでの手順により、Arduino IDEのツール/ボード/Adafruit nRF52 Boards のオプションの一つとして、Seeed XIAO nRF52840 が選択できるようになる。

注意点

以前から、BSPに対してファイルを追加したり修正したりすることでもともとサポートしていないボードをビルドできるようにしたりしている。この方法は、BSP自体を更新すると実施した修正内容がすべて消えてしまうので、更新時には注意が必要だろう。

きょうのまとめ

このところCH9350Lを使ったhoboNicolaアダプターを使ってメールだったりツイートだったりブログだったりを書いているが、特段の問題点は感じない。そのうち何か問題が出るかもしれないので、そのときはTwitter ( https://twitter.com/okiraku_camera )で報告することします。

RP2040にせよnRF52840にせよ、USBホストコントローラとシリアル接続して低速なキーボード入力をサポートするだけのhoboNicolaアダプターで使うのは、明らかに役不足だろう。しかしながら、RP2040というデバイスは性能の面でも価格の面でもこれからの主流になっていくのは間違いのないところと感じる。