[Armadillo:04704] [a500fx][ttymxc] 送っていない 0xff を連続受信するモードに陥る
URATAN Shigenobu
email@hidden
2009年 10月 27日 (火) 17:01:17 JST
うらたんと申すものです。
以下の環境で、Armadillo-500 FX、Armadillo-500 のあたりをとっております。
・Armadillo-500 FX 液晶モデル開発セット
・Armadillo-500 + 開発ボード
・atmark-dist-20090318.tar.gz
・linux-2.6.26-at6.tar.gz
・atde2-20090403.zip
さて UART を使うプログラムを作成して動作を確認していたところ、
以下のような挙動に遭遇してしまいました。
取り急ぎ ご報告いたします。
- * - * -
症状
9600bps に設定された ttymxc4 に、115200bps の SPACE, '@', '`' などを
送信すると、(何も送信していないのに) 0xff を連続受信し続けるモードに
なることが たいへんよくある。
構成
a500fx
+-----------+ +----------+
| ttymxc0 | console | TeraTerm |
| 115200 |<-------->| 115200 |(マザーボードの COM ポート)
| | +----------+
| | +----------+
| ttymxc4 | '@' | TeraTerm |
| 9600 |<---------| 115200 |(USB-Serail 変換 USB-RSAQ3 を使用)
+-----------+ +----------+
再現手順 [1]
(1) uart の受信状況が見える debug-kernel を用意する (patch は末尾に)
(2) debug-kernel と標準の userland で起動
(3) console より root で login
(4) /etc/inittab を編集し、ttymxc4 を 9600bps に変更
(5) killall getty; init -q して ttymxc4 を 9600bps に再設定
(6) 9600bps にて 通常通り通信できることを確認
(7) ttymxc4 に向け 115200bps にて SPACE, '@', '`' などを送信する…
再現手順 [2] (a500で行ったので ttymxc1 だ)
(1) (ほぼ) atmark-dist 標準環境で起動
(2) /etc/inittab を編集し、ttymxc1 を 9600bps に変更
(3) killall getty; init -q して ttymxc1 を 9600bps に再設定
(4) 9600bps にて 通常通り通信できることを確認
(5) /etc/inittab を編集し、ttymxc1 を コメントアウト
(6) killall getty; init -q して ttymxc1 をフリーに
(7) cat /dev/ttymxc1 | od -hv
(8) 9600bps で 16文字送るごとにダンプされることを確認
(9) ttymxc1 に向け 115200bps にて SPACE, '@', '`' などを送信する…
暴走状態のログ
上記 再現手順 [1] において ttymxc0(115200bps) より採取したログを
以下に示します。行ったアクションほかを、ログ中に補足してあります。
アクションとログ
+---------------------------------------------------
|a500fx#
|a500fx# sr2:0x4229 status:0x810d <--- 9600bps で [RETURN] 送信 ... 正常
|sr2:0x4229 status:0x810d <--- 同上 ... 正常
|sr2:0x4229 status:0x81ff <--- 115200bps で SPACE 送信→
|sr2:0x4229 status:0x81ff →0xff を連続受信し始める
|sr2:0x4229 status:0x81ff (ログがだーっと流れ始めます)
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x4229 status:0x81ff
|sr2:0x422b status:0x81ff <--- ここで sr2 が変化
|sr2:0x422b status:0x81ff
29 sr2:0x422b status:0x81ff ... (同じ出力 29行分を 1行に省略)
|sr2:0x422b status:0xe1ff <--- ここで status が変化
|sr2:0x422b status:0xe1ff
|sr2:0x422b status:0xe1ff
|...
|..
|. 途中を uniq -c したもの
| 210 sr2:0x422b status:0xe1ff
| 1 sr2:0x4229 status:0xe1ff
| 255 sr2:0x422b status:0xe1ff
| 1 sr2:0x4229 status:0xe1ff <--- 256回に 1回は sr2 が違う?
| 255 sr2:0x422b status:0xe1ff
| 1 sr2:0x4229 status:0xe1ff
| 255 sr2:0x422b status:0xe1ff
| 1 sr2:0x4229 status:0xe1ff
| 255 sr2:0x422b status:0xe1ff
| 1 sr2:0x4229 status:0xe1ff
| 118 sr2:0x422b status:0xe1ff
+---------------------------------------------------
その他の条件
●a500fx において (A5027Z-C, S/N 080503-003132, ChipRev: M91EN)
・ttymxc0 でも ttymxc4 でも出た。
・マザーボードの COM ポートでも USB-Serial 変換(USB-RSAQ3)でも出た。
・暴走中にシリアルのコネクタを抜いても連続受信状態は継続する。
・受信 4800bps 設定でも 57600bps で送信することにより出る。
他の組み合わせでは、下の表のとおり合理的(?)な受信エラー状態となる。
** ttymxc4(9600bps 設定)に PC から異なったボーレートで
** 文字を送ったときの URXD レジスタの値と反応
ttymxc4 (9600) +---------------+---------------+
URXD reg status | ' ' (0x20) | '@' (0x40) |
+-----------------+---------------+---------------+
| 300bps(1/32) | 0xd900,0xd900 | 0xd900,0xd900 | <== (2)
| 600bps(1/16) | 0xd900,0xd900 | 0xd900,0xd900 |
| 1200bps (1/8) | 0xd900,0xd900 | 0xd900,0x8180 |
| 2400bps (1/4) | 0xd900,0x8180 | 0xd900,0x81f8 |
| 4800bps (1/2) | 0xd900,0x81f8 | 0xd900,0x81fe |
+-----------------+---------------+---------------+
| 9600bps (1/1) | 0x8120 | 0x8140 | <== (1)
+-----------------+---------------+---------------+
| 14400bps(x1.5) | 0x81e8 | 0x81d0 | <== (3)
| 19200bps (x2) | 0x81f8 | 0x81fc |
| 38400bps (x4) | 0x81ff | 0x81fe |
| 57600bps (x6) | 0x81ff | 0x81ff |
| 115200bps (x12) | 0x81ff (!) | 0x81ff | <== (4)
| 230400bps (x24) | (no-sense) | (no-sense) | <== (5)
+-----------------+---------------+---------------+
(1) 0xNNCC の下2桁:CC が文字コードです。あってます。
(2) しゃべるほうが遅いので 2文字到着したと扱われてます。
(3) しゃべるほうが速いので start-bit は(誤)検出しても
データは拾いきれません。
(4) この (!) のとき、問題のモードに入るときがあります。
(5) しゃべるのが速すぎて start-bit (誤)検出もせず、
なにも来ない扱いです。
** ttymxc4(4800bps 設定)に PC から異なったボーレートで
** 文字を送ったときの URXD レジスタの値と反応
ttymxc4 (4800) +---------------+---------------+
URXD reg status | ' ' (0x20) | '@' (0x40) |
+-----------------+---------------+---------------+
| 38400bps (x8) | 0x81ff | 0x81ff |
| 57600bps (x12) | 0x81ff (!) | 0x81ff | <== (4)
| 115200bps (x24) | (no-sense) | (no-sense) | <== (5)
+-----------------+---------------+---------------+
●a500 において (A5001Z-B, S/N 070201-003125, ChipRev: M45G)
・a500 でも ttymxc1(9600bps) で出た、他は未確認。
考察
・再現手順 [2] であればユーザープロセスにも CPU が回ることから、
ハードウェアの「受信*中*ステートに中途半端に入って抜けない」問題か?
(再現手順 [1] だと debug 出力で CPU/uart を食い尽くすようで)
余談
・kernel から見たレジスタアドレスが、iMX31 仕様書のアドレス値に対して
オフセットされているのはなぜ?
・今回の問題とは(たぶん)まったく関係ないが、
mxc_uart.c の この(patch参照) if() 文の記述、ボクはまずいと思います。
・cp /dev/xxx ... すると device file そのものがコピーされちゃうんですね !?
以上ですが、よろしくお願いいたします。
--
email@hidden
==================== patch ここから ====================
diff -c orig/linux-2.6.26-at6/drivers/serial/mxc_uart.c linux-2.6.26-at6/drivers/serial/mxc_uart.c
*** orig/linux-2.6.26-at6/drivers/serial/mxc_uart.c Fri Jun 19 15:49:16 2009
--- linux-2.6.26-at6/drivers/serial/mxc_uart.c Tue Oct 27 11:05:37 2009
***************
*** 339,344 ****
--- 339,345 ----
sr2 = readl(umxc->port.membase + MXC_UARTUSR2);
while (((sr2 & MXC_UARTUSR2_RDR) == 1) && (max_count-- > 0)) {
+ // ~~~~is this truly correct ?~~~~
ch = readl(umxc->port.membase + MXC_UARTURXD);
flag = TTY_NORMAL;
***************
*** 351,356 ****
--- 352,361 ----
* character. Perform the appropriate actions based on the
* error bit that was set.
*/
+ // if(umxc->port.membase == (char *)0xfc090000/*mxc0*/) ...
+ if((int)umxc->port.membase == 0xfc0b4000/*mxc4*/) {
+ printk(KERN_INFO "sr2:0x%04x status:0x%04x\n", sr2, status);
+ }
if (status & MXC_UARTURXD_ERR) {
if (status & MXC_UARTURXD_BRK) {
/*
==================== patch ここまで ====================
armadillo メーリングリストの案内