PICのUSB割込の優先度を変更。
リコモンの赤外線信号をPCに転送するのに、PIC18Fシリーズの18F14K50でコードを書いてみた。赤外線受信モジュールをPICの入力端子に接続して、端子の状態変化に対して高優先度割込みを設定。状態変化が起きるごとにタイマをリセットして、タイマ値から時間経過を測定して、リングバッファを経由して同時並行でUSBを介してPCに転送という感じ。しかしオシロの結果と比較すると妙に誤差が大きい。考えてみたらUSBもフレームワークで高優先度割込に設定されていたのだった。USBの処理って結構重そうだから、これが原因かも。
試しに赤外線受信中にUSB転送をするのをやめて、一通り受信し終わってからUSBに転送するようにしてみたところ、誤差が大幅に改善された。とはいえ、このPICはRAMが768バイトしかなく、USBのバッファとかランタイム用で512バイト近く持っていかれてしまい、スタックにも128バイトくらいは欲しい(USBフレームワークからアプリのエントリに来た時点で64バイトくらい消費されてしまっている)ので、アプリには128バイトくらいしか残されていない。しかも最初に実験に使っていた東芝のリモコンは割と信号長が短かくて、これなら頑張れば行けるかもと思っていたのが、ふと日立のエアコンのリモコンを試したら、その10倍くらいデータ量が多くてびっくり。流石に無理かもしれない。赤外線受信だけならまだしも、このあとXBeeという無線モジュールを介して別の場所にあるリモコン対応機器を制御したいなと思っているので。PIC24の24F64GB002のカタログを横目で見つつ、他に手はないかと悪あがき。そもそもUSB割込を高優先度にしなければ良いような気がしてきた。USBのところはバッファもふんだんに割り当てられているし、そもそもフレームワークではポーリングという選択肢も用意されている。それならUSBを低優先度割込にして、高優先度割込の処理をなるべく軽くしておいてやればいいのではないか。
とはいえUSBフレームワークのソースを見ても、優先度設定のオプションが見当たらない。仕方がないのでパッチを当てることにした。USBのフレームワークのMicrochip/Include/USB/usb_hal_pic18.hというファイルの383行あたり。
# if defined USB_INTERRUPT_PRIORITY_LOW (追加)
#define USBEnableInterrupts() {RCONbits.IPEN = 1;IPR2bits.USBIP = 0;PIE2bits.USBIE = 1;INTCONbits.GIEH = 1;} (追加)
# else (追加)
#define USBEnableInterrupts() {RCONbits.IPEN = 1;IPR2bits.USBIP = 1;PIE2bits.USBIE = 1;INTCONbits.GIEH = 1;}
# endif (追加)
あとは自分のアプリケーションのusb_config.hの中に、USB_INTERRUPT_PRIORITY_LOWのdefineを追加してやる。
//#define USB_POLLING #define USB_INTERRUPT #define USB_INTERRUPT_PRIORITY_LOW
とりあえず、これで動いているようだ。





