USBD ROM Stack  1.0
ROM based USB device stack
USB Device ROM Stack

The boot ROM contains flexible USB device stack to simplify the USB application development. The USB ROM stack has built-in support for Communication Device Class (CDC), the Human Interface Device (HID), the Mass Storage Class (MSC) and Device Firmware Upgrade (DFU) class. It also supports composite device model consisting of multiple interfaces of above supported classes.

USB Device Stack Architecture

The following figure shows the architectural block diagram of the USB device ROM stack. The stack consists of three main layers:

  1. The Class Layer
  2. The USB Core Layer
  3. The Device Controller Driver Layer

The bottom-most layer is Device Controller Driver (DCD) layer which is also referred as hardware layer in this document. Above that is the USB Core Layer which handles the USB protocol specific code. Above that is the Class layer which contains various class Function Drivers (FD). Finally, the application sits at the top of the stack.

arch.png


Each layer has one or more components which are accessible to user application. Each component has two main structures USBD_xxx_API_T and USBD_xxx_INIT_PARAM_T. The USBD_xxx_API_T structure contains all the user callable routines to use the component. The USBD_xxx_INIT_PARAM_T structure is used by application to specify various initialization parameters along with pointers to call-back routines. These call-back routines can be categorized as event callbacks and stack overrides.

  • Event callbacks: These are called by the stack in interrupt context when an appropriate event occurs.
  • Stack overrides: These routines are defined to allow customization (override the default behavior) of the stack by user, if the default behavior/handling of the stack is not appropriate for the user application.

The USB Class Layer

All the function drivers implemented by the USB device ROM stack reside in this layer. The current stack implements following function drivers:

Zero-Copy Data Transfer model

The function drivers (CDC, DFU, HID & MSC) implemented in stack are written with zero-copy model. Meaning the stack doesn't make an extra copy of buffer before writing/reading data from USB hardware FIFO. Hence the read callback functions of function drivers DFU_Read(), MSC_Read() and HID_GetReport() have pointer to a pointer containing address buffer (uint8_t** pBuffer). So that the user application can update the buffer pointer instead of copying data to address pointed by the parameter. /note The updated buffer address should be accessible by USB DMA master. If user doesn't want to use zero-copy model, then the user should copy data to the address pointed by the passed buffer pointer parameter and shouldn't change the address value.
Similarly the write callback functions of function drivers DFU_Write(), MSC_Write() and HID_SetReport() have pointer to a pointer containing address buffer (uint8_t** pBuffer). So that the user application can update the buffer pointer at the end of write call and stack will use the updated buffer address to program DMA for next write transfer. The mechanism to get the very first transfer's buffer address varies by function driver. See individual function driver details page for more information. In most cases the function driver gets the destination buffer pointer for the first time, by calling the write routines with zero length. If user doesn't want to use zero-copy model, then the user shouldn't updated buffer address in write call.

The USB Core Layer

The USB Core Layer uses the device abstraction defined in the Universal Serial Bus Specification to interact with the USB device interface on the device. The software in this layer responds to standard requests and returns standard descriptors, essentially taking care of Chapter 9 requirements of USB specification. In current stack the Init() routine part of USBD_HW_API_T structure initializes both hardware layer and core layer. Other routines exposed by this layer are accessible through USBD_CORE_API_T structure.

The Device Controller Driver Layer

The Device Controller Driver Layer implements the routines to deal directly with the hardware. All the functions exposed by this layer are available through USBD_HW_API_T structure.

Memory Model

The USBD ROM stack uses the system stack for local variables and allocates all global variables & buffers in memory space specified by the user through USBD_API_INIT_PARAM_T. Hence the user application doesn't have to deal with linker control files. The user has to specify the memory space to be used by stack by providing the base address in mem_base field of USBD_API_INIT_PARAM_T initialization parameter structure. The stack allocates some of the DMA transferable buffers in this memory space; hence the user should assign a memory area which is accessible by USB DMA master on the chip.

Each component of the stack exposes GetMemSize() routine which returns the size of memory buffer required by the component. Users should make sure that the buffer passed to Init() routines is at least as big as the size returned by GetMemSize() of the component.

Calling the USB device driver

A fixed location in ROM contains a pointer to the ROM driver table i.e. 0x1FFF 1FF8 (ROM table address varies from chip to chip, see chip user manual for exact address). The ROM driver table contains a pointer to the USB driver table. Pointers to the various USB driver functions are stored in this table. USB driver functions can be called by using a C structure.

typedef struct USBD_API 
{
  const USBD_HW_API_T* hw; /* Pointer to function table which exposes functions 
                           which interact directly with USB device stack's core 
                           layer.*/
  const USBD_CORE_API_T* core; /* Pointer to function table which exposes functions 
                           which interact directly with USB device controller 
                           hardware.*/
  const USBD_MSC_API_T* msc; /* Pointer to function table which exposes functions 
                           provided by MSC function driver module.
                           */
  const USBD_DFU_API_T* dfu; /* Pointer to function table which exposes functions 
                           provided by DFU function driver module.
                           */
  const USBD_HID_API_T* hid; /* Pointer to function table which exposes functions 
                           provided by HID function driver module.
                           */
  const USBD_CDC_API_T* cdc; /* Pointer to function table which exposes functions 
                           provided by CDC-ACM function driver module.
                           */
  const uint32_t* reserved6; /* Reserved for future function driver module.
                           */
  const uint32_t version; /* Version identifier of USB ROM stack. The version is
                          defined as 0x0CHDMhCC where each nibble represents version
                          number of the corresponding component.
                          CC -  7:0  - 8bit core version number
                           h - 11:8  - 4bit hardware interface version number
                           M - 15:12 - 4bit MSC class module version number
                           D - 19:16 - 4bit DFU class module version number
                           H - 23:20 - 4bit HID class module version number
                           C - 27:24 - 4bit CDC class module version number
                           H - 31:28 - 4bit reserved 
                           */

} USBD_API_T;

See also: