emusb-host
SEGGER emUSB-Host for ModusToolbox User Guide

emUSB-Host is a CPU-independent USB Host stack. emUSB-Host is a high-performance library that has been optimized for speed, versatility and small memory footprint. Infineon has licensed emUSB-Host from SEGGER and offers it for free to its customers. This Middleware library provides emUSB-Host in the form of pre-build libraries.

Features:

  • High performance
  • Small footprint
  • No configuration required
  • Control, bulk, interrupt and isochronous transfers
  • Very simple host controller driver structure
  • Support for external USB hub devices
  • Support for devices with alternate settings
  • Support for multi-interface devices
  • Support for multi-configuration devices

Supported USB Device Drivers/Classes:

  • BULK Device Driver
  • CCID Device Driver
  • CDC Device Driver
  • CP210X Device Driver
  • FT232 Device Driver
  • Human Interface Devices (HID) class
  • MIDI Device Driver
  • Mass Storage Device (MSD) class
  • MTP Device Driver
  • Printer class
  • Video Device Driver (Only for PSE84)

Device families supported by the Middleware:

  • PSE84

General Description

This manual provides only the basic concepts of emUSB-Host and integration specifics of the emUSB-Host into ModusToolbox flow. For a detail description of the emUSB-Host features, implementation, and APIs, refer to: SEGGER emUSB-Host User Guide & Reference Manual.

The Quick Start Guide is available in this API Reference Guide.

emUSB-Host consists of the following layers:

  • The driver for hardware access
  • The emUSB-Host core
  • The USB class driver

emUSB-Host and the USB class drivers are device-independent, while the driver for hardware access is applicable only for one device family. The driver is selected in the USBH_X_Config() function, the template of implementation of USBH_X_Config() is in the Config folder.

The drivers for emUSB-Host can support not all available features and may need to be configured in a special manners, refer to the: SEGGER emUSB-Host User Guide & Reference Manual Host controller specifics chapter.

Supported Drivers by the Device family

Device familyDriversFunction to add driver
PSE84 PSoCE84 Driver USBH_Infineon_PSOCE84_DMA_Add
Note
For the function description, refer to the: SEGGER emUSB-Host User Guide & Reference Manual Host controller specifics chapter.

For the PSE84 device, the DMA engine of the USB IP block does not have access to all SRAM regions. For details, see the PSE84 Reference Manual. As a result, the memory pool for the PSE84 driver must be located only to the SRAM region with DMA access. An example of the allocation memory pool is in the usbd_config.c file.

The emUSB-Host is provided in the form of pre-build libraries. The pre-build library is selected automatically based on configuration of Application project.

The emUSB-Host includes an OS abstraction implemented by abstraction-rtos, so this Middleware can be used with any RTOSes supported by abstraction-rtos. The RTOS is required for the emUSB-Host operation.

The hardware dependency files are presented in export/Config directory:

  • One common file responsible for the debug message output
  • Device-specific files for the hardware configuration of each supported device family

Also, the emUSB-Host/Device personality is present in the Device-configurator for simplify routine of configuration clocks and pins for USB IP block operation. The personality is a part of mtb-device-support-pse8xxgp for PSE84 devices.

The Quick Start Guide

To set up emUSB-Host for Human Interface Devices (HID), follow the below- described steps. This code snippets will try to enumerate a connected mouse or keyboard and output data about a pressed key or mouse movements and clicks. The current snippet is based on SEGGER sample application.

Note
You can kickstart your project by using Code Examples from Project Creator app. Those contain already configured clocks and pins, you can take it as a basis for easy start.

STEP 1: Add the emUSB-Host middleware.

  1. Launch the ModusToolbox Library Manager, click Add Library button and select the next libraries: emUSB-Host and FreeRTOS middleware. This step is required only if the ModusToolbox IDE is used. Otherwise, ensure include the emUSB-Host middleware in your project.
    Note
    To use the terminal output, add retarget-io middleware from the Library Manager.
  2. Open Makefile of the project. Add USBH_BASE, FREERTOS and RTOS_AWARE to the COMPONENTS section of the Makefile.

    Warning
    Typically, the default interrupt priority-configuration from the usbh_config.c file will work with the default FreeRTOS config file. For a malfunctioned USB project, ensure that the USB interrupt priority is aligned with MAX_API_CALL_INTERRUPT_PRIORITY. See Using emUSB-Host in an RTOS Environment.

STEP 2: Configure pins and clocks for emUSB-Host.

PSE84 Devices:

  1. Launch the ModusToolbox Device Configurator and switch to the Peripherals tab (#1.1).
  2. Enable the USB personality under Communication (#1.2) and select the emUSB-Host/Device personality (#1.3).
  3. Select Host mode (#1.4) and connect available clocks (#1.5).
  4. Switch to the System tab (#2.1).

    Note
    The clocking system can be different between devices.
  5. Enable DPLL_HP (#2.2), Set Desired Frequency to 400 MHz (#2.3),
  6. Select CLK_PATH2 as the source clock for CLK_HF1 (#2.4). Ensure that CLK_HF1 has the frequency of 400 MHz (#2.5).
  7. Enable DPLL_LP1 (#2.6), set Desired Frequency to 200 MHz (#2.7) as a clock source. Use a clock with the accuracy of 0.05 % or better (#2.8).
  8. Select CLK_PATH0 or CLK_PATH1 as the source clock for CLK_HF8 (#2.9). Ensure that CLK_HF8 frequency is 50 MHz with accuracy 0.05 % or better (#2.10).
  9. If the Power personality is enabled, the System Idle Power Mode must be Active or CPU Sleep, and the HP profile is selected for System Active Power Profile.
  10. Under Clocks tab in the Peri1 Memory MappedIO (#3.1).
  11. Ensure APP_MMIO3 Divider is enabled and set to 4 in the Divider field (#3.2).
  12. Select File->Save to generate initialization code.

    Note
    Configure some boards additionally to select the USB-Host connector. Refer to the applicable board user guide.

STEP 3: Write the code in main.c.

  1. Include headers to get access to the emUSB drivers, retarget-io and FreeRTOS.
    #include "cybsp.h"
    #include "cy_retarget_io.h"
    #include "mtb_hal.h"
    /* Include emUSB-Host headers */
    #include "USBH.h"
    #include "USBH_HID.h"
    /* Include FreeRTOS headers */
    #include "FreeRTOS.h"
    #include "task.h"
    #include "event_groups.h"
  2. Define the RTOS memory parameters and event bits for the mouse and keyboard HID events.
    #define USB_MAIN_TASK_MEMORY_REQ (500U)
    #define USB_ISR_TASK_MEMORY_REQ (500U)
    #define PRINT_TASK_MEMORY_REQ (500U)
    /* Event bits for HID events */
    #define USB_TRIGGER_MOUSE_MESSAGE (0x1U)
    #define USB_TRIGGER_KEYBOARD_MESSAGE (0x2U)
  3. Add a keyboard code array to connect to the keyboard:
    /* Keyboard code array */
    static const char* key_string[] =
    {
    "Reserved/(no event indicated)",
    "Key ErrorRollOver ",
    "Key POSTFail ",
    "Key ErrorUndefined ",
    "Key a/A ",
    "Key b/B ",
    "Key c/C ",
    "Key d/D ",
    "Key e/E ",
    "Key f/F ",
    "Key g/G ",
    "Key h/H ",
    "Key i/I ",
    "Key j/J ",
    "Key k/K ",
    "Key l/L ",
    "Key m/M ",
    "Key n/N ",
    "Key o/O ",
    "Key p/P ",
    "Key q/Q ",
    "Key r/R ",
    "Key s/S ",
    "Key t/T ",
    "Key u/U ",
    "Key v/V ",
    "Key w/W ",
    "Key x/X ",
    "Key y/Y ",
    "Key z/Z ",
    "Key 1/! ",
    "Key 2/@ ",
    "Key 3/# ",
    "Key 4/$ ",
    "Key 5/% ",
    "Key 6/^ ",
    "Key 7/& ",
    "Key 8/* ",
    "Key 9/( ",
    "Key 0/) ",
    "Key Return (ENTER) ",
    "Key ESCAPE ",
    "Key DELETE(Backspace) ",
    "Key Tab ",
    "Key Spacebar ",
    "Key -/(underscore) ",
    "Key =/+ ",
    "Key [/{ ",
    "Key ]/} ",
    "Key \\/| ",
    "Key Non-US #/~ ",
    "Key ;/: ",
    "Key Apostrophe/Quotation mark",
    "Key GraveAccent/Tilde ",
    "Key,/< ",
    "Key ./> ",
    "Key //? ",
    "Key Caps Lock ",
    "Key F1 ",
    "Key F2 ",
    "Key F3 ",
    "Key F4 ",
    "Key F5 ",
    "Key F6 ",
    "Key F7 ",
    "Key F8 ",
    "Key F9 ",
    "Key F10 ",
    "Key F11 ",
    "Key F12 ",
    "Key PrintScreen ",
    "Key Scroll Lock ",
    "Key Pause ",
    "Key Insert ",
    "Key Home ",
    "Key PageUp ",
    "Key Delete Forward ",
    "Key End ",
    "Key PageDown ",
    "Key RightArrow ",
    "Key LeftArrow ",
    "Key DownArrow ",
    "Key UpArrow ",
    "Keypad NumLock/Clear ",
    "Keypad / ",
    "Keypad * ",
    "Keypad - ",
    "Keypad + ",
    "Keypad ENTER ",
    "Keypad 1/End ",
    "Keypad 2/Down Arrow ",
    "Keypad 3/PageDn ",
    "Keypad 4/Left Arrow ",
    "Keypad 5 ",
    "Keypad 6/Right Arrow ",
    "Keypad 7/Home ",
    "Keypad 8/Up Arrow ",
    "Keypad 9/PageUp ",
    "Keypad 0/Insert ",
    "Keypad ./Delete ",
    "Key Non-US \\/| ",
    "Key Application ",
    "Key Power ",
    "Keypad = ",
    "Key F13 ",
    "Key F14 ",
    "Key F15 ",
    "Key F16 ",
    "Key F17 ",
    "Key F18 ",
    "Key F19 ",
    "Key F20 ",
    "Key F21 ",
    "Key F22 ",
    "Key F23 ",
    "Key F24 ",
    "Key Execute ",
    "Key Help ",
    "Key Menu ",
    "Key Select ",
    "Key Stop ",
    "Key Again ",
    "Key Undo ",
    "Key Cut ",
    "Key Copy ",
    "Key Paste ",
    "Key Find ",
    "Key Mute ",
    "Key Volume Up ",
    "Key Volume Down ",
    "Key Locking CapsLock ",
    "Key Locking NumLock ",
    "Key Locking ScrollLock ",
    "Keypad Comma ",
    "Keypad Equal Sign ",
    "Key International1 ",
    "Key International2 ",
    "Key International3 ",
    "Key International4 ",
    "Key International5 ",
    "Key International6 ",
    "Key International7 ",
    "Key International8 ",
    "Key International9 ",
    "Key LANG1 ",
    "Key LANG2 ",
    "Key LANG3 ",
    "Key LANG4 ",
    "Key LANG5 ",
    "Key LANG6 ",
    "Key LANG7 ",
    "Key LANG8 ",
    "Key LANG9 ",
    "Key Alternate Erase ",
    "Key SysReq/Attention ",
    "Key Cancel ",
    "Key Clear ",
    "Key Prior ",
    "Key Return ",
    "Key Separator ",
    "Key Out ",
    "Key Oper ",
    "Key Clear/Again ",
    "Key CrSel/Props ",
    "Key ExSel ",
    "Keypad 00 ",
    "Keypad 000 ",
    "Thousands Separator ",
    "Decimal Separator ",
    "Currency Unit ",
    "Currency Sub-unit ",
    "Keypad ( ",
    "Keypad ) ",
    "Keypad { ",
    "Keypad } ",
    "Keypad Tab ",
    "Keypad Backspace ",
    "Keypad A ",
    "Keypad B ",
    "Keypad C ",
    "Keypad D ",
    "Keypad E ",
    "Keypad F ",
    "Keypad XOR ",
    "Keypad ^ ",
    "Keypad % ",
    "Keypad < ",
    "Keypad > ",
    "Keypad & ",
    "Keypad && ",
    "Keypad | ",
    "Keypad || ",
    "Keypad : ",
    "Keypad # ",
    "Keypad Space ",
    "Keypad @ ",
    "Keypad ! ",
    "Keypad Memory Store ",
    "Keypad Memory Recall ",
    "Keypad Memory Clear ",
    "Keypad Memory Add ",
    "Keypad Memory Subtract ",
    "Keypad Memory Multiply ",
    "Keypad Memory Divide ",
    "Keypad +/- ",
    "Keypad Clear ",
    "Keypad Clear Entry ",
    "Keypad Binary ",
    "Keypad Octal ",
    "Keypad Decimal ",
    "Keypad Hexadecimal ",
    "Key LeftControl ",
    "Key LeftShift ",
    "Key LeftAlt ",
    "Key Left GUI ",
    "Key RightControl ",
    "Key RightShift ",
    "Key RightAlt ",
    "Key Right GUI "
    };
    Add the mouse code to connect to the mouse:
    /* Mouse code array */
    static const char* btnState_string[] =
    {
    "No click",
    "Left Button click",
    "Right Button click",
    "Reserved/(no event indicated)",
    "While Button click"
    };
  4. Create a structure prototype for tracking the status of keyboard and mouse events.
    typedef struct usb_hid_status
    {
    USBH_HID_MOUSE_DATA mouse_data;
    USBH_HID_KEYBOARD_DATA keyboard_data;
    } usb_hid_status_t;
  5. Declare the emUSB-Host HID global variables
    /***************************************
    * Global Variables
    ****************************************/
    static USBH_NOTIFICATION_HOOK usbh_hid_notification;
    static uint32_t usbh_not_used_context;
    /* Declare a variable to hold the created event group. */
    static EventGroupHandle_t hid_event;
    /* The custom variable to save the status of events */
    static usb_hid_status_t usb_hid_status;
  6. Add functions for two mandatory tasks for the emUSB-Host functionality:
    /*******************************************************************************
    * Function Name: usbh_task_free_rtos
    ********************************************************************************
    * Summary:
    * USBH_Task calling.
    *
    * \param arg is not used in this function but required by FreeRTOS.
    *
    *******************************************************************************/
    static void usbh_task_free_rtos(void* arg)
    {
    (void)arg;
    USBH_Task();
    for (;;)
    {
    USBH_Logf_Application("Error: USBH_Task() end execution\n\r");
    }
    }
    /*******************************************************************************
    * Function Name: usbh_isr_task_free_rtos
    ********************************************************************************
    *
    * USBH_ISRTask calling.
    *
    * \param arg is not used in this function but required by FreeRTOS.
    *
    *******************************************************************************/
    static void usbh_isr_task_free_rtos(void* arg)
    {
    (void)arg;
    USBH_ISRTask();
    for (;;)
    {
    USBH_Logf_Application("Error: USBH_ISRTask() end execution\n\r");
    }
    }
  7. Create a callback function for the device Add/Remove notification:
    /*******************************************************************************
    * Function Name: new_device_notify
    ********************************************************************************
    *
    * Callback function implementation. Informs when a device is added or removed.
    *
    *******************************************************************************/
    static void new_device_notify(void* pContext, U8 DevIndex, USBH_DEVICE_EVENT Event)
    {
    (void)pContext;
    switch (Event)
    {
    case USBH_DEVICE_EVENT_ADD:
    USBH_Logf_Application("Device added [%d]", DevIndex);
    break;
    case USBH_DEVICE_EVENT_REMOVE:
    USBH_Logf_Application("Device removed [%d]", DevIndex);
    break;
    default:
    USBH_Logf_Application("Invalid event [%d]", DevIndex);
    break;
    }
    }
  8. Add callback functions for tracking the status of mouse and keyboard events:
    /*******************************************************************************
    * Function Name: mouse_event
    ********************************************************************************
    *
    * Callback function implementation. Saves the statuses of mouse events.
    *
    *******************************************************************************/
    static void mouse_event(USBH_HID_MOUSE_DATA* pMouseData)
    {
    usb_hid_status.mouse_data.xChange = pMouseData->xChange;
    usb_hid_status.mouse_data.yChange = pMouseData->yChange;
    usb_hid_status.mouse_data.WheelChange = pMouseData->WheelChange;
    usb_hid_status.mouse_data.ButtonState = pMouseData->ButtonState;
    usb_hid_status.mouse_data.InterfaceID = pMouseData->InterfaceID;
    (void)xEventGroupSetBits(hid_event, USB_TRIGGER_MOUSE_MESSAGE);
    }
    /*******************************************************************************
    * Function Name: keyword_event
    ********************************************************************************
    *
    * Callback function implementation. Saves the statuses of mouse events.
    *
    *******************************************************************************/
    static void keyword_event(USBH_HID_KEYBOARD_DATA* pKeyData)
    {
    usb_hid_status.keyboard_data.Code = pKeyData->Code;
    usb_hid_status.keyboard_data.Value = pKeyData->Value;
    usb_hid_status.keyboard_data.InterfaceID = pKeyData->InterfaceID;
    (void)xEventGroupSetBits(hid_event, USB_TRIGGER_KEYBOARD_MESSAGE);
    }
  9. Create a function for printing mouse and keyboard events tasks:
    /*******************************************************************************
    * Function Name: print_message
    ********************************************************************************
    *
    * Prints a message when a mouse or keyboard event happens.
    *
    * \param arg is not used in this function but required by FreeRTOS.
    *
    *******************************************************************************/
    static void print_message(void* arg)
    {
    (void)arg;
    EventBits_t uxBits;
    for (;;)
    {
    /* Gets the event group value */
    uxBits = xEventGroupWaitBits(hid_event,
    USB_TRIGGER_MOUSE_MESSAGE | USB_TRIGGER_KEYBOARD_MESSAGE, true,
    false, portMAX_DELAY);
    if ((uxBits & USB_TRIGGER_MOUSE_MESSAGE) == USB_TRIGGER_MOUSE_MESSAGE)
    {
    USBH_Logf_Application("Mouse event:");
    /* Prints mouse data */
    USBH_Logf_Application(
    "X change - %d\n\rY change - %d\n\rWheel change - %d\n\rButton state - %d\n\rInterface ID - %d",
    usb_hid_status.mouse_data.xChange,
    usb_hid_status.mouse_data.yChange,
    usb_hid_status.mouse_data.WheelChange,
    usb_hid_status.mouse_data.ButtonState,
    usb_hid_status.mouse_data.InterfaceID);
    /* Prints mouse buttons state */
    USBH_Logf_Application("The button - %s\n\r", btnState_string[usb_hid_status.mouse_data.ButtonState]);
    }
    else if ((uxBits & USB_TRIGGER_KEYBOARD_MESSAGE) == USB_TRIGGER_KEYBOARD_MESSAGE)
    {
    USBH_Logf_Application("Keyboard event:");
    /* Prints keyboard data */
    USBH_Logf_Application("Code -- %d, Value - %d, Interface ID - %d",
    usb_hid_status.keyboard_data.Code,
    usb_hid_status.keyboard_data.Value,
    usb_hid_status.keyboard_data.InterfaceID);
    if (usb_hid_status.keyboard_data.Code > sizeof(key_string) / sizeof(char*))
    {
    USBH_Logf_Application("The key - Invalid code\n\r");
    }
    else
    {
    /* Prints the character of pressed key */
    USBH_Logf_Application("The key - %s\n\r", key_string[usb_hid_status.keyboard_data.Code]);
    }
    }
    }
    }
  10. Create a main_task() function:
    /*******************************************************************************
    * Function Name: main_task
    ********************************************************************************
    *
    * Initializes the emUSB-Host stack, registers all necessary tasks.
    *
    * \param arg is not used in this function but required by FreeRTOS.
    *
    *******************************************************************************/
    void main_task(void* arg)
    {
    (void)arg;
    retarget_io_init();
    /* Initializes the USBH stack */
    USBH_Init();
    /* Creates the two tasks mandatory for USBH operation */
    /* Creates a task for USBH_ISR() function */
    xTaskCreate(usbh_isr_task_free_rtos,
    "usbh_isr_task_free_rtos",
    USB_ISR_TASK_MEMORY_REQ,
    NULL,
    configMAX_PRIORITIES - 1,
    NULL);
    /* Creates a task for USBH_Task() function */
    xTaskCreate(usbh_task_free_rtos,
    "usbh_task_free_rtos",
    USB_MAIN_TASK_MEMORY_REQ,
    NULL,
    configMAX_PRIORITIES - 2,
    NULL);
    /* Creates an additional task for printing message */
    xTaskCreate(print_message,
    "print_message",
    PRINT_TASK_MEMORY_REQ,
    NULL,
    configMAX_PRIORITIES - 3,
    NULL);
    /* Creates an event group for printing message */
    hid_event = xEventGroupCreate();
    /* Check if event is created */
    CY_ASSERT(hid_event != NULL);
    /* Initializes the HID classes */
    USBH_HID_Init();
    /* Add callback functions for
    * - The HID devices are connected event
    * - The mouse state change event
    * - The keyboard state change event
    */
    /* Adds callback function for HID devices are connected event */
    USBH_HID_AddNotification(&usbh_hid_notification,
    new_device_notify,
    (void*)&usbh_not_used_context);
    /* Adds callback function for mouse state change event */
    USBH_HID_SetOnMouseStateChange(mouse_event);
    /* Adds callback function for keyboard state change event */
    USBH_HID_SetOnKeyboardStateChange(keyword_event);
    for (;;)
    {
    vTaskDelay(1000U);
    }
    }
  11. Initialize retarget-io to use the debug UART port:

    For PSE84 devices: Open the Device Configurator, select the Peripherals tab and the desired SCB resource (#1.1), UART under Personality (#1.2), click OK (#1.3).

    Select the desired name for the SCB (#2.1) and pins and clock for SCB (#2.2). The other UART options can be set by default, see the screenshot below.

    The desired name for the SCB resource is important because the generated structures, defines, and variables bear the name prefix as you can see below:

    static void retarget_io_init(void)
    {
    cy_rslt_t result;
    static cy_stc_scb_uart_context_t CYBSP_DEBUG_UART_context;
    static mtb_hal_uart_t CYBSP_DEBUG_UART_hal_obj;
    result = (cy_rslt_t)Cy_SCB_UART_Init(CYBSP_DEBUG_UART_HW, &CYBSP_DEBUG_UART_config, &CYBSP_DEBUG_UART_context);
    if (result != CY_RSLT_SUCCESS)
    {
    CY_ASSERT(0);
    }
    Cy_SCB_UART_Enable(CYBSP_DEBUG_UART_HW);
    result = mtb_hal_uart_setup(&CYBSP_DEBUG_UART_hal_obj, &CYBSP_DEBUG_UART_hal_config, &CYBSP_DEBUG_UART_context, NULL);
    if (result != CY_RSLT_SUCCESS)
    {
    CY_ASSERT(0);
    }
    result = cy_retarget_io_init(&CYBSP_DEBUG_UART_hal_obj);
    if (result != CY_RSLT_SUCCESS)
    {
    CY_ASSERT(0);
    }
    }
  12. Create a FreeRTOS task of the main_task() function into main():
    /* Creates a FreeRTOS task of the main_task() function */
    xTaskCreate(main_task, "main_task", 500U, NULL, configMAX_PRIORITIES - 1, NULL);
    vTaskStartScheduler();

STEP 4: Check the emUSB-Host workability.

  1. Build and program your project.
  2. Open the terminal and set baud rate 115200.
  3. Connect the mouse or keyboard to the USB-Host connector of the board and observe log-messages of the HID device status.

Configuration Considerations

This section explains the details of the emUSB-Host configuration.

Hardware-dependent Configuration

The hardware resources (Pins, clocks, interrupts) required for USB must be configured before the start of USB operation before calling USBH_Init() or in USBH_X_Config(). Interrupts must be configured in the USBH_X_Config() function.

For PSE84 devices, the USB hardware does not control the power on VBUS line. This feature is essential for some cases, so, the appropriate logic should be implemented on the Application side. For some evaluation boards, this logic is already implemented - typically, an additional MCU pin controls VBUS power. To allow emUSB-Host control power (enable or disable) on VBUS line, register a callback function by USBH_SetOnSetPortPower().

The implementation template of USBH_X_Config() is provided for each device category in the Config directory under COMPONENT_CATx. This template is automatically copied into your project when middleware is added to project. This template does not include the configuration of clock and pins required for USB operation.

The template file define USBH_ALLOC_SIZE macro for the size of the memory pool. The size of memory is selected to satisfy RAM usage of Driver and a few connected devices, to provide the best experience for running code examples and evaluating the emUSB-Host software for the widest range of boards. Update this value with the optimal memory pool size (strongly recommended) for the application to find the balance between the memory consumption and features support. For details on selecting the optimal memory pool size, refer to the SEGGER emUSB-Host User Guide & Reference Manual Memory pools chapter.

Warning
For PSE84, the template file also configures a pin responsible for enabling/disabling power to connected USB devices by the VBUS line. The default value of the pin number is selected only for the KIT_PSE84_EVK (PSE84) and must be modified for other boards.

For details on Hardware Dependent Configuration, refer to the - SEGGER emUSB-Host User Guide & Reference Manual.

USB Pins Configuration

PSE84 Devices

The D+/D- pins are dedicated and do not require configuration.

USB Clock Configuration

The USB 2.0 specification defines the required bit rate accuracy for the USB Host in section 7.1.11. Ensure that the clock sources for USB meet the requirements.

The emUSB-Host/Device personality in the Device Configurator allows for easy configuration of the clocks for USB operation and also check if the clocks meet the requirements. Otherwise, the clocks can be configured manually by PDL/HAL Next APIs.

PSE84 Devices

The USB Host requires two clocks for operation:

  • Phy Pll reference clock configured at 50 MHz with the required bit rate accuracy according to the USB 2.0 specification. Typically, this clock is the CLK_HF8 output signal, but refer to the device datasheet to identify the clock source for USB for a specific device.
  • The main clock configured at 400 MHz. This clock does not have requirements for the bit rate accuracy. Typically, this clock is the CLK_HF1 output signal, but refer to the device datasheet to identify the clock source for USB for a specific device. In addition, set to 4 the Divider of Peri 1 Group 3 to generate 100 MHz signal after CLK_HF1 for the USB controller.

Also, enable the corresponding Peri Group by the Cy_SysClk_PeriGroupSlaveInit() function from the SysClk driver of mtb-device-support-pse8xxgp.

Note
If the USB must operate during Deep Sleep, keep both clocks enabled.

USB Interrupt Configuration

The interrupt is mandatory for the emUSB-Host Middleware operation. The interrupt priority selection is a part of Application level - the interrupt priority selected in the template files is not suitable for real project. For USB recommended setting the interrupt priority as high as possible.

PSE84 Devices

emUSB-Host uses one interrupt source - usbhs_interrupt_usbhsctrl_IRQn. The emUSB-Host can be executed on the CM33 or CM55 core. The interrupt configuration is the same for both cores.

The following code snippet shows the interrupt configuration for PSE84 devices:

/* Define the interrupt priority */
#define USBH_ISR_PRIO (3U)
/* USB Interrupt handler */
static void isr(void)
{
USBH_ServiceISR(0);
}
static void config_interrupt_pse84(void)
{
/* Install the interrupt service routine */
cy_stc_sysint_t usb_int_cfg =
{
.intrSrc = usbhs_interrupt_usbhsctrl_IRQn,
.intrPriority = USBH_ISR_PRIO
};
cy_en_sysint_status_t status;
/* Install the interrupt service routine */
status = Cy_SysInt_Init(&usb_int_cfg, isr);
CY_ASSERT(CY_RSLT_SUCCESS == status);
(void) status; /* To avoid the compiler warning in Release mode */
/* Enable USB interrupt */
NVIC_EnableIRQ(usbhs_interrupt_usbhsctrl_IRQn);
}

Debug Message Output

The debug builds of emUSB-Host allow using the debug message outputs. The template implementation of the message output functions is in export/Config/usbh_config_io.c file. This file is automatically copied into the ModusToolbox project when emUSB-Device middleware is added for the first time by the Library manager. Otherwise, copy this file manually. By default, retarget-io is used for the message output, but message outputs can be redefined to any suitable output way. To disable the default message outputs, set USBH_DISABLE_STANDARD_OUTPUT=1 in the DEFINES variable in the application project Makefile. To provide a custom output method in addition to setting a variable add corresponding API under the #if (USBH_DISABLE_STANDARD_OUTPUT == 1U) condition inside the _puts() function.

For details on Hardware Debug Message Output, refer to the - SEGGER emUSB-Host User Guide & Reference Manual Debugging chapter.

Note
The retarget-io Middleware must be configured outside of the emUSB-Host Middleware for the message output. Refer to the retarget-io Quick Start.

Low Power Support

Typically, RTOS goes to Idle state when no active tasks remain active. Often, the transition into Idle state is accompanied by entering the microcontroller in one of low-power modes (Depends on RTOS configuration). If the USB IP block does not support operation in some of the low-power modes, the emUSB-Host stack must be shut down by the USBH_Exit() function before entering this mode, and after exiting, emUSB-Host must be completely reinitialized by the application.

Supported power modes by the Device family

Device familyIP block power modes support
PSE84 Active and Sleep

PSE84 Devices The USB IP block operates in Active and Sleep modes without any limitations, but in Deep Sleep, the USB IP block is disabled. emUSB-Host does not support any operations in low-power modes, in which the USB IP block is disabled. Also, emUSB-Host does not support the preparing and restoring before/after low-power modes, in which the USB IP block is disabled. As a result, if the microcontroller goes into Deep Sleep, emUSB-Host must be shut down by the USBH_Exit() function before entering this mode, and after exiting, emUSB-Host must be reinitialized.

The Suspended/Resume condition generation from emUSB-Host

emUSB-Host can generate the Suspend/Resume condition for any connected device (directly or through the HUB). For more details, refer to the SEGGER emUSB-Host User Guide & Reference Manual by keywords Suspend or Resume.

Picking an emUSB-Host Library Variant

The Middleware provides emUSB-Host as pre-build libraries. The pre-build libraries are selected automatically based on configurations of Makefile configurations. The table below shows the availability of the configuration options.

ConfigurationOptionsMake Variable
Device family PSE84 COMPONENTS
Build configuration Debug, Release CONFIG
Core
  • CM33, CM55 for PSE84;
CORE
Floating point hardfp, softfp VFP_SELECT
Toolchain GCC_ARM, IAR, ARM, LLVM-ARM TOOLCHAIN
Note
Typically, the device family and core are selected in BSP Makefile.
CM55 LLVM-ARM supports only hardfp.

The header file USBH_ConfDefaults.h under the USBH directory contains common configuration used in the libraries generation. Similarly, USBH_Conf.h under each COMPONENT_<Device family>/CONFIG_< Build configuration> directory contains configuration specific to the set of library variants.

Integration with emFile

The MSD class is supplied with already implemented interface for emFile. To enable this interface, provide the address of the USBH_MSD_FS_Driver structure to the FS_AddDevice() function. The implementation of USBH_MSD_FS_Driver is present in additional pre-build libraries. By default, these libraries are not added to the build, so, to enable them - add USBH_EMFILE to the COMPONENTS variable in Makefile. The additional pre-build libraries with emFile interface support the three different FAT sub types: FAT12, FAT16 and FAT32. The selection of a specific FAT type is the same as for the emFile middleware - add EMFILE_FAT16 for FAT12/16 or EMFILE_FAT32 for supporting all three sub types to the COMPONENTS variable in Makefile.

Using emUSB-Host in an RTOS Environment

The emUSB-Host has been already implemented the Target OS Interface. The OS layer uses the abstraction-rtos library, so, emUSB-Device can be used with RTOSes supported by the abstraction-rtos library.

USBH_OS_DisableInterrupt() and USBH_OS_EnableInterrupt() are the weak functions. The weak implementation of USBH_OS_DisableInterrupt() and USBH_OS_EnableInterrupt() uses the enter/exit critical section functions from mtb-dsl-pse8xxgp libraries. The implementation of USBH_OS_DisableInterrupt() and USBH_OS_EnableInterrupt() may by overridden in the user's code by providing a function with the same name. This allows you to provide a custom implementation that can better satisfy application requirements, for example doesn't disable all interrupts.

Note
The USBH_OS_DisableInterrupt() and USBH_OS_EnableInterrupt() functions must always disable the USB interrupts and task switching.

The emUSB-Host middleware calls some functions of the OS layer from the USB interrupt. As a result, the USB interrupt priority must be aligned with the RTOS configuration. For example, for FreeRTOS, the USB interrupt must have a lower or equal priority to the MAX_API_CALL_INTERRUPT_PRIORITY macro.

Note
The emUSB-Host operation requires the RTOS.

emUSB-Host Package Structure

The Middleware structure:

  • export/Config: Contains sample configuration files for hardware-specific configuration.
  • OS: Contains the OS layer implementation.
  • USBH: Contains a set of pre-build emUSB-Host libraries for different configurations of user applications (Device family, Build configuration, Core, Floating point, Toolchain), and a set of header files.
  • docs: Contains the API Reference Guide, SEGGER-provided emUSB-Host User Guide & Reference Manual and other supporting documentation.

Changelog

Note
The emUSB-Host Middleware by Infineon and emUSB-Host stack by Segger have different versions.
VersionChangesReason for Change
2.1.0
  • Updated the emUSB-Host stack to 2.48.0.
  • New version is available
2.0.0
  • Added LLVM compiler support.
  • Migrated to HAL-Next.
  • Updated the emUSB-Host stack to 2.42.1
  • Extending the supported features for emUSB-Device middleware
  • New version is available
1.4.0
  • Add the interface for emFile implemented by MSD class APIs. For more details, refer to the Integration with emFile.
  • Updated the emUSB-Host stack to 2.42.0
  • New version is available
1.3.0
  • Add OTG support for XMC4000 devices
  • Add new driver for PSoC 6 with DMA support
  • Updated the emUSB-Host stack to 2.40.0
  • Minor documentation updates
  • New version is available
1.2.1
  • Fixed the build warning in the OS layer, which was caused by the indirect including the xmc_common.h header file
  • Bug fixing
1.2.0
  • Provided support for XMC4000 devices.
  • Updated the emUSB-Host stack to 2.36.3
  • Minor documentation updates
  • New version is available
1.1.0
  • Updated the emUSB-Host stack to 2.36.1
  • The OS layer uses abstraction-rtos APIs instead of FreeRTOS. This means that emUSB-Device can be used with RTOS supported by abstraction-rtos included FreeRTOS
  • Added the functionality in the usbh_config.c file to control enabling/disabling power on VBUS line
  • Updated the implementation of Debug Message Output. The usbh_config_io.c file became more friendly for updating and a USBH_DISABLE_STANDARD_OUTPUT macro was added. For details, refer to Debug Message Output
  • Minor documentation updates
  • New version is available
  • Extend the number of supported RTOS
  • The changes allow to support the correct reinitialization of emUSB-Host
  • Improved the usability of Debug Message Output
1.0.1
  • Updating the LICENSE file
1.0.0
  • Initial release of emUSB-Host stack 2.36.0