Texas Instruments Incorporated and its subsidiaries (TI) reserve the right to make corrections, modifications,
enhancements, improvements, and other changes to its products and services at any time and to discontinue
any product or service without notice. Customers should obtain the latest relevant information before placing
orders and should verify that such information is current and complete. All products are sold subject to TI’s terms
and conditions of sale supplied at the time of order acknowledgment.
TI warrants performance of its hardware products to the specifications applicable at the time of sale in
accordance with TI’s standard warranty. Testing and other quality control techniques are used to the extent TI
deems necessary to support this warranty . Except where mandated by government requirements, testing of all
parameters of each product is not necessarily performed.
TI assumes no liability for applications assistance or customer product design. Customers are responsible for
their products and applications using TI components. To minimize the risks associated with customer products
and applications, customers should provide adequate design and operating safeguards.
TI does not warrant or represent that any license, either express or implied, is granted under any TI patent right,
copyright, mask work right, or other TI intellectual property right relating to any combination, machine, or process
in which TI products or services are used. Information published by TI regarding third-party products or services
does not constitute a license from TI to use such products or services or a warranty or endorsement thereof.
Use of such information may require a license from a third party under the patents or other intellectual property
of the third party, or a license from TI under the patents or other intellectual property of TI.
Reproduction of information in TI data books or data sheets is permissible only if reproduction is without
alteration and is accompanied by all associated warranties, conditions, limitations, and notices. Reproduction
of this information with alteration is an unfair and deceptive business practice. TI is not responsible or liable for
such altered documentation.
Resale of TI products or services with statements different from or beyond the parameters stated by TI for that
product or service voids all express and any implied warranties for the associated TI product or service and
is an unfair and deceptive business practice. TI is not responsible or liable for any such statements.
Following are URLs where you can obtain information on other Texas Instruments products and application
solutions:
ProductsApplications
Amplifiersamplifier.ti.comAudiowww.ti.com/audio
Data Convertersdataconverter.ti.comAutomotivewww.ti.com/automotive
DSPdsp.ti.comBroadbandwww.ti.com/broadband
Interfaceinterface.ti.comDigital Controlwww.ti.com/digitalcontrol
Logiclogic.ti.comMilitarywww.ti.com/military
Power Mgmtpower.ti.comOptical Networkingwww.ti.com/opticalnetwork
Microcontrollersmicrocontroller.ti.comSecuritywww.ti.com/security
Telephonywww.ti.com/telephony
Video & Imagingwww.ti.com/video
Wirelesswww.ti.com/wireless
Mailing Address:Texas Instruments
Post Office Box 655303 Dallas, Texas 75265
Copyright 2004, Texas Instruments Incorporated
About This Manual
This user’s guide contains pertinent information about the bootcode process
of the TUSB5052.
How to Use This Manual
This document contains the following chapters:
Notational Conventions
Preface
- Chapter 1—Introduction
- Chapter 2—TUSB5052 USB Firmware Flow
- Chapter 3—Function
- Chapter 4—Bootcode Defaults
- Chapter 5—Header Format and Vendor USB Request
- Chapter 6—Programming Considerations and Bootcode File List
Notational Conventions
This document uses the following conventions.
- Program listings, program examples, and interactive displays are shown
in a special typeface similar to a typewriter’s. Examples use a bold
version of the special typeface for emphasis; interactive displays use a
bold version of the special typeface to distinguish commands that you
enter from items that the system displays (such as prompts, command
output, error messages, etc.).
Here is an example of a system prompt and a command that you might
enter:
C: csr −a /user/ti/simuboard/utilities
iii
FCC Warning
In syntax descriptions, the instruction, command, or directive is in a bold
-
typeface font and parameters are in an italic typeface. Portions of a syntax
that are in bold should be entered as shown; portions of a syntax that are
in italics describe the type of information that should be entered. Here is
an example of a directive syntax:
.asect ”section name”,address
.asect is the directive. This directive has two parameters, indicated by sec-
tion name and address. When you use .asect, the first parameter must be
an actual section name, enclosed in double quotes; the second parameter
must be an address.
- Square brackets ( [ and ] ) identify an optional parameter. If you use an
optional parameter, you specify the information within the brackets; you
don’t enter the brackets themselves. Here’s an example of an instruction
that has an optional parameter:
LALK 16-bit constant [, shift]
The LALK instruction has two parameters. The first parameter, 16-bit constant, is required. The second parameter, shift, is optional. As this syntax
shows, if you use the optional second parameter, you must precede it with
a comma.
Square brackets are also used as part of the pathname specification for
VMS pathnames; in this case, the brackets are actually part of the pathname (they are not optional).
FCC Warning
- Braces ( { and } ) indicate a list. The symbol | (read as or) separates items
within the list. Here’s an example of a list:
{ * | *+ | *− }
This provides three choices: *, *+, or *−.
Unless the list is enclosed in square brackets, you must choose one item
from the list.
- Some directives can have a varying number of parameters. For example,
the .byte directive can have up to 100 parameters. The syntax for this directive is:
.byte value
[, ... , valuen]
1
This syntax shows that .byte must have at least one value parameter, but
you have the option of supplying additional value parameters, separated
by commas.
This equipment is intended for use in a laboratory test environment only. It generates, uses, and can radiate radio frequency energy and has not been tested
for compliance with the limits of computing devices pursuant to subpart J of
part 15 of FCC rules, which are designed to provide reasonable protection
against radio frequency interference. Operation of this equipment in other environments may cause interference with radio communications, in which case
the user at his own expense will be required to take whatever measures may
be required to correct this interference.
Chapter 1 illustrates the bootcode process with bootcode flow charts. It
contains a description of the TUSB5052 bootcode document main program
and a flow chart of the interrupt service routine, control (setup) endpoint
handler, input endpoint 0 interrupt handler, output endpoint 0 handler, and the
output endpoint 1 handler.
After power-on reset, the bootcode copies predefined USB descriptors to the
shared RAM. The first USB descriptor is the device descriptor . It describes the
embedded function class, vendor ID, product ID, etc. The second USB
descriptor is the configuration descriptor, which contains information such as
how the device is powered, the number of configurations available, type and
number of interfaces, and end-point descriptors. From these two descriptors,
Windows loads the necessary device drivers and performs pertinent actions.
Vendor and product IDs are crucial to the bootcode. Windows gets VID and
PID through the standard USB device request and then tries to match the two
IDs with its own database. If Windows finds them in the database, it loads the
corresponding device driver. If it is not able to match the IDs it provides a
prompt directing the user to provide the driver disks, which contain the INF
files.
Once the bootcode finishes copying descriptors, it looks for the EEPROM on
2
C port. If a valid signature is found, it reads the data type byte. If the data
the I
type is application code, it downloads the code to an external data space. Once
the code is loaded and the checksum is correct, bootcode releases control to
the application code. If the data contains USB device information, the
bootcode interprets the data and copies it to hub registers and to the
embedded function device descriptor, if the checksum is correct. If the data
does not contain USB device information, bootcode restores predefined
settings to the hub register and device descriptor.
After the bootcode updates the hub register and device descriptor, it sets up
for a USB transaction and connects itself to the USB. It remains there until the
host drivers download the application code. Once complete, it disconnects
from the USB and releases control to the application code. Figure 1−1
illustrates bootcode operation.
1-2
Figure 1−1.Main Routine
Copy default descriptors and
initialize necessary variables
Bootcode Main Program
No
Does EEPROM
contain valid
signature?
Yes
Does EEPROM
contain
firmware?
No
Read and copy VID and PID
from EEPROM to TUSB5052
USB data initialization
Yes
Download firmware to xdata RAM
Is firmware
loaded and ready
Disable all interrupts and switch
xdata space to code space
Run firmware
to run?
Yes
No
Load firmware
from USB
Introduction
1-3
Interrupt Service Routine
1.2Interrupt Service Routine
Interrupt service is generated from external interrupt 0. TUSB5052 uses this
interrupt for internal peripherals. This interrupt consists of input/output
endpoints, setup packet, I
The main service routine confirms the source of interrupt then notifies
corresponding functions. Once interrupt is performed, the main service routine
clears INTVEC registers to inform hardware that the service is complete, then
releases control back to the main program. Figure 1−2 illustrates how each
service is processed.
2
C, UART, printer port, and DMA.
1-4
Figure 1−2.Interrupt Service Routine
Disable global interrupt
Interrupt Service Routine
Is output
endpoint 0
interrupt?
No
Is output
endpoint 1
interrupt?
No
Is input
endpoint 0
interrupt?
No
Yes
Yes
Yes
Output endpoint 0 handler
Output endpoint 1 handler
Input endpoint 0 handler
Is setup
packet received
interrupt?
No
Clear interrupt vector and
enable global interrupt
End of interrupt
Yes
Setup packet interrupt handler
Introduction
1-5
Control (Setup) Endpoint Handler
1.3Control (Setup) Endpoint Handler
Once bootcode receives a setup packet from the host, a control packet
interrupt handler acquires control from the interrupt service routine. This
handler processes the incoming packet, performs the appropriate action, then
returns control to the interrupt service routine, as shown in Figure 1−3.
Figure 1−3.Control (Setup) Endpoint Handler
Setup packet handler
Process standard USB
request and configuration
End of interrupt
Stall IEP0 if the incoming setup
packet is illegal
1.4Input Endpoint 0 Interrupt Handler
Figure 1−4 illustrates the process of sending data back to the host. If the last
packet is sent, the handler stalls the input endpoint, which prevents the host
from getting more data.
Figure 1−4.Input Endpoint 0 Interrupt Handler
Input endpoint 0 handler
Is this
the last
packet?
Yes
The last packet was sent. Stall IEP0.
If host asks for more data, bootcode
will stall. This scheme works fine even
in status stage because stall will be
clear once setup packet is received.
No
In data stage now, call
FillEp0TxFifoWithNextDataPacket()
routine to send out next data packet
End of interrupt
1-6
1.5Output Endpoint 0 Handler
Figure 1−5 demonstrates the process bootcode uses to deal with an output
endpoint 0 interrupt. Because bootcode does not support control write with a
data stage, it merely clears the NAK bit in the handler.
Figure 1−5.Output Endpoint 0 Interrupt Handler
Output endpoint 0 handler
Clear NAK bit
End of interrupt
1.6Output Endpoint 1 Handler
Output Endpoint 0 Handler
Bootcode does not support control
write with data stage. Therefore, this
interrupt only happens in status stage
of control read. Clear the NAK bit in
OEP0 so next OEP0 can receive next
OUT packet in status stage, or
bootcode does nothing.
The application code is downloaded from output endpoint 1, as shown in
Figure 1−6. This endpoint supports double buffered. Therefore, it switches to
the other buffer as soon as the current buffer receives data from the host.
Figure 1−6.Output Endpoint 1 Interrupt Handler
Output endpoint 1 handler
Get the size of incoming packet
from current buffer and copy
it to xdata RAM
Switch the pointer to the other
buffer. Clear the NAK in
original buffer.
End of interrupt
Introduction
1-7
1-8
Chapter 2
There are three types of control transfers in standard USB requests.
Figure 2−1 through Figure 2−3 and Table 2−1 and Table 2−2 demonstrate the
process bootcode uses to respond to each control transfer.
Control Write Transfer With Data (Bootcode does not support this)
2.1Control Write Transfer With Data (Bootcode does not support this)
Figure 2−1.Control Write Transfer With Data
Setup stageData stageStatus stage
SETUP(0)OUT(1)OUT(0)OUT(0/1)IN(1)
INTINTINT
1. Hardware generates interrupt
to MCU.
2. Set NAK on both endpoints.
3. Set DIR bit in USBCTL to
indicate the data direction
and SIR bit to indicate setup
interrupt is being served.
4. Decode the setup packet.
5. If another setup packet
arrives, abandon this one.
6. Execute appropriate routines.
a) Clear NAK bit in OUT
endpoint.
b) Clear NAK bit in IN endpoint
for status stage.
.
1. Hardware generates interrupt to
MCU.
2. Copy data from OUT buffer.
3. Clear the NAK bit.
4. If all data has been received,
stall output endpoint.
.
More
packets
INT
1. Hardware handles this but
does not generate interrupt
to MCU.
2.2Control Write Without Data
Table 2−1.Boot Code Response to Control Write Without Data
Control Write Without DataAction In Boot Code
Clear feature of deviceStall endpoint
Clear feature of interfaceStall endpoint
Clear feature of endpointClear stall on requested endpoint
Set feature of deviceSet remote wake-up feature
Set feature of interfaceStall endpoint
Set feature of endpointStall requested endpoint
Set addressSet device address
Set descriptorStall endpoint
Set configurationSet bConfiguredFlag
Set interfaceStall endpoint
Synchronization frameStall endpoint
2-2
Figure 2−2.Control Read Without Data
Setup stageStatus stage
SETUP(0)IN(1)
INT
Control Read Transfer
1. Hardware generates interrupt
to MCU.
2. Set NAK on both endpoints.
3. Set DIR bit in USBCTL to
indicate the data direction
and SIR bit to indicate setup
interrupt is being served.
4. Decode the setup packet.
5. If another setup packet
arrives, abandon this one.
6. Execute appropriate routines.
a) Clear NAK bit in OUT
endpoint.
b) Clear NAK bit in IN endpoint
for status stage.
.
1. Hardware handles this but
does not generate interrupt
to MCU.
2.3Control Read Transfer
Table 2−2.Boot Code Response to Control Read
Control ReadAction In Boot Code
Get status of deviceReturn remote wake-up and power status
Get status of interfaceNo action and return zero
Get status of endpointReturn the endpoint status (stall or not)
Get descriptor of deviceReturn device descriptor
Get descriptor of configurationReturn configuration descriptor
Get descriptor of stringIllegal requests, stall endpoint
Get descriptor of interfaceIllegal requests, stall endpoint
Get descriptor of endpointIllegal requests, stall endpoint
Get configurationReturn bConfiguredFlag value
Get interfaceNo action and return zero
TUSB5052 USB Firmware Flow
2-3
Control Read Transfer
Figure 2−3.Control Read
Setup stageData stageStatus stage
SETUP(0)IN(1)IN(0)IN(0/1)OUT(1)
INTINTINT
1. Hardware generates interrupt
to MCU.
2. Set NAK on both endpoints.
3. Set DIR bit in USBCTL to
indicate the data direction
and SIR bit to indicate setup
interrupt is being served.
4. Decode the setup packet.
5. If another setup packet
arrives, abandon this one.
6. Execute appropriate routines.
a) Clear NAK bit in OUT
endpoint for status stage.
b) Copy data to IN endpoint
buffer and set byte count.
.
1. Hardware generates interrupt to
MCU.
2. Copy data to IN buffer.
3. Clear the NAK bit.
4. If all data has been received,
stall IN endpoint.
.
More
packets
INT
1. Hardware handles this but
does not generate interrupt
to MCU.
2-4
Chapter 3
Chapter 3 contains a bootcode module list with a functional description of each
bootcode module.
This function is alerted by an interrupt service routine if there is an IN token
addressed to endpoint 0 from the host. This routine packetizes the
remainder of the data and sends one packet to the host. If the data is more
than packet size, the next packet is sent during the next interrupt
immediately after hardware receives the next IN token.
- VOID TransmitBufferOnEp0(PBYTE pbBuffer)
This checks the length and then requests the
FillEp0TxWithNextDataPacket() function to send data out.
- VOID TransmitNullResponseOnEp0(VOID)
This sends a zero length packet to the host, which is used as an
acknowledgement in the status page
- VOID Stall EndPoint0(VOID)
This stalls both input and output endpoint0, preventing the host from
sending or receiving data from endpoint0. It is sometimes used to indicate
there is an error in the transaction.
- VOID Endpoint0Control(VOID)
This supplies and executes standard USB and several vendor-specific
requests.
- VOID UsbDataInitialization(VOID)
This enables interrupts and initializes USB registers.
- VOID CopyDefaultSettings(VOID)
This copies default descriptors and initializes variables.
- VOID SetupPacketInterruptHandler(VOID)
This is called by the interrupt service routine when a setup packet is
received. This function presets some variables before it calls the
Endpoint0Control() function.
- VOID Ep0InputInterruptHandler(VOID)
This is transmitted by the interrupt service routine when an IN token is
received. If there is more data to send, it notifies the
FillEp0TxWithNextDataPacket() function to send data. Immediately
following the last packet of data is sent, it stalls the endpoint, which
prevents the host from getting data.
- VOID Ep0OutputInterruptHandler (VOID)
This is transmitted during the status stage of the control read transfer in
the bootcode. Bootcode always stalls the output endpoint due to the lack
of control write with data stage support.
- VOID Ep1OutputInterruptHandler(VOID)
This function is transmitted if there is an OUT token to endpoint 1. The first
packet of data contains the size and checksum of the application code.
Since endpoint1 is a double buffer, this routine keeps tracking the buffer
sequence.
3-2
3.1.2I2C.c File
Bootcode Functional Module List
Interrupt [0x03] VOID EX0_int(VOID)
-
All UMP-related interrupts are performed in this routine. It reads in vector
numbers in order to determine the type of interrupt and notifies the
appropriate functions.
- VOID main(VOID)
This is performed by the interrupt service routine when a setup packet is
received. It presets some variables then contacts the Endpoint0Control()
function.
- VOID I2CSetBusSpeed(BYTE bBusSpeed)
2
This function sets the I
C speed. If bBusSpeed is 1, the I2C bus operates
at 400 kHz.
- BYTE I2CSetMemoryType(VOID)
This function sets the I2C memory type. The ranges are from 0x01, Type
I, to 0x03, Type III device.
- BYTE I2CWaitForRead(VOID)
2
Wait routine for I
- BYTE I2CWaitForWrite(VOID)
C read
Wait routine for I2C write
3.1.3Header.c File
- BYTE I2CRead(BYTE bDeviceAddress, WORD wAddress, WORD
wNumber, PBYTE pbDataArray)
This routine reads from one to wNumber of bytes.
- BYTE I2CWrite(BYTE bDeviceAddress, WORD wAddress, WORD
wNumber, PBYTE pbDataArray)
This routine writes from one to wNumber of bytes. It is possible that some
2
C devices have physical limitations for the number of bytes that can be
I
written each time. See the I2C device data sheet.
- BYTE headerCheckProductIDonI2C(VOID)
2
This function checks for a valid ID on the I
- BYTE headerSearchForValidHeader(VOID)
C device.
Checks for a valid signature.
- BYTE headerGetDataType(WORD wNumber)
Delivers the data type indexed by a wNumber.
- BYTE LoadFirmwareBasicFromI2C(VOID)
Loads the firmware from the I
- BYTE LoadUsbInfoBasicFromI2C(VOID)
Loads the USB data from the I
2
C device.
2
C device.
- BYTE headerProcessCurrentDataType(VOID)
- WORD headerReturnFirmwareRevision(VOID)
Checks the data type and processes the data.
This function returns the current firmware revision.
Function
3-3
3-4
Chapter 4
Chapter 4 lists the defaults used for hub and bootcode settings. There are
tables in each category that list the offset, field, size, and value, and provide
short descriptions for the hub, device, configuration, interface, and interrupt
endpoint1 descriptors.
0bLength10x09Size of this descriptor in bytes
1bDescriptorType10x29Device descriptor type
2bNbrPorts16Number of downstream ports
3wHubCharacteristics20x0D[1:0] Power switching = 01 (individual)
[15:5] reserved = 0
4bPwrOn2PwrGood10x32Time (in 2ms intervals) from power on to power good
6bHubContrCurrent10x32Maximum current requirements of the hub controller
electronics in mA
7DeviceRemovable10x60Device removable
8PortPwrCtrlMask10xFFPort power control mask
Table 4−2.Device Descriptor
Offset FieldSizeValueDescription
0bLength118Size of this descriptor in bytes
1bDescriptorType11Device descriptor type
2BcdUSB20x0110USB spec 1.1
4bDeviceClass10xFFVendor-specific class
5bDeviceSubClass10None
6bDeviceProtocol10None
7bMaxPacketSize018Max. packet size for endpoint zero
8ID Vendor20x0451USB assigned vendor ID = TI
10ID Product20x22602 Functions and 6 ports
12BCD Device20x0100Device release number = 1.0
14iManufacturer10Index of string descriptor describing manufacturer
15iProduct10Index of string descriptor describing product
16iSerialNumber10Index of string descriptor describing device serial number
17bNumConfigurations11Number of possible configurations
4-2
Default Hub Settings
Table 4−3.Configuration Descriptor
Offset FieldSizeValueDescription
0bLlength19Size of this descriptor in bytes
1bDescriptorType12Configuration descriptor type
2wTotalLength225 = 9 + 9 + 7 Total length of data returned for this configuration.
Includes the combined length of all descriptors
(configuration, interface, endpoint, and class- or
vendor-specific) returned for this configuration.
4bNumInterfaces11Number of interfaces supported by this configuration
5bConfigurationValue11Value to use as an argument to the
SetConfiguration() request to select this
configuration.
6iConfiguration10Index of string descriptor describing this
D7:Reserved (set to one)
D6:Self-powered
D5:Remote wake-up is supported
D4−D0: Reserved (reset to zero)
8bMaxPower10This device consumes no power from the bus.
Table 4−4.Interface Descriptor
OffsetFieldSizeValueDescription
0bLength19Size of this descriptor in bytes
1bDescriptorType14Interface descriptor type
2bInterfaceNumber10Number of interfaces. Zero-based value identifying the
index in the array of concurrent interfaces supported
by this configuration.
3bAlternateSetting10Value used to select alternate setting for the interface
identified in the prior field
4bNumEndpoints11Number of endpoints used by this interface (excluding
endpoint zero). If this value is zero, this interface uses
the default control pipe.
5bInterfaceClass10x09Vendor-specific class
6bInterfaceSubClass10
7bInterfaceProtocol10
8iInterface10Index of string descriptor describing this interface
Bootcode Defaults
4-3
Default Bootcode Settings
Table 4−5.Interrupt Endpoint 1 Descriptor
Offset FieldSizeValueDescription
0bLength17Size of this descriptor in bytes
1bDescriptorType15Endpoint descriptor type
2bEndpointAddress10x81Bits 3−0:The endpoint number
Bit 7:Direction
0 = OUT endpoint
1 = IN endpoint
3bmAttributes13Bits 1−0:Transfer type
10 = Bulk
11 = Interrupt
4wMaxPacketSize21Max packet size this endpoint is capable of sending or
receiving when this configuration is selected.
6bInterval10xFFInterval for polling endpoint for data transfers, expressed
in milliseconds
4.2Default Bootcode Settings
Table 4−6.Device Descriptor
Offset FieldSizeValueDescription
0bLength118Size of this descriptor in bytes
1bDescriptorType11Device descriptor type
2BcdUSB20x0110USB spec 1.1
4bDeviceClass10xFFVendor-specific class
5bDeviceSubClass10None
6bDeviceProtocol10None
7bMaxPacketSize018Max packet size for endpoint zero
8ID Vendor20x0451USB assigned vendor ID = TI
10ID Product20x5052TI part number=TUSB5052
12BCD Device20x0100Device release number = 1.0
14iManufacturer10Index of string descriptor describing manufacturer
15iProduct10Index of string descriptor describing product
16iSerialNumber10Index of string descriptor describing device serial number
17bNumConfigurations11Number of possible configurations
4-4
Default Bootcode Settings
Table 4−7.Configuration Descriptor
Offset FieldSizeValueDescription
0bLlength19Size of this descriptor in bytes
1bDescriptorType12Configuration descriptor type
2wTotalLength225 = 9 + 9 + 7 Total length of data returned for this configuration.
Includes the combined length of all descriptors
(configuration, interface, endpoint, and class- or
vendor-specific) returned for this configuration.
4bNumInterfaces11Number of interfaces supported by this configuration
5bConfigurationValue11Value to use as an argument to the
SetConfiguration() request to select this
configuration
6iConfiguration10Index of string descriptor describing this
D7:Reserved (set to one)
D6:Self-powered
D5:Remote wake-up is supported
D4−D0: Reserved (reset to zero)
8bMaxPower10This device consumes no power from the bus.
Table 4−8.Interface Descriptor
OffsetFieldSizeValueDescription
0bLength19Size of this descriptor in bytes
1bDescriptorType14Interface descriptor type
2bInterfaceNumber10Number of interfaces. Zero-based value identifying the
index in the array of concurrent interfaces supported by
this configuration.
3bAlternateSetting10Value used to select alternate setting for the interface
identified in the prior field
4bNumEndpoints11Number of endpoints used by this interface (excluding
endpoint zero). If this value is zero, this interface uses
the default control pipe.
5bInterfaceClass10xFFVendor-specific class
6bInterfaceSubClass10
7bInterfaceProtocol10
8iInterface10Index of string descriptor describing this interface
Bootcode Defaults
4-5
Default Bootcode Settings
Table 4−9.Output Endpoint 1 Descriptor
Offset FieldSizeValueDescription
0bLength17Size of this descriptor in bytes
1bDescriptorType15Endpoint descriptor type
2bEndpointAddress10x01Bits 3−0:The endpoint number
Bit 7:Direction
0 = OUT endpoint
1 = IN endpoint
3bmAttributes12Bits 1−0:Transfer type
10 = Bulk
11 = Interrupt
4wMaxPacketSize264Maximum packet size this endpoint is capable of sending
or receiving when this configuration is selected.
6bInterval10Interval for polling endpoint for data transfers, expressed
in milliseconds
4-6
Chapter 5
! " #
Chapter 5 explains the header format. It describes the product signature and
descriptors and gives examples for ease of understanding. There are also
tables that list the offset, field, size, value, and description for the USB info
basic descriptor, as well as the USB info basic and firmware basic descriptor.
The header is stored in various storage devices such as a ROM, parallel/serial
EEPROM, or flash ROM. The current header format routine supports only the
2
C device (serial EEPROM). A valid header contains one correct product
I
signature and one or more descriptors. The descriptor contains a descriptor
prefix and its content. Data type, size, and checksum are specified in the
descriptor prefix to describe its content. Descriptor content contains the
necessary information for bootcode to process.
5.1.1Product Signature
There are two bytes for a signature field. They are identical to the product
number. For example, UMP (TUSB5052) is 0x5052. TUSB2136 is 0x2136.
Numerical order is LSB first.
5.1.2Descriptor
Each descriptor contains a prefix and content. The prefix is always 4 bytes and
contains data type, size, and checksum to ensure data integrity. The descriptor
content contains information corresponding to that specified in the prefix. It
can be as small as one byte or as large as 65535 bytes. After the last
descriptor, the first byte (data type) in the descriptor prefix is zero, indicating
the end of the descriptors.
5.1.3Descriptor Prefix
In a prefix, the first byte is the data type. This instructs the bootcode how to
parse the data in the descriptor content. The second and third bytes are the
size of the descriptor content, and the last byte is the checksum of the
descriptor content.
5.1.4Descriptor Content
Information stored in the descriptor content is either USB information,
firmware, or another type of data. Size of the content varies from 1 to 65535
bytes.
5-2
5.2Examples
5.2.1USB Info Basic Descriptor
Table 5−1 contains generic USB information for the bootcode. Once the
bootcode loads the data and verifies the checksum, it then copies information
to corresponding registers. The last byte is a zero, which indicates the end of
2
the descriptor. The descriptor easily fits into a 16-byte I
Table 5−1 and Table 5−2 are the only two supported descriptors in the
bootcode.
Table 5−1.USB Info Basic Descriptor
OffsetTypeSizeValueDescription
0Signature010x52FUNCTION_PID_L
1Signature110x51FUNCTION_PID_H
2Data Type10x01USB info basic
3Data Size (low byte)10x09Size of descriptor content (9 bytes total)
4Data Size (high byte)10x00
C EEPROM. Note that
Examples
5Check Sum10x80Checksum of descriptor content
6Bit Setting10x81Self powered and power switching
7Vendor ID (low byte)10x51TI VID = 0x0451
8Vendor ID (high byte)10x04
9Hub PID (low byte)10x34Hub PID = 0x1234
10Hub PID (high byte)10x12
11Function PID (low byte)10x78Function PID = 0x5678
12Function PID (high byte)10x56
13HUBPOTG10x32Time from power-on to power-good in 2-mA
units = 100 ms
14HUBCURT10x64Hub current descriptor = 100 mA
15Data Type10x00End of descriptor
Header Format and Vendor USB Request
5-3
Examples
Table 5−2.USB Info Basic and Firmware Basic Descriptor
OffsetTypeSizeValue Description
0Signature010x52FUNCTION_PID_L
1Signature110x51FUNCTION_PID_H
2Data type10x01USB info basic
3Data size (low byte)10x08Size of descriptor content (8 bytes total)
4Data size (high byte)10x00
5Check sum10x45Checksum of descriptor content
6Bit setting10x80Bus-powered and overcurrent protection
7Vendor ID (low byte)10xAAHub and function VID = 0x55AA
8Vendor ID (high byte)10x55
9Hub PID (low byte)10x20Hub PID = 0x1020
0x0AHub PID (high byte)10x10
0x0BFunction PID (low byte)10x22Function PID = 0x1122
0x0CFunction PID (high byte)10x11
0x0DHUBPOTG10x10Time from power-on to power-good in 2-mA
units = 32 ms
0x0EHUBCURT10x20Hub current descriptor = 32 mA
0x0FData type10x02Firmware basic
0x10Data size (low byte)10x25Size of descriptor content
0x11Data size (high byte)10x10The size is 0x1025 bytes
0x12Check sum1XX
This command requests bootcode to execute the downloaded firmware. If the
checksum is correct, bootcode disconnects from the USB, then releases
control to the firmware or it stalls the command.
5.3.3Get Firmware Revision
bmRequestTypeUSB_REQ_TYPE_DEVICE |
bRequestBTC_EXECUTE_FIRMWARE0x82
wValueNone0x0000
wIndex
wLengthNone0x0002
DataNone0xNNNN
1100 0000b
USB_REQ_TYPE_VENDOR |
USB_REQ_TYPE_IN
None0x0000
(specified in the header)
Bootcode returns the 2-byte value described in the header file.
†Vendor specific requests are for internal testing only. TI does not assure their performance.
This command tells bootcode that pending data downloaded through the
output endpoint 1 is a header file rather than firmware.
The following procedures update the header file.
1) The host driver sends a BTC_PRE_UPDATE_HEADER request informing bootcode that the pending data from the output endpoint 1 is a header
file.
2) The host driver transmits a header file through OEP1.
3) After the header file is downloaded, the host driver sends a BTC_UPDATE_HEADER request, which allows bootcode to update the header
file. The update to the host driver is not immediate.
5.4Update Header
4) The host driver sends the last request, BTC_REBOOT, which prompts
bootcode to start over with an updated PID and VID.
LO: Wait time in ms
wIndexNone0x0000
wLengthNone0x0000
DataNone
0100 0000b
0xNNNN
This command instructs the bootcode to update the header to I2C EEPROM.
Block size is the size of page write and wait time is the time between each page
2
write. Be aware that different I
C EEPROMs may have dif ferent physical page
boundaries. If the block size is too large, it might possibly cross the physical
page boundary and, as a result, that data could be lost or overwrite the data
address 0x0000.
This command instructs bootcode to write data to the specified address.
5.9I2C Memory Read
bmRequestTypeUSB_REQ_TYPE_DEVICE |
bRequestBTC_I2C_MEMORY_READ0x92
wValueHI: I2C Device Number
0100 0000b
USB_REQ_TYPE_VENDOR |
USB_REQ_TYPE_OUT
0x00NN
LO: Data
(from 0x0000 to
0xFFFF)
0100 0000b
USB_REQ_TYPE_VENDOR |
USB_REQ_TYPE_IN
0xNNNN
LO: Memory Type BIt[0−1] and
Speed Bit[7]
wIndexData address0xNNNN
(from 0x0000 to
0xFFFF)
wLengthOne byte0x0001
DataByte in the specified address0xNNN
Bootcode returns the content of the specified address in I2C EEPROM.
In the wValue field, the I
2
C device number is from 0x00 to 0x07 in the high field.
Memory type is from 0x01 to 0x03 for CAT I to CAT III devices. If bit 7 of bValueL
is set, 400 kHz is used. If bit 7 of bValueL is not set, 100 kHz is used. This
2
request is also used to set the device number and speed before an I
C write
request.
5-8
5.10 I2C Memory Write
I2C Memory Write
bmRequestTypeUSB_REQ_TYPE_DEVICE |
bRequestBTC_I2C_MEMORY_WRITE0x93
wValueHI: I2C device number
wIndexData address0xNNNN
wLengthNone0x0000
DataNone
This command instructs the bootcode to write data to the specified address.
2
C device number is specified in the bValueH field.
The I
5.11 Internal ROM Memory Read
bmRequestTypeUSB_REQ_TYPE_DEVICE |
bRequestBTC_INTERNAL_ROM_MEMORY_READ0x94
0100 0000b
USB_REQ_TYPE_VENDOR |
USB_REQ_TYPE_OUT
0xNNNN
LO: Data
(from 0x0000 to
0xFFFF)
0100 0000b
USB_REQ_TYPE_VENDOR |
USB_REQ_TYPE_OUT
wValueNone0xNNNN
wIndexData address0xNNNN
(from 0x0000 to
0xFFFF)
wLengthOne byte0x0001
DataByte in the specified address0xNN
Bootcode returns the byte (binary code of the bootcode) of the specified
address in ROM.
Header Format and Vendor USB Request
5-9
5-10
Chapter 6
$
%
Chapter 6 addresses programing considerations and includes a short section
on USB requests and a table on vector interrupt values and sources. The
remaining portion comprises the bootcode file list.
For each USB request the firmware follows these steps, which ensure proper
hardware operation.
1) Firmware first sets NAK bit on both input data endpoint 0 and output data
endpoint 0, clears the interrupt sources, then clears the VECINT register.
For example, for a setup packet, the firmware must clear the USBSTA_SETUP bit by writing a 1 to the bit of the register.
2) Firmware determines the direction of the request by checking the MSB of
the bmRequestType field. It then sets the USBCTL_DIR bit.
3) Firmware sets USBCTL_SIR, indicating it is providing the current request.
4) Firmware decodes the command and serves the request.
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Texas Instruments |
| Bootcode |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Source: bootcode.c, v 1.0 2000/01/26 16:45:55 |
| Author: Horng−Ming Lobo Tai lobotai@ti.com |
| |
| For more information, contact |
| Lobo Tai |
| Texas Instruments |
| 12500 TI Blvd, MS 8761 |
| Dallas, TX 75243 |
| USA |
| Tel 214−480−3145 |
| Fax 214−480−3443 |
| |
| External EEPROM Format
| |
| Offset
| 0 Signature0 1 0x52, FUNCTION_PID_L |
| 1 Signature1 1 0x51, FUNCTION_PID_H |
| 2 Data Type 1 0x00 = End |
| 0x01 = USB Info Basic |
| 0x02 = Application Code |
| 0x03..0xEF Reserved |
| 0xff = Reserved for Extended Data |
| 3 Data Size 2 Size of Data |
| 9 for TUSB5052 & TUSB2136 Usb Info|
| 5 Check Sum 1 Check Sum of Data Section |
| 6 Bit Setting 1 Bit 0: Bus/self power in bUSBCRL |
| Bit 7: PWRSW |
| 7 VID 2 Vendor ID |
| 9 PID hub 2 Product ID for hub |
| 11 PID device 2 Product ID for bootrom |
| 13 HUBPOTG 1 Time from power-on to power-good |
| 14 HUBCURT 1 HUB Current descriptor register |
| |
| The following examples is for application code |
| 15 Data Type 1 0x00 = End |
| 0x02 = Application Code |
| 16 Data Size 2 Size of Data Section |
| 18 Check Sum 1 Check Sum of Data Section |
| 19 App. Rev. 2 Application Code Revision |
| |
| 21 Application Code Starts here... |
| Logs: |
WHEN WHAT |
| WHO
| HMT 20000126 born |
| HMT 20000301 add PWRSW and HUBPOTG |
| HMT 20000331 Set address request (check illigeal address) |
Type Size Value & Remark |
|
6-4
| HMT 20000517 modified header and added bus power support |
| HMT 20000525 added HUBCURT |
| modified header |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#include <io51.h> // 8051 sfr definition
#include <stdio.h>
#include <stdlib.h>
#include ”types.h” // Basic Type declarations
#include ”usb.h” // USB−specific Data Structures
#include ”i2c.h”
#include ”tusb5052.h”
#include ”delay.h”
#include ”header.h”
#include ”bootcode.h”
#ifdef SIMULATION
#include ”gpio.h”
#endif
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Constant Definition |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
// for double buffer pointer
#define X_BUFFER 0
#define Y_BUFFER 1
BYTE code abromDeviceDescriptor[SIZEOF_DEVICE_DESCRIPTOR] = {
SIZEOF_DEVICE_DESCRIPTOR, // Length of this descriptor (12h bytes)
DESC_TYPE_DEVICE, // Type code of this descriptor (01h)
0x10,0x01, // Release of USB spec (Rev 1.1)
0xff, // Device’s base class code−vendor specific
0, // Device’s sub class code
0, // Device’s protocol type code
EP0_MAX_PACKET_SIZE, // End point 0’s max packet size = 8
HUB_VID_L,HUB_VID_H, // Vendor ID for device, TI=0x0451
FUNCTION_PID_L,FUNCTION_PID_H, // Product ID for device, TUSB5052
0x00,0x01, // Revision level of device, Rev=1.0
0, // Index of manufacturer name string desc
0, // Index of product name string desc
0, // Index of serial number string desc
1 // Number of configurations supported
};
BYTE code abromConfigurationDescriptorGroup[SIZEOF_BOOTCODE_CONFIG_DESC_GROUP] =
{
// Configuration Descriptor, size=0x09
SIZEOF_CONFIG_DESCRIPTOR, // bLength
DESC_TYPE_CONFIG, // bDescriptorType
SIZEOF_BOOTCODE_CONFIG_DESC_GROUP, 0x00, // wTotalLength
0x01, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0x80, // bmAttributes, bus−powered hub
0x32, // Max. Power Consumption at 2mA unit
// Interface Descriptor, size = 0x09
SIZEOF_INTERFACE_DESCRIPTOR, // bLength
DESC_TYPE_INTERFACE, // bDescriptorType
0x00, // bInterfaceNumber
File List
Programming Considerations and Bootcode File List
6-5
File List
0x00, // bAlternateSetting
1, // bNumEndpoints
0xFF, // bInterfaceClass − vendor−specific
0, // bInterfaceSubClass, zero for hub
0, // bInterfaceProtocol
0x00, // iInterface
// Endpoint Descriptor, size = 0x07 for OEP1
SIZEOF_ENDPOINT_DESCRIPTOR, // bLength
DESC_TYPE_ENDPOINT, // bDescriptorType
0x01 , // bEndpointAddress; bit7=1 for IN, bits 3−0=1 for ep1
EP_DESC_ATTR_TYPE_BULK, // bmAttributes, bulk transfer
0x40, 0x00, // wMaxPacketSize, 64 bytes
0x00 // bInterval
};
// Global Memory Map
#pragma memory = idata
BYTE bEp0TxBytesRemaining; // For endpoint zero transmitter only
// Holds count of bytes remaining to be
// transmitted by endpoint 0. A value
// of 0 means that a 0−length data packet
// A value of 0xFF means that transfer
// is complete.
BYTE bHostAskMoreDataThanAvailable;
// If the host ask more data then TUSB2136 has
// It sends one zero−length packet
// if the asked lenght is a multiple of
// max. size of endpoint 0
BYTE bConfiguredFlag; // Set to 1 when USB device has been
// configured, set to 0 when unconfigured
PBYTE pbEp0Buffer; // A pointer to end point 0
WORD wCurrentFirmwareAddress; // for firmware downloading
WORD wFirmwareLength;
BYTE bFirmwareChecksum;
BYTE bRAMChecksum;
BOOL bExecuteFirmware; // flag set by USB request to run the firmware
BOOL bRAMChecksumCorrect;
BOOL bCurrentBuffer;
BYTE abBootCodeStatus[4];
extern WORD wCurrentUploadPointer; // in header.c
extern BYTE bi2cDeviceAddress; // in header.c
#pragma memory = default
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| TUSB5052 Register Structure Definition |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#pragma memory = dataseg(TUSB5052_SETUPPACKET_SEG) // 0xff00
tDEVICE_REQUEST tSetupPacket;
#pragma memory = default
#pragma memory = dataseg(TUSB5052_EP0_EDB_SEG) // 0xff80
tEDB0 tEndPoint0DescriptorBlock;
#pragma memory = default
#pragma memory = dataseg(TUSB5052_IEP_EDB_SEG) // 0xff48
tEDB tInputEndPointDescriptorBlock[1];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_OEP_EDB_SEG) // 0xf940
6-6
tEDB tOutputEndPointDescriptorBlock[1];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_IEP0BUFFER_SEG) // 0xfef8
BYTE abIEP0Buffer[EP0_MAX_PACKET_SIZE];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_OEP0BUFFER_SEG) // 0xfef0
BYTE abOEP0Buffer[EP0_MAX_PACKET_SIZE];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_DESC_SEG) // 0xfc00
BYTE abDeviceDescriptor[SIZEOF_DEVICE_DESCRIPTOR];
BYTE abConfigurationDescriptorGroup[SIZEOF_BOOTCODE_CONFIG_DESC_GROUP];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_OEP1_X_BUFFER_SEG)
BYTE abXBufferAddress[EP_MAX_PACKET_SIZE];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_OEP1_Y_BUFFER_SEG)
BYTE abYBufferAddress[EP_MAX_PACKET_SIZE];
#pragma memory = default
#pragma memory = dataseg(TUSB5052_EXTERNAL_RAM_SEG) // 0x0000
BYTE abDownloadFirmware[1024*16];
#pragma memory = default
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Sub−routines go here... |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID FillEp0TxWithNextDataPacket(VOID)
{
BYTE bPacketSize,bIndex;
// First check if there are bytes remaining to be transferred
if (bEp0TxBytesRemaining != 0xFF)
{
if (bEp0TxBytesRemaining > EP0_MAX_PACKET_SIZE)
{
// More bytes are remaining than are capable of fitting in one packet
bPacketSize = EP0_MAX_PACKET_SIZE;
bEp0TxBytesRemaining −= EP0_MAX_PACKET_SIZE;
// there are more IN Stage
}
else if (bEp0TxBytesRemaining < EP0_MAX_PACKET_SIZE)
{
// The remaining data fits in one packet.
// This case properly handles bEp0TxBytesRemaining == 0
bPacketSize = bEp0TxBytesRemaining;
bEp0TxBytesRemaining = 0xFF; // No more data need to be Txed
}
else //bEp0TxBytesRemaining == EP0_MAX_PACKET_SIZE
{
bPacketSize = EP0_MAX_PACKET_SIZE;
if(bHostAskMoreDataThanAvailable == TRUE) bEp0TxBytesRemaining = 0;
else bEp0TxBytesRemaining = 0xFF;
}
for (bIndex=0; bIndex<bPacketSize; bIndex++)
abIEP0Buffer[bIndex] = *pbEp0Buffer++;
tEndPoint0DescriptorBlock.bIEPBCNT = bPacketSize & EPBCT_BYTECNT_MASK;
File List
Programming Considerations and Bootcode File List
6-7
File List
}
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID TransmitBufferOnEp0(PBYTE pbBuffer)
{
pbEp0Buffer = pbBuffer;
// Limit wLength to FEh
if (tSetupPacket.bLengthH != 0){
tSetupPacket.bLengthH = 0;
tSetupPacket.bLengthL = 0xFE;
}
// Limit transfer size to wLength if needed
// this prevent USB device sending ’more than require’ data back to the host
if (bEp0TxBytesRemaining > tSetupPacket.bLengthL)
bEp0TxBytesRemaining = tSetupPacket.bLengthL;
if(bEp0TxBytesRemaining < tSetupPacket.bLengthL)
bHostAskMoreDataThanAvailable = TRUE;
else bHostAskMoreDataThanAvailable = FALSE;
FillEp0TxWithNextDataPacket();
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID TransmitNullResponseOnEp0 (VOID)
{
pbEp0Buffer = NULL; // to indicate a partial packet
bEp0TxBytesRemaining = 0; // or ACK during standard USB request
FillEp0TxWithNextDataPacket();
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID StallEndPoint0(VOID)
{
tEndPoint0DescriptorBlock.bIEPCNFG |= EPCNF_STALL;
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID Endpoint0Control(VOID)
{
BYTE bTemp;
WORD wIndex;
BYTE abReturnBuffer[3];
BOOL InTransaction;
// copy the MSB of bmRequestType to DIR bit of USBCTL
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_INPUT) != 0x00){
InTransaction = TRUE;
bUSBCTL |= USBCTL_DIR;
}else{
InTransaction = FALSE;
bUSBCTL &= ~USBCTL_DIR;
}
// Set setup bit in USB control register
bUSBCTL |= USBCTL_SIR; // on bit 1
// clear endpoint stall here
// If hardware in setup stage(hardware clears stall) but firmware still
// in data stage(stall at the last packet), sometimes hardware clears stall
// but firmware later on stall again. This causes problem in the new transfer
6-8
File List
// while firmware still in the previous transfer.
tEndPoint0DescriptorBlock.bIEPCNFG &= ~EPCNF_STALL;
tEndPoint0DescriptorBlock.bOEPCNFG &= ~EPCNF_STALL;
abReturnBuffer[0] = 0;
abReturnBuffer[1] = 0;
abReturnBuffer[2] = 0;
switch(tSetupPacket.bmRequestType & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_STANDARD:
// check if high byte of wIndex is p184 of spec 1.1
if((tSetupPacket.bIndexH != 0x00)){
StallEndPoint0();
return;
}
switch (tSetupPacket.bRequest)
{
case USB_REQ_GET_STATUS:
// check if it is a read command
if(InTransaction == FALSE){
// control read but direction is OUT
StallEndPoint0();
return;
}
// check if wValue is zero
if((tSetupPacket.bValueH != 0x00) || (tSetupPacket.bValueL != 0x00)){
StallEndPoint0();
return;
}
// check if bLengthL = 0x02, wLength = 0x00
if((tSetupPacket.bLengthL != 0x02) || (tSetupPacket.bLengthH != 0x00)){
StallEndPoint0();
return;
}else tEndPoint0DescriptorBlock.bOEPBCNT = 0x00; // for status stage
switch (tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK)
{
case USB_REQ_TYPE_DEVICE:
// check if wIndex is zero
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
}
// Return self power status, no remote wakeup
bEp0TxBytesRemaining = 2;
if((bUSBCTL & USBCTL_SELF) == USBCTL_SELF)
abReturnBuffer[0] = DEVICE_STATUS_SELF_POWER;
TransmitBufferOnEp0((PBYTE)abReturnBuffer);
break;
case USB_REQ_TYPE_INTERFACE: // return all zeros
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
}
bEp0TxBytesRemaining = 2;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
Programming Considerations and Bootcode File List
6-9
File List
break;
case USB_REQ_TYPE_ENDPOINT:
// Endpoint number is in low byte of wIndex
bTemp = tSetupPacket.bIndexL & EP_DESC_ADDR_EP_NUM;
if(bTemp==0){ // EndPoint 0
if(tSetupPacket.bIndexL & EP_DESC_ADDR_DIR_IN)
// input endpoint
abReturnBuffer[0] = (BYTE)
}
abReturnBuffer[0] >>= 3; // STALL is on bit 3
bEp0TxBytesRemaining = 2;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
break;
case USB_REQ_TYPE_OTHER:
default:
StallEndPoint0();
break;
}
break;
case USB_REQ_CLEAR_FEATURE:
// check if it is a write command
if(InTransaction == TRUE){
// control write but direction is IN
StallEndPoint0();
return;
}
// check if bLengthL = 0x00, wLength = 0x00
if((tSetupPacket.bLengthL != 0x00) || (tSetupPacket.bLengthH != 0x00)){
StallEndPoint0();
return;
}
// control write, stall output endpoint 0
// wLength should be 0 in all cases
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
switch (tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK)
6-10
File List
{
case USB_REQ_TYPE_ENDPOINT:
// Endpoint number is in low byte of wIndex
if(tSetupPacket.bValueL == FEATURE_ENDPOINT_STALL){
bTemp = tSetupPacket.bIndexL & EP_DESC_ADDR_EP_NUM;
if(bTemp){
if(bTemp > MAX_ENDPOINT_NUMBER){
StallEndPoint0();
return;
}
bTemp−−; // EP is from EP1 to EP7 while C
language start from 0
if(tSetupPacket.bIndexL & EP_DESC_ADDR_DIR_IN)
// input endpoint
tInputEndPointDescriptorBlock[bTemp].bEPCNF &=
~EPCNF_STALL;
}else{ // EP0
// clear both in and out stall
// no reason to have one stall while the other is
not for EP0
tEndPoint0DescriptorBlock.bIEPCNFG &= ~EPCNF_STALL;
tEndPoint0DescriptorBlock.bOEPCNFG &= ~EPCNF_STALL;
}
}else{
StallEndPoint0();
return;
}
TransmitNullResponseOnEp0();
break;
case USB_REQ_TYPE_DEVICE:
case USB_REQ_TYPE_INTERFACE:
case USB_REQ_TYPE_OTHER:
default:
StallEndPoint0();
break;
}
break;
case USB_REQ_SET_FEATURE:
// check if bLengthL = 0x00, wLength = 0x00
if((tSetupPacket.bLengthL != 0x00) || (tSetupPacket.bLengthH != 0x00)){
StallEndPoint0();
return;
}
// check if it is a write command
if(InTransaction == TRUE){
// control write but direction is IN
StallEndPoint0();
return;
}
// control write, stall output endpoint 0
// wLength should be 0 in all cases
Programming Considerations and Bootcode File List
6-11
File List
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
switch (tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK)
{
// Feature selector is in wValue
case USB_REQ_TYPE_ENDPOINT:
// Endpoint number is in low byte of wIndex
if (tSetupPacket.bValueL == FEATURE_ENDPOINT_STALL){
bTemp = tSetupPacket.bIndexL & EP_DESC_ADDR_EP_NUM;
// Ignore EP0 STALL, no reaon to have EP0 STALL
if(bTemp){ // other endpoints
if(bTemp > MAX_ENDPOINT_NUMBER){
StallEndPoint0();
return;
}
bTemp−−; // EP is from EP1 to EP3 while C
language start from 0
if(tSetupPacket.bIndexL & EP_DESC_ADDR_DIR_IN)
// input endpoint
tInputEndPointDescriptorBlock[bTemp].bEPCNF |=
EPCNF_STALL;
}
}else {
StallEndPoint0();
return;
}
TransmitNullResponseOnEp0();
break;
case USB_REQ_TYPE_DEVICE:
case USB_REQ_TYPE_INTERFACE:
case USB_REQ_TYPE_OTHER:
default:
StallEndPoint0();
break;
}
break;
case USB_REQ_SET_ADDRESS:
// check if recipient is device
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK) !=
USB_REQ_TYPE_DEVICE){
StallEndPoint0();
return;
}
// check if bLengthL = 0x00, wLength = 0x00
if((tSetupPacket.bLengthL != 0x00) || (tSetupPacket.bLengthH != 0x00)){
StallEndPoint0();
return;
}
// check if wIndex is zero
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
6-12
File List
}
// check if it is a write command
if(InTransaction == TRUE){
// control write but direction is IN
StallEndPoint0();
return;
}
// control write, stall output endpoint 0
// wLength should be 0 in all cases
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
if(tSetupPacket.bValueL < 128){
bFUNADR = tSetupPacket.bValueL ;
TransmitNullResponseOnEp0();
}else StallEndPoint0();
break;
case USB_REQ_GET_DESCRIPTOR:
// check if recipient is device
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK) !=
USB_REQ_TYPE_DEVICE){
StallEndPoint0();
return;
}
// check if it is a read command
if(InTransaction == FALSE){
// control read but direction is OUT
StallEndPoint0();
return;
}
// check if wLength = 0
if((tSetupPacket.bLengthL | tSetupPacket.bLengthH)==0x00){
// control read but wLength = 0
StallEndPoint0();
return;
}else tEndPoint0DescriptorBlock.bOEPBCNT = 0x00;
switch (tSetupPacket.bValueH)
{
case DESC_TYPE_DEVICE:
bEp0TxBytesRemaining = SIZEOF_DEVICE_DESCRIPTOR;
TransmitBufferOnEp0((PBYTE)&abDeviceDescriptor);
break;
case DESC_TYPE_CONFIG:
bEp0TxBytesRemaining = SIZEOF_BOOTCODE_CONFIG_DESC_GROUP;
TransmitBufferOnEp0((PBYTE)&abConfigurationDescriptorGroup);
break;
case DESC_TYPE_STRING:
case DESC_TYPE_INTERFACE:
case DESC_TYPE_ENDPOINT:
default:
StallEndPoint0();
return;
}
break;
case USB_REQ_GET_CONFIGURATION:
// check if recipient is device
StallEndPoint0();
return;
}
// check if it is a read command
if(InTransaction == FALSE){
// control read but direction is OUT
StallEndPoint0();
return;
}
// check if wIndex = 0x00
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
}
// check if wValue = 0x00
if((tSetupPacket.bValueL != 0x00) || (tSetupPacket.bValueH != 0x00)){
StallEndPoint0();
return;
}
// check if wLength = 1
if((tSetupPacket.bLengthL != 0x01) || (tSetupPacket.bLengthH!=0x00)){
StallEndPoint0();
return;
}else tEndPoint0DescriptorBlock.bOEPBCNT = 0x00;
bEp0TxBytesRemaining = 1;
TransmitBufferOnEp0 ((PBYTE)&bConfiguredFlag);
break;
case USB_REQ_SET_CONFIGURATION:
// check if recipient is device
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK) !=
USB_REQ_TYPE_DEVICE){
StallEndPoint0();
return;
}
// check if it is a write command
if(InTransaction == TRUE){
// control write but direction is IN
StallEndPoint0();
return;
}
// check if wIndex = 0x00
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
}
// check if wLength = 0x00
if((tSetupPacket.bLengthH != 0x00) || (tSetupPacket.bLengthL != 0x00)){
StallEndPoint0();
return;
}
// control write, stall output endpoint 0
// wLength should be 0 in all cases
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
6-14
File List
// check if bValueL is greater than 1
if(tSetupPacket.bValueL > 0x01){
StallEndPoint0();
return;
}
bConfiguredFlag = tSetupPacket.bValueL;
TransmitNullResponseOnEp0();
return;
case USB_REQ_GET_INTERFACE:
// check if recipient is interface
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK) !=
USB_REQ_TYPE_INTERFACE){
StallEndPoint0();
return;
}
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
}
// check if it is a read command
if(InTransaction == FALSE){
// control read but direction is OUT
StallEndPoint0();
return;
}
// check if wValue = 0x00
if((tSetupPacket.bValueL != 0x00) || (tSetupPacket.bValueH != 0x00)){
StallEndPoint0();
return;
}
// check if wLength = 1
if((tSetupPacket.bLengthL != 0x01) || (tSetupPacket.bLengthH != 0x00)){
StallEndPoint0();
return;
}else tEndPoint0DescriptorBlock.bOEPBCNT = 0x00;
bEp0TxBytesRemaining = 1;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
break;
case USB_REQ_SET_INTERFACE:
// check if recipient is interface
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK) !=
USB_REQ_TYPE_INTERFACE){
StallEndPoint0();
return;
}
if(tSetupPacket.bIndexL != 0x00){
StallEndPoint0();
return;
}
// check if it is a write command
if(InTransaction == TRUE){
// control write but direction is IN
StallEndPoint0();
return;
}
Programming Considerations and Bootcode File List
6-15
File List
// check if wLength = 0x00
if((tSetupPacket.bLengthL != 0x00) || (tSetupPacket.bLengthH != 0x00)){
StallEndPoint0();
return;
}
// check if wValue = 0x00
if((tSetupPacket.bValueL != 0x00) || (tSetupPacket.bValueH != 0x00)){
StallEndPoint0();
return;
}
// control write, stall output endpoint 0
// wLength should be 0 in all cases
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
TransmitNullResponseOnEp0();
return;
case USB_REQ_SET_DESCRIPTOR:
case USB_REQ_SYNCH_FRAME:
default:
// stall input and output endpoint 0
StallEndPoint0();
return;
}
break;
case USB_REQ_TYPE_VENDOR:
// check if recipient is device
if((tSetupPacket.bmRequestType & USB_REQ_TYPE_RECIP_MASK) !=
USB_REQ_TYPE_DEVICE){
StallEndPoint0();
return;
}
// general requests related to fiemware
switch(tSetupPacket.bRequest){
case 0x80: // get bootcode status
bEp0TxBytesRemaining = 4;
TransmitBufferOnEp0 ((PBYTE)abBootCodeStatus);
break;
case 0x81: // run firmware
if(bFirmwareChecksum == bRAMChecksum){
bExecuteFirmware = TRUE;
bRAMChecksumCorrect = TRUE;
TransmitNullResponseOnEp0();
}else StallEndPoint0();
break;
case 0x82: // Get firmware version
wIndex = headerReturnFirmwareRevision();
abReturnBuffer[0] = (BYTE)(wIndex & 0x00ff);
abReturnBuffer[1] = (BYTE)(wIndex >> 8);
bEp0TxBytesRemaining = 2;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
break;
case 0x83: // prepare for update header
wCurrentUploadPointer = 0x0000;
wCurrentFirmwareAddress = 0x0000;
bRAMChecksum = 0x00;
MASK_I2C_DEVICE_ADDRESS,wIndex,1,&abReturnBuffer[0])== NO_ERROR){
DelaymSecond(0x05);
TransmitNullResponseOnEp0();
}else StallEndPoint0();
break;
case 0x94: // internal ROM memory read
wIndex = (WORD)(tSetupPacket.bIndexH << 0x08) +
(WORD)tSetupPacket.bIndexL;
abReturnBuffer[0] = *(pbInternalROM+wIndex);
bEp0TxBytesRemaining = 1;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
break;
#ifdef SIMULATION
// for internal testing only! The host driver should NOT make these
requests
case 0xe0: // get current checksum
abReturnBuffer[0] = bRAMChecksum;
bEp0TxBytesRemaining = 1;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
break;
case 0xe1: // get downloaded size
abReturnBuffer[0] = (BYTE)(wCurrentFirmwareAddress & 0x00ff);
abReturnBuffer[1] = (BYTE)((wCurrentFirmwareAddress & 0xff00) >> 8);
bEp0TxBytesRemaining = 2;
TransmitBufferOnEp0 ((PBYTE)abReturnBuffer);
break;
case 0xe2: // set download size and checksum
// wValue(firmware size)
// bIndexL(checksum)
wCurrentFirmwareAddress = (WORD)(tSetupPacket.bValueH << 0x08) +
(WORD)tSetupPacket.bValueL;
bRAMChecksum = tSetupPacket.bIndexL;
TransmitNullResponseOnEp0();
break;
case 0xF0: // ROM Address Dump
wIndex = (WORD)(tSetupPacket.bIndexH << 0x08) +
// clear out status bits
abBootCodeStatus[0] = 0x00;
abBootCodeStatus[1] = 0x00;
abBootCodeStatus[2] = 0x00;
abBootCodeStatus[3] = 0x00;
// disconnect from USB
bUSBCTL = 0x00;
// Disable endpoints EP1
tOutputEndPointDescriptorBlock[0].bEPCNF = 0x00;
// set default values for hub
bHUBPIDL = HUB_PID_L;
bHUBPIDH = HUB_PID_H;
bHUBVIDL = HUB_VID_L;
bHUBVIDH = HUB_VID_H;
// copy descriptor to allocated address
// copy device and configuration descriptor to external memory
for(bTemp=0;bTemp<SIZEOF_DEVICE_DESCRIPTOR;bTemp++)
abDeviceDescriptor[bTemp] = abromDeviceDescriptor[bTemp];
for(bTemp=0;bTemp<SIZEOF_BOOTCODE_CONFIG_DESC_GROUP;bTemp++)
abConfigurationDescriptorGroup[bTemp] =
abromConfigurationDescriptorGroup[bTemp];
// set power wait time for the hub
bHUBPOTG = HUBPOTG_100MS; // 100 ms from power−on to power−good
// set power rating for the hub
bHUBCURT = HUBCURT_100MA; // 100 ms from power−on to power−good
// set i2c speed
i2cSetBusSpeed(I2C_100KHZ);
}
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Interrupt Sub−routines |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID SetupPacketInterruptHandler(VOID)
{
bEp0TxBytesRemaining = 0xFF; // setup packet received successfully
pbEp0Buffer = NULL; // clear remaining to be transmitted on endpoint 0
Endpoint0Control();
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID Ep0InputInterruptHandler(VOID)
{
// check if the last packet sent
tEndPoint0DescriptorBlock.bOEPBCNT = 0x00; // is set by the hardware
if(bEp0TxBytesRemaining == 0xff){
// last packet just sent, stall input endpoint 0
// so error conditions would occurs when the host asks more data
tEndPoint0DescriptorBlock.bIEPCNFG |= EPCNF_STALL;
}else FillEp0TxWithNextDataPacket();
}
6-20
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID Ep0OutputInterruptHandler(VOID)
{
// happened only in status stage
// Bootrom doesn’t handle data stage of control write.
// stall for any OUT, this is cleared in the setup stage.
tEndPoint0DescriptorBlock.bOEPCNFG |= EPCNF_STALL;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID Ep1OutputInterruptHandler(VOID)
{
BYTE bTemp,bSize,bCode;
// check if it is the first packet
if(wFirmwareLength == 0x0000){
wFirmwareLength = (WORD)abXBufferAddress[0];
wFirmwareLength += (WORD)(abXBufferAddress[1] << 8);
bFirmwareChecksum = abXBufferAddress[2];
bSize = tOutputEndPointDescriptorBlock[0].bEPBCTX & EPBCT_BYTECNT_MASK;
for(bTemp=3;bTemp<bSize;bTemp++){
bCode = abXBufferAddress[bTemp];
abDownloadFirmware[wCurrentFirmwareAddress] = bCode;
bRAMChecksum += bCode;
wCurrentFirmwareAddress++;
}
bCurrentBuffer = Y_BUFFER;
// clear NAK bit
tOutputEndPointDescriptorBlock[0].bEPBCTX = 0x00;
}else{
if(bCurrentBuffer == X_BUFFER){
// firgure out the size of packet
bSize = tOutputEndPointDescriptorBlock[0].bEPBCTX & EPBCT_BYTECNT_MASK;
for(bTemp=0;bTemp<bSize;bTemp++){
bCode = abXBufferAddress[bTemp];
abDownloadFirmware[wCurrentFirmwareAddress] = bCode;
bRAMChecksum += bCode;
wCurrentFirmwareAddress++;
}
bCurrentBuffer = Y_BUFFER;
// clear NAK bit
tOutputEndPointDescriptorBlock[0].bEPBCTX = 0x00;
}else{ // data in y buffer
// firgure out the size of packet
bSize = tOutputEndPointDescriptorBlock[0].bEPBCTY & EPBCT_BYTECNT_MASK;
for(bTemp=0;bTemp<bSize;bTemp++){
bCode = abYBufferAddress[bTemp];
abDownloadFirmware[wCurrentFirmwareAddress] = bCode;
bRAMChecksum += bCode;
wCurrentFirmwareAddress++;
}
bCurrentBuffer = X_BUFFER;
// clear NAK bit
tOutputEndPointDescriptorBlock[0].bEPBCTY = 0x00;
}
}
File List
Programming Considerations and Bootcode File List
6-21
File List
// check if firmware is ready
if((WORD)wCurrentFirmwareAddress >= wFirmwareLength){
// check is checksum is correct
if(bRAMChecksum == bFirmwareChecksum){
#ifdef SIMULATION
lcdPutString(”USB Checksum Correct!”);
DelaymSecond(2000);
#endif
bRAMChecksumCorrect = TRUE;
bExecuteFirmware = TRUE;
}else{
#ifdef SIMULATION
lcdPutString(”USB Checksum Incorrect!”);
DelaymSecond(2000);
#endif
bRAMChecksumCorrect = FALSE;
}
}
}
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Interrupt Service Routines |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
interrupt [0x03] void EX0_int(void) // External Interrupt 0
{
EA = DISABLE; // Disable any further interrupts
// always clear the interrupt source first and then bVECINT
switch (bVECINT){ // Identify Interrupt ID
case VECINT_OUTPUT_ENDPOINT0:
bVECINT = 0x00;
Ep0OutputInterruptHandler();
break;
case VECINT_INPUT_ENDPOINT0:
bVECINT = 0x00;
Ep0InputInterruptHandler();
break;
case VECINT_OUTPUT_ENDPOINT1:
bVECINT = 0x00;
Ep1OutputInterruptHandler();
break;
case VECINT_STPOW_PACKET_RECEIVED:
SetupPacketInterruptHandler();
// clear setup packet flag (clear source first)
bUSBSTA = USBSTA_STPOW;
bVECINT = 0x00;
break;
case VECINT_SETUP_PACKET_RECEIVED:
SetupPacketInterruptHandler();
// clear setup packet flag
bUSBSTA = USBSTA_SETUP;
bVECINT = 0x00;
break;
case VECINT_RSTR_INTERRUPT:
UsbDataInitialization();
6-22
// clear reset flag
bUSBSTA = USBSTA_RSTR;
bVECINT = 0x00;
break;
default:break; // unknown interrupt ID
}
EA = ENABLE; // Enable the interrupts again
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
#ifdef SIMULATION
BYTE code abTestHeader[16]
= { 0x52,0x51, // product ID
0x01, // Data Type (USB Info)
0x09,0x00, // Data Size (9 bytes)
0x80, // checksum
0x81, // bit setting (slef and switching)
0x51,0x04, // VID
0x34,0x12, // PID for hub
0x78,0x56, // PID for function
0x32, // for HUBPOTG
0x64, // for HUBCURT
0x00 // End of descriptor
};
BYTE code abNullHeader[8] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};
#endif
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID main(VOID)
{
#ifdef SIMULATION
WORD wAddress;
for(wAddress = 0; wAddress < 0x8000; wAddress++)
abDownloadFirmware[wAddress] = 0x00;
gpioInitialization();
lcdPutString(”UMP BootSim ”);
// clear i2c
// for(wAddress=0x0100; wAddress < 0x200;wAddress+=8){
// i2cWrite(0x00,wAddress,8,abNullHeader);
// DelaymSecond(20);
// }
i2cSetBusSpeed(I2C_100KHZ);
i2cSetMemoryType(I2C_CATEGORY_3);
for(wAddress=0;wAddress<16;wAddress++){
// i2cWrite(0x00,wAddress,1,&abTestHeader[wAddress]);
DelaymSecond(20);
}
// lcdI2cDump(0x0000,4);
// ledPutChar(0x01,0x64);
// while(1);
#endif
CopyDefaultSettings();
UsbDataInitialization();
// partial support due to memory size
if(headerSearchForValidHeader() == DATA_MEDIUM_HEADER_I2C){
if(bExecuteFirmware == FALSE){
// use default value
EA = ENABLE; // Enable global interrupt
EX0 = ENABLE; // Enable interrupt 0
bUSBCTL |= USBCTL_CONT; // connect to upstream port
#ifdef SIMULATION
lcdPutString(”Connecting”);
bUSBCTL |= 0xc0;
#endif
while(bExecuteFirmware == FALSE);
}
// Disable all interrupts
EA = DISABLE; // disable global interrupt
// disconnection
bUSBCTL = USBCTL_FRSTE;
// map xdata to code space if checksum correct
// now application code is in code space
if(bRAMChecksumCorrect == TRUE){
#ifdef SIMULATION
lcdPutStringXY(0,2,”Set Shadow Bit”);
DelaymSecond(4000);
#endif
bROMS |= ROMS_SDW;
}else{
#ifdef SIMULATION
lcdPutStringXY(0,2,”Shadow Bit Not Set!”);
DelaymSecond(4000);
#endif
}
(*(void(*)(void))0x0000)(); // run firmware now
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Cut along the line −−−−−−−−−−−−−−−−−−−−−−−−−−−−
6-24
6.2.2I2C.c I2C Routines
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Texas Instruments |
| I2C |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Source: i2c.c, v 1.0 99/01/28 11:00:36 |
| Author: Horng−Ming Lobo Tai lobotai@ti.com |
| Header: (none) |
| |
| For more information, contact |
| Lobo Tai |
| Texas Instruments |
| 12500 TI Blvd, MS 8761 |
| Dallas, TX 75243 |
| USA |
| Tel 214−480−3145 |
| Fax 214−480−3443 |
| |
| Notes: |
WHEN WHAT |
| WHO
| HMT 19990128 born |
| HMT 19990414 add the following functions (SiCore’s format) |
| HMT 19990423 modified i2cWaitForRead & i2cWaitForWrite |
| to write ’1’ clear and removed eUMP functions |
| HMT 19990611 fixed bug in i2cRead when bNumber is 1 |
| HMT 19991124 port to usb keyboard |
| HMT 20000122 add control code 0xa0 |
| HMT 20000614 add to support cat i,ii, and iii devices |
| HMT 20000615 i2c on cat 2 device: |
| some cat 2 uses A0,A1 and A2(or partially) but some |
| donesn’t. Therefore, in the i2c routine, if the |
| address is more than 0xff, it overwrites the |
| device address by higher data address. In this way, |
| routine can cover most of devices with minor issues. |
| HMT 20000630 Bug fixed on wait for read for last byte in high |
| speed. uC is too slow to set SRD bit. |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#include ”types.h”
#include ”i2c.h”
#include ”tusb5052.h”
#ifdef I2C_TEST
#include ”delay.h”
#include ”gpio.h”
#endif
static BYTE bDeviceCategory;
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID i2cSetBusSpeed(BYTE bBusSpeed)
{
if(bBusSpeed == I2C_400KHZ) bI2CSTA |= I2CSTA_400K; // set bus speed at 400Khz
else bI2CSTA &= ~I2CSTA_400K; // set bus speed at 100Khz
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
VOID i2cSetMemoryType(BYTE bType)
{
File List
Programming Considerations and Bootcode File List
6-25
File List
if( bType > I2C_CATEGORY_LAST) return; // invalid memory type
else bDeviceCategory = bType;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
BYTE i2cWaitForRead(VOID)
{
// wait until data is ready or ERR=1
while((bI2CSTA & I2CSTA_RXF) != I2CSTA_RXF)
if((bI2CSTA & I2CSTA_ERR) == I2CSTA_ERR){
bI2CSTA |= I2CSTA_ERR; // clear error flag
return ERROR;
}
return NO_ERROR;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
BYTE i2cWaitForWrite(VOID)
{
// wait until TXE bit is cleared or ERR=1
while((bI2CSTA & I2CSTA_TXE) != I2CSTA_TXE)
if((bI2CSTA & I2CSTA_ERR) == I2CSTA_ERR){
bI2CSTA |= I2CSTA_ERR; // clear error flag
return ERROR;
}
return NO_ERROR;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
BYTE i2cRead(BYTE bDeviceAddress, WORD wAddress, WORD wNumber, PBYTE pbDataArray)
{
BYTE bTemp,bHiAddress;
// If error, return a value other than zero.
if(wNumber == 0x00) return NO_ERROR;
return MSG_HEADER_NO_ERROR;
}
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
WORD headerReturnFirmwareRevision(VOID)
{
WORD wCurrentFirmwareRevision;
SIZEOF_CONFIG_DESCRIPTOR+SIZEOF_INTERFACE_DESCRIPTOR+SIZEOF_ENDPOINT_DESCRIPTOR
// Power Control Register (@ SFR 87h)
// PCON 0x87 // sfr 0x87
#define PCON_IDL 0x01 // MCU idle bit
// 0: MCU NOT in idle, 1:MCU idle
#define PCON_GF0 0x04 // General purpose bit
#define PCON_GF1 0x08 // General purpose bit
#define PCON_SMOD 0x80 // Double baud rate control bit
// External Memory Pointer
// don’t use this one because it is not efficient in the binary code.
// char *pbExternalRAM = (char *)0x010000;
#define pbExternalRAM ((char xdata *)0x0000) // use this for the future design
#define pbInternalROM ((char code *)0x0000)
// TUSB5052 VID and PID Definition
#define HUB_VID_L 0x51 // TI = 0x0451
#define HUB_VID_H 0x04
#define HUB_PID_L 0x45
#define HUB_PID_H 0x31
// on−board I/O address are c00x. This is the same as f80x.
#define IEP1_X_BUFFER_ADDRESS 0xF800 // Input Endpoint 1 X Buffer Base−address
#define IEP1_Y_BUFFER_ADDRESS 0xF840 // Input Endpoint 1 Y Buffer Base−address
#define OEP1_X_BUFFER_ADDRESS 0xF880 // Output Endpoint 1 X Buffer Base−address
#define OEP1_Y_BUFFER_ADDRESS 0xF8C0 // Output Endpoint 1 Y Buffer Base−address
#define IEP2_X_BUFFER_ADDRESS 0xF900 // Input Endpoint 2 X Buffer Base−address
#define IEP2_Y_BUFFER_ADDRESS 0xF940 // Input Endpoint 2 Y Buffer Base−address
#define OEP2_X_BUFFER_ADDRESS 0xF980 // Output Endpoint 2 X Buffer Base−address
#define OEP2_Y_BUFFER_ADDRESS 0xF9C0 // Output Endpoint 2 Y Buffer Base−address
#define IEP3_X_BUFFER_ADDRESS 0xFA00 // Input Endpoint 3 X Buffer Base−address
#define IEP3_Y_BUFFER_ADDRESS 0xFA40 // Input Endpoint 3 Y Buffer Base−address
#define OEP3_X_BUFFER_ADDRESS 0xFA80 // Output Endpoint 3 X Buffer Base−address
#define OEP3_Y_BUFFER_ADDRESS 0xFAC0 // Output Endpoint 3 Y Buffer Base−address
#define IEP4_X_BUFFER_ADDRESS 0xFB00 // Input Endpoint 4 X Buffer Base−address
#define IEP4_Y_BUFFER_ADDRESS 0xFB40 // Input Endpoint 4 Y Buffer Base−address
#define OEP4_X_BUFFER_ADDRESS 0xFB80 // Output Endpoint 4 X Buffer Base−address
#define OEP4_Y_BUFFER_ADDRESS 0xFBC0 // Output Endpoint 4 Y Buffer Base−address
Programming Considerations and Bootcode File List
6-39
tusb5052.h UMP-Related Header File
#define IEP5_X_BUFFER_ADDRESS 0xFC00 // Input Endpoint 5 X Buffer Base−address
#define IEP5_Y_BUFFER_ADDRESS 0xFC40 // Input Endpoint 5 Y Buffer Base−address
#define OEP5_X_BUFFER_ADDRESS 0xFC80 // Output Endpoint 5 X Buffer Base−address
#define OEP5_Y_BUFFER_ADDRESS 0xFCC0 // Output Endpoint 5 Y Buffer Base−address
#define IEP6_X_BUFFER_ADDRESS 0xFD00 // Input Endpoint 6 X Buffer Base−address
#define IEP6_Y_BUFFER_ADDRESS 0xFD40 // Input Endpoint 6 Y Buffer Base−address
#define OEP6_X_BUFFER_ADDRESS 0xFD80 // Output Endpoint 6 X Buffer Base−address
#define OEP6_Y_BUFFER_ADDRESS 0xFDC0 // Output Endpoint 6 Y Buffer Base−address
#define IEP7_X_BUFFER_ADDRESS 0xFE00 // Input Endpoint 7 X Buffer Base−address
#define IEP7_Y_BUFFER_ADDRESS 0xFE20 // Input Endpoint 7 Y Buffer Base−address
#define OEP7_X_BUFFER_ADDRESS 0xFE40 // Output Endpoint 7 X Buffer Base−address
#define OEP7_Y_BUFFER_ADDRESS 0xFE60 // Output Endpoint 7 Y Buffer Base−address
// Miscellaneous Registers
#define ROMS_SDW 0x01
#define ROMS_R0 0x02 // Revision Number R[3:0]
#define ROMS_R1 0x04
#define ROMS_R2 0x08
#define ROMS_R3 0x10
#define ROMS_S0 0x20 // Code Size S[1:0]
#define ROMS_S1 0x40 // 00: 4K, 01:8k, 10:16k, 11:32k
#define ROMS_ROA 0x80 // Code Space 0:in ROM, 1:in RAM
#define GLOBCTL_LPWR 0x04 // Low Power Bit Mode, 0:Low Power, 1:Normal Operation
#define GLOBCTL_RSTP 0x08 // Reset Ouput Polarity 0:Active Low, 1:Active High
#define GLOBCTL_C0 0x20 // Output Clock Frequency Select, C[1:0]
#define GLOBCTL_C1 0x40 // 00:48Mhz, 01:24Mhz, 10:12Mhz, 11:6Mhz
#define GLOBCTL_24MHZ 0x80 // Clock Slect for MCU, 0:12Mhz, 1:24Mhz
// EndPoint Desciptor Block
#define EPCNF_USBIE 0x04 // USB Interrupt on Transaction Completion. Set By MCU
// 0:No Interrupt, 1:Interrupt on completion
#define EPCNF_STALL 0x08 // USB Stall Condition Indication. Set by UBM
// 0: No Stall, 1:USB Install Condition
#define EPCNF_DBUF 0x10 // Double Buffer Enable. Set by MCU
// 0: Primary Buffer Only(x−buffer only), 1:Toggle Bit
// Selects Buffer
#define EPCNF_TOGLE 0x20 // USB Toggle bit. This bit reflects the toggle sequence bit
// of DATA0 and DATA1.
#define EPCNF_ISO 0x40 // ISO=0, Non Isochronous transfer. This bit must be cleared
// by MCU since only non isochronous transfer is supported.
#define EPCNF_UBME 0x80 // UBM Enable or Disable bit. Set or Clear by MCU.
// 0:UBM can’t use this endpoint
// 1:UBM can use this endpoint
#define EPBCT_BYTECNT_MASK 0x7F // MASK for Buffer Byte Count
#define EPBCT_NAK 0x80 // NAK, 0:No Valid in buffer, 1:Valid packet in buffer
// Endpoint 0 Descriptor Registers
#define IEPBCNT_NAK 0x80 // NAK bit
// 0:buffer contains valid data
// 1:buffer is empty
// USB Registers
#define USBSTA_STPOW 0x01 // Setup Overwrite Bit. Set by hardware when setup
// packet is received
// while there is already a packet in the setup buffer.
// 0:Nothing, 1:Setup Overwrite
#define USBSTA_RWUP 0x02 // Remote wakeup pin status
// 0:Nothing, 1:Remote wakeup request
#define USBSTA_SETUP 0x04 // Setup Transaction Received Bit. As long as SETUP is ’1’,
6-40
tusb5052.h UMP-Related Header File
// IN and OUT on endpoint−0 is NAKed regardless
// of their real NAK bits values.
#define USBSTA_UART1 0x08 // Uart 1 Ring Indicator
// 0: no ring coming, 1:ring coming
#define USBSTA_UART2 0x10 // Uart 2 Ring Indicator
// 0: no ring coming, 1:ring coming
#define USBSTA_RESR 0x20 // Function Resume Request Bit. 0:clear by MCU,
// 1:Function Resume is detected.
#define USBSTA_SUSR 0x40 // Function Suspended Request Bit. 0:clear by MCU,
// 1:Function Suspend is detected.
#define USBSTA_RSTR 0x80 // Function Reset Request Bit. This bit is set in
// response to a global or selective suspend condition.
// 0:clear by MCU, 1:Function reset is detected.
#define USBMSK_STPOW 0x01 // Setup Overwrite Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_RWUP 0x02 // Remote wakeup Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_SETUP 0x04 // Setup Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_UART1 0x08 // Uart1 RI Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_UART2 0x10 // Uart2 RI Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_RESR 0x20 // Function Resume Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_SUSR 0x40 // Function Suspend Interrupt Enable Bit
// 0: disable, 1:enable
#define USBMSK_RSTR 0x80 // Function Reset Interrupt Enable Bit
// 0: disable, 1:enable
#define USBCTL_DIR 0x01 // USB traffic direction 0: USB out packet, 1:in
// packet (from TUSB5052 to The host)
#define USBCTL_SIR 0x02 // Setup interrupt status bit
// 0: SETUP interrupt is not served.
// 1: SETUP interrupt in progess
#define USBCTL_SELF 0x04 // Bus/self powered bit
// 0: bus, 1:self
#define USBCTL_FRSTE 0x10 // Function Reset Condition Bit.
// This bit connects or disconnects the USB
// Function Reset from the MCU reset
// 0:not connect, 1:connect
#define USBCTL_RWUP 0x20 // Remote wakeup request
#define USBCTL_HUBV 0x40 // USB hub version Read only
// 0:1.x hub, 1:2.x hub
#define USBCTL_CONT 0x80 // Connect or Disconnect Bit
// 0:Upstream port is disconnected. Pull−up disabled
// 1:Upstream port is connected. Pull−up enabled
#define HUBCNF1_P1E 0x01 // Hub Port 1 enable/disable control bit
// 0: disable, 1:enable
#define HUBCNF1_P1A 0x02 // Hub Port 1 connection bit
// 0: removable, 1:fixed
#define HUBCNF1_P2E 0x04 // Hub Port 2 enable/disable control bit
// 0: disable, 1:enable
#define HUBCNF1_P2A 0x08 // Hub Port 2 connection bit
// 0: removable, 1:fixed
#define HUBCNF1_P3E 0x10 // Hub Port 3 enable/disable control bit
// 0: disable, 1:enable
Programming Considerations and Bootcode File List
6-41
tusb5052.h UMP-Related Header File
#define HUBCNF1_P3A 0x20 // Hub Port 3 connection bit
// 0: removable, 1:fixed
#define HUBCNF1_P4E 0x40 // Hub Port 4 enable/disable control bit
// 0: disable, 1:enable
#define HUBCNF1_P4A 0x80 // Hub Port 4 connection bit
// 0: removable, 1:fixed
#define HUBCNF2_P5E 0x01 // Hub Port 5 enable/disable control bit
// 0: disable, 1:enable
#define HUBCNF2_P5A 0x02 // Hub Port 5 connection bit
// 0: removable, 1:fixed
#define HUBCNF2_P6_NONE 0x00 // Hub Port 6: no function
#define HUBCNF2_P6_EN 0x10 // Hub Port 6: fixed attach, enable (normal
// operation)
#define HUBCNF2_P6_NOT_ATTACH 0x20 // Hub Port 6: removable, NOT attach
#define HUBCNF2_P6_ATTACH 0x30 // Hub Port 6: attached, removable
#define HUBCNF2_P6_MASK 0x30
#define HUBCNF2_PWRSW 0x80 // Power Switch controle bit
// 0: not available, 1:available
#define HUBPOTG_100MS 0x32 // power−on to power−good time is 100ms
( in 2msincrement)
#define HUBCURT_100MA 0x64 // hub requires 100mA
// DMA Control Registers
#define DMA_BASE_ADDRESS 0xFFE0 // all DMA register starts at this address
#define DMACDR_ENDPOINT_MASK 0x07 // Endpoint Select Mask
#define DMACDR_ENDPOINT1 0x01 // Select Endpoint 1
#define DMACDR_ENDPOINT2 0x02 // Select Endpoint 2
#define DMACDR_ENDPOINT3 0x03 // Select Endpoint 3
#define DMACDR_ENDPOINT4 0x04 // Select Endpoint 4
#define DMACDR_ENDPOINT5 0x05 // Select Endpoint 5
#define DMACDR_ENDPOINT6 0x06 // Select Endpoint 6
#define DMACDR_ENDPOINT7 0x07 // Select Endpoint 7
#define DMACDR_TR 0x08 // DMA Direction (not used in UMP)
// 0:out, 1:in
#define DMACDR_XY 0x10 // XY Buffer Select (valid only when CNT=0)
// 0:X buffer 1:Y buffer
#define DMACDR_CNT 0x20 // DMA Continuous Transfer Control bit
// 0:Burst Mode, 1:Continuos Mode
#define DMACDR_INE 0x40 // DMA Interrupt Enable or Disable bit.
// 0:disable, 1:enable
#define DMACDR_EN 0x80 // DMA Channel Enable
// 0:disable, 1:enable
#define DMACSR_OVRUN 0x01 // Overrun Condition Bit. Set by DMA and
// Cleared by MCU
// 0: no overrun, 1:overrun
#define DMACSR_PPKT 0x01 // Overrun Condition Bit. Set by DMA and
// Cleared by MCU
// 0: no overrun(no partial packet), 1:overrun
#define DMACSR_TXFT 0x02 // Transfer Timeout Condition. Cleared by MCU
// 0: no timeout, 1:timeout
#define DMACSR_TIMEOUT_MASK 0x7C // Select Timeout Value
#define DMACSR_TIMEOUT_1MS 0x00 // Select Timeout 1ms Value
#define DMACSR_TIMEOUT_2MS 0x04 // Select Timeout 2ms Value
#define DMACSR_TIMEOUT_3MS 0x08 // Select Timeout 3ms Value
#define DMACSR_TIMEOUT_4MS 0x0C // Select Timeout 4ms Value
#define DMACSR_TIMEOUT_5MS 0x10 // Select Timeout 5ms Value
6-42
tusb5052.h UMP-Related Header File
#define DMACSR_TIMEOUT_6MS 0x14 // Select Timeout 6ms Value
#define DMACSR_TIMEOUT_7MS 0x18 // Select Timeout 7ms Value
#define DMACSR_TIMEOUT_8MS 0x1C // Select Timeout 8ms Value
#define DMACSR_TIMEOUT_9MS 0x20 // Select Timeout 9ms Value
#define DMACSR_TIMEOUT_10MS 0x24 // Select Timeout 10ms Value
#define DMACSR_TIMEOUT_11MS 0x28 // Select Timeout 11ms Value
#define DMACSR_TIMEOUT_12MS 0x2C // Select Timeout 12ms Value
#define DMACSR_TIMEOUT_13MS 0x30 // Select Timeout 13ms Value
#define DMACSR_TIMEOUT_14MS 0x34 // Select Timeout 14ms Value
#define DMACSR_TIMEOUT_15MS 0x38 // Select Timeout 15ms Value
#define DMACSR_TIMEOUT_16MS 0x3C // Select Timeout 16ms Value
#define DMACSR_TIMEOUT_17MS 0x40 // Select Timeout 17ms Value
#define DMACSR_TIMEOUT_18MS 0x44 // Select Timeout 18ms Value
#define DMACSR_TIMEOUT_19MS 0x48 // Select Timeout 19ms Value
#define DMACSR_TIMEOUT_20MS 0x4C // Select Timeout 20ms Value
#define DMACSR_TIMEOUT_21MS 0x50 // Select Timeout 21ms Value
#define DMACSR_TIMEOUT_22MS 0x54 // Select Timeout 22ms Value
#define DMACSR_TIMEOUT_23MS 0x58 // Select Timeout 23ms Value
#define DMACSR_TIMEOUT_24MS 0x5C // Select Timeout 24ms Value
#define DMACSR_TIMEOUT_25MS 0x60 // Select Timeout 25ms Value
#define DMACSR_TIMEOUT_26MS 0x64 // Select Timeout 26ms Value
#define DMACSR_TIMEOUT_27MS 0x68 // Select Timeout 27ms Value
#define DMACSR_TIMEOUT_28MS 0x6C // Select Timeout 28ms Value
#define DMACSR_TIMEOUT_29MS 0x70 // Select Timeout 29ms Value
#define DMACSR_TIMEOUT_30MS 0x74 // Select Timeout 30ms Value
#define DMACSR_TIMEOUT_31MS 0x78 // Select Timeout 31ms Value
#define DMACSR_TIMEOUT_32MS 0x7C // Select Timeout 32ms Value
#define DMACSR_TEN 0x80 // Transaction Timeout Conouter Enable
// device function address.
#ifdef __cplusplus
}
#endif
#endif /* _TUSB5052_H_ */
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Cut along the line −−−−−−−−−−−−−−−−−−−−−−−−−−−−
Programming Considerations and Bootcode File List
6-51
usb.h USB-Related Header File
6.5usb.h USB-Related Header File
/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Texas Instruments |
| USB Header File |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
| Source: usb.h, v 1.0 99/02/01 10:05:58 |
| Author: Horng−Ming Lobo Tai lobotai@ti.com |
| Header: (none) |
| |
| For more information, contact |
| Lobo Tai |
| Texas Instruments |
| 8505 Forest Lane, MS 8761 |
| Dallas, TX 75243 |
| USA |
| Tel 972−480−3145 |
| Fax 972−480−3443 |
| |
| Notes: |
| 1. 990202 born |
| 2. 990422 add device status definition |
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#ifndef _USB_H_
#define _USB_H_
#define USB_SPEC_REV_BCD 0x0101 /*BCD coded rev level of USB spec*/
// DEVICE_REQUEST Structure
#define SIZEOF_DEVICE_REQUEST 0x08
typedef struct _tDEVICE_REQUEST
{
BYTE bmRequestType; // See bit definitions below
BYTE bRequest; // See value definitions below
BYTE bValueL; // Meaning varies with request type
BYTE bValueH; // Meaning varies with request type
BYTE bIndexL; // Meaning varies with request type
BYTE bIndexH; // Meaning varies with request type
BYTE bLengthL; // Number of bytes of data to transfer (LSByte)
BYTE bLengthH; // Number of bytes of data to transfer (MSByte)
} tDEVICE_REQUEST, *ptDEVICE_REQUEST;
// Bit definitions for DEVICE_REQUEST.bmRequestType
// Bit 7: Data direction
#define USB_REQ_TYPE_OUTPUT 0x00 // 0 = Host sends data to device
#define USB_REQ_TYPE_INPUT 0x80 // 1 = Device sending data to the host
// Bit 6−5: Type
#define USB_REQ_TYPE_MASK 0x60 // Mask value for bits 6−5
#define USB_REQ_TYPE_STANDARD 0x00 // 00 = Standard USB request
#define USB_REQ_TYPE_CLASS 0x20 // 01 = Class specific
#define USB_REQ_TYPE_VENDOR 0x40 // 10 = Vendor specific
// Bit 4−0: Recipient
#define USB_REQ_TYPE_RECIP_MASK 0x1F // Mask value for bits 4−0
#define USB_REQ_TYPE_DEVICE 0x00 // 00000 = Device
#define USB_REQ_TYPE_INTERFACE 0x01 // 00001 = Interface
#define USB_REQ_TYPE_ENDPOINT 0x02 // 00010 = Endpoint
#define USB_REQ_TYPE_OTHER 0x03 // 00011 = Other
// Values for DEVICE_REQUEST.bRequest
6-52
usb.h USB-Related Header File
// Standard Device Requests
#define USB_REQ_GET_STATUS 0
#define USB_REQ_CLEAR_FEATURE 1
#define USB_REQ_SET_FEATURE 3
#define USB_REQ_SET_ADDRESS 5
#define USB_REQ_GET_DESCRIPTOR 6
#define USB_REQ_SET_DESCRIPTOR 7
#define USB_REQ_GET_CONFIGURATION 8
#define USB_REQ_SET_CONFIGURATION 9
#define USB_REQ_GET_INTERFACE 10
#define USB_REQ_SET_INTERFACE 11
#define USB_REQ_SYNCH_FRAME 12
// Descriptor Type Values
#define DESC_TYPE_DEVICE 1 // Device Descriptor (Type 1)
#define DESC_TYPE_CONFIG 2 // Configuration Descriptor (Type 2)
#define DESC_TYPE_STRING 3 // String Descriptor (Type 3)
#define DESC_TYPE_INTERFACE 4 // Interface Descriptor (Type 4)
#define DESC_TYPE_ENDPOINT 5 // Endpoint Descriptor (Type 5)
#define DESC_TYPE_HUB 0x29 // Hub Descriptor (Type 6)
// Feature Selector Values
#define FEATURE_REMOTE_WAKEUP 1 // Remote wakeup (Type 1)
#define FEATURE_ENDPOINT_STALL 0 // Endpoint stall (Type 0)
// Device Status Values
#define DEVICE_STATUS_REMOTE_WAKEUP 0x02
#define DEVICE_STATUS_SELF_POWER 0x01
// DEVICE_DESCRIPTOR structure
#define SIZEOF_DEVICE_DESCRIPTOR 0x12
#define OFFSET_DEVICE_DESCRIPTOR_VID_L 0x08
#define OFFSET_DEVICE_DESCRIPTOR_VID_H 0x09
#define OFFSET_DEVICE_DESCRIPTOR_PID_L 0x0A
#define OFFSET_DEVICE_DESCRIPTOR_PID_H 0x0B
#define OFFSET_CONFIG_DESCRIPTOR_POWER 0x07
#define OFFSET_CONFIG_DESCRIPTOR_CURT 0x08
typedef struct _tDEVICE_DESCRIPTOR
{
BYTE bLength; // Length of this descriptor (12h bytes)
BYTE bDescriptorType; // Type code of this descriptor (01h)
WORD bcdUsb; // Release of USB spec (0210h = rev 2.10)
BYTE bDeviceClass; // Device’s base class code
BYTE bDeviceSubClass; // Device’s sub class code
BYTE bDeviceProtocol; // Device’s protocol type code
BYTE bMaxPacketSize0; // End point 0’s max packet size (8/16/32/64)
WORD wIdVendor; // Vendor ID for device
WORD wIdProduct; // Product ID for device
WORD wBcdDevice; // Revision level of device
BYTE wManufacturer; // Index of manufacturer name string desc
BYTE wProduct; // Index of product name string desc
BYTE wSerialNumber; // Index of serial number string desc
BYTE bNumConfigurations; // Number of configurations supported
} tDEVICE_DESCRIPTOR, *ptDEVICE_DESCRIPTOR;
// CONFIG_DESCRIPTOR structure
#define SIZEOF_CONFIG_DESCRIPTOR 0x09
typedef struct _tCONFIG_DESCRIPTOR
{
Programming Considerations and Bootcode File List
6-53
usb.h USB-Related Header File
BYTE bLength; // Length of this descriptor (9h bytes)
BYTE bDescriptorType; // Type code of this descriptor (02h)
WORD wTotalLength; // Size of this config desc plus all interface,
// endpoint, class, and vendor descriptors
BYTE bNumInterfaces; // Number of interfaces in this config
BYTE bConfigurationValue; // Value to use in SetConfiguration command
BYTE bConfiguration; // Index of string desc describing this config
BYTE bAttributes; // See CFG_DESC_ATTR_xxx values below
BYTE bMaxPower; // Power used by this config in 2mA units
} tCONFIG_DESCRIPTOR, *ptCONFIG_DESCRIPTOR;
// Bit definitions for CONFIG_DESCRIPTOR.bmAttributes
#define CFG_DESC_ATTR_SELF_POWERED 0x40 // Bit 6: If set, device is self powered
#define CFG_DESC_ATTR_BUS_POWERED 0x80 // Bit 7: If set, device is bus powered
#define CFG_DESC_ATTR_REMOTE_WAKE 0x20 // Bit 5: If set, device supports remote wakeup
// INTERFACE_DESCRIPTOR structure
#define SIZEOF_INTERFACE_DESCRIPTOR 0x09
typedef struct _tINTERFACE_DESCRIPTOR
{
BYTE bLength; // Length of this descriptor (9h bytes)
BYTE bDescriptorType; // Type code of this descriptor (04h)
BYTE bInterfaceNumber; // Zero based index of interface in the configuration
BYTE bAlternateSetting; // Alternate setting number of this interface
BYTE bNumEndpoints; // Number of endpoints in this interface
BYTE bInterfaceClass; // Interface’s base class code
BYTE bInterfaceSubClass; // Interface’s sub class code
BYTE bInterfaceProtocol; // Interface’s protocol type code
BYTE bInterface; // Index of string desc describing this interface
} tINTERFACE_DESCRIPTOR, *ptINTERFACE_DESCRIPTOR;
// ENDPOINT_DESCRIPTOR structure
#define SIZEOF_ENDPOINT_DESCRIPTOR 0x07
typedef struct _tENDPOINT_DESCRIPTOR
{
BYTE bLength; // Length of this descriptor (7h bytes)
BYTE bDescriptorType; // Type code of this descriptor (05h)
BYTE bEndpointAddress; // See EP_DESC_ADDR_xxx values below
BYTE bAttributes; // See EP_DESC_ATTR_xxx value below
WORD wMaxPacketSize; // Max packet size of endpoint
BYTE bInterval; // Polling interval of endpoint in milliseconds
} tENDPOINT_DESCRIPTOR, *tpENDPOINT_DESCRIPTOR;
// Bit definitions for EndpointDescriptor.EndpointAddr
#define EP_DESC_ADDR_EP_NUM 0x0F // Bit 3−0: Endpoint number
#define EP_DESC_ADDR_DIR_IN 0x80 // Bit 7: Direction of endpoint, 1/0 = In/Out
// Bit definitions for EndpointDescriptor.EndpointFlags
#define EP_DESC_ATTR_TYPE_MASK 0x03 // Mask value for bits 1−0
#define EP_DESC_ATTR_TYPE_CONT 0x00 // Bit 1−0: 00 = Endpoint does control transfers
#define EP_DESC_ATTR_TYPE_ISOC 0x01 // Bit 1−0: 01 = Endpoint does isochronous transfers
#define EP_DESC_ATTR_TYPE_BULK 0x02 // Bit 1−0: 10 = Endpoint does bulk transfers
#define EP_DESC_ATTR_TYPE_INT 0x03 // Bit 1−0: 11 = Endpoint does interrupt transfers
#endif /* _USB_H */
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Cut along the line −−−−−−−−−−−−−−−−−−−−−−−−−−−−