趣味の電子工作などの記録。時にLinuxへ行ったり、ガジェットに浮気したりするので、なかなかまとまらない。※サイト移転しました(tomono.eleho.net ⇒ tomono.tokyo)
RSS icon
  • PIC18F用のHIDブートローダの調査

    投稿日 2013年 11月 2日 コメントはありません

    PIC18F14K50は割り切って使うにはなかなか便利なデバイスなのですが、MPLAB-X(Linux版)とPICkit3の組み合わせで毎回書き換えて使うには、書き込む度に

    1. PIC18F14K50側のUSBケーブルを抜いて、
    2. PICkit3を接続し、
    3. ダウンロードをして、
    4. PICkit3側のUSBケーブルを外してから
    5. PICkit3を外して、
    6. PIC18F14K50側のUSBケーブルを挿す
    7. (次回書き込みに備えて)PICkit3側のUSBケーブルを挿す

    というなかなか面倒くさい手順が必要です。理由は、

    1. ICSPの端子とUSBのD+/D-端子を共有している
    2. MPLAB-XのPICkit3に対する制御がイマイチ
      (MPLAB-Xからターゲットへの電源が供給されっぱなしなので、一旦PICkit3を外して電源供給を止める必要がある)

    というためです。

    そこで調べていたところ、HIDプロトコルによるブートローダがMicrochipから提供されていることがわかりました。これを使うと、

    • ブートローダを書き込んであればPICkit3なしでターゲットプログラムを書き換えることができる
    • PowerON時のポートの状態に応じてブートローダを起動させたり、ターゲットプログラムを起動させたりするのを切り替えることができる
    • ターゲットプログラムのダウンロード用のLinux用のホストプログラムはブートローダに同梱されている(Qtベースっぽい)
    • ブートローダは0番地付近の約4KBを占有する模様。割り込みベクタは4KB上のアドレス(1000H~)に移動させる細工がされている。
    • アプリケーションプログラムも当然1000Hあたりからに置かれるように細工しなければならない

    ということがわかりました。

    どこから手をつけるか考えていたところ、CDCクラスのBasic Demoのlkrファイルが「rm18f4550 – HID Bootload.lkr」となっていていかにも対応していそうなファイル名です。中身も、

    102A番地から7FFF番地までに配置されそうな感じです。
    そこで、手始めにPIC18F4550(AE-18F4550ボード)でブートローダを動かしてみることにしました。

    途中までは順風満帆かと思われたのですが・・・・

    ブートローダのプロジェクトは microchip_solutions_v2013-06-15/USB/Device – Bootloaders/HID/Firmware – PIC18 Non-J/MPLAB.X に収められています。これを開いて、ProjectのPropertyを開いてPIC18F4550の設定をActiveにすることと、PICkit3から電源供給するように設定変更します。
    ブートローダ用のSWとLEDは io_cfg.h を見ると68行目付近から記述があり、LEDはPORT D0、SWはPORT B4に接続する前提になっていることがわかります。そこで、ブレッドボード上で適当にLEDとSW(プルアップ抵抗をつけておきます)を配線します。
    ビルド自体はこれで難なく通り、書き込みもできました。(コンパイラは例によってMPLABC18です)
    18F4550のPORT B4をGNDに落とした状態でUSBポートをホストPCと接続するとLEDがチカチカ点滅します。そして、「microchip_solutions_v2013-06-15/USB/Device – Bootloaders/HID/Firmware – PIC18 Non-J/HIDBootloader(Linux)」を起動すると「Device Attatched」という表示が出て、無事に認識されました。

    次にアプリケーションですが、先に調査した通り、CDC Basic Demoで試してみます。

    microchip_solutions_v2013-06-15/USB/Device – CDC – Basic Demo/Firmware/MPLAB.X に格納されたプロジェクトを開いて、ProjectのPropertyを開いてPIC18F4550の設定をActiveにしてビルドします。
    ビルドして出来上がったHEXファイルはmicrochip_solutions_v2013-06-15/USB/Device – CDC – Basic Demo/Firmware/MPLAB.X/dist/PICDEM_FSUSB/productionの下に格納されています。これをHIDBootloader(Linux)で File → Import Firmaware Image で読み込ませた後、Program → Erase/Program/Verify Device で書き込みます。書き込み後、PORT B4をHレベルになるようにした後、Program → Reset Device でリセットを掛けます。・・・が、再びBootloaderに認識されてしまいました。

    うーん、HID Bootloader上のアプリケーション・・・動きません。

    ここからが苦難の道のり・・・(涙)

    ブートローダのファームウェア側main.cを見ると、421行目近辺に

    というコードがあって、APP_SIGNATURE_ADDRESS番地にAPP_SIGNATURE_VALUEが書かれていないと、BootMain(ブートローダのMain)に飛んでいくことがわかります。具体的には、0x1006番地が0x600Dでなければなりません。
    そこで、MPLAB IPEでROMの内容を吸い出して確認してみたところ、見事に0xFFFFになっていました・・・。ここをMPLAB IPEで0x600Dに変更して書き戻してみたところ、ブートローダプログラムでは「Detached」になり、さらにGtkTermで /dev/ttyACM0 にアクセスしてCDC Basic Demo(入力した文字が1文字ずれてエコーバックされる)の機能を確認することができました。
    つまり、SIGNATURE VALUEが書かれていないことが原因であることがわかりました。

    では、SIGNATURE VALUEは誰が書くのか?

    ソースコードの「BootPIC18NonJ.c」の359行目からのProcessIO()を見ると、532行目付近に

    というコードがあって、これはホスト(PC)からのコマンド解析部分のようです。ホストから「SIGN_FLASH」というコマンド(ちなみに値は0x09)が来ると、591行目付近のSignFlash()という関数が呼び出されて、該当領域を読み込んだ後、バッファ内のSIGNATUREの部分を書き換えて、書き込む処理を行うように見えます。
    つまり、そもそもこの「SIGN_FLASH」というコマンドが来ていないのではないか、ということになります。

    SIGN_FLASHが送られてくるコードになっているのか?

    こんどはホスト側のソースコードが格納されている「microchip_solutions_v2013-06-15/USB/Device – Bootloaders/HID/software_cross_platform/Bootloader」の下を見てみました。

    「SIGN_FLASH」を送出するっぽいコードは、Comm.cppの640行目付近にある、「Comm::SignFlash(void)」という関数のようです。送られていれば、それなりのデバッグメッセージを出すコードのようなのですが、残念ながらビルドできる環境がありません。(方法もわかりません)
    この部分を呼び出すのはMainWindow.cppの555行目付近のようです。

    書き込み後にVerifyをする関数の最後の方で、Verifyに問題がなく、なおかつdeviceFirmwareIsAtLeast101がセットされていれば、呼び出されるようです。で、この値はブートローダファームウェアのバージョンが1.01以上であればセットされるようです。
    実際にセットしている箇所は、MainWindow.cppの1150行目付近、GetQuery()という関数・・・GetQueryコマンドに対する応答パケットを解析する部分の中で、

    bootInfo構造体のversionFlagがBOOTLOADER_V1_01_OR_NEWER_FLAG(これはDeviceData.hの中で0xA5として定義されています)となっているかで判別しているようです。そしてこの構造体は、Comm.hというヘッダファイルで、

    として宣言されています。BootInfoは受信したパケットそのもののようなので、WiresharkでUSBのパケットキャプチャをしてみました。

    Screenshot-USB bus number 1   [Wireshark 1.6.7 ]

    0040Hからが受信したデータの部分で、構造体の構造にそって読んでいくと、赤丸の部分がversionFlagで0xa5になっていることがわかります。つまり、ブートローダのファームウェア側からは正しく情報が上がっているようです。

    SIGN_FLASHは送出されているのか?

    書き込みの処理の部分全体をUSBパケットキャプチャしてみたところ、最後のパケットは、

    Screenshot-USB bus number 1   [Wireshark 1.6.7 ]-1

    となっていて、最後のコマンドは0x07で「GET_DATA」でした。遡っていってもずーっと0x07で、その前が0x06(PROGRAM_COMPLETE)が2つ、その前が0x05(PROGRAM_DEVICE)がずっと続きます。先頭から書いていくと、

    • 0x04(ERASE_DEVICE)
    • 0x02(QUERY_DEVICE)
      これに対する応答もきちんとVer1.01以上である0xa5が含まれていました。
    • 0x05(PROGRAM_DEVICE)がたくさん
    • 0x06(PROGRAM_COMPLETE)が2つ
    • 0x07(GET_DEVICE)はたくさん

    という感じで、0x09(SIGN_FLASH)は含まれていません。・・・・そりゃあ、ダウンロードしたプログラムが動くわけがありません。

    で、ここで気づいたことが・・・・

    よくみると、ブートローダアプリケーションに表示される文字列は、ブートローダアプリのソースコードではコメントアウトされているものになっています。つまり、ソースコードはついているけど、それをコンパイルしたアプリケーションがついているわけではないようです。・・・・おいおい。

    ちなみに、タイムスタンプをみると、ソースコードのタイムスタンプは2013年6月18日2時37分18秒で、添付されているアプリケーションのタイムスタンプは2013年6月18日2時36分36秒です。・・・・この微妙な逆転、一体何なんでしょうね・・・・。

    最終的な対策

    Qt5をコンパイルする環境はないので、 処置するとしたらブートローダのファームウェア側で処置するしかありません。
    簡単に対策するなら、SIGNATUREのチェックを外す、ということになります。

    main.c の317行め付近に、

    というコードがあって、コメントには、「ここはコメントするな!」と書いてありますが、そんなことを言っても仕方ありませんので、ここをコメントアウトしてSIGNATUREチェックをやめさせます。コメントの内容によると、書き換え中に電源を切ったりUSBケーブルを抜いたりすると、復活できなくなる・・・・ということみたいです。

    ここをコメントしてビルドしたブートローダを書き込んで、PORT B4をGNDに落としてブートローダを起動、ブートローダアプリケーションでCDC Basic Demoを書き込んでみました。その後、PORT B4をHにしてブートローダアプリの「Reset Device」をクリックしたところ、無事にCDC Basic Demoが動作しました。

    疲れてしまったので、PIC18F14K50でのトライはまた今度ということで。

    おまけ

    HIDブートローダを使う場合の各PICでのリンカスクリプトは「microchip_solutions_v2013-06-15/USB/Device – Bootloaders/HID/Firmware – PIC18 Non-J/Linker files for applications」にあるようです。


    コメントをどうぞ(日本語のみ/Only in Japanese)

    日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)