2022年2月24日木曜日

PIC32MX210F016BでUSBデバイスは作れるか

PIC32MX210F016BとHarmony

 秋月で190円(2022年1月現在)で売っているUSB搭載最安PICです。半導体不足の影響か、PICが軒並み値上げになっているので昔はもっと安かったと思います。ともかく、この値段で32bitアーキテクチャであり、ハードウェア乗算機を積んでいる超賢い石がこの値段で手に入るのはすごいですね。
 さて、USB積んでるならUSB機器作れて当たり前だろという感じですが、210F016Bはメモリ4kB, フラッシュ19kB という(PIC32としては)地を這うようなリソースの制限があります。加えて、Microchip社はPIC32、特にMXシリーズ以上でHarmonyというフレームワークを使用して開発することを想定しており、FreeRTOSが否応なしに走るのでリソースを馬鹿食いします。
 MHC(Microchip Harmony Configurator)を使ってプロジェクトを作った方なら分かると思いますが、USBの適当なクラス(HIDとかCDCなど)を搭載したプロジェクトを作ると、メモリアロケーションできずにビルドが通りません。ヒープとかスタックのサイズを調整してもどこかしらのアロケーションエラーが出ます。少なくともフリー版XC32では最適化レベルを変更してもどうやっても通りません。
 使っていない機能の変数割当をエラーが出なくなるまで削るといいんでしょうが、本当に使っていない変数ならコンパイル時に除去されるので、いい感じに容量削減するのは骨が折れそうです。
 いくらググっても32MX210でUSB機器開発した情報が出てこないので、今回はこれをなんとかしてみたいと思います。  
 
 先に結論を書くと、 32MX210F016BでもUSB機器(デバイス側)を作ることができます。とはいえリソース問題で悩みたくなかったら容量の大きいPICで開発することをおすすめします。以下の文章は、どうしても安いPICでUSB機器を作りたい人や、PIC買ったのはいいけど、いざHarmonyで書いてみたらビルドが通らなくて「話が違うじゃん…」になった人向けです。私は後者です。
 

さらばHarmony

 Harmonyとはここでお別れです。リッチな開発環境を使いたい方は容量の大きいPICを買ってHarmonyしましょう。
 ここからはゴリゴリのXC32です。Harmonyを入れなくていいのでMPLABが肥大化せずにスッキリするのはいいですね。ちなみにXC32はフリー版の想定です。
 
 イチからUSB関数を書くのはやってられないのでMLA(Microchip Library for Applications) を利用します。MLAの最終版は2018年で、一通りUSBのサンプルがありますが、PIC32は32MMしかありません。32MX以上はHarmonyを使ってねってことです。2013年版までは32MXのサンプルがありますが、流石に5年違うと結構改変されており、2013年版をあえて使いたくはありません。ということで最新2018年版を32MXで使えるように改変します。

ソフトウェア開発

 MLAはHAL(Hardware Abstraction Layer / ハードウェア抽象化レイヤー)を採用しているため、下位レイヤーだけ32MX210F016B用に書き換えるだけで済みます。ついでなのでその他のMXシリーズでも動くように色々書き換えましたが、検証はできていないのであしからず。
 
 Harmonyと違ってデータメモリもプログラムメモリもまだ空きがあるので機能追加の余地があるのが魅力です。まぁMIPS32だと1命令4Byteも消費することもあり、プログラムメモリは割とあっという間に枯渇するのであまり機能モリモリにはできないですが。XC32のフリー版だとMIPS16命令にできませんし。 

ハードウェア開発

 PIC32には16Fに比べて繋ぐべきピンがたくさんあります。
 
<電源系>
5.0V ... Vbus
3.3V ... Vdd, AVdd, Vusb3.3
GND ... GND(2本), AVss

<その他必須ピン>
MCLR = 3.3Vにプルアップ
OSC1,2 = 適当なクリスタルで外部発振。今回は8MHz
Vcap = GNDにパスコン
D+ = USB D+
D- = USB D-
 
<汎用IO> 
~サンプルでは以下の接続としています~
RA0 = プルアップ抵抗とプッシュスイッチをプルダウン
RA1 = LED+抵抗をGNDに接続
 

注意点

・5Vから3.3Vにする外部レギュレータが必要です。間違ってもVddに5Vを繋がないように。壊れます。
内部クロックで48MHzは作れますが、USBクロックに供給できないという罠があります。 USBを使うなら外部発振が必須になります。逓倍と分周で48MHzになるなら周波数は何でもいいです。精度が必要なのでセラロックではなくクリスタルが推奨されています。
・USBIDピンとVUSBONピンはUSB-OTGじゃなければ汎用IOとして使えます。
 

ソースコード

ライセンスはオリジナルと同じくApache Licence 2.0 とします。
お約束ですが、自己責任でどうぞ。
 

CDCクラスのサンプル

 
 
COMポートとして認識されます。デバイス側は、受信した文字コードに+1した値を即時送信します。また、ボタンを押すとメッセージを送信します。LEDは点滅速度にて接続が確立されたかどうかを示します。
 
下の写真は最適化レベル2MIPS32コード(デフォルト)でコンパイルした場合です(XC32 v4.00)。ダッシュボードに表示されるプログラムメモリ容量は、一般的なプログラムを置ける領域以外に、ベクターテーブルやブートメモリも母数に含まれるので、実際は見た目ほど空き領域はありません。Memory-Usage Reportだと詳細な領域使用率が見られ、今回だと現実的な使用率は82%でした。
 
MIPS16コードの場合です。使用率は69%です。


HIDクラスのサンプル

 
 
キーボードとして認識されます。デバイスのボタンを押すたびにaから順にインクリメントしながらキーコードを送信します。LEDはCapsLockを示します。
 
MIPS32コードの場合。使用率は73%です。
 
MIPS16コードの場合。使用率は66%です。
 
 

コンパイルの設定

MPLAB X IDE(5.50)でのコンパイル設定を記載しておきます。プロジェクトを右クリックしてプロパティから設定します。
 
プロジェクトを新規作成をすると、なぜかgccの最適化レベルは0にされてしまいます。optimization-levelを2に変更しましょう。それでもどうしてもサイズがキツかったらOsにしましょう。「フリー版だからOs無効化したよ!」という警告の割には若干縮みます。

MIPS16コードを作る場合は"Generate MIPS16 16-bit code"にチェックを入れます。結構縮む割にデメリットも特に感じないので有効でいいでしょう。
ちなみにこのオプションだとMIPS16にできないアセンブリ命令があるとコンパイルできません。身近なところだとグローバル割り込み有効化の"ei"はダメでした(代わりに組み込み命令を使えばOK)。

usb関係を論理フォルダにまとめる場合、そのままではincludeのパスが通らなくなります。必要に応じてincludeディレクトリを追加します。自身のディレクトリである"."の追加も忘れないように。

あとはリンカの"Remove unused sections"に精神衛生上チェックを入れてます。ほとんど効果を実感しませんが。
 

 その他注意点

少なくともWindowsでは同じVID/PIDのUSB機器が2度目以降に刺された場合に前回使用時のドライバを問答無用で使うため、クラスが変わったり(e.g. HID→CDC)、インターフェイスが変わったり(e.g. Keyboard→Mouse)した場合に正しく動作しないことがあります。そういうときはデバイスマネージャなどで対象機器を一度削除するとドライバを再探索してくれます。お遊びでPID固定したまま頻繁にクラスチェンジしてる場合は気をつけましょう。 

最後に

じゃじゃ馬と思っていたPIC32MXと戯れてみると案外普通に使えます。今回は記載していませんがDMAなども素直に動くので、ペリフェラルの乏しさに目を瞑れるなら普通にアリなマイコンだと思いました。

1 件のコメント:

  1. 16F1454 & MLA で簡単にUSBデバイスが作れたので、MX210F016B & Harmonyでも同じように作れるだろうとタカをくくってメモリオーバーで玉砕し、困り果ててこちらに辿り着きました。
    大変、有用な情報ありがとうございました。

    返信削除