USB Peripheral Controller John Jones 12/11/08 Embedded Systems Architecture.
-
Upload
dana-beasley -
Category
Documents
-
view
231 -
download
0
Transcript of USB Peripheral Controller John Jones 12/11/08 Embedded Systems Architecture.
USB Peripheral Controller
John Jones
12/11/08
Embedded Systems Architecture
USB Peripheral Controller
ARM USBCONTROLLER
PHY
USB Peripheral Device
HOST
System Block Diagram
Peripheral Controller
ARM PHY
Setup Data8 bytes
4 IN Endpoints128 bytes each
4 OUT Endpoints128 bytes each
AR
M In
terf
ace
PH
Y In
terf
ace
SMSC USB3300 USB PHY
Source: USB3300 datasheet
ARM & FPGA Development Board
ARM ProcessorNXP LPC2132
Xilinx FPGASpartan-3EX3CS500E
USB PHY Evaluation Board
Complete System
Interconnect
Problems…
No external address and databus on ARM
Only connection to FPGA is with P0.2 - P0.17.
Could not get 8 continuous pins to form bus
Some FPGA pins are dedicated inputs 3 port pins on the ARM were not functioning
Workaround…
Bit Bang Port 0 I/O Access FPGA using a multiplexed
address/data bus. Need to map and unmap bits to go
around bad pins.unsigned int map_bits (unsigned int data){
unsigned int upper;unsigned int lower;unsigned int join;
upper = (data & 0xF0) << 12;lower = (data & 0x0F) << 4;join = upper | lower;return join;
}
unsigned int unmap_bits (unsigned int data){
unsigned int upper;unsigned int lower;unsigned int join;
upper = (data >> 12) & 0xF0;lower = (data >> 4) & 0x0F;join = upper | lower;return join;
}
FPGA Write Function
void fpga_wr(unsigned int address, unsigned int data)
{
unsigned int map_data;
unsigned int map_addr;
map_data = map_bits(data);
map_addr = map_bits(address);
IODIR0 = P0_OUTPUTS | P0_DATA; // Set BUS to output
// Write address
IOCLR0 = P0_LA|P0_RD|P0_WR|P0_DATA; // Initialize I/O
IOSET0 = map_addr; // Drive Address
IOSET0 = P0_LA; // Latch address
// Write Data
IOCLR0 = P0_LA|P0_RD|P0_WR|P0_DATA; // Initialize I/O
IOSET0 = map_data; // Drive data
IOSET0 = P0_WR; // Latch address
IOCLR0 = P0_WR; // Negate WR
IODIR0 = P0_OUTPUTS; // Tri-state Bus
}
92 Assembly Instructions!
FPGA Read Function
unsigned char fpga_rd(unsigned int address){
unsigned int map_addr;unsigned int raw_data, data;
map_addr = map_bits(address);
// Write addressIODIR0 = P0_OUTPUTS | P0_DATA; // Set BUS to outputIOCLR0 = P0_LA|P0_RD|P0_WR|P0_DATA; // Initialize I/OIOSET0 = map_addr; // Drive AddressIOSET0 = P0_LA; // Latch AddressIOCLR0 = P0_LA; // NegateIODIR0 = P0_OUTPUTS; // Tri-state Bus
// Read DataIOSET0 = P0_RD; // Assert RD controlraw_data = IOPIN0; // Latch dataIOCLR0 = P0_RD; // Negate RD control
data = unmap_bits(raw_data);
return (unsigned char) data;}
90 Assembly Instructions!
USB Peripheral Controller
Features… Four Endpoints
4 IN Buffers – 128 bytes each 4 OUT Buffers – 128 bytes each
Setup Data Buffer Interrupt
Start-of-frame, Setup Data, IN/OUT packets Shortcomings…
No CRC support No double-buffering Manually toggle DATA0/DATA1
System Block Diagram
Peripheral Controller
ARM PHY
Setup Data8 bytes
4 IN Endpoints128 bytes each
4 OUT Endpoints128 bytes each
AR
M In
terf
ace
PH
Y In
terf
ace
ARM Interface
USB Controller
FPGA Registers
IN0CNT, IN1CNT, IN2CNT, IN3CNT ARM writes to these registers to indicate how many bytes to transmit.
OUT0CNT, OUT1CNT, OUT2CNT, OUT3CNT ARM reads these registers to determine how many bytes were received.
IN_RDY – bits 3-0 ARM sets bit(s) to indicate if buffer has been transmitted. Set by ARM. Cleared by Controller.
1 – Buffer ready (waiting to be sent) 0 – Buffer has been sent. Controller will NAK IN-packet requests to an endpoint buffer not ready.
OUT_RDY – bits 3-0 ARM reads bit(s) to determine which buffer has new data. Set by Controller. Cleared by ARM.
1 – New data available, 0 – No new data Controller will NAK OUT-packets if buffer has not been read by ARM (bit
= 0).
FPGA Registers - continued
IRQ Status Register ARM reads this register to determine source of interrupt. Four bits – four interrupt sources
Bit 0 – Start-of-Frame Interrupt Bit 1 – Setup Data Available Bit 2 – IN Buffer Ready
ARM must read IN RDY register to determine which buffer caused the interrupt.
Bit 3 – OUT Buffer Ready ARM must read OUT RDY register to determine which
buffer caused the interrupt. Write ‘1’ to clear
FPGA Registers - continued
TOGGLE ARM must alternate DATA0 and DATA1 PID’s used for IN
transactions. Four bits – one for each of the four IN buffers. Select which DATA PID to use for IN transactions.
0 – DATA0 PID 1 – DATA1 PID
Device Address 0x00 on reset ARM re-programs this register after obtaining a new device address
from host during the enumeration process.
FRAME(HIGH) and FRAME(LOW) 11 bit frame number from SOF packets.
FPGA Registers - continued
ULPI Address 6 bit address of USB3300 register to access. Refer to USB3300
datasheet. ULPI RW
Bit 0 – ARM writes ‘1’ to initiate a write. Bit 1 – ARM writes ‘1’ to initiate a read.
ULPI Data 8 bit read or write data.
Simulation – IN Transactions
1. ARM loads IN0, IN1, IN2, IN3 buffers.2. ARM writes to byte count registers IN0CNT,…,IN3CNT.3. ARM sets IN Ready Flags.4. USB IN Transactions
1 2 3 4
Simulation – IN Transaction (ZOOM)
Simulation – OUT Transactions
1. USB SETUP Packet2. USB OUT transactions to endpoints 0, 1, 2, 3.3. ARM reads Setup Data and OUT0, OUT1, OUT2, OUT3
buffers.
1 32
Simulation – OUT Transactions (zoom)
Start-of-Frame Packets
“phy_dir”
“phy_nxt”
“Rx_Active”
“SOF Detect”
RXCMD updates
BYTE 1 BYTE 2 BYTE 3
Start-of-Frame Packet Interval
1 millisecond
Setup Transaction
“new_data”
“Rx Active”
“Start of Frame”
“IRQ”
SOF PacketSETUP Packet
Setup Data (11bytes): PID + 8 bytes + CRC16
Setup Data
Byte Value Description0 0x80 bmRequestType1 0x06 Get Descriptor2 0x003 0x01 Device4 0x005 0x006 0x40 Number of bytes7 0x00
Screen capture from Insight (GUI for GNU GDB)
Device Descriptor
unsigned char DeviceDescriptor[] = {18, // Length1, // Type0x10,1, // USB Rev 1.1 (=0110H,low=10H,
High=01H)0, // Class0, // Subclass0, // Protocol64, // Maximum Packet Size0x42, 0x42, // Vendor ID1, 0x42, 0, 1, // Product ID and Version1, 2, 0, // Manufacturer, Product & Serial# Names1 // #Configs
};
ARM Interrupt Handling
void IRQ_Service(void){
if ( VICIRQStatus & 0x00000020 )
TMR1_Service();
if ( VICIRQStatus & 0x00000010 )
TMR0_Service();}
/********************************************//* Vector table and reset entry *//********************************************/_vectors: ldr pc, ResetAddr /* Reset */ ldr pc, UndefAddr /* Undefined instruction */ ldr pc, SWIAddr /* Software interrupt */ ldr pc, PAbortAddr /* Prefetch abort */ ldr pc, DAbortAddr /* Data abort */ ldr pc, ReservedAddr /* Reserved */ ldr pc, IRQAddr /* IRQ interrupt */ ldr pc, FIQAddr /* FIQ interrupt */
::
IRQAddr: .word IRQHandlerFIQAddr: .word FIQHandler
:IRQHandler: stmdb sp!, {r0-r12, lr} /* save all registers */ bl IRQ_Service ldmia sp!, {r0-r12, lr} /* restore all registers */ subs pc, lr, #4 /* Restore CPSR and return */
Assembly Code C-code