NOTICE: The Processors Wiki will End-of-Life in December of 2020. It is recommended to download any files or other content you may need that are hosted on processors.wiki.ti.com. The site is now set to read only.

StarterWare USB

From Texas Instruments Wiki
Jump to: navigation, search
{{#switchcategory:MSP430=<McuHitboxHeader/>|C2000=<McuHitboxHeader/>|Stellaris=<McuHitboxHeader/>|TMS570=<McuHitboxHeader/>|MCU=<McuHitboxHeader/>|MAVRK=<MAVRKHitboxHeader/>|<HitboxHeader/>}}

Contents

Introduction[edit]

The StarterWare USB stack is an OS-independent USB solution that is migrated from the StellarisWare. For more information on the original StellarisWare USB library, please refer to the StellarisWare user guide.

The API reference guide for StarterWare USB is available as part of release package. Look for the [Device]_StarterWare_x_xx_xx_xx.chm file in docs for the for detailed API documentation.

The StarterWare USB stack currently supports the following features:

Release Device Mode Host Mode Host + Device Mode Host + Host Mode
CDC Serial (PIO Mode) Custom Bulk (PIO Mode) HID Mouse (PIO Mode) MSC (PIO Mode) MSC (DMA Mode) HID Mouse (PIO Mode) MSC (PIO Mode) MSC (DMA Mode) MSC (PIO Mode) MSC (DMA Mode) MSC (PIO Mode)/Mouse (PIO Mode) MSC (DMA Mode)/Mouse (PIO Mode)
1.00.01.01 YES YES YES YES YES YES YES YES NO NO NO NO
1.10.01.01 YES YES YES YES YES YES YES YES NO NO NO NO
1.20.01.01 YES YES YES YES YES YES YES YES NO NO NO NO
2.00.00.05(AM335x EVM) YES YES YES YES YES YES YES YES NO NO NO NO
2.00.00.05(AM335x Beaglebone) YES YES NO YES YES NO NO NO NO NO NO NO
2.00.00.06(AM335x EVM) YES YES YES YES YES YES YES YES NO YES NO NO
2.00.00.06(AM335x Beaglebone) YES YES NO YES YES NO NO NO NO NO NO NO
2.00.00.07(AM335x EVM) YES YES YES YES YES YES YES YES YES YES YES YES
2.00.00.07(AM335x Beaglebone) YES YES NO YES YES NO YES YES YES YES NO NO
2.00.00.07(AM335x EVMSK) YES YES YES YES YES YES YES YES YES YES NO NO

Comparison to StellarisWare USB[edit]

The following table compares the StarterWare and StellarisWare USB stacks.

Feature AM1808/OMAPL138/C6748 AM335x Stellaris USB Subsystem
Core IP MUSB MUSB MUSB
Number Of Endpoints 4 + 1 15 + 1 15 + 1
DMA CPPI DMA 4.1 CPPI DMA 4.1 Micro DMA
Mapped to Wrapper Registers Yes, Only the Interrupt registers Yes, Only the Interrupt registers No
Endpoint 0 FIFO size 64 Bytes 64 Bytes 64 Bytes
Other Endpoint FIFO 8 to 8192 bytes configurable (Verified for 64/512 only) 8 to 8192 bytes configurable (Verified for 64/512 only) 8 to 8192 bytes configurable
Speed High Speed/Full Speed (Refer to Class Description for details) High Speed/Full Speed (Refer to Class Description for details) High Speed Not Supported

Core Design[edit]

The following diagram shows the architecture of the StarterWare USB stack.

USB Design.JPG

Mentor Controller Device Abstraction Layer (MUSB DAL)[edit]

The USBOTG Subsystem is based on Mentor Graphics USB Controller. IP core supports 4Tx/4Rx endpoints and an integrated CPPI41 DMA engine. The Device Abstraction Layer (DAL) is the only module in StarterWare USB which directly communicates with the Mentor controller. The MUSB DAL layers abstracts all the functionalities or services used by the layer above to configure and control the USB OTG Controller. The DAL APIs are used by the other components of device or host stack.

The MUSB DAL is implemented in single file (usb.c), and important APIs are summarized below.

  • USBDevConnect - Connects the USB controller to the bus in device mode. This API is used by the USB Core module during initialization.
  • USBDevDisconnect - Removes the USB controller from the bus in device mode. This API is used by the USB core while unplugging or resetting the device.
  • USBReset - Resets the USB controller. This API is used by the core during enumeration or whenever the reset is necessary.
  • USBEndpointDataPut - Puts data into the given endpoint's FIFO. This API is used by the individual device stack.
  • USBEndpointDataSend - Starts the transfer of data from an endpoint's FIFO. This API is used by the individual device stack in order to send the data.
  • USBEndpointDataGet - Retrieves data from the given endpoint's FIFO. This API is used by the individual device stack.

Device Core Layer[edit]

The Device Core Layer is responsible for device enumeration and handling all of the control transfers. The interrupt service routine (ISR) is a part of the core, so interrupt handling is also done by the core. The typical tasks handled by the device core layer are as follows:

  • Initialize the device controller driver
  • Enable clocking to the USB controller
  • Switch on the USB PHY
  • USB enumeration handling
  • Interrupt handling
  • Standard request handling
  • Terminate the device controller driver

The standard requests that are handled by the device core are as follows:

  • USBDGetStatus
  • USBDClearFeature
  • USBDSetFeature
  • USBDSetAddress
  • USBDGetDescriptor
  • USBDSetDescriptor
  • USBDGetConfiguration
  • USBDSetConfiguration
  • USBDGetInterface
  • USBDSetInterface
  • USBDSyncFrame

In USBDeviceIntHandlerInternal, the device core layer handles the following interrupts, invoking their corresponding callbacks:

  • Reset
  • Suspend
  • Resume
  • Disconnect
  • Start of Frame (SOF)
  • Endpoint Interrupt

The initialization API is called by the class driver in order to start enumeration. Once enumeration is started, all of the standard request routines are called from the ISR in response to the appropriate interrupt event. For any class-specific request, the application or class driver must register the callback handler with the core so that the ISR can branch there when necessary.

The device core layer is implemented by a single source file, usbdenum.c. The major APIs provided by this layer are summarized below:

  • USBDCDInit - Initializes the USB library device control driver for a given hardware controller. This API is used by the individual class stack.
  • USBDCDTerm - Frees the USB library device control driver for a given hardware controller.
  • USBDCDSendDataEP0 - Requests transfer of data to the host on endpoint zero.
  • USBDCDStallEP0 - Generates a stall condition on endpoint zero.
  • USBDeviceEnumHandler - Interrupt handler for endpoint zero.
  • USBDeviceIntHandlerInternal - Internal USB device interrupt handler.

USB Configuration Layer[edit]

This layer contains all of the parameters required to configure the USB device. These parameters include VID, PID, Descriptors, event handlers, buffers, and more. These parameters are specified by the application writer. Once all the information is fed in to this layer, the configuration layer can give a device instance structure to the other layers within the USB stack. This device instance contains all of the information regarding the device, and the required information is extracted when necessary.

This layer is considered to be part of application, and most of the data is specified by the application programmer. This layer is implemented by the source file usb_serial_structs.c. The following parameters are configurable by the application programmer:

  • Global instance for the USB device structure
  • Rx and Tx Buffers
  • Vendor ID
  • Product ID
  • Power configuration parameters
  • Control event call backs
  • Application event call backs
  • String descriptors
  • Language descriptor

System Configuration Layer[edit]

This layer provides APIs which can be used to configure platform-related parameters such as the clock speed, timers, pinmux, and more. These parameters are specified by the application developers as well as the underlying peripheral driver (i.e. DAL). Sometimes the entire system behavior depends on these parameters (ex. clock speed), so it is very important to select appropriate values for these parameters.

CDC Device Class[edit]

Sitaraware USB.JPG

The USB Communication Device Class (CDC) class driver supports the CDC Abstract Control Model variant and allows a client application to be seen as a virtual serial port to the USB host system. The driver provides two channels: one transmit and one receive. The channels may be used in conjunction with USB buffers to provide a simple read/write interface for data transfer to and from the host. Additional APIs and events are used to support serial link-specific operations such as notification of UART errors, sending break conditions, and setting communication line parameters. The data transmission capabilities of this device class driver are very similar to the generic bulk class, but (because this is a standard device class) the host operating system should be able to access the device without the need for any host-side drivers. On Windows, a simple INF file is all that is required to make the USB device appear as a COM port that can be accessed by any serial terminal application. This device class uses three endpoints in addition to endpoint zero. Two bulk endpoints carry data to and from the host and an interrupt IN endpoint is used to signal any serial errors such as break, framing error, or parity error detected by the device. Endpoint zero carries standard USB requests and also CDC-specific requests which translate to events passed to the application via the control channel callback . This layer is implemented in the source file usbdcdc.c.


Example Application[edit]

Running the Application[edit]

  • Since this is a USB device mode application, the target (EVM) must be connected to host (Windows PC) by a USB cable.
  • Connect your host PC's serial port to the UART connector on the EVM using a null modem cable.
  • The CDC device requires an INF file at the host side in order to enable as virtual COM port. Please use the INF provided in the tools/usb_inf folder.
    • The INF file is required only with a windows based host.
    • To use different VID and PID, the INF file must be updated with the new VID and PID.
  • Once the device is connected to the host, the host will ask for INF file. The user must browse to the INF file to proceed.

Cdc11.JPG

  • Once the proper INF file is pointed out by the user, then virtual COM port will appear in the device manager

Cdc12.JPG

  • Open a serial terminal application (ex. Teraterm, Hyperterminal) and choose the virtual COM port.

Cdc13.JPG

  • Set the parameters as shown.

Cdc14.JPG

  • Open another terminal window and choose COM1 (or whichever serial port you previously connected to the EVM's UART connector).
  • Type in either terminal window on the host PC. The text should appear on the other terminal screen.

Note: The CDC class is configured and tested for Hi-Speed PIO mode only

Modules used by this application:

  • USB
  • Interrupt

CDC Device Enumeration[edit]

The Application main must perform the following steps:

  • Configure the system interrupts
  • Register the interrupt handler (i.e. ISR)
  • Initialize the buffers
  • Call USBDCDCInit() with the device instance structure as a parameter

With this call, control is given to the CDC device class layer. The device class layer must perform the following steps:

  • Assign endpoints to the device instance structure
  • Apply the configuration descriptor to the device instance structure
  • Call USBDCDInit() and pass the device instance structure to the core

With this call, control is passed to the core layer. The core layer must perform the following steps in order to complete enumeration:

  • Enable the PSC clock
  • Reset the USB module
  • Switch on the USB PHY
  • Initialize the USB tick module
  • Clear all pending interrupts
  • Enable the required interrupts
  • Set the configuration parameters
  • Disconnect the device
  • Reconnect the device

Now the device will start receiving interrupts from the host. The interrupt handler in the core layer will identify all of the Ep0 interrupts and call the appropriate handler. If all the standard requests are serviced by the device, then enumeration is complete and the device is ready for communication. Now control return to the application and wait for data interrupts.

Control1.JPG

CONNECT / DISCONNECT[edit]

If required, the MUSB can allow software to control its connection to the USB bus. When the Soft Connect/Disconnect option is selected with the MUSB operating in peripheral mode, the UTMI+-compliant PHY (used alongside the MUSB) can be switched between normal mode and non-driving mode by setting or clearing bit 6 of the Power register. (This bit is identified as the Soft Conn bit.) When this Soft Conn bit is set to 1, the PHY is placed in its normal mode and the D+/D- lines of the USB bus are enabled. At the same time, the MUSB is placed in "Powered" state, where it will not respond to any USB signaling except a USB reset. When this feature is enabled and the Soft Conn bit is zero, the PHY is put into non-driving mode, D+ and D- are tri-stated, and the MUSB appears to other devices on the USB bus as if it has been disconnected.

After a hardware reset (NRST = 0), Soft Conn is cleared to 0. The MUSB will therefore appear disconnected until the software sets Soft Conn to 1. The application software can then choose when to set the PHY into its normal mode. Systems with a lengthy initialization procedure may use this to ensure that initialization is complete and the system is ready to perform enumeration before connecting to the USB. Once the Soft Conn bit has been set to 1, the software can also simulate a disconnect by clearing this bit to 0.

USB Tick module[edit]

The USB tick module contains the functions related to USB stack tick timer handling. It has functions to initialize the variables used in processing timer ticks, function handles registering OTG, Host, or Device SOF timer handler functions. This module is implemented in the source file usbtick.c.

CDC Application Data Flow[edit]

Cdc data flow.JPG

Data out Flow (From Host to Device)[edit]

When data arrives from the host, the device will receive an interrupt from the host. The interrupt handler must perform the following steps on reception:

  • Read the interrupt status register
  • Identify the interrupt
  • Call the appropriate handler (i.e. Read Data handler)
  • Read handler checks whether the RX Packet Ready bit is set
  • Check the number of byte available in the buffer
  • Read the data to buffer
  • Clear the RX Packet Ready bit
  • Give the read data to the application

RX mode1.jpg

Count Register[edit]

RxCount is a 13-bit read-only register that holds the number of received data bytes in the packet currently in line to be read from the Rx FIFO. If the packet was transmitted as multiple bulk packets, the number given will be for the combined packet. The value returned changes as the FIFO is unloaded and is only valid while RxPktRdy is set.

Data in Flow (From Device to Host)[edit]

When the device side application needs to send data to the host, the device must follow the below steps.

  • Application calls the write data API and passes the data buffer to the CDC layer
  • Write data API checks the amount of data to be sent
  • Copy data the TX buffer
  • Set the TX Packet Ready bit
  • After the transmit operation completes, the host sends a TX completion interrupt
  • TX Packet Ready bit will be cleared automatically
  • After receiving the TX Complete Interrupt, the ISR sends an event to the application indicating the completion of data transfer

TX mode.JPG

How To Write a New CDC Device Application[edit]

A new application must take the following steps to add CDC transmit and receive capability.

  • Define the 6-entry string descriptor table, which is used to describe various features of your new device (i.e. application) to the host system.
  • Define a tCDCSerInstance structure, which the USB CDC serial device class driver uses to store its internal state information. This should never be accessed directly by the application.
    tCDCSerInstance g_sSerialInstance;
  • Define a tUSBDCDCDevice structure and initialize all fields as required by your application.
  • Add a receive event handler function to your application. This function must handle all messages that require a particular response. For the CDC device class, USB_EVENT_RX_AVAILABLE and USB_EVENT_DATA_REMAINING must be handled by the receive event handler.
  • Add a transmit event handler function to your application. This function must handle all messages that require a particular response. For the CDC device class, there are no events sent to the transmit callback that must be handled, but applications typically handle SB_EVENT_TX_COMPLETE since this is an interlock message indicating that the previous packet sent has been acknowledged by the host and a new packet can now be sent.
  • Add a control event handler function to your application and ensure that it handles USBD_CDC_EVENT_GET_LINE_CODING, returning a valid line coding configuration even if the device is not actually driving a UART. Handle any other control events as required by your application.
  • From your main initialization function call the CDC device class driver initialization function to configure the USB controller and place the device on the bus.
    pDevice = USBDCDCInit(0, &g_sCDCDevice);
  • Assuming pDevice returned is not NULL, the device is now ready to communicate with a USB host.
  • Once the host connects, your control event handler will be receive a USB_EVENT_CONNECTED event, and the first packet of data may be sent to the host as soon as USB_EVENT_TX_COMPLETE is received via the transmit event handler.

For connector information please check the connector information table

Power Configuration[edit]

The power configuration for the CDC class device is held in two of the tUSBDCDCDevice members variables, usMaxPowermA and ucPwrAttributes. The usMaxPowermA variable holds the maximum power consumption for the device and is expressed in milliamps. The power configuration is held in the ucPwrAttributes member variable and indicates whether the device is self- or bus-powered. Valid values are USB_CONF_ATTR_SELF_PWR or USB_CONF_ATTR_BUS_PWR.

Bulk Device Class[edit]

Bulk.JPG

The generic bulk device class driver offers a very simple method for an application to set up USB communication with a paired application running on the USB host system. The class driver offers a single bulk receive channel and a single bulk transmit channel and, when coupled with USB buffers on each channel, provides a straightforward read/write interface to the application. The device supports a single interface containing bulk IN and bulk OUT endpoints. The configuration and interface descriptors published by the device contain vendor-specific class identifiers, so an application on the host will have to communicate with the device using either a custom driver or a subsystem such as WinUSB or libusb-win32 on Windows to allow the device to be accessed. An example of this is provided in the usb_dev_bulk application. This class driver is particularly useful for applications that need to pass high volumes of data via USB and where host-side application code is being developed in partnership with the device.

Bulk Device Enumeration[edit]

An application using the USB bulk device class must perform the following initialization steps:

  • Configure the system interrupts
  • Register the interrupt handler (i.e. ISR)
  • Initialize the buffers
  • Call the USBDBulkInit() API with the device instance structure as a parameter

This function call gives contol to the bulk device class layer. The device class layer then performs the following steps:

  • Assign the endpoints to the device instance structure
  • Assign the configuration descriptor to the device instance structure.
  • Call the USBDCDInit() API and pass the device instance structure to the core

This function call gives contol to the core layer. The core layer then performs the following steps in order to complete the bulk device enumeration:

  • Enable the PSC clock
  • Reset the USB module
  • Switch on the USB PHY
  • Initialize the USB tick module
  • Clear all pending interrupts
  • Enable the required interrupts
  • Set the configuration parameters
  • Disconnect the device
  • Reconnect the device

Now the device will start receiving interrupts from the host. The interrupt handler in the core layer will identify all the Ep0 interrupts and call the appropriate handler. Once all the standard requests are serviced by the device, enumeration is complete and the device is ready for communication. Now control will return to the application to wait for data interrupts.

Bulk enum.JPG

How to Write a New Bulk Application[edit]

To add USB bulk data transmit and receive capability to an application, take the following steps:

  • Add the following header files to the source file(s) that will support USB:
    #include "usb.h"
    #include "usblib.h"
    #include "usbdevice.h"
    #include "usbdbulk.h"
  • Define the 5-entry string table that is used to describe various features of your new device to the host system.
  • Define an area of RAM of for the private data for the bulk device class driver. This structure should never be accessed by the application.
  • Define a tUSBDBulkDevice structure and initialize all fields as required for your application. The following example illustrates a simple case where no USB buffers are in use. For an example using USB buffers, see the source file usb_bulk_structs.c in the usb_dev_bulk example application.
  • Add a receive event handler function (ex. YourUSBReceiveEventCallback() in the previous example) to your application, taking care to handle all messages that require a particular response. For the generic bulk device class, only the USB_EVENT_RX_AVAILABLE must be handled by the receive event handler. In response to SB_EVENT_RX_AVAILABLE, your handler should check the amount of data received by calling the USBDBulkRxPacketAvailable() API then read it by calling USBDBulkPacketRead(). This causes the newly received data to be acknowledged to the host and instructs the host that it may now transmit another packet. If you are unable to read the data immediately, return 0 from the callback handler and it will be called again a few milliseconds later. Although no other events must be handled, USB_EVENT_CONNECTED and USB_EVENT_DISCONNECTED are typically required since these indicate when a host connects or disconnects and allow the application to flush any buffers or reset state as required. Attempts to send data when the host is disconnected will fail.
  • Add a transmit event handler function (ex. YourUSBTransmitEventCallback() in the previous example) to your application, taking care to handle all messages that require a particular response. For the generic bulk device class, there are no events sent to the transmit callback that must be handled, but applications typically want to note USB_EVENT_TX_COMPLETE since this is an interlock message indicating that the previous packet sent has been acknowledged by the host and a new packet can now be sent
  • From your main initialization function call the generic bulk device class driver initialization function to configure the USB controller and place the device on the bus.
    pDevice = USBDBulkInit(0, &g_sBulkDevice);
  • Assuming pDevice returned is not NULL, your device is now ready to communicate with a USB host. Once the host connects, your receive event handler receives USB_EVENT_CONNECTED, and the first packet of data may be sent to the host using the USBDBulkPacketWrite() API as soon as USB_EVENT_TX_COMPLETE is received.

Windows Drivers for Generic Bulk Devices[edit]

Since generic bulk devices appear to a host operating system as vendor-specific devices, no device drivers on the host system will be able to communicate with them without device-specific drivers. This require writing a Windows kernel driver for the device or, if that task is too daunting, steering Windows to use one of several generic kernel drivers that can manage the device with assistance from a Windows application. The second option does not require the developer to write any Windows driver code, but the developer instead needs to to write an application or DLL that interfaces with the device via user-mode APIs offered by generic USB drivers.

The developer is also responsible for producing a suitable INF file to allow Windows to associate the device (identified via its VID/PID combination) with a particular driver. A least two suitable USB subsystems are available for Windows:

  1. WinUSB - from Microsoft
  2. libusb-win32 - an opensource project available from SourceForge

WinUSB supports only WindowsXP and Vista systems. Further information can be obtained from the MSDN website.

To develop applications using WinUSB, the Windows Driver Development Kit (DDK) must be installed on your host PC. These applications can be found in the package PDL-LM3S-win, which is available for downloaded from the Stellaris website.

libusb-win32 supports all versions of Windows from Windows98SE onward and can be downloaded from the SourceForge website.

Running the Example Application[edit]

  • Download and install Windows host driver and application (SW-USB-WIN and SW-USB-WINDRIVERS) from the StellarisWare download page.
    • The INF file is located at windows_drivers/usb_dev_bulk.inf.
    • The host application is located at usb_examples/usb_bulk_example.exe.
    • The host application should only be run after the target application is already running (see below).
  • Build and download the usb_dev_bulk application to the target board .
  • Connect the target board to PC via a USB cable.
  • When Windows detects your target device, browse to the INF file downloaded above.
  • Open the host application on the host PC. (Note: the host application will fail if you run it before the target application is running and connected to the PC.)
  • Type any text in the host application window to send it to the target device.
  • Follow the instructions from the host application to stop execution.

Note: The bulk class is configured and tested for Full-Speed PIO mode only

For connector information please check the connector information table

Modules used by this application:

  • USB
  • Interrupt
  • Timer (for 100 ms delay during USB enumeration; graphics too?)
  • UART (non-interrupt; for debug output)
  • LCDC (raster mode; display # bytes transferred )

HID Device Class[edit]

Please note that in the current EVM only uses touchscreen hardware as the pointer device. The below text uses HIDMouse as a generic term to refer to this.

The USB Human Interface Class device class supports a wide variety of input/output devices, not all of which actually pertain to "Human Interfaces." While the most commonly supported devices are keyboards, mice, and joysticks, the specification can cover practically any device offering user controls or data gathering functionality. Communication between the HID device and host is conducted according to a collection of "report" structures. The device populates HID report descriptors, which the host can query. Reports are defined both for communication of device input to the host and for output or feature selection from the host.

In addition to the flexibility offered by the basic architecture, HID devices also benefit from excellent operating system support for the class. This means that device-specific drivers are generally not necessary. For standard devices such as keyboards and joysticks, the device can connect to and operate with the host system without any new host software having to be written. Even in the case of a nonstandard or vendor-specific HID device, the operating system support makes writing the host-side software very straightforward compared to developing the device using a vendor-specific class.

Despite these advantages, there is one downside to using HID. The interface is limited in the amount of data that can be transferred, so HID is not suitable for devices that need to use a significant percentage of the USB bus bandwidth. Devices are limited to a maximum of 64KB per second for each report descriptor they support. Multiple reports can be used if necessary, but high bandwidth devices are better implemented using a class that supports bulk rather than interrupt endpoints, such as CDC or the generic bulk device class.

The HID device class uses one or two endpoints in addition to endpoint zero. One interrupt IN endpoint carries HID input reports from the device to the host. Output and Feature reports from the host to the device are typically carried via endpoint zero but devices with high host-to-device data rates can select to offer an independent interrupt OUT endpoint to carry these. Endpoint zero carries standard USB requests and also HID-specific descriptor requests. This layer is implemented in the source files Usbdhid.c and Usbdhidmouse.c.

Hid Mouse.JPG

HID Device Enumeration[edit]

The Application must perform the following steps to enumerate the USB in HID device mode:

  • Configure the system interrupts
  • Register the Interrupt handlers
  • Initialize the buffers
  • Call the USBDHIDMouseInit() API with the device instance structure as a parameter

With this call, control passes to the HID mouse layer, which performs the following additional steps:

  • Initialize the various fields in the instance structure
  • Initialize the HID device class instance structure based on input from the caller
  • Initialize the lower layer HID driver by calling the USBDHIDInit() API

With this call, control passes to the HID device class layer, which performs the following additional steps:

  • Assign the endpoints to the device instance structure
  • Assign the configuration descriptor to the device instance structure
  • Call the USBDCDInit() API and pass the device instance structure to the core

With this call, control passes to the core layer, which performs the following additional steps to complete enumeration:

  • Enable the PSC clock
  • Reset the USB module
  • Switch on the USB PHY
  • Initialize the USB tick module
  • Clear all the pending interrupts
  • Enable the required interrupts
  • Set the configuration parameters
  • Disconnect the device
  • Reconnect the device

Now the device starts receiving interrupts from the host. The interrupt handler in the core layer identifies all the Ep0 interrupts and calls the appropriate handler. If all the standard requests are serviced by the device, then enumeration is complete and the device is ready for communication. Now the control returns to the application, where it waits for touch screen inputs.

HID Mouse Flow.JPG

Example Application[edit]

Mouse app flow.JPG

The above figure shows how the HID device (mouse) application works. The application continuously polls for a touch screen event. Once an event is detected, the application reads the x and y values. The touch handler checks whether this is a button press or not (i.e. if the x and y coordinates belongs to the button area). If this is not a button press event, then read the x and y values are re-read multiple times. This helps to avoid the "bouncing" effects and confirm the touch event. Afterward, the current and previous x and y values are used to calculate how much we moved from the previous x/y location. The new location values are sent to the host through HID report.

Running the Application[edit]

  • Connect the target board to the host PC via a USB cable
  • Load and run the target application
  • Once the device is connected to the host, it enumerates as HID mouse
  • User can check the device manager of the host to confirm the completion of the enumeration
  • Touch screen is initialized and buttons are displayed
  • User can use the touch screen to move the cursor on the host PC and press the mouse button to trigger mouse clicks

For connector information please check the connector information table

Modules used by this application:

  • USB HID
  • LCD raster
  • Graphics library
  • Touch screen (I2C)
  • Interrupt

In Data Flow (Device to Host)[edit]

HID Report flow.JPG

How to write a new HID Application[edit]

To add USB HID mouse support to an application using the USB stack, use the following procedure:

  • Add the following header files to the source file(s) that will support USB:
    #include "src/usb.h"
    #include "usblib/usblib.h"
    #include "usblib/device/usbdhidmouse.h"
  • Define the string table that is used to describe various features of your new device to the host system. This table must include a minimum of 6 entries: string descriptor 0 defines the language(s) available, and 5 strings for each supported language.
  • Define an area of RAM for the HID mouse class driver private data. This structure should never be accessed by the application.
    static tHIDMouseInstance g_sMouseInstance;
  • Define a tUSBDHIDMouseDevice structure and initialize all fields as required by your application.
  • Add a mouse event handler function to your application. A minimal implementation can ignore all events, but USB_EVENT_TX_COMPLETE is typically used to ensure that mouse messages are not sent when a previous report is still in transit to the host. Attempts to send a new mouse report when the previous report has not yet been acknowledged will result in return code MOUSE_ERR_TX_ERROR from USBDHIDMouseStateChange().
  • From your main initialization function call the HID mouse device initialization API to configure the USB controller and place the device on the bus.
    pDevice = USBDHIDMouseInit(0, &g_sMouseDevice);
  • Assuming pDevice is not returned as NULL, your mouse device is now ready to communicate with a USB host
  • Once the host connects, your mouse event handler receives an USB_EVENT_CONNECTED event. Afterward, calls can be made to USBDHIDMouseStateChange() to inform the host of mouse position and button state changes.

Mass Storage Device Class[edit]

The USB mass storage device class allows an application to act as a physical storage device for use by another USB application or host PC. Because the type of storage can vary per application, the mass storage class abstracts the storage with a set of block-based APIs that are provided by the application to the USB library. These APIs allow the USB mass storage class to call an external set of functions that actually perform the operations on the physical storage media. The storage APIs are given to the USB library’s mass storage device class initialization function and are called by the USB library whenever it needs to access the physical media.

Msc.JPG

Initialization and Data Flow[edit]

The USB library’s mass storage class provides a simple interface to initialize the mass storage class and pass it the needed functions to access a device without having any knowledge of the physical media. The USBDMSCInit() API is the only initialization required by the mass storage class, and it uses the structure tUSBDMSCDevice to hold all customizable values for the mass storage class.

The USB library’s mass storage class provides the ability to customize how the device is reported to the USB host controller in the tUSBDMSCDevice structure. The members of this structure contain all of the customizable parameters.

The below diagram shows how data and commands flow to and from the MSC device. The diagram does not show using DMA to automate any data transfers.

Msc flow.JPG

Block Media Access[edit]

The media access functions are passed in to the USB mass storage device class in the sMedia->Functions member variable. This structure holds the access functions used by this instance of the mass storage class device. All of the functions in this structure are required to be populated with valid functions. These functions are called by the USB mass storage device class whenever it needs to read or write the physical media, and they always use a fixed block size of 512 bytes.

In some cases, the application may need to be informed when the state of the mass storage device has changed. The pfnEventCallback member of the MSCDevice structure provides event notification to applications for the following events:

  • USBD_MSC_EVENT_IDLE
  • USBD_MSC_EVENT_READING
  • USBD_MSC_WRITING

When a function of type tUSBCallback is called, only the first two parameters (pvCBData and ulEvent) are valid. The pvCBData parameter is the value that was returned when the application called USBDMSCInit() and can be used with other APIs. These events are not used in the example application provided with StarterWare. Application writers can make use of these events as required.

RAM Disk Support[edit]

The MSC is provided with a RAM disk implementation as its block media. The current size supported by the RAM disk is 16 MB. Developers can change it by modifying the RAMDISK_SIZE macro in the ramdisk.c source file, depending on their board's RAM capacity.

DMA Support[edit]

The CPPI 4.1 DMA engine is interfaced with MUSB controller, and MSC device class supports DMA mode for data transfers by default. Currently, only transparent DMA mode is supported for RX and TX transactions.Please note: to switch to PIO mode, the DMA_MODE macro must be removed from the compiler options.

Example Application[edit]

  • Application calls USBDMSCInit() with the device instance structure as a parameter
  • Application also initializes the DMA, MUSB interrupts, MMU, etc.
  • The MSC initialization API provided by the MSC stack populates the device info structure with Endpoint numbers, descriptors, device state, etc.
  • MSC init calls DCDInit() with the device instance structure as parameter. The core layer then performs the following steps in order to complete the enumeration:
    1. Enable the PSC clock
    2. Reset the USB module
    3. Switch on the USB PHY
    4. Initialize the USB tick module
    5. Clear all the pending interrupts
    6. Enable the required interrupts
    7. Set the configuration parameters
    8. Disconnect the device
    9. Reconnect the device
  • Once enumeration is complete, the device will appear on the host PC as a mass storage device
  • When the user attempts to access the MSC device on the host PC, the host formats the RAM disk
  • Once the format operation is complete, the device is ready for data transaction
  • If any command comes from host, the device is notified through an interrupt
  • The interrupt handler in the device core (HandleEndpoint()) reads the CBW and retrieves the command op code
  • This op-code is passed to the command handler, and command handler calls the appropriate command
  • The data transaction happens through DMA by default
  • At the end of the transaction, The device will send a command status word (CSW) to indicate the end of the command

Running the Application[edit]

  • Connect the target board to the host PC via a USB cable
  • Load and run the target application
  • Once the device is connected to the host PC, the device will enumerate as an MSC device
  • The user can check the disk drives to see the mass storage device
  • When the user attempts to access the MSC device on the host PC, the host formats the RAM disk
  • Once the format operation is complete, the device is ready for data transaction
  • Currently the device supports 16MB of RAM disk

For connector information please check the connector informationtable

Note: The MSC device class is configured and tested for Hi-Speed DMA mode only

Modules used in this example

  • Interrupt module
  • USB driver
  • USB stack (including Cppi 4.1 DMA)
  • LCD raster
  • Graphics library

How to Integrate Alternate Block Media[edit]

The current package is provided with 16 MB of RAM Disk. If the user wants to use another block media, the following steps are required.

  • Rename the source files usbdmscglue.c and usbdmscglue.h as appropriate
  • The alternate block media must support the following APIs:
    1. Disk_read()
    2. Disk_write()
    3. Disk_ioctl()
  • These APIs should be replaced in the new "glue" source file:
    1. Disk_read() should be replaced in the USBDMSCStorageRead() API
    2. Disk_write() should be replaced in the USBDMSCStorageWrite() API
    3. Disk_ioctl() should be replace in the USBDMSCStorageNumBlocks() API with appropriate parameters to return the total number of blocks.

The default block size is 512 bytes. If the alternate block media has a different block size, then this must be updated in the USB stack. This can be achieved by updating macros DEVICE_BLOCK_SIZE and MAX_TRANSFER_SIZE with the new block size.

Composite Device Class[edit]

The USB composite device class allows classes that are already defined in the USB library to be combined into a single composite device. The device configuration descriptors for the included device classes are merged at run time and returned to the USB host controller during device enumeration as a single composite USB device. Since each device class requires some unique initialization, the device classes provide a separate initialization API that does not touch the USB controller but does perform all other initialization. The initialization of the USB controller is deferred until the USB composite device is initialized and has merged the multiple device configuration descriptors into a single configuration descriptor so that it can properly initialize the USB controller. The endpoint numbers, interface numbers, and string indexes that are included in the device configuration descriptors are modified by the USB composite device class so that the values are valid in the composite device configuration descriptor.

Composite CDC Serial and HID-Mouse device Example Application[edit]

Composite HID CDC.JPG

Device Enumeration[edit]

The Application must perform the following steps to enumerate the USB in Composite device mode:

  • Configure the system interrupts
  • Register the Interrupt handlers
  • Initialize the buffers
  • Call the USBDHIDMouseCompositeInit() API with the mouse device instance structure as a parameter.With this call, control passes to the HID mouse layer, which performs the following additional steps
    • Initialize the various fields in the instance structure
    • Initialize the HID device class instance structure based on input from the caller
    • Initialize the lower layer HID driver by calling the USBDHIDCompositeInit() API.With this call, control passes to the HID device class layer, which performs the following additional steps
      • Assign the endpoints to the device instance structure.
      • Assign the device, configuration descriptor to the device instance structure.
  • Call the USBDCDCCompositeInit API with the CDC device instance structure as a parameter.With this call, control is given to the CDC device class layer. The device class layer must perform the following steps
    • Assign endpoints to the device instance structure
    • Apply the configuration descriptor to the device instance structure
  • Call the USBDCompositeInit API to initialize the USB composite device class, with the composite device instance structure as a parameter.with this call, contol is given to the composite device class layer. The device class layer must perform the following steps
    • Initialize the various fields in the instance structure
    • Assign the device, configuration descriptor to the device instance structure
    • Call the BuildCompositeDescriptor() API to merge the configuration descriptors into a single multiple instance device.
    • Call the USBDCDInit() API and pass the device instance structure to the core

With this call, control passes to the core layer, which performs the following additional steps to complete enumeration:

  • Enable the PSC clock
  • Reset the USB module
  • Switch on the USB PHY
  • Initialize the USB tick module
  • Clear all the pending interrupts
  • Enable the required interrupts
  • Set the configuration parameters
  • Disconnect the device
  • Reconnect the device
  • Now the device starts receiving interrupts from the host. The interrupt handler in the core layer identifies all the Ep0 interrupts and calls the appropriate handler. If all the standard requests are serviced by the device, then enumeration is complete and the device is ready for communication. Now the control returns to the application, where it waits for touch screen inputs and data interrupts.

Running the Application[edit]

  • Since this is a USB device mode application, the target (EVM) must be connected to host (Windows PC) by a USB cable.
  • Load and run the target application
  • Connect your host PC's serial port to the UART connector on the EVM using a null modem cable.
  • The CDC device requires an INF file at the host side in order to enable as virtual COM port. Please use the INF provided in the tools/usb_inf folder.
    • The INF file is required only with a windows based host.
    • To use different VID and PID, the INF file must be updated with the new VID, PID and Interface ID.
  • Once the device is connected to the host,it enumerates one device as HID mouse and for other CDC device host will ask for INF file. The user must browse to the INF file to proceed.

Cdc11.JPG

  • Once the proper INF file is pointed out by the user, then virtual COM port will appear in the device manager

Cdc12.JPG

  • Open a serial terminal application (ex. Teraterm, Hyperterminal) and choose the virtual COM port.

Cdc13.JPG

  • Set the parameters as shown.

Cdc14.JPG

  • Open another terminal window and choose COM1 (or whichever serial port you previously connected to the EVM's UART connector).
  • Type in either terminal window on the host PC. The text should appear on the other terminal screen.
  • For HID device, Touch screen is initialized and buttons are displayed
  • User can use the touch screen to move the cursor on the host PC and press the mouse button to trigger mouse clicks.
  • Both devices ( HID mouse and CDC Serial ) can be accessed at the same time.

Composite Dual CDC Serial Port device Example Application[edit]

Composite CDC CDC.JPG

Device Enumeration[edit]

The Application must perform the following steps to enumerate the USB in Composite device mode:

  • Configure the system interrupts
  • Register the Interrupt handlers
  • Initialize the buffers
  • Call the USBDCDCCompositeInit API twice with the CDC device instance structure as a parameter.With this call, control is given to the CDC device class layer. The device class layer must perform the following steps
    • Assign endpoints to the device instance structure
    • Apply the configuration descriptor to the device instance structure
  • Call the USBDCompositeInit API to initialize the USB composite device class, with the composite device instance structure as a parameter.with this call, contol is given to the composite device class layer. The device class layer must perform the following steps
    • Initialize the various fields in the instance structure
    • Assign the device, configuration descriptor to the device instance structure
    • Call the BuildCompositeDescriptor() API to merge the configuration descriptors into a single multiple instance device.
    • Call the USBDCDInit() API and pass the device instance structure to the core

With this call, control passes to the core layer, which performs the following additional steps to complete enumeration:

  • Enable the PSC clock
  • Reset the USB module
  • Switch on the USB PHY
  • Initialize the USB tick module
  • Clear all the pending interrupts
  • Enable the required interrupts
  • Set the configuration parameters
  • Disconnect the device
  • Reconnect the device
  • Now the device starts receiving interrupts from the host. The interrupt handler in the core layer identifies all the Ep0 interrupts and calls the appropriate handler. If all the standard requests are serviced by the device, then enumeration is complete and the device is ready for communication. Now the control returns to the application, where it waits for data interrupts.

Running the Application[edit]

  • Since this is a USB device mode application, the target (EVM) must be connected to host (Windows PC) by a USB cable.
  • Load and run the target application
  • The CDC device requires an INF file at the host side in order to enable as virtual COM port. Please use the INF provided in the tools/usb_inf folder.
    • The INF file is required only with a windows based host.
    • To use different VID and PID, the INF file must be updated with the new VID, PID and Interface IDs.
  • Once the device is connected to the host,it enumerates as composite device, host will ask for INF file to enumerate one CDC device. The user must browse to the INF file to proceed.

Cdc11.JPG

  • Once the proper INF file is pointed out by the user, then virtual COM port will appear in the device manager

DevMgr1.JPG

  • Once one device is enumerated, host will ask for INF file to enumerate other CDC device. The user must browse to the INF file to proceed.

Cdc11.JPG

  • Once the proper INF file is pointed out by the user, then two virtual COM ports will appear in the device manager

DevMgr12.JPG

  • Open a serial terminal application (ex. Teraterm, Hyperterminal) and choose the virtual COM port.

HyperTrm1.JPG

  • Set the parameters as shown.

HyperTrm2.JPG

  • Do the above two steps for other virtual COM port.
  • Type in either terminal window on the host PC. The text should appear on the other terminal screen.

USB Host Class[edit]

The USB library host controller driver provides an interface to the host controller’s hardware register interface. This is the lowest level of the driver interface, and it interacts directly with the driver library's USB APIs. The host controller driver provides all of the functionality necessary to perform enumeration of devices regardless of any type. This portion of the stack code only enumerates the device; higher level drivers handle further device operations. To allow the application to conserve code and data memory, the host controller driver only includes the host class drivers for USB device types used in the application. This allows an application to handle multiple classes of devices but only include the USB library code that the application needs for those devices that the application actually supports. While the host controller driver handles the enumeration of devices, it relies on USB pipes (allocated by the higher level class drivers) as the direct communications method with device end points.

Host Class Enumeration[edit]

The USB host controller driver handles all of the details necessary to discover and enumerate any USB device. The USB host controller driver only performs enumeration and relies on the host class drivers to perform any other communications with USB devices including the allocation of the endpoints for the device. Most of the code used to enumerate devices is run in interrupt context and is contained in the enumeration handler. In order to complete the enumeration process, the host controller driver also requires that the application periodically call the USBHCDMain() function. When a host class driver or an application needs access to endpoint 0 of a device, it uses the USBHCDControlTransfer() interface to send data to the device or receive data from the device. During the enumeration process the host controller driver searches a list of host class drivers provided by the application in the USBHCDRegisterDrivers() call. The details of this structure are covered in the host class drivers section of this document. If the host controller driver finds a host class driver that matches the class of the enumerated device, it will call the open function for that host class driver. If no host class driver is found the host controller driver will ignore the device and there will be no notification to the application. The host controller driver or the host class driver can provide callbacks up through the USB library to inform the application of enumeration events. The host class drivers are responsible for configuring the USB pipes based on the type of device that is discovered. The application will be notified that a new device has been discovered by a callback from the device interface that a device of that given type has been enumerated. When the device is removed the application will also get a callback that the device is no longer present. The events USB_EVENT_CONNECTED and USB_EVENT_DISCONNECTED are the only event notifications that will make it up to the application as a result of enumeration.

USB Pipes[edit]

The host controller driver layer uses interfaces called USB pipes as the primary method of communication with USB devices. These USB pipes are dynamically or statically allocated by the USB class drivers during enumeration. The USB pipes are usually only used within the USB library or by host class drivers and are usally not accessed directly by applications. The USB pipes are allocated and freed by calling USBHCDPipeAlloc() and USBHCDPipeFree() functions and are initially configured by calling USBHCDPipeConfig(). The USBHCDPipeAlloc() and USBHCDPipeConfig() APIs are used during USB device enumeration to allocate USB pipes for specific endpoints of the USB device. On disconnect, the USBHCDPipeFree() API is called to free up the USB pipe, which can then be used by a new USB device. While in use, the USB pipes can provide status and perform read and write operations. Calling USBHCDPipeStatus() allows a host class driver to check the status of a pipe. However, most access to the USB pipes occurs through the USBHCDPipeWrite() and USBHCDPipeRead() APIs and the callback function provided when the USB pipe was allocated. These are used to read or write to endpoints on USB devices on endpoints other than the control endpoint on endpoint 0. Since endpoint 0 is shared with all devices, the host controller interface does not use USB pipes for communications over endpoint 0 and instead uses the USBHCDControlTransfer() API.

Control Transactions[edit]

All USB control transactions are handled through the USBHCDControlTransfer() API. This function is primarily used inside the host controller driver itself during enumeration, but some devices may require using control transactions through endpoint 0. The HID class drivers are a good example of a USB class driver that uses control transactions to send data to a USB device. The USBHCDControlTransfer() API should not be called from within interrupt context because control transfers are blocking operations that rely on interrupts to proceed. Since most callbacks occur in interrupt context, any calls to USBHCDControlTransfer() should be deferred until running outside the callback event.

Interrupt Handling[edit]

All interrupt handling is done by the USB library host controller driver. Most callbacks are called in interrupt context and, like interrupt handlers, should defer any real processing of events until execution returns from the interrupt context. Callbacks are used to notify the upper layers when events occur during enumeration or during normal operation. Because most of enumeration code is handled by interrupt handlers, the enumeration code requires the application to call USBHCDMain() in order to progress through the enumeration states without running all code in an interrupt context.

HID Host Class[edit]

The host class drivers provide access to devices that use a common USB class interface. In order to use the class drivers, the application must call USBHCDRegisterDrivers() to provide a list of the host class drivers that the application will use. The g_USBHIDClassDriver structure defines the interface for the Host HID class driver, and the host class driver provides the following interfaces:

  • To the USB host controller driver (bottom layer)
  • Device specific interfaces (top layer)

The lower layer interface to the USB host controller interface is the same for all USB host class drivers, while the device interface layer on top is common to all USB host device drivers of a given class. Aside from enumeration, all communication with the host class driver happens through its endpoint pipes. The host class driver parses and allocates any endpoints that it needs by calling the USBHCDPipeAlloc() and USBHCDPipeConfig() functions. These USB pipes provide methods to read/write and receive callback notification from the USB host controller driver layer.

HID host.JPG

The HID class driver provides access to any type of HID class by leaving the details of the HID device to the layer above the HID class driver. The top layer of the HID class driver provides common functions to open or close an instance of a HID device, read a device’s report descriptor so that it can be parsed by the HID device code, and get/set reports on an HID device. The lower level interface that is connected to the host controller driver is specified in the g_USBHIDClassDriver structure. This structure is used to register the HID class driver with the host class driver so that it is called when an HID device is connected and enumerated. The functions in the g_USBHIDClassDriver structure should never be called directly by and application or a host class driver as they are reserved for access by the host controller driver. In the following example, the generic HID class driver is registered with the USB host controller driver and then a call is made to open an instance of a mouse class device. Typically, the call to USBHHIDOpen() is made from within a device class interface while the call to SBHCDRegisterDrivers() is made from the application directly. For instance, the USBHHIDOpen() API for the mouse device provided with the USB library is called from USBHMouseOpen(), which is part of the USB mouse interface.

Device Interface[edit]

At the top layer of the HID class driver, the driver has a device class interface for use with various HID devices. In order for the HID class driver to recognize a device, the device class must call USBHHIDOpen(). This call specifies the type of device and a callback for this device type so that any events related to this device type can be passed back to the device class driver. The defined classes are in the tHIDSubClassProtocol type and are passed into the USBHHIDOpen() call via the eDeviceType parameter. In order to release an instance of an HID class driver, the HID device class or application must call USBHHIDClose() to allow a new or different type of device to be connected. In the examples provided with the USB library, the report descriptors are retrieved but are not used as the examples rely on the "boot" mode of the USB keyboard and mouse to fix the format of the report descriptors. This is accomplished by using the USBHHIDSetReport() API to force the device into its boot protocol mode. As this could be limiting or not available in other types of applications or devices, the USBHHIDGetReportDescriptor() API provides the ability for generic HID devices to query the device for its report descriptor(s). The last two remaining HID APIs, USBHHIDSetReport() and USBHHIDGetReport(), provide access to the HID reports.

Once a HID device has been opened, the application receives a USB_EVENT_CONNECTED callback event. This indicates that a HID device of the type passed into the USBHHIDOpen() has been connected and the USB library host controller driver has completed enumeration of the device. When the HID device is removed, a SB_EVENT_DISCONNECTED event occurs. When shutting down or to release a device, the application must call USBHHIDClose() to disable callbacks. This does not actually power down the device, but it stops the driver from calling the application. During normal operation, the host class driver receives USB_EVENT_SCHEDULER and USB_EVENT_RX_AVAILABLE events. The USB_EVENT_SCHEDULER event indicates that the HID class driver should schedule a new request if it is ready to do so. This done by calling USBJHCDPipeSchedule() to request that a new IN request be made on the given Interrupt IN pipe. When the USB_EVENT_RX_AVAILABLE occurs, this indicates that new data is available due to completion of the previous request for data on the Interrupt IN pipe. The USB_EVENT_RX_AVAILABLE is passed on the device class interface to allow it to request the data by calling USBHHIDGetReport(). It is up to the device class driver to interpret the data in the report structure that is returned. In some cases, like the keyboard example, the device class may also need to call the host class driver to issue a set report to send data to the device. This is done by calling USBHHIDSetReport() in the host class driver. This will send data to the device by using the correct USB OUT pipe.

Example Application (Mouse)[edit]

The USB library host stack initialization is handled in the USBHCDInit() API. This function must be called after registering class drivers using USBHCDRegisterDrivers() and (optionally) configuring power pins using USBHCDPowerConfigInit(). Both of these APIs are described later.

The USBHCDInit() API takes three parameters, the first of which specifies which USB controller to initialize. This is a zero-based index value. The next two parameters specify a memory pool for use by the host controller driver. The size of this buffer must be large enough to hold a typical configuration descriptor for devices that are going to be supported. This value is system-dependent, so it is left to the application to set the size. It should never be less than 32 bytes; in most cases it should be at least 64 bytes. If there is not enough memory to load a configuration descriptor from a device, the device will not be recognized by USB library’s host controller driver. The USB library also provides a method to shut down an instance of the host controller driver by calling the USBHCDTerm() function. The USBHCDTerm() function should be called any time the application wants to shut down the USB host controller in order to disable it, or possibly switch modes in the case of a dual role controller. The USB library assumes that the power pin configuration has an active high signal for controlling the external power. If this is not the case or if the application wants control over the power fault logic provided by the library, then the application should call USBHCDPowerConfigInit() before calling USBHCDInit() in order to properly configure the power control pins. The polarity of the power pin, the polarity of the the power fault pin, and any actions taken in response to a power fault are all controlled by passing a combination of values in the ulPwrConfig parameter. See the documentation for the USBHCDPowerConfigInit() API for more details on this function.

The USB library host stack requires that some portion of the code not run in the interrupt handler, so the SBHCDMain() function must be called periodically by the application during normal execution. This can be as a result of a timer tick or just once per main loop in a simple application. It should not be called by an interrupt handler. Calling the function too often is harmless as it will simply return if the USB host stack has no pending tasks. Calling USBHCDMain() too infrequently can cause enumeration to take longer than normal. It is up to the application to prioritize the importance of USB communications by calling USBHCDMain() at a rate that is reasonable to the application. All support devices will have a host class driver loaded in order to communicate with each type of device that is supported. The details of interacting with these host class drivers is explained in the host class driver sections that follow on this page.

When the application needs to shut down the host controller, it must shut down all host class drivers before shutting down the host controller itself. This gives the host class drivers a chance to close cleanly by calling each host class driver’s close function. Finally, the USBHCDTerm() function should be called to shut down the host controller. This sequence will leave the USB controller and the USB library stack in a state such that it is ready to be re-initialized or switched to USB device mode (i.e. from host).

Running the Application[edit]

  • Connect a USB mouse to the target board
    • Note: On the OMAP-L138/AM1808/C6748 EVM, use the J6 (mini) USB connector
  • Load and run the target application
  • The display at the bottom left of the screen will show “Connected” if the mouse is enumerated and connected to the host
  • Move the mouse and see its motion tracked by the cursor on the screen
  • Press the mouse buttons and observe the button indicator on the bottom right corner of the screen
  • Press and hold the left mouse button and drag the cursor to draw lines or curves on the screen
  • Unplug the mouse from the board and see the display at bottom left changes to “No device”

For connector information please check the connector information table

Modules used in this application:

  • USB HID host
  • LCD raster
  • Graphics lib rary
  • Timer
  • Interrupt

Writing a New HID Host Application[edit]

The following shows the basic setup code needed for any application that is using the USB library in host mode.

  • The g_pHCDPool array that is passed to the USBHCDInit() API is used as heap memory by the USB library. This memory should not be used by the application. In the HID host mouse example, the g_ppHostClassDrivers array holds HID driver that makes it possible to support various devices.
  • When calling USBHCDRegisterDrivers(), one argument specifies a static array of supported USB host class drivers that are be supported by the application.
  • The application must initialize the interrupt controller and register the ISR for the MUSB controller.
  • The application should always call the USB device interface open routines before calling USBHCDInit(). This enables the USB host controller and starts enumerating any connected device.
  • The initial call to USBHMouseOpen() prepares the mouse device application interface to receive notifications from any USB mouse device that is connected.
  • Since the mouse interface needs some basic configuration after being connected, the application should wait for the mouse to be connected and then call USBHMouseInit() to complete the mouse configuration.
  • Once the mouse has been configured, the application’s mouse callback routine will be notified any time there is a state change with the mouse. This includes the switching to the MOUSE_INIT state when a USB_EVENT_CONNECTED event occurs in order to trigger mouse device initialization.
  • The USB_EVENT_DISCONNECTED event switches the state of the application to let it know that the mouse is no longer connected. The remaining events are mouse state changes that can be used by the application to move a cursor or take action based on a mouse click.

Hidhostexample1.JPG

Mass Storage Host Class[edit]

The mass storage host class driver allows applications to access external devices that support the mass storage class protocol. The driver provides a simple block based interface to the devices that can be matched up with an application’s file system. A USB host class driver for MSC devices is included with the USB library. It provides direct access to mass storage devices based on logical block address.

MscHost.JPG

The mass storage host class driver provides APIs to access USB mass storage drives. These APIs are meant to match with file systems that need block based read/write access to the drives. The USBHMSCBlockRead() and USBHMSCBlockWrite() APIs provide block read and block write device access. These functions perform block operations at the size specified by the drive. Since some drives require setup time after enumeration before they are ready for drive access, the mass storage class driver provides the USBHMSCDriveReady() API to check if the drive is ready for normal operation. The mass storage host class driver also provides an interface to the USB library host controller driver to complete enumeration of mass storage class devices. The mass storage class driver information is held in the global structure g_USBMSCClassDriver. This structure should only be referenced by the application, and the function pointers in this structure should never called directly by anything other than the host controller driver. The USBHMSCOpen() and USBHMSCClose() APIs allow the host controller’s enumeration code to signal when a mass storage class device is detected or removed. The mass storage host class driver is responsible for providing a callback to the file system or application for notification when the drive is connected or disconnected. To make the the mass storage class driver visible to the host controller driver, it must be added in the list of drivers provided when calling USBHCDRegisterDrivers(). The class enumeration constant is set to USB_CLASS_MASS_STORAGE so any devices enumerating with value will load this class driver.

Device Interface[edit]

This section describes how an application or file system interacts with the host mass storage class driver provided by the USB library. The application or file system must register the mass storage class driver with a call to USBHCDRegisterDrivers() with g_USBHostMSCClassDriver provided as a member of the array argument. Once the host mass storage class driver has been registered, the application must call USBHMSCDriveOpen() to allow the application or file system to be called when a new mass storage device is connected or disconnected or when any other mass storage class event occurs.

The first callback is the USB_EVENT_CONNECTED event, indicating that a mass storage class flash drive has been inserted and the USB library host stack has successfully enumerated the device. This does not indicate that the flash drive is ready for read/write operations; the device has only been detected. The USBHMSCDriveReady() API can be called to determine when the flash drive is ready for read/write operations. When the device is removed, a USB_EVENT_DISCONNECTED event occurs. When shutting down, the application must call USBHMSCDriveClose() to disable callbacks. This does not actually power down the mass storage device, but it does stop the driver from calling the application with further events. Once calling USBHMSCDriveReady() indicates that the flash drive is ready, the application can use the USBHMSCBlockRead() and USBHMSCBlockWrite() APIs to access the device. These are block-based functions that use the logical block address to indicate which block to access. It is important to note that the size passed to these functions is specified in blocks, not bytes. The most common block size is 512 bytes. These calls always read or write a full block, so space must be allocated and managed appropriately. The following example shows calls for both reading and writing blocks from a mass storage class device.

Host SCSI Layer[edit]

Since most mass storage class devices adhere to the SCSI protocol for block based calls, the USB library provides SCSI functions for the mass storage class driver to communicate with MSC drives. The commands and data pass over the USB pipes provided by the host controller driver. The only types of mass storage class device that are supported are devices that use the SCSI protocol. Since flash drives only support a limited subset of the SCSI protocol, only the SCSI functions needed by mass storage class to mount and access flash drives are implemented. The SCSIRead10() and SCSIWrite10() APIs are the two functions used for reading and writing to mass storage class devices. The remaining SCSI functions are used to get information about the mass storage class devices, including the device's block size and total number of blocks. Other APIs are used for error handling or to check whether or not the device is ready for a new command.

Example Application[edit]

The application must call USBHMSCDriveOpen() in order for the application to be ready for a new mass storage device. The application should also wait for the mass storage class device to be ready to receive commands by calling USBHMSCDriveReady() and waiting for a return value of 0 before attempting to read or write to the device. Typically, reading and writing to the device is handled by a file system layer.

The example application executes the following sequence:

  1. Configure and enable the interrupts
  2. Enable the USB clocking
  3. Register the host class driver
  4. Open an instance of the mass storage class driver
  5. Initialize the power configuration
  6. Initialize the host controller
  7. Initialize the file system
  8. Check for the device readiness

Running the Application[edit]

  • Connect a USB flash drive to the target board using Host cable
    • Note: On the OMAP-L138/AM1808/C6748 EVM, use the J6 (mini) USB connector
  • Connect the board to a PC through UART. A serial terminal application should be running on the host. Refer here for more details. The serial terminal displays a command line interface to the user at run time
  • Load and run the example application on to target
  • Connect a mass storage device to the board
  • The PC terminal should display “Mass storage device connected”
  • Type "help" to see the supported commands
  • Use the necessary command to brows through the storage device

Note: The MSC Host class is by default configured for Hi-Speed DMA transfer mode. For Full-Speed mode, define 'USB_MODE_FULLSPEED' in 'Drivers', 'USBLib' and 'Application' make files.

For connector information please check the connector information table

Modules used by this example:

  • USB MSC host
  • UART
  • Timer
  • Interrupt

Integrating a Different File System[edit]

Using a different file system rather than the one provided with the package (i.e. FatFs) requires the following steps:

  • Look for a source file containing the wrapper function to insert the stack APIs. In the current package, fat_usbmsc.c is the file that integrates the stack with the file system.
  • Find the appropriate file system initialization APIs and use them in the application.
  • Replace the file Open/Read/Write APIs as necessary in the application.

Multi-instance Support Information[edit]

StarterWare USB package provides the necessary software support for multi-instance capability. The application can select each of the USB instance and initialize, configure and start separately as per the corresponding class specific details detailed above. The multi-instance support is demonstrated/tested using below sample application(s).

  • Note: EVM-AM335x/EVMSK-AM335x/BeagleBone has a Micro connector for USB0 and a Standard-A receptacle for USB1. Thus, USB0 can be exercised in host mode or in device mode, while USB1 can be exercised only in host mode.

MSC Device + MSC Host Example Application[edit]

The initialization, data flow, interfacing and other details remains same as that for MSC Device Class and MSC Host Class. In this example, USB0 is used for device mode and USB1 is used for host mode.

The example application executes in the following sequence:

  1. Configure and enable the interrupts
  2. Enable the USB clocking
  3. Initialize the power configuration
  4. Register the host class driver
  5. Initialize the host controller with USB1
  6. Initialize DMA for Host mode
  7. Open an instance of the mass storage class driver
  8. Initialize DMA for Device mode with endpoint details
  9. Initialize the USB0 for MSC Device class
  10. Initialize the file system
  11. Check for the device readiness in Host mode

Running the Application[edit]

  • Connect a USB flash drive to the target board on USB1
  • Connect the target board to the host PC via a USB cable from USB0
  • Connect the board to a PC through UART. A serial terminal application should be running on the host. Refer here for more details. The serial terminal displays a command line interface to the user at run time
  • Load and run the example application on to target
  • Host-mode: The PC terminal should display “Mass storage device connected”
  • Host-mode: Type "help" to see the supported commands
  • Host-mode: Use the necessary command to browse through the storage device
  • Device-mode: On the host PC, the device will appear as a mass storage device
  • Device-mode: On attempting to access the MSC device on the host PC, the host formats the RAM disk
  • Device-mode: Once the format operation is complete, the device is ready for data transaction
    • Note: Device-mode: Currently the device supports 16MB of RAM disk
    • Note: User will have to wait till the current issued command completes to issue next command

For connector information please check the connector information table

Modules used by this example:

  • USB MSC host
  • USB MSC Device
  • UART
  • Timer
  • Interrupt

MSC Host + MSC Mouse Example Application[edit]

The initialization, data flow, interfacing and other details remains same as that for Mouse Host Class and MSC Host Class. In this example, USB0 is used for MSC host mode and USB1 is used for Mouse host mode.

The example application executes in the following sequence:

  1. Configure and enable the interrupts
  2. Enable the USB clocking
  3. Initialize the power configuration
  4. Register the Mouse host class driver
  5. Initialize the host controller and register mouse driver with USB1
  6. Register the MSC host class driver
  7. Initialize DMA for MSC Host mode
  8. Initialize the host controller for MSC with USB0
  9. Initialize the file system for MSC class
  10. Check for the device readiness in Host mode

Running the Application[edit]

  • Connect a USB flash drive to the target board on USB0
  • Connect a USB mouse to the target board on USB1
  • Connect the board to a PC through UART/virtual serial port. A serial terminal application should be running on the host. Refer here for more details. The serial terminal displays a command line interface to the user at run time
  • Load and run the example application on to target
  • MSC Host-mode: The PC terminal should display “Mass storage device connected”
  • MSC Host-mode: Type "help" to see the supported commands
  • MSC Host-mode: Use the necessary command to browse through the storage device
  • Mouse Host-mode: The display at the bottom left of the screen will show “Connected” if the mouse is enumerated and connected to the host
  • Mouse Host-mode: Move the mouse and see its motion tracked by the cursor on the screen
  • Mouse Host-mode: Press the mouse buttons and observe the button indicator on the bottom right corner of the screen
  • Mouse Host-mode: Press and hold the left mouse button and drag the cursor to draw lines or curves on the screen
  • Mouse Host-mode: Unplug the mouse from the board and see the display at bottom left changes to “No device”

Note: User will have to wait till the current issued command completes

For connector information please check the connector information table

Modules used by this example:

  • USB MSC host
  • USB Mouse host
  • UART
  • Timer
  • Interrupt

Performance[edit]

Steps to capture performance[edit]

  • Open 'usblib\include\usblib.h'. Define 'PROFILE_USB_MSC_WRITE' OR 'PROFILE_USB_MSC_READ' based on what is being profiled. Build the example usb_dev_msc (Note: Below performance figures are captured using GCC build).
  • Setup the CCS IDE and h/w environment as documented in USB user-guide to execute usb_dev_msc example.
  • Add variable 'g_USBPerfInfo' to watch window.
  • Execute the example.
  • Format and copy two ~50MB files to USB device. Copy the two ~50MB files back to PC.
  • Eject the device.
  • "Pause" the example execution using CCS IDE.
  • Open "memory browser" of CCS,
    • select "save memory" option,
    • provide <filename>.hex and click 'Next' button
    • Select 'Raw Data' option for 'Format'
    • Set 'Length' to 10000
    • Set 'Start Address' to address of 'g_USBPerfInfo'
    • 'Finish'
  • Build '..\tools\hex2text.c' and execute it with command line argument being the <filename>.hex. E.g: hex2text write.hex
  • A file namely '<filename>.hex.txt' will be created.
  • Rename '<filename>.hex.txt' to '<filename>.hex.csv', open with Windows Excel to view the data used to profile and the summary at the end.


Warning: Timer 7 is currently used for capturing performance figures. One should not use the 'delay' function in between the code being profiled as it too uses Timer 7.

Performance Figures Table[edit]

Examples

                                                                        EVM-AM335x

Read (DMA Mode - Raw read) Write (DMA Mode - Raw write)
usb_host_msc 16.6 MB/Sec 17.0 MB/Sec
usb_dev_msc 14.2 MB/Sec 17.6 MB/Sec

Connector Information[edit]

  Below table shows, which USB receptacle to use for each example in the package.

Examples

                                                                        EVMs

AM1808 AM335xEVM Beaglebone
usb_dev_serial J6 - USB0 - mini AB receptacle J14 - USB0 - micro AB receptacle P3 - USB0 - mini B receptacle 
usb_dev_bulk J6 - USB0 - mini AB receptacle J14 - USB0 - micro AB receptacle P3 - USB0 - mini B receptacle
usb_dev_mouse J6 - USB0 - mini AB receptacle J14 - USB0 - micro AB receptacle NA
usb_dev_msc J6 - USB0 - mini AB receptacle J14 - USB0 - micro AB receptacle P3 - USB0 - mini B receptacle
usb_host_mouse J6 - USB0 - mini AB receptacle J18 - USB1 - USB A type receptacle NA
usb_host_msc J6 - USB0 - mini AB receptacle J18 - USB1 - USB A type receptacle NA

 

 Limitations[edit]

  1. SOF counter approach for timer can’t be used in High Speed mode. Need to see other options for the functionalities where SOF counter/timer is used
E2e.jpg {{
  1. switchcategory:MultiCore=
  • For technical support on MultiCore devices, please post your questions in the C6000 MultiCore Forum
  • For questions related to the BIOS MultiCore SDK (MCSDK), please use the BIOS Forum

Please post only comments related to the article StarterWare USB here.

Keystone=
  • For technical support on MultiCore devices, please post your questions in the C6000 MultiCore Forum
  • For questions related to the BIOS MultiCore SDK (MCSDK), please use the BIOS Forum

Please post only comments related to the article StarterWare USB here.

C2000=For technical support on the C2000 please post your questions on The C2000 Forum. Please post only comments about the article StarterWare USB here. DaVinci=For technical support on DaVincoplease post your questions on The DaVinci Forum. Please post only comments about the article StarterWare USB here. MSP430=For technical support on MSP430 please post your questions on The MSP430 Forum. Please post only comments about the article StarterWare USB here. OMAP35x=For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article StarterWare USB here. OMAPL1=For technical support on OMAP please post your questions on The OMAP Forum. Please post only comments about the article StarterWare USB here. MAVRK=For technical support on MAVRK please post your questions on The MAVRK Toolbox Forum. Please post only comments about the article StarterWare USB here. For technical support please post your questions at http://e2e.ti.com. Please post only comments about the article StarterWare USB here.

}}

Hyperlink blue.png Links

Amplifiers & Linear
Audio
Broadband RF/IF & Digital Radio
Clocks & Timers
Data Converters

DLP & MEMS
High-Reliability
Interface
Logic
Power Management

Processors

Switches & Multiplexers
Temperature Sensors & Control ICs
Wireless Connectivity

{{#switchcategory:MSP430=<McuHitboxFooter/>|C2000=<McuHitboxFooter/>|Stellaris=<McuHitboxFooter/>|TMS570=<McuHitboxFooter/>|MCU=<McuHitboxFooter/>|MAVRK=<MAVRKHitboxFooter/>|<HitboxFooter/>}}