2007年11月2日金曜日

LuaPlayer+シリアル通信復活!!

LuaPlayer@3.xx カーネル のシリアル通信が復活!

3.xx カーネルではシリアル通信が出来ないのかとあきらめていたところ,新型 PSP ですでにシリアル通信が動いているとの情報を頂き,それを組み込んでみた.…だが,やっぱり動かない.んー残念!! こうなりゃ意地だと,いろいろ解析してみると奇妙な事が分かった.

シリアル通信のルーチンでは,「シリアルデータを受信してバッファに書き込む割り込みルーチン」と,「バッファから 1バイト読み出すスレッド」から成り立っており,割り込みルーチンと読み出しスレッドは変数を介して通信するのだが,割り込みルーチンが書き込んだ値を読み出しスレッドで読めないという事に気づいた (無論変数は volatile 指定している).さらに解析を進めたところ,大きい配列を介すると,変数を介した通信が成功する.

何でだ? と思って,C コードをアセンブラに落としてみた.

上手くいかないほうのコード:

lw $3,%gp_rel(uRxBufWp)($28)


これは,uRxBufWp という変数の値を,レジスタ $3 にロードしているところだが,怪しいのが %gp_rel(...)($28) で,$28 からの相対アドレスでロードする事によって,命令数を少なくしている.$28 はおそらくスレッド開始時に初期化されて,その後変更されないのだろう.

一方上手くいくほうのコード:

lui   $2,%hi(cRxBufWp)     ; $2 = (cRxBufWp のアドレス値の上位)
addiu $2,$2,%lo(cRxBufWp) ; $2 += (cRxBufWp のアドレス値の下位)
lw $4,0($2) ; $4 = [$2], すなわち $4 には変数 cRxBufWp の値が入る


このように,$28 の相対アドレスではなく,$2 に直接 cRxBufWp のアドレス値を代入してから,$4 に cRxBufWp の値をロードしている.

以上の事から推測すると,スレッドごとに $28 の値が異ることがあり,C 言語上では同一の変数を指定していても,異なるスレッド同士では実際のアドレスは異なる事がありうる?

でもこんな仕様ありえねー.コレってコンパイラか BIOS か,なんかのバグだよなぁ.

-----

で,シリアル通信のほうは,けっきょく元々のソースコードの,通信に使用していた変数をちょこっと変更するだけで,無事動いたヽ(´ー`)ノ

というわけで,データロガー + GPS 計画復活!!

0 件のコメント:

コメントを投稿