USB Device Driver

The Universal Serial Bus (USB) is an industry standard that defines the cables, connectors, and communication protocols used in a bus for connection, communication, and power supply between computers and electronic devices.

The USB device driver provides necessary APIs to support USB Device states and USB data flow, so that the USB Device enumeration, class, and vendor support can be implemented based on it. The driver is asynchronous, which means that all USB data processing is done in callbacks.

To be recognized by a host, a USB device must handle a subset of the USB events. The USB device should build up control communication to report its descriptors to the host and accept host's requests. An application or upper stack that uses the USB device driver should have its descriptors prepared, catch the callbacks, monitor the control requests and handle them correctly. Usually, a USB device application that can be enumerated may use the following sequence:

  • Initialize

  • Register callback and handle Reset event, where:
    • Initialize endpoint 0

    • Register callbacks for endpoint 0, where some of the standard requests defined in Chapter 9, USB specification (see USB 2.0 Documents http://www.usb.org/developers/docs/usb20_docs_) are handled
      • Setup request handling callback
        • On GetDeviceDescriptor request, sends device descriptor

        • On GetConfigurationDescriptor request, sends configuration descriptors

        • On SetAddress request sends no data, just goes to status phase

        • On SetConfigure request initialize and enable other endpoints, sends no data, just goes to status phase

      • Transfer done handling callback
        • On SetAddress request apply the new address

        • On SetConfigure request a global variable can be set to indicates that the host driver is loaded and device is ready to work

    • Enable endpoint 0

  • Enable

  • Attach device

To support USB transfer on endpoints, endpoints information is stored by the driver internally, including control request data, endpoint status, callbacks and transfer data pointers. The number of endpoints that the driver can support is defined through configuration. To optimize RAM usage, the number of endpoints the driver needs to support should be minimized.

Summary of the API's Functional Features

The API provides functions to:
  • Initialization/de-initialization

  • Enabling/disabling

  • USB device attachment/detachment

  • USB device address control

  • USB working speed status

  • USB device frame number and micro frame number status

  • Sending remote wakeup to host

  • Callback management for following USB events:
    • Start of Frame (SOF)

    • Other USB events:
      • VBus change

      • Reset

      • Wakeup

      • Linked Power Management (LPM) Suspend

      • Suspend

      • Error

  • Endpoints management:
    • Endpoint initialization/de-initialization

    • Endpoint enabling/disabling

    • Control endpoint setup request packet

    • Data transfer and abort

    • Endpoint halt state control

    • Endpoint status, including:
      • Endpoint address

      • Last transfer result status code

      • Last error status code

      • Current transfer state

      • Transfer size and done count

    • Endpoint callback management for endpoint and its transfer events:
      • In case a setup request received on control endpoint

      • In case transfer finished with/without error

Driver Implementation Description

Limitations

  • When a buffer is used by a USB endpoint to transfer data, it must be kept unchanged while the transfer is in progress.

  • After receiving a request that has no data expected, the transfer function must be called with data length zero to complete control status phase.

Dependencies

  • The USB device capable hardware

  • 48MHz clock for low-speed and full-speed and 480MHz clock for high-speed

Considerations for SAM D21 USB

Clocks

DFLL must be used to generate 48MHz clock for USB device with either of the following mode:

  • USB Clock Recovery Mode
    • Set "DFLL Enable", "Bypass Coarse Lock", "Chill Cycle Disable", "USB Clock Recovery Mode", "Stable DFLL Frequency"

    • Clear "Wait Lock"

    • Leave "Operating Mode Selection" to "Closed Loop Mode"

  • Closed Loop Mode
    • Set "DFLL Enable"

    • Clear "USB Clock Recovery Mode", "Stable DFLL Frequency"

    • Select "Closed Loop Mode" of "Operating Mode Selection"

    • Set "DFLL Multiply Factor" to 1464 or 1465 (48000000/32768)

    • Select "Reference Clock Source" to use 32768Hz source, e.g., use GCLK1 and for GCLK1 settings:
      • Set "Generic Clock Generator Enable"

      • Select "XOSC32K" of "Generic clock generator 1 source", and for XOSC32K settings:
        • Set "External 32K Oscillator Enable", "Enable 32KHz Output", "Enable XTAL"

        • Set a right value for "Startup time for the 32K Oscillator", e.g., 1125092 us

Endpoints

Each USB device endpoint number supports two endpoint addresses, corresponding to IN and OUT endpoint. E.g., for endpoint 1, the endpoint IN has address 0x81 and endpoint OUT has address 0x01. Thus, the possible supported endpoint addresses are almost two times of max endpoint number (endpoint 0 must be used as control endpoint instead of dedicated IN and OUT endpoints).

Buffering and RAM usage optimization

When transferring data through USB device endpoints, buffer pointers can be used to let endpoint get access to the buffer, but there are some limits:

  • For control endpoint there must always be a buffer available to put received setup packet.

  • For IN endpoint (transmit to host) the data must in RAM.

  • For OUT endpoint (receive from host) the data pointer must be aligned, and the data size must be aligned by max endpoint size and not zero.

The driver has option for each endpoint to allocate internal static buffer as cache to buffer input/output data, to remove upper limits. The configuration affects the parameter check of transfer functions, and the RAM usage.

  • For control endpoints, cache buffer must be enabled to fill setup packet. In addition, to support unaligned OUT packet and IN packet inside flash, the buffer size must be equal to or larger than max endpoint size.

  • For OUT endpoints, if the cache is allocated, it's possible to pass unaligned buffer address and buffer size to transfer function. Else the transfer function only accepts aligned buffer with it's size multiple of endpoint packet size.

  • For IN endpoints, if the cache is allocated, it's possible to pass buffer pointer to internal flash or other memory part other than RAM to the transfer function.

To optimize the RAM usage, the configuration of max endpoint number, max number of endpoints supported and the buffer usage of used input and/or output endpoints can be adjusted.