PIC16F1454/5/9 用のUSB512ワードCDCブートローダー

PIC16F145xはUSBガジェットを作るには最高だ。価格は安く入手もしやすい。でも問題はファームウェアの書き込みをどうするかだ。ICSPは接続が面倒くさいし、かといってマイクロチップが公開しているUSBブートローダーはプログラム領域の半分も使ってしまうため同じくUSBを使うプログラムなどには対応できない。なんか意味ねーじゃんということでUSBブートローダーを使うのは諦めていたのだが世の中には凄いことをやってのける人がいるものでUSBブートローダーを512ワード以下で作ってしまった猛者を発見してしまった。

74hc595/PIC16F1-USB-Bootloader

6年ほど前に作ったものらしいが本人曰くPICアセンブラもMPLABXも大嫌いということで個人的にはとても好感が持てそうな人のようだ。お友達になってもらいたいかも。(笑)

windowsで試したところ全く動作しなかったが、そもそも当時のmac-osで試験しただけらしいので動かなくても当たり前。さらにDFU対応したのも発見したがドライバーの登録や事前にファイル形式変換が必要だったりして何かと面倒臭いのに加え完全に動作することはなく結局使いものにはならなかった。

majbthrd/PIC16F1-USB-DFU-Bootloader

でも、512ワードのブートローダーがあるとなんとなく幸せになれそうな気がしたのでwindows/linuxでも使えるように改良してみることにした。見たくもない理解したくもなかったPICアセンブラ命令+USBハードウェアを相手に戦ってみたが全く埒が明かない状況が暫し続いた。が、分からないながらもプログラムを見続けているうちに少しずつ光が見えてくるようになるものだ。幾度となく諦めかけたがとうとう動作させることができてしまったのだ。これは奇跡的というかもう嬉しい限り。(/・ω・)/

元のプログラムの大きな問題点と思うのは、次の通り。
1.GNU-gpasmでしかコンパイルできない。mpasmではエラーになる。
2.USBのGET-CONFIG-DESCRIPTOR要求時に不正なデータを返すためOSがUSB認識に失敗する。(ことがある)
3.フラッシュ書き込み時のベリファイに失敗する。(ことがある)
4.アドレス0x0800以上のコードを実行中にHW割り込みが発生すると誤動作する。
5.アプリを書き込んでも実行できない可能性がある。(恐らく問題ないとは思うが)
6.アプリ書き込み後にブートローダー・モード(書き込みモード)に入るにはGPIO(RA3)をGNDに落とす外部スイッチが必要。(仕様)

これらを修正した上で、外部スイッチなしで再プログラムできるように特別なソフトウェア・リセット、或いは、ウォッチドック・リセットでブートローダーモードに入れるようにしてみた。

但し、ウォッチドック・リセットを使う方法については開発段階ではいいのかもしれないが、本番運用中に突然ブートローダー・モードに入られて、だんまりになるのはいかがなものか?と言う気もするのでソース・コード上で設定(WDT_BOOTLOADER_MODE=1)するようにしてみた。開発環境専用のブートローダーとしては便利かも。

細かいところまでは見てないしこれ以上やる気もないのでバグってる可能性は否定できないが、今のところ私の環境では問題なく動作はしている。

ソフトウェアで、ブートローダー・モードに入るためには、割り込みを禁止してからFSR1L=0xFD,FSR0L=0xBEを設定後にreset命令を実行すれば良い。これはソフトウェアリセット時にFSR1L/FSR0Lの値が変更されないことを利用している。ソフトウェアリセット時に値が変更されない他のレジスタを使っても良いだろう。このへんはデータシートを真剣に読まないとわからないことではあるが、安直に人に聞く前に可能な限り自分で精いっぱい調べてみる努力をしてみよう。それができるかどうかがご自身の将来に大きな与える影響を与えることになると思うので...

ちなみに、元ソースではUSB電源設定(セルフパワー/バスパワー&消費電流等)をアプリから変更できるようになってはいたが、512ワードでは厳しいことに加え今後のメンテナンスのことも考えた結果、バスパワー(100mA)固定としコード領域を削減している。

なお、CDC-ACMデバイスなので古いOSでないかぎりOS側に特別なドライバー等の組み込みは必要ない。

【アブリをブートローダー対応にする方法】

1.リンカー設定が必要

[XC8 Linker commandline option] –codeoffset=0x200

or

[MPLABX] XC8-linker->Additinal options->Codeoffset 0x200

2.ウォッチドッグを使用する場合はソフトウェア制御が必要。

ウォッチドッグは次のコードで制御可能。スリープ中にウォッチドッグを停止したい場合にも制御が必要となることに注意しよう。

WDTCONbits.SWDTEN = 1 or 0; // 1=enable, 0=disable

3.アプリ側のCONFIG設定は無視され、常にブートローダーのCONFIG設定で動作することに注意。

不都合がある場合は、設定を書き換えたブートローダを使うしか方法がない。

【USBブートローダー】

【PC側の書き込みユーティリティ】

【ダウンロード】
boot loader: MPLABX-project
pc-utility: eclipse-cdt(mingw)-project