2014年2月20日木曜日

SDCC for PIC Tips

PIC18F14K50でUSBデバイスを作るのにSDCCを使ってみた。PIC18F2550系とは互換性がないという事前情報だったけど、レジスタ並びやUSB用RAMのアドレスが違うくらいで、基本的にUSB周りのコードはほぼそのまま動きそう。

むしろハマったのはSDCC周辺。このあたり、やっぱり非公式ツールチェインは辛い。大きくハマったのは次の2点。

  1. bootloaderを使おうとすると色々細工が必要で、信頼できるコードが書けない
  2. USB用RAMのポインタをアドレスから普通に作ると動かない
bootloaderについて、まずtext領域を後ろ(0x800以降)にずらすために専用のリンカスクリプトを用意する必要がある。コンパイラオプションにもそれっぽい--code-locというのがあるが、指定しても動かなかった。また、割り込みベクタはbootloader側がトラップして後ろのアドレスにフォワードしてくれるので、後ろのずれた位置に割り込みベクタを配置する必要がある。こっちはコンパイラオプション--ivt-loc=0x800が正しく動く。また、crtが通常の配置を想定したコード(割り込み周りかな?)を持っているようで、ふとしたタイミングで暴走する。stdio/stdlib使ってなくても、例えばcharをやめてintでforループを回すと暴走、とか悩ましい問題が普通に起きる。海外サイトでcrtを同じフラグでコンパイルし直せば安定する、という話も見かけたけど、どこまで信じていいかわからない状態で実験を続けたくなかったので、bootloaderは諦めた。回路側でバランスをとったら、なんとかICSP指しっぱなしで書き込みしつつ、USBバスも安定ドライブできた。

USB用RAMについてはコンパイラの問題とは思わずに長時間悩んだ。いわゆるBuffer Descriptor Tableを構成するコード。コンパイラの仕様が変わったのか、バグなのか、2550の時のコードからアドレス変えただけでは動かなかった。具体的にはstruct bd* bdt = (struct bd*)0x0200;的な事をやってアドレスを作ってたんだけど、今回はこのポインタで読み書きしても値が変わっていなかった。起動すれば一応USBはしゃべるんだけど。アドレスリセットとパワーセーブ関連の割り込みだけ届いて、その後はだんまり。トランザクションが届かないってことはエンドポイントが正しく初期化できてないのかなぁ・・・というあたりから問題の目星をつけた。結局コンパイル結果を眺めながらの間違い探し。原因が判明してからは、正しい出力を出せそうな表記を勘を頼りに探すお仕事。通らないと承知で間違ったキャストをコンパイラにかけると、内部的な秘密の型がエラーメッセージを通して推測できるのでオススメ。
__at(0x0200) struct bd BD0;static struct bd __near* const bdt = &BD0;
あと、やっぱり配列でアクセスしたくなるUEP0, UEP1, ...なんかもchar *uep = (char*)&UEP0; uep[0] = ...とか書くと正しくアクセスできない。
static __sfr* uep = &UEP0;static __UEP0bits_t* uepbits = &UEP0bits;uep[0] = 0;uepbits[0].EPHSHK = 1;
って感じの__sfr*という特殊な指定が必要。特定用途レジスタの略だと思う。こっちはシステムヘッダを眺めて予想。

2014年2月3日月曜日

HIDじゃないSPX

とりあえず手元のAKI-PICで焼けるPIC18F2550で作ったpic18spx(オリジナルそのまま版)と、それを使ってPIC18F14K50に焼いて作った非HID化改造版pic18spx。
非HID化によりOS Xでも動くようになりました。あと、次にbuildしようとした時にbuildできる環境が作れる気がしないのでhexをウェブ上に置きました。必要になったらここからダウンロードして焼くべし>未来の自分。

あと、昔tcl/tkで書いたhidspx用のGUIが昔の記事にあります。開発中はもっぱらmakeを叩くんだけど、デバイスを確認する時とか、FUSEの値を確認する時、今でも使ってます。

しかし、環境乗り換えの時間的コストは高いな、やっぱり。

2014年2月2日日曜日

pic18spx/mac

HIDクラスを使ってるとOS Xで標準ドライバから制御が奪えない問題。HIDをやめれば解決するかな、と思って試したら解決した。具体的にはUSBデスクリプタのインタフェースクラスをHIDからベンダ固有値0xffに変えるだけ。picmonとか特に修正しなくても、そのまま利用できる。

むしろpic18spxのファームのbuild環境を整えるのに苦戦した。mcc18向けに書かれてるんだけど、現在はmcc18は配布されておらずMPLABXとXC8が標準。いっそXC8かSDCCに移植しようかと思ったけど、そこまで時間かけても仕方ないかな、と思って大昔のディスクを漁ってmcc18をインストール。持ってたのはMPLAB-C18-Academic-v3_30.exeとかいう古めのバージョンだったので、そのままではリンクできない。とりあえず$(TARGET).cofのビルドルールを以下のように変えて凌いだ。

$(LD) /l$(MCC18)/lib /k$(MCC18)/lkr rm$(DEVICE).lkr $(OBJS) \
/u_CRUNTIME /z__MPLAB_BUILD=1 /m$(TARGET).map /o$(TARGET).cof

とりあえず、自分のファーム作るときは最初からSDCC考えた方が良さそうだなぁ・・・。