2014.2.24

前へ
次へ
ホームページトップへ戻る

CPLD+SIMMを使ってUSBプロトコルの解析を!
VHDLを速習! XC95144XL+16MB・SIMMを使ってUSBプロトコルアナライザを作ってしまいました!
主目的は差し迫った事情からUSBプロトコルの解析をすることだったのですが、その手段として選んだのがコレ!


[第21回]


●違いが分かりましたでしょうか?

前回は私が所有するWindows7(Homepremium、32bit)に秋月のPICWRITERを接続したときの記録と、吉崎様からお借りしたWindowsXPパソコンに、秋月のPICWRITERを接続して得られた記録とをお見せして、両者の「驚くべき違い」が分かりますでしょうか?と書いたところで終わってしまいました。
もう一度下にその違いがよくわかる部分を再掲してお見せします。
こちらが私のWindows7パソコンです。

0087428 SOF FNO=46F [101001011111011000110110]
0087523 SOF FNO=470 [101001010000111000100001]
        SETUP ADRS=01 ENDP=00  [101101001000000000010111]
        DATA0 
        80 06 00 01 00 00 12 00   GET_DESCRIPTOR DEVICE
        ACK 
0087617 SOF FNO=471 [101001011000111000111110]
        IN ADRS=01 ENDP=00  [1001011010000000000]
        DATA1 
        12 01 00 02 00 00 00 08   
        ACK 
0087711 SOF FNO=472 [101001010100111000111100]
        IN ADRS=01 ENDP=00  [1001011010000000000]
        DATA0 
        D8 04 33 00 02 00 01 02   
        ACK 
0087804 SOF FNO=473 [101001011100111000100011]
        IN ADRS=01 ENDP=00  [1001011010000000000]
        DATA1 
        03 02 7F 7E FB 81 D2 0B   
0087898 SOF FNO=474 [101001010010111000111101]
        OUT ADRS=01 ENDP=00  [1000011110000000000]
        DATA1 
        00 00 FB 80 D2 FB 4B 2F   
0087991 SOF FNO=475 [101001011010111000100010]
0088086 SOF FNO=476 [101001010110111000100000]
        SETUP ADRS=01 ENDP=00  [101101001000000000010111]
        DATA0 
        80 06 00 02 00 00 FF 00   GET_DESCRIPTOR CONFIG
        ACK 
0088180 SOF FNO=477 [101001011110111000111111]
        IN ADRS=01 ENDP=00  [1001011010000000000]
        DATA1 
        09 02 29 00 01 01 02 80   
        ACK 
0088274 SOF FNO=478 [101001010001111000101111]
        IN ADRS=01 ENDP=00  [1001011010000000000]
        DATA0 
        32 09 04 00 00 02 03 00   
        ACK 
0088367 SOF FNO=479 [101001011001111000110000]
        IN ADRS=01 ENDP=00  [1001011010000000000]


こちらが吉崎様からお借りしたWindowsXPパソコンです。

0025584 SOF FNO=650 [101001010000101001111010]
0025584 PRE 
0025678 SOF FNO=651 [101101011000101001100101]
0025758 DATA0 
        80 06 00 01 00 00 12 00   GET_DESCRIPTOR DEVICE
        ACK 
0025760 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025761 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025763 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025765 IN ADRS=04 ENDP=00  [1001011000100000000]
        DATA1 
        12 01 00 02 00 00 00 08   
        ACK 
0025772 SOF FNO=652 [101001010100101001100111]
0025773 PRE 
0025777 IN ADRS=04 ENDP=00  [1001011000100000000]
        DATA0 
        D8 04 33 00 02 00 01 02   
        ACK 
0025778 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025779 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025779 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025781 IN ADRS=04 ENDP=00  [1001011000100000000]
        DATA1 
        03 02 7F 7E 1B 50 7A 7F   
0025783 OUT ADRS=04 ENDP=00  [1000011100100000000]
0025807 SETUP ADRS=04 ENDP=00  [101101000010000000010100]
        DATA0 
        80 06 00 02 00 00 09 00   GET_DESCRIPTOR CONFIG
        ACK 
0025809 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025810 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025811 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025813 IN ADRS=04 ENDP=00  [1001011000100000000]
        DATA1 
        09 02 29 00 01 01 02 80   
        ACK 
0025814 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025815 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025817 IN ADRS=04 ENDP=00  [1001011000100000000]
        DATA0 
        32 C1 6A 1B 50 7A 7F C0   
0025818 OUT ADRS=04 ENDP=00  [1000011100100000000]
0025856 SETUP ADRS=04 ENDP=00  [101101000010000000010100]
        DATA0 
        80 06 00 03 00 00 FF 00   GET_DESCRIPTOR 
        ACK 
0025857 ACK 
0025858 IN ADRS=04 ENDP=00  [1001011000100000000]
        NAK 
0025866 SOF FNO=653 [101001011100101001111000]

違いが分かりましたでしょうか?

●これはスピード違反です!

私自身はその違いに全く気がつきませんでした。
毎日何回も何回もデータを取り直して、そしてそれこそ穴があくほど見比べていたのですけれど、気が付きませんでした。
いくら眺めていても埒があきませんので、攻める方向を変えて、PICの中の動きも同時進行で見えるようにツールを組み立て直して、PICの中と外の動きを比べてみて、やっと気が付きました。

吉崎様からお借りしたパソコンのUSB信号は余りに速過ぎたのです。
いえ。クロックのことではありません。
どちらも12MHzで、そこに違いはありません。
問題はホストから送出されるコマンドのタイミングの速さの違いにありました。

上の2つのリストの違いはそこにありました。
もう一度最初のリストを見てください。
FNO(フレームナンバー)が並んでいます。
その間隔は1msです。
最初のリストはSETUPコマンドやINパケットが1フレームに1回の割合で出されています。
そもそものPICUSBプログラムの作成を開始するにあたって参考にした「トランジスタ技術」2000年6月号の参考例(202ページ)でも全く同じ記載でしたので、そういうものだとすっかり信じ込んでしまいました。

ところが吉崎様からお借りしたWindowsXPパソコンでのリストを見てみますと、そこではとんでもないことがおきています。
このリストはFNO=651と652のわずか2フレームの間でのコマンド、データのやり取りであることに注目してください。

なんと1つのフレームの中で矢継ぎ早にSETUPコマンドとINパケットが送出されていたのです。

たとえば0025678行のSOF FNO=651で始まったフレームでは、DATA0でコマンドが送出されたあと、INパケットが連続して4回も送出されています。
PICWRITERはとてもそれには応答できないので、連続してNAKを返しています。

ところが私のPICプログラムはといいますと、何しろ1msに1回応答すればよいと信じてしまっていたものですから、間に合わなかったらNAKを返す、というようには作っていなかったのでした。
なにしろ1msに1回ですから、間に合わないはずがないと思い込んでいました。
当然ホストからの要求にまともに応えられませんので、「不明なデバイス」にされてしまっていたのだと思います。

速いと書きましたが、それは一体どの程度の速さなのか?
上のリストでは今ひとつピンとこないかも知れません。
そこで上のリストのさらに一部分をもとの16進数ダンプデータで説明することにいたします。
下は上のリストの中ほど、25807行から25809行のあたりの16進数データと、その部分を解読したものです。

D6PX_4.TXT
25806 FF FF FF FF FF 03 B6 10 A0 28 E0 30 A0 01 80 00 
25807 00 40 02 80 2B C1 3E A0 F4 FE FF FF FF FF FF FF 
25808 FF FF FF FF FF FF FF FF FF FF FF FF FF 7F C0 34 
25809 02 14 7D 40 AD FD FF FF FF FF FF FF FF FF FF FF 

03       B6       10       A0       28       E0       30       A0       01 
11000000 01101101 00001000 00000101 00010100 00000111 00001100 00000101 10000000
          |        |       |   |     |            |        |        |        |
  SYNC     SETUP    ADRS=4  EP=0 CRC5     SYNC     DATA0    80       06

80       00       00       40       02       80       2B       C1       3E 
00000001 00000000 00000000 00000010 01000000 00000001 11010100 10000011 01111100
     |        |        |        |        |        |        |        |
00    02       00       00       09       00       CRC16

A0       F4       FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
00000101 00101111 
     |        |
SYNC  ACK

7F       C0       34       02       14       7D       40       AD       FD 
11111110 00000011 00101100 01000000 00101000 10111110 00000010 10110101 10111111
               |        |       |    |    |                 |        |
       SYNC     IN       ADRS=4  EP=0 CRC5           SYNC    NAK

ホストからDATA0に続いて8バイトのコマンドが出力されています。
そのあと少しの間無信号(FF)が続いたあと、INパケットが送出されています。
USB機器は本来は8バイトのコマンドを受け取ったあと、それを解読して、そのコマンドに合ったデータを次のINパケットに合わせて送出することが要求されています。
それでは上の場合、コマンドデータの送出が終わってから、次にINパケットが出力されるまでの時間はどれほどでしょうか。
コマンドをPIC18F14K50のSIE(Serial Interface Engine)が受信してそれがユーザープログラムに渡せるようになるタイミングはおそらくCRC16の受信が終わってからだと思いますから、そこからINパケットに続いてCRC5が受信されるまでの間は28バイトデータほどです。
USBのクロックは12MHzで28×8=224bitですから、224/12≒18.7μsです。
たったそれだけの時間でコマンドを解読してデータを送り返さなければなりません。
さすがにそれはクロック48MHzで動くPIC18F14K50でもいかにもきびしい要求です。
さきほどのWindowsXPに接続したPICWRITERでも3回NAKを返したあとでやっとデータを送出しています。

この速さは一体どういうことなのでしょう。
吉崎様からメールをいただいてやっと得心いたしました。

吉崎様からお借りしたパソコンはUSB3.0という規格のインターフェイスを搭載しているということを教えていただきました。
私の所有するパソコンははっきり確認したわけではありませんが、おそらくUSB2.0規格なのでありましょう。
上の2つのデータから類推しますと、おそらくUSB2.0規格ではEnumerationのコマンドやデータの送受信は最速でも1フレームに1回の頻度で行なわれると思われるのに対して、USB3.0では1つのフレームで複数回の送受信が行なわれるようです。

それで私のところではWindows7でも認識されるのに、お客様によってはWindowsXPでも認識されないというおかしな現象がおきていたのでした。
やっと原因らしきものがわかってきましたので、さっそくそれに合わせてPICプログラムの改良に取り掛かりました。

CPLD+SIMMを使ってUSBプロトコルの解析を![第21回]
2014.2.24upload

前へ
次へ
ホームページトップへ戻る