Vývoj USB 1.1 řadiče na FPGA: praktický průvodce připojením HID zařízení
Vytvoření vlastního USB řadiče na bázi FPGA vyžaduje hluboké pochopení protokolu a hardwarových specifik. V tomto průvodci se rozebírá implementace řadiče pro standard USB 1.1 s připojením klávesnice, včetně klíčových modulů, inicializace zařízení a zpracování HID deskriptorů.
Hardwarové specifikace USB 1.1
USB 1.1, na rozdíl od USB 2.0, používá dvě digitální linky (D+ a D-), které pracují v protifázi, což umožňuje jejich přímé připojení k digitálním výstupům FPGA. Existují dva podstandardy: Low Speed (1,5 Mbit/s) a Full Speed (12 Mbit/s). Pro určení rychlosti zařízení přivádí logickou jedničku na linku D- pro Low Speed nebo na D+ pro Full Speed při připojení.
Důležité hardwarové nuance:
- Datové linky musí být připojeny k zemi přes rezistory na straně hostitele.
- Je nutná ochrana před napětím 5V na vstupy FPGA, například pomocí Zenerových diod na 3,3V.
- Pro testování lze použít desky jako STM32 BluePill, které emulují HID zařízení.
Architektura modulu USB řadiče
Řadič se skládá z několika vzájemně propojených modulů, z nichž každý odpovídá za konkrétní úlohu v zásobníku protokolu USB.
- M_DATA — hlavní modul pro přenos a příjem dat.
- M_CRC16_USB — vypočítá kontrolní součet CRC16 pro datové pakety.
- M_GET_PACKET — řídí proces příjmu dat: odešle token IN, přijme paket, zkontroluje CRC a odešle potvrzení (ACK).
- M_RECEIVE_MODULE — modul pro příjem dat, zahrnující:
* M_GET_DATA — přímo čte data ze sběrnice.
* M_MEMORY_BUF_CRC16 — buffer s výpočtem CRC16 za běhu.
* M_BUF_RETRANSLATOR — retransluje data z bufferu pouze po úspěšné kontrole CRC.
- M_SEND_PACKET — řídí proces odesílání dat: token OUT, přenos dat, čekání na ACK.
- M_TRANSMIT_MODULE — přenáší data, tokeny, pakety začátku rámce (SOF) a služební pakety.
- M_CRC_5 — vypočítá kontrolní součet CRC5 pro tokeny, SOF a potvrzení.
- M_SEND_DATA — odesílá datové pakety s CRC16.
- M_SEND_TOKEN — odesílá tokeny, SOF a potvrzení (vše s CRC5).
- M_SEND_END_OF_PACKET — vytváří signál konce paketu (EOP).
- M_DATA_TRANSFER — fyzická vrstva pro přenos bitů na sběrnici.
- M_SOF_SENDER — periodicky odesílá pakety SOF pro synchronizaci.
- M_MAIN_AUTOMAT — hlavní konečný automat, který řídí stav řadiče.
- M_USB_INIT — provádí inicializaci USB zařízení.
- M_TRANSACTION — zpracovává řídicí transakce (Control Transfers).
- M_HID_ANALYZER — analyzuje HID deskriptory zařízení pro pochopení formátu dat.
- MEMORY_BUF (4 instance) — buffery pro data analýzy HID.
Proces inicializace zařízení
Inicializace začíná určením rychlosti zařízení podle stavu linek D+ a D-. Následuje přísná sekvence kroků, implementovaná v hlavním konečném automatu (M_MAIN_AUTOMAT).
always @(posedge clk)
begin
if (rst)
begin
State_main <= S_IDLE;
SOF_En <= 1'b0;
FullSpeedConnect <= 1'b0;
// ... reset dalších signálů
end
else
begin
case (State_main)
S_IDLE:
// Čekání na připojení a určení rychlosti
if (Dm & !Dp) // Low Speed
begin
FullSpeedConnect <= 1'b0;
ResetTime <= 15_000; // 10 ms při 1.5 MHz
// ... nastavení časovačů pro Low Speed
State_main <= S_POWER_RISE;
end
else if(Dp & !Dm) // Full Speed
begin
FullSpeedConnect <= 1'b1;
ResetTime <= 120_000; // 10 ms při 12 MHz
// ... nastavení časovačů pro Full Speed
State_main <= S_POWER_RISE;
end
S_POWER_RISE:
// Čekání 100 ms na stabilizaci napájení zařízení
if (WaiteCount == PowerRiseTime || SKIP_POWER_RISE)
begin
WaiteCount <= 0;
State_main <= S_USB_RESET;
end
S_USB_RESET:
// Reset zařízení (0 na D+ a D- po dobu 10 ms)
if (WaiteCount == ResetTime || SKIP_POWER_RISE)
begin
WaiteCount <= 0;
State_main <= S_INIT_SOF_SENDER;
end
S_INIT_SOF_SENDER:
// Okamžitý start odesílání paketů SOF po resetu
if (Eof1) State_main <= S_WAITE_SOF;
else SOF_En <= 1'b1;
S_WAITE_SOF:
if (!Eof1) State_main <= S_USB_RESET_RECOWERY;
S_USB_RESET_RECOWERY:
// Obnova po resetu (10 ms)
if (WaiteCount == ResetTime || SKIP_POWER_RISE)
begin
WaiteCount <= 0;
State_main <= S_USB_INIT;
end
S_USB_INIT:
// Provedení sekvence řídicích transakcí
if (InitComplite)
begin
State_main <= S_REQUEST;
end
else if (InitFail)
State_main <= S_FAIL;
// ... stavy pro dotazování zařízení (S_REQUEST, S_WAIT atd.)
endcase
end
end
Kriticky důležitý moment: odeslání paketů SOF (Start Of Frame) musí začít ihned po fázi resetu (S_USB_RESET), nikoli po období obnovy. SOF slouží k synchronizaci zařízení s hostitelem. Pro Full Speed jde o paket s číslem rámce a CRC5, pro Low Speed je to pouze signál EOP (dva takty s nulou na obou linkách). Zpoždění s odesláním SOF může vést k nefunkčnosti některých zařízení.
Analýza HID deskriptorů a dotazování zařízení
Po úspěšné inicializaci, která zahrnuje přiřazení adresy zařízení (odlišné od 0), řadič přechází do stavu dotazování (S_REQUEST). Modul M_HID_ANALYZER zkoumá deskriptory zařízení, získané přes řídicí transakce, aby určil formát a velikost datových paketů. Například pro klávesnici je nutné extrahovat informace o počtu reportů, jejich velikosti a identifikátorech.
Typický cyklus dotazování HID zařízení:
- Odeslání tokenu IN na adresu zařízení a koncovou bodu (Endpoint) 1.
- Příjem datového paketu.
- Kontrola CRC16.
- Odeslání potvrzení ACK v případě úspěchu.
- Extrakce užitečných dat (např. scan kódů kláves), přeskočením služebních bajtů na začátku paketu.
- Čekání na stanovený interval (např. 24 ms) před dalším dotazem.
Pokud zařízení odpoví NAK (Not Acknowledged), hostitel později opakuje požadavek. Při absenci odpovědi nebo chybách může řadič přejít do stavu čekání nebo provést opětovnou inicializaci.
Co je důležité
- Včasné odeslání SOF: Spuštění paketů Start Of Frame ihned po resetu zařízení je kritické pro stabilní provoz, zejména s různorodými HID zařízeními.
- Ochrana vstupů FPGA: Je nutná schématická ochrana proti zvýšenému napětí na datových linkách, protože standard USB používá úrovně 3,3V/5V.
- Analýza deskriptorů: Správná práce s HID zařízeními není možná bez parsování deskriptorů pro pochopení struktury dat.
- Zpracování chyb: Řadič musí správně zpracovávat NAK, STALL a časové limity, zajišťující odolnost spojení.
- Rozdělení odpovědnosti: Modulární architektura zjednodušuje ladění a umožňuje opakované použití komponent pro další projekty.
— Editorial Team
Zatím žádné komentáře.