・2022/07/17
USBの通信プロトコルを勉強する
(今まで漠然としていた USBデバイスの通信方法を理解します)
Tags: [FPGA], [電子工作], [Xilinx XC6SLX9], [FPGA 2022]
● USBの信号仕様、通信プロトコルを勉強する
今まで漠然としていた USBデバイスの通信方法を理解します。
今回は USBの
・信号仕様
・通信プロトコル
の両方を勉強します。
● AVRマイコンの GPIOを操作して自前で USB HOST機能を実装する
いしかわきょーすけさんの製作記事。
USB ホスト倶楽部 - asahi net
当時はこの AVRの実装をマルパクして Philips LPC2106の ARMマイコンに移植しました。
・2004/03/16
OLIMEX LPC-H40(Philips LPC2106)
MOTHER BOARD for LPC-H40(LPC-H2106) and ASM Sample Program.
しかし、その当時は単純に移植しただけで USBの通信プロトコル等は理解しませんでした。
ビット送受信のタイミングとビット送受信のマイコンチップの違い部分だけを変更したら動いたので。
今回は、プログラムの内容を読んで実装から USBの通信を理解します。
いしかわさんのプログラムの内容と下記の資料が USBの通信プロトコルの理解に役立ちました。
USB Human Interface Devices
USBspcs.pdf (703KB) 1.0D 14/6/10 USB概説
TECH_I Vol.30~「改訂新版 USBハード&ソフト開発のすべて」
USB の基礎知識 Interface 2007年 1月号
USBの通信速度
High Speed - 480Mbits/s USB 2.0
Full Speed - 12Mbits/s USB 1.1
Low Speed - 1.5Mbits/s USB 1.1
USB Low Speedは USBデバイスの D-にプルアップ抵抗(1.5kΩ)
USB Full Speed USBデバイスの D+にプルアップ抵抗(1.5kΩ)
(これでデバイスの接続を確認できる)
USB Host側は D+と D-に大きいプルダウン抵抗(15kΩ)
(デバイス側のプルアップ抵抗が勝つ様にプルダウン側の抵抗値が大きい)
USBの通信は NRZI符号化データ
(0の時は電位を反転し、1の時は変化させない)
USBの通信で 1が 6個連続した場合は 0を入れる(ビット・スタッフィング)
(信号の状態が変化しないからタイミングのズレが発生するから)
USBの信号線の状態
State | Low speed | Full speed |
J | D+ = L、D- = H | 左記の逆 |
K | D+ = H、D- = L | 左記の逆 |
SE0 | D+ = L、D- = L | 左記と同じ |
SE1 通常は発生しない | D+ = H、D- = H | 左記と同じ |
Sync | KJKJKJKK(00000001) |
EOP | SE0、SE0、J |
USB (Communications)
そして、PicoBlazeでの実装を試します。(ARMマイコンに移植した時と同じくマルパク)
・2022/07/01
Xilinxの FPGA Spartan-6で PicoBlaze KCPSM 8 ビット マイクロコントローラーを動かす!
PicoBlaze KCPSM6 in Spartan-6 with ISE WebPack
●いしかわきょーすけさんの AVR 用 USB マウス/ゲームパッド接続ファームウェア
softusbh2313.lzh
の
usbh2313.asm
を読み進めます。
わかりやすいプログラムだー!
AT2313の AVRマイコンを 12MHzで動かして 8clockで USBの 1bitを送受信しています。
12MHz / 8clock = 1.5Mbps USB Low Speed
1bit = 66.67ns
●ポート定義
; AVR Port Assign List
; PortD
; bit2 USB BUS D+
; bit3 USB BUS D-
●変数
.def icount = r19 割込みカウンタ 10回ループ
.def connect = r20 USBデバイスの接続状態 0 = 未接続、1 = 接続中
.def tcount = r21 割込みタイマーで 1ms毎に +1する
.equ INTERVAL = 10 ; Interrupt Inverval(ms)(1msを 10回ループ)
rjmp TIM0_OVF ; Timer0 Overflow Handler 1ms毎の割込みタイマー
● USBの送信データをハードコードしている
先頭は SYNC 8bit長
最後は EOP 4bit長
DATA_EOP:
.db 0x02, 0x02, 0x08, 0x08 EOP = SE0,SE0,J,J
DATA_PKT_ACK:
.db 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x04 SYNC = KJKJKJKK
.db 0x08, 0x08, 0x04, 0x08, 0x08, 0x04, 0x04, 0x04 ACK = 01001011
.db 0x02, 0x02, 0x08, 0x08 EOP = SE0,SE0,J,J
DATA_PKT_SETUP_TOKEN_0:
...
●プログラムの開始
MAIN:
AVRマイコンを初期化する
--- メインループ 1ms毎に実行 ---
MAIN_LOOP:
1ms待つ
connect変数が「未接続」なら MAIN_DISCONNECTにジャンプ
MAIN_CONNECT:
USBの D-端子が Lowなら MAIN_DISCONNECTINGにジャンプ
EOPを送信する(10回送信する)
icountを +1して INTERVAL(10)に成るまで MAIN_LOOPにジャンプ
DATA_PKT_DATA_IN_1_1を送信する
USBパケットを受信する
受信した内容が NAK/STALLなら MAIN_LOOPにジャンプ
(簡易的に D-信号線の PID byteの LSB(PID0)のビットだけをチェックして、1の場合に NAK/STALLと判定している)
DATA_PKT_ACKを送信する
MAIN_PROCESS:
上で受信したパケットの内容を本格的に解析する
USB_CONVを呼び出して NRZI符号化データをバイトデータに変換する
バイトデータをイイ感じに解析して LED表示やデバグ用に通信出力を行なう
MAIN_LOOPにジャンプ
MAIN_DISCONNECTING:
USBデバイスが切断したかも?の時の処理
LEDを 500ms 全点灯にする
USBの D-端子が Lowなら connect変数を「未接続」にする
(USBデバイスの接続状態を再チェックしている)
MAIN_LOOPにジャンプ
MAIN_DISCONNECT:
USBデバイスが切断中の時の処理
USBの D-端子が Lowなら MAIN_LOOPにジャンプ
MAIN_CONNECTING:
USBデバイスが接続したかも?の時の処理
(上記の MAIN_DISCONNECTから処理が移ってくる)
LEDを 500ms 全点灯にする
USBの D-端子が Lowなら MAIN_LOOPにジャンプ
LEDを全点灯にする
USBの D+端子と D-端子を出力モードにする
USBの D+端子と D-端子を Lowにする
10ms待つ
USBの D+端子と D-端子を入力モードにする
MAIN_CONNECTING_AFTER_RESET:
1ms待つ
EOPを送信する(40回送信する)
DATA_PKT_SETUP_TOKEN_0を送信する
DATA_PKT_SET_ADDRESS_1を送信する
USBパケットを受信する(受信した内容は破棄している)
MAIN_CONNECTING_SET_ADDRESS:
DATA_PKT_DATA_IN_0_0を送信する
USBパケットを受信する
受信した内容が NAK/STALLなら MAIN_CONNECTING_SET_ADDRESSにジャンプ
(簡易的に D-信号線の PID byteの LSB(PID0)のビットだけをチェックして、1の場合に NAK/STALLと判定している)
DATA_PKT_ACKを送信する
1ms待つ
EOPを送信する
DATA_PKT_SETUP_TOKEN_1を送信する
DATA_PKT_SET_CONFIGURATION_1を送信する
USBパケットを受信する(受信した内容は破棄している)
MAIN_CONNECTING_SET_CONFIG:
DATA_PKT_DATA_IN_1_0を送信する
USBパケットを受信する
受信した内容が NAK/STALLなら MAIN_CONNECTING_SET_CONFIGにジャンプ
(簡易的に D-信号線の PID byteの LSB(PID0)のビットだけをチェックして、1の場合に NAK/STALLと判定している)
DATA_PKT_ACKを送信する
LEDを全消灯にする
connect変数を「接続」にする
MAIN_LOOPにジャンプ
USB_SND_ROM:
USBに指定のビット長で指定の内容を送信するサブルーチン
1bitの送信処理を 8clkで実装しており、1.5Mbpsに成る様にしている。
左側のカッコの数字が命令のクロック数
USB_SND_ROM_LOOP:
[3] lpm ; r0 = (Z)
[1] inc ZL
[1] out PORTD, r0
[1] dec arg1
[2] brne USB_SND_ROM_LOOP
USB_SND_ROM_LOOPEND:
USB_RCV:
USBから EOPに成るまで受信するサブルーチン
1bitの受信処理を 8clkで実装しており、1.5Mbpsに成る様にしている。
左側のカッコの数字が命令のクロック数
USB_RCV_RCVLOOP:
[1] in arg1, PIND
[2] st Z+, arg1
[1] andi arg1, 0x0C
[1] breq USB_RCV_ENDLOOP
[1] dec tmp1
[2] brne USB_RCV_RCVLOOP
USB_RCV_ENDLOOP:
USB_CONV:
下記の処理を行なうサブルーチン
USB_CONV_NRZI:
NRZI符号化データを 0/1の情報にビット変換する
USB_CONV_BYTE:
0/1のビット情報をバイトデータに変換する(1が 6ビット連続した時の処理も行なう)
HEX_TO_CHAR:
CONSOLE_PUT_CHAR:
CONSOLE_PUT_HEX1:
CONSOLE_PUT_HEX2:
CONSOLE_PUT_HEX4:
デバグ用のイイ感じの通信出力
TIM0_OVF:
タイマー割り込みの処理
tcountを +1する
DELAY_1MS:
1ms待つ
(tcountの値が変化するまで待つ)
DELAY_100MS:
100ms待つ(上記を 100回呼んでいる)
Tags: [FPGA], [電子工作], [Xilinx XC6SLX9], [FPGA 2022]
●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)
USB HOST機能を FPGAに実装する方法、FPGAの GPIOに USB HIDデバイスを接続したい!!
FPGAに USB HOST機能を実装して Low Speedの USB HIDデバイスを接続するのら
USB HOST機能が欲しいのでワンチップマイコンの GPIOで USB HOST機能を実現する
FPGAに USBデバイスを接続したいのですが、USB HOSTの通信を実装できないので困っています
OLIMEX LPC-H40(Philips LPC2106)
MOTHER BOARD for LPC-H40(LPC-H2106) and ASM Sample Program.
AMD Xilinxの FPGA Spartan-6 XC6SLX16のボードを買ってアーケード ゲームを動かす
ALINX AX309 XC6SLX9の中華クローンの XC6SLX16版を購入しました
FPGA Spartan-6 XC6SLX16でファミコンを動かす!
Xilinx FPGA Spartan-6 XC6SLX16 NES clone in ALINX AX309
Xilinxの FPGA Spartan-6で PicoBlaze KCPSM 8 ビット マイクロコントローラーを動かす!
PicoBlaze KCPSM6 in Spartan-6 with ISE WebPack
パソコンと USBで接続して使用する USB 8ch 24MHzロジック アナライザ
Cypress EZ-USB FX2LP CY7C68013A使用で内部のバッファ ICに LVC245Aを使用のチョイ性能アップ版
[HOME]
|
[BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c)
2022 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator
http://www.neko.ne.jp/~freewing/hardware/usb_protocol/