PIC16系のUSARTとMPLAB/PICCのこと(2)
(昨日の記事の続き)
■ 9.60PL2/STDはひどいバグ持ち
9.60PL2/STDでコンパイルしなおした時にどうも実行させた時の様子がおかしい。
if (TXIF)
{
ABC();
}
と書いてあるところでTXIFレジスタ(0x0cのbit4)が1になっているにも関わらず、ABC()が実行されない。MPLABのシミュレータでView→File Registersで0x0cのbit4を確認するが1になっている。
MPLAB 8.10のシミュレータは長年の実績があり、流石に完璧な動作をしているのでシミュレータがbugっている可能性はまず考えなくて良い。
View→Disassembleで調べてみると btfss 0xc,0x4 (0xcのbit4がsetされていれば次の命令をskipする)と変換されていて、部分的には正しくコンパイルされていることがわかる。
となれば、bankの選択がおかしいのだから、File Registerを表示させて、STATUSレジスタ(0x03)のbit5,6(RP0,RP1)を調べると、RP0 = 1になっている。なんてこった…bank1が選択されてやがる。
これはどこかでコード生成に失敗している証拠である。ひょっとして割り込みルーチンかと思って、まず割り込みルーチンのソースをチェック。
MOVF 0x6d,W ; W = [0x6d]
MOVWF 0x3 ; [0x3] = W
が割り込みコードから抜けるところにあるので、きちんとSTATUSレジスタ(0x03)に事前に0x6dに保存しておいた値を書き戻していることがわかる。
割り込みハンドラは悪くないことがわかったので、いつRP=1になるのか調べてみたのだが、条件付きブレークポイントが使えないのでF7(step into)を連打して追いかける。確かに関数を抜ける時にbank1を選択するコードがある。
bsf 0x3,0x5はSTATUSレジスタ(0x3)のbit5をsetする命令で、RP0 = 1の意味である。ここでbank1に切り替えているのに関数を抜ける時にbank0に戻さなくて良いのだろうか?
そもそも、
1) bankは関数が呼び出された時にはbank0だと仮定できる
2) 関数を抜ける時にはbank0だと仮定できる
3) 1),2)のような仮定はできない
かいずれなのだろうか。
常識的には、1)であって欲しい気はするが、ある関数の呼び出し元が決まっている場合、無駄なbank切り替えのコードが必要になってしまうから、大局的な最適化を行なう場合には、3)であるべきような気もする。実際、PICC STDの生成しているコードは、3)のようなのだ。そして、この最適化にbugがあるようなのだ。とほほほほ。
とまぁ、そんなこんなで丸一日潰れたので、PICがまた一段と嫌いになった私であった。
■ 追記(2008/09/14)
PRO版の9.60PL3が出た。
Corrections to problems reported since the last release;
前回のリリース後に報告されていた問題の修正
と書かれているが、このバンク切り替えのバグが修正されているのかどうかはさっぱりわからない。
また、STD/Lite版も同じバグを修正して9.60PL3を出すべきだと思うのだが、1ヶ月以上経っているのに修正版がリリースされない。とほほほほ。