CAT2 Peripheral Driver Library
USBFS (USB Full-Speed Device)

The USBFS driver provides APIs to configure and access the USBFS hardware block on the EZ-PD PMG1 family of devices. More...

Modules

 Macros
 
 Functions
 
 Data Structures
 
 Enumerated Types
 

Detailed Description

The USBFS driver provides APIs to configure and access the USBFS hardware block on the EZ-PD PMG1 family of devices.

The PMG1 family is a set of USB Power-Delivery (USBPD) enabled Micro-Controllers for the general market. The devices PMG1-S2 & PMG1-S3 in this family support the USBFS Device Sub-System (USBFS) in addition to other standard MCU peripherals available.

The USBFS driver provides an API to interact with a fixed-function USB block.

The functions and other declarations used in this driver are in cy_usbfs_dev_drv.h. You can include cy_pdl.h to get access to all functions and declarations in the PDL.

The USB block supports Host and Device modes of operation. This version of the driver supports only Device mode.

Features:

Common Use Cases

The primary usage model for the USBFS driver is to provide a defined API interface to USB Device Middleware component that works on top of it.
The driver also provides an API interface for the application to implement the required functionality:

Configuration Considerations

This section explains how to configure the USBFS driver and system resources to enable USB Device operation. The pointers to the populated cy_stc_usbfs_dev_drv_config_t configuration structure and allocated context are passed in the middleware initialization function Cy_USB_Dev_Init. After middleware initialization, it calls Cy_USBFS_Dev_Drv_Init to initialize the USBFS driver for Device operation.

Warning
The USBFS driver's DMA feature is disabled by default. To enable it, set the CY_USBFS_DRV_DMA_ENABLE macro to 1 in the application Makefile. Before doing that, do the steps given in the section below.

Configure Driver

To configure the USBFS driver in Device mode, the configuration structure cy_stc_usbfs_dev_drv_config_t parameters must be populated. The configuration structure content significantly depends on the selected endpoints management mode parameter:

Note
The endpoint buffer allocation depends on the access type used: 8-bit or 16-bit. Refer to Hardware Buffer Access for more information.

Assign and Configure Pins

Only dedicated USB pins can be used for USB operation. Keep the default USB pins configuration because after the USBFS driver initializes, the USB block takes control over the pins and drives them properly.

Assign and Configure Clocks

The USB hardware block requires two clock sources for operation:

Refer to SysClk (System Clock) driver API for more detail about clock

Assign and Route DMA Channels

The USBFS driver requires a DMA controller to operate in DMA Manual and Automatic modes. The USB hardware block supports the DMA request and feedback lines for each data endpoint. Therefore, up to eight DMA channels serve eight data endpoints. The connection between the USB block and the DMA channels is set using the trigger muxes infrastructure. The USB block output DMA request line is connected to the DMA channel trigger input. This allows the USB block to request a DMA transfer. The DMA completion output is connected to the USB block burst end input. This allows the USB block to get notification that a DMA transfer has been completed and a next DMA request can be sent. The USBFS driver DMA configuration structure requires the outTrigMux field to provide the trigger mux that performs DMA completion and USB block burst end connection.

Refer to TrigMux (Trigger Multiplexer) for more detail on the routing capabilities.

The code examples below shows a connection DMA channel and USB block and the define for outTrigMux field initialization for the PMG1-S3 device.

/* Trigger mux that performs DMA completion and USB block burst end connection */
#define CYBSP_USB_dma_burstend_0_TRIGGER_OUT TRIG2_OUT_USB_DMA_BURSTEND0
/* USB Block and DMA channel connection */
Cy_TrigMux_Connect(TRIG1_IN_USB_DMA_REQ0, TRIG1_OUT_CPUSS_DMAC_TR_IN8);
Cy_TrigMux_Connect(TRIG2_IN_CPUSS_DMAC_TR_OUT8, TRIG2_OUT_USB_DMA_BURSTEND0);

Configure Interrupts

The interrupts are mandatory for the USBFS driver operation. The USBFS block provides multiple interrupt sources to be assigned to trigger one of the three interrupts: Low, Medium, or High. This allows to assign different priority to the interrupt sources handling. The cy_stc_usbfs_dev_drv_config_t structure provides the intrLevelSel field which initializes the INTR_LVL_SEL register. This register configures which interrupt the interrupt source will trigger.

Note
The interrupt name (Low, Medium, or High) does not specify the interrupt priority. The interrupt priority is configured in NVIC.

The recommended/default configuration is:

However, the final configuration must be defined by the application.

/* Interrupt Level Select register initialization */
#define USBD_INTR_LVL_SEL \
(CY_USBFS_DEV_DRV_SET_SOF_LVL (CY_USBFS_DEV_DRV_LVL_LOW) | \
CY_USBFS_DEV_DRV_SET_BUS_RESET_LVL(CY_USBFS_DEV_DRV_LVL_LOW) | \
CY_USBFS_DEV_DRV_SET_EP0_LVL (CY_USBFS_DEV_DRV_LVL_LOW) | \
CY_USBFS_DEV_DRV_SET_ARB_EP_LVL(CY_USBFS_DEV_DRV_LVL_HIGH) | \
CY_USBFS_DEV_DRV_SET_EP1_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP2_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP3_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP4_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP5_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP6_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP7_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM) | \
CY_USBFS_DEV_DRV_SET_EP8_LVL(CY_USBFS_DEV_DRV_LVL_MEDIUM))

The Cy_USBFS_Dev_Drv_Interrupt function must be called in the interrupt handler for the selected USB block instance. Note that the Cy_USBFS_Dev_Drv_Interrupt has the parameter intrCause that must be assigned by calling the appropriate interrupt cause function:

/*******************************************************************************
* Function Name: USBD_IsrHigh
****************************************************************************/
static void USBD_IsrHigh(void)
{
/* Call interrupt processing */
}
/*******************************************************************************
* Function Name: USBD_IsrMedium
****************************************************************************/
static void USBD_IsrMedium(void)
{
/* Call interrupt processing */
}
/*******************************************************************************
* Function Name: USBD_IsrLow
****************************************************************************/
static void USBD_IsrLow(void)
{
/* Call interrupt processing */
}

Finally, the interrupts must be configured and interrupt handler routines hook up to NVIC. The code below assigns the interrupt priorities accordingly to interrupt names. The priorities among the USBFS interrupts are as follows: High - the greatest; Medium - the middle; Low - the lowest.

Note
For proper operation in Manual DMA mode (Mode 2) the Arbiter interrupt source must be assigned to interrupt which priority is greater than interrupt triggered by Data Endpoint 1-8 Completion interrupt sources.
For Automatic DMA mode (Mode 3) the rule above is recommend to follow.
/* Assign USBFS Device interrupt number and priority */
const cy_stc_sysint_t USBD_IntrHighConfig =
{
.intrSrc = (IRQn_Type) usb_interrupt_hi_IRQn,
.intrPriority = 0U,
};
const cy_stc_sysint_t USBD_IntrMediumConfig =
{
.intrSrc = (IRQn_Type) usb_interrupt_med_IRQn,
.intrPriority = 1U,
};
const cy_stc_sysint_t USBD_IntrLowConfig =
{
.intrSrc = (IRQn_Type) usb_interrupt_lo_IRQn,
.intrPriority = 2U,
};
/* Hook interrupt service routines */
(void) Cy_SysInt_Init(&USBD_IntrLowConfig, &USBD_IsrLow);
(void) Cy_SysInt_Init(&USBD_IntrMediumConfig, &USBD_IsrMedium);
(void) Cy_SysInt_Init(&USBD_IntrHighConfig, &USBD_IsrHigh);

Endpoint Buffer Management Modes

The USBFS hardware block supports three endpoint buffer management modes: CPU (No DMA) mode (Mode 1), Manual DMA mode (Mode 2), and Automatic DMA mode (Mode 3). These modes are listed using enum cy_en_usbfs_dev_drv_ep_management_mode_t. The following sub-sections provide more information about the endpoint buffer management.

Hardware buffers

The USBFS block has a 512-byte hardware buffer that is divided between all data endpoints used in the selected configuration. How the hardware buffer is divided between endpoints depends on the selected endpoint buffer management modes:

To access the hardware buffer, the endpoint data register is read or written by CPU or DMA. On each read or write, buffer pointers are updated to access a next data element.

Hardware Buffer Access

The USBFS block provides two sets of data registers: 8-bit and 16-bit. Either the 8-bit endpoint data register or the 16-bit endpoint data register can be used to read/write to the endpoint buffer. The buffer access is controlled by the epAccess field of the driver configuration structure cy_stc_usbfs_dev_drv_config_t. The endpoint hardware buffer and SRAM buffer must be allocated using the rules below when the 16-bit access is used:

The driver provides the CY_USBFS_DEV_DRV_ALLOC_ENDPOINT_BUFFER macro that applies the rules above to allocate the SRAM buffer for an endpoint. This macro should be used by application to hide configuration differences. However, in this case the application must ignore extra bytes in the buffer. Alternately, apply the rules above only for the 16-bits access type configuration.

The driver firmware allocates an endpoint hardware buffer (dividing hardware buffer between utilized endpoints). Therefore, for CPU mode (Mode 1) and Manual DMA mode (Mode 2), an endpoint whose maximum packet size is odd, consumes an extra byte in the hardware buffer when the 16-bit access is used. This is not applicable for Automatic DMA mode (Mode 3) because endpoints dedicated buffer are even and aligned.

In addition, to operate in Automatic DMA mode (Mode 3), the driver needs an internal SRAM buffer for endpoints. The buffer size is a sum of all endpoint buffers. When the 16-bit access is used, each endpoint buffer must be allocated using the rules above. The driver configuration structure cy_stc_usbfs_dev_drv_config_t has epBuffer and epBufferSize fields to pass the allocated buffer to the driver.
For example: the USB Device uses three data endpoints whose max packets are 63 bytes, 63 bytes, and 8 bytes. The endpoints buffer for the driver must be allocated as follows:

CPU mode (Mode 1)

CPU handles data transfers between the user-provided SRAM endpoint-buffer and the USB block hardware-buffer when Cy_USBFS_Dev_Drv_ReadOutEndpoint or Cy_USBFS_Dev_Drv_LoadInEndpoint is called.

usbfs_ep_mngmnt_mode1.png

Manual DMA mode (Mode 2)

DMA handles data transfers between the user-provided SRAM endpoint buffer and the USB block hardware buffer. The DMA request is issued by CPU to execute a data transfer when Cy_USBFS_Dev_Drv_ReadOutEndpoint or Cy_USBFS_Dev_Drv_LoadInEndpoint.

usbfs_ep_mngmnt_mode2.png

Automatic DMA mode (Mode 3)

DMA handles data transfers between the driver SRAM endpoints buffer and the USB block hardware buffer. The USB block generates DMA requests automatically. When USB transfer starts, the USB block triggers DMA requests to transfer data between the driver endpoint buffer and the hardware buffer until transfer completion. The common area acts as a FIFO to (and keeps data that does not fit into) the endpoint dedicated buffer. For IN endpoints, the dedicated buffer is pre-loaded before enabling USB Host access to the endpoint. This gives time for the DMA to provide remaining data before underflow occurs. The USB block hardware has a feedback connection with the DMA and does not issue new DMA request until it receives notification that the previous DMA transfer completed. When the Cy_USBFS_Dev_Drv_ReadOutEndpoint or Cy_USBFS_Dev_Drv_LoadInEndpoint function is called, the memcpy function is used to copy data from/into the driver endpoints buffer to the user-provided endpoint buffer. The driver provides the Cy_USBFS_Dev_Drv_OverwriteMemcpy function to replace memcpy function by one that has been custom implemented (the DMA can be used for data copy).

usbfs_ep_mngmnt_mode3.png
Warning
When DMA data transfer is not fast enough, an overflow or underflow interrupt triggers for the impacted endpoint. This must never happen because this error condition indicates a system failure with no recovery. To fix this, get the DMA channel assigned to this endpoint greater priority or increase the clock the DMA operates at.

Callbacks Usage

The driver provides the following callbacks that can be used by the application:

  1. Data endpoint 1-8 completion. This callback is invoked when the USB Host completed communication with the endpoint. For IN endpoints, it means that data has been read by the USB Host. For OUT endpoints, it means that data has been written by the USB Host. Call Cy_USBFS_Dev_Drv_RegisterEndpointCallback to register callback function.
  2. Start Of Frame packet received. This can be used in the application to synchronize with SOF packets or for monitoring the bus activity. Call Cy_USBFS_Dev_Drv_RegisterSofCallback to register callback function.

Also, the driver provides callbacks for a Bus Reset event and Control Endpoint 0 communication events (setup packet, in packet, out packet). But these callbacks are used by middleware and must not be used by the application directly. The middleware provides appropriate hooks for these events.

VBUS Detection

The USB specification requires that no device supplies current on VBUS at its upstream facing port at any time. To meet this requirement, the device must monitors for the presence or absence of VBUS and removes power from the Dp/Dm pull-up resistor if VBUS is absent. The USBFS driver does not provide any support of VBUS monitoring or detection. The application firmware must implement the required functionality using a VDDUSB power pad or GPIO. Refer to the Universal Serial Bus (USB) Device Mode section, sub-section VBUS Detection in the technical reference manual (TRM).

Connect the VBUS through a resistive network when the regular GPIO is used for VBUS detection to save the pin from voltage picks on VBUS, or use GPIO tolerant over the voltage. An example schematic is shown below.

usbfs_vbus_connect_schem.png
Note
Power is removed when the USB cable is removed from the USB Host for bus-powered USB Device. Therefore, such a USB Device complies with specification requirement above.

Low Power Support

The USBFS driver supports the USB Suspend, Resume, and Remote Wakeup functionality. This functionality is tightly related with the user application. The USBFS driver provides only the API interface which helps the user achieve the desired low-power behavior. The additional processing is required from the user application. The description of application processing is provided below.

Normally, the USB Host sends an SOF packet every 1 ms (at full speed), and this keeps the USB Device awake. The USB Host suspends the USB Device by not sending anything to the USB Device for 3 ms. To recognize this condition, the bus activity must be checked. This can be done using the Cy_USBFS_Dev_Drv_CheckActivity function or by monitoring the SOF interrupt. A suspended device may draw no more than 0.5 mA from VBUS. Therefore, put the device into low-power mode to consume less current. The Cy_USBFS_Dev_Drv_Suspend function must be called before entering low-power mode. When the USB Host wants to wake the device after a suspend, it does so by reversing the polarity of the signal on the data lines for at least 20 ms. The resume signaling is completed with a low-speed end-of-packet signal. The USB block is disabled during Deep Sleep or Hibernate low-power modes. To exit a low-power mode when USB Host drives resume, a falling edge interrupt on Dp must be configured before entering these modes. The Cy_USBFS_Dev_Drv_Resume function must be called after exiting the low-power mode. To resume communication with the USB Host, the data endpoints must be managed: the OUT endpoints must be enabled and IN endpoints must be loaded with data.

Note
After entering low-power mode, the data which was left in the IN or OUT endpoint buffers is not restored after the device's wake-up and is lost. Therefore, it must be stored in the SRAM for OUT endpoint or read by the Host for the IN endpoint before entering Low-power mode.

If the USB Device supports remote wakeup functionality, the application has to use middleware function Cy_USB_Dev_IsRemoteWakeupEnabled to determine whether remote wakeup was enabled by the USB Host. When the device is suspended and it determines the conditions to initiate a remote wakeup are met, the application must call the Cy_USBFS_Dev_Drv_Force function to force the appropriate J and K states onto the USB bus, signaling a remote wakeup condition. Note that Cy_USBFS_Dev_Drv_Resume must be called first to restore the condition.

More Information

For more detail on the USB Full-Speed Device peripheral, refer to the section Universal Serial Bus (USB) Device Mode in the technical reference manual (TRM).

Changelog

VersionChangesReason for Change
2.20 Resolved compiler warnings related to USBFS DMAC APIs. Defect fix.
2.10 Corrected variable type name. Defect fix.
2.0 The USBFS driver's DMA feature is disabled by default. You can enable it by setting the macro CY_USBFS_DRV_DMA_ENABLE to 1 in the application Makefile.
Note
If DMA was enabled in an existing project, the CY_USBFS_DRV_DMA_ENABLE macro should be set to 1.
Feature support
Updated the Cy_USBFS_Dev_Drv_Ep0Read function to read upto 64 bytes of data at a time. Defect fix
1.10 Add DMA endpoint buffer management New feature support
1.0.1 Update the paths to the code snippets. PDL structure update.
1.0 The initial version.