むしろハマったのはSDCC周辺。このあたり、やっぱり非公式ツールチェインは辛い。大きくハマったのは次の2点。
- bootloaderを使おうとすると色々細工が必要で、信頼できるコードが書けない
- USB用RAMのポインタをアドレスから普通に作ると動かない
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*という特殊な指定が必要。特定用途レジスタの略だと思う。こっちはシステムヘッダを眺めて予想。