Implementation of Dual USB Host on RT1060 EVK

cancel
Showing results for 
Search instead for 
Did you mean: 

Implementation of Dual USB Host on RT1060 EVK

No ratings

Implementation of Dual USB Host on RT1060 EVK

Introduction

NXP i.MXRT106x has two USB2.0 OTG instance. And the RT1060 EVK has both of the USB interface on the board. But the RT1060 SDK only has single USB host example. Although RT1060’s USB host stack support multiple devices, but we still need a USB HUB when user want to connect two device. This article will show you how to make both USB instance as host.

RT1060 SDK has single host examples which support multiple devices, like host_hid_mouse_keyboard_bm. But this application don’t use these examples. Instead, MCUXpresso Config Tools is used to build the demo from beginning. The config tool is a very powerful tool which can configure clock, pin and peripherals, especially the USB. In this application demo, it can save 95% coding work.

Hardware and software tools

RT1060 EVK

MCUXpresso 11.4.0

MIMXRT1060 SDK 2.9.1

Step 1

This project will support USB HID mouse and USB CDC. First, create an empty project named MIMXRT1062_usb_host_dual_port. When select SDK components, select “USB host CDC” and “”USB host HID” in Middleware label. IDE will select other necessary component automatically.

jingpan_0-1628590034278.png

 

 

After creating the empty project, clock should be configured first. Both of the USB PHY need 480M clock.

jingpan_1-1628590034307.png

 

Step 2

Next step is to configure USB host in peripheral config tool. Due to the limitation of config tool, only one host instance of the USB component is allowed. In this project, CDC VCOM is added first.

jingpan_2-1628590034383.png

 

Step 3

After these settings, click “Update Code” in control bar. This will turn all the configurations into code and merge into project.

Then click the “copy to clipboard” button. This will copy the host task call function. Paste it in the forever while loop in the project’s main(). Besides that, it also need to add BOARD_InitBootPeripherals() function call in main().

At this point, USB VCOM is ready. The tool will not only copy the file and configure USB, but also create basic implementation framework. If compile and download the project to RT1060 EVK, it can enumerate a USB CDC VCOM device on USB1. If characters are send from CDC device, the project can send it out to DAPLink UART port so that you can see the character on a terminal interface in computer.

Step 4

To get USB HID mouse code, it need to create another USB HID project. The workflow is similar to the first project. Here is the screenshot of the USB HID configuration.

jingpan_3-1628590034427.png

 

Click “Update code”, the HID mouse code will be generated. The config tool generate two files, usb_host_interface_0_hid_mouse.c and usb_host_interface_0_hid_mouse. Copy them to the “source” folder in dual host project.

jingpan_4-1628590034502.png

 

 

Step 5

Next step is to modify some USB macro definitions.

<usb_host_config.h>

#define USB_HOST_CONFIG_EHCI 2   /*means there are two host instance*/
#define USB_HOST_CONFIG_MAX_HOST 2  /*The USB driver can support two ehci*/
#define USB_HOST_CONFIG_HID (1U)     /*for mouse*/

Next step is merge usb_host_app.c. The project initialize USB hardware and software in USB_HostApplicationInit().

usb_status_t USB_HostApplicationInit(void)
{
    usb_status_t status;

    USB_HostClockInit(kUSB_ControllerEhci0);
    USB_HostClockInit(kUSB_ControllerEhci1);  

#if ((defined FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT))
    SYSMPU_Enable(SYSMPU, 0);
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */

    status = USB_HostInit(kUSB_ControllerEhci0, &g_HostHandle[0], USB_HostEvent);
    status = USB_HostInit(kUSB_ControllerEhci1, &g_HostHandle[1], USB_HostEvent);  /*each usb instance have a g_HostHandle*/ 
    if (status != kStatus_USB_Success)
    {
        return status;
    } else {
        USB_HostInterface0CicVcomInit();
        USB_HostInterface0HidMouseInit();
    }
    USB_HostIsrEnable();

    return status;
}

In USB_HostIsrEnable(), add code to enable USB2 interrupt.  

    irqNumber = usbHOSTEhciIrq[1];
    NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY);
    EnableIRQ((IRQn_Type)irqNumber);

Then add and modify USB interrupt handler.

void USB_OTG1_IRQHandler(void)
{
    USB_HostEhciIsrFunction(g_HostHandle[0]);
}

void USB_OTG2_IRQHandler(void)
{
    USB_HostEhciIsrFunction(g_HostHandle[1]);
}

Since both USB instance share the USB stack, When USB event come, all the event will call USB_HostEvent() in usb_host_app.c. HID code should also be merged into this function.

static usb_status_t USB_HostEvent(usb_device_handle deviceHandle,
                                  usb_host_configuration_handle 
                                  configurationHandle,
                                  uint32_t eventCode)
{
    usb_status_t status1;
    usb_status_t status2;
    usb_status_t status = kStatus_USB_Success;

    /* Used to prevent from multiple processing of one interface;
     * e.g. when class/subclass/protocol is the same then one interface on a device is processed only by one interface on host */

    uint8_t processedInterfaces[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE] = {0};

    switch (eventCode & 0x0000FFFFU)
    {
        case kUSB_HostEventAttach:
            status1 = USB_HostInterface0CicVcomEvent(deviceHandle, 
                      configurationHandle, eventCode, processedInterfaces);
            status2 = USB_HostInterface0HidMouseEvent(deviceHandle, 
                      configurationHandle, eventCode, processedInterfaces);
            if ((status1 == kStatus_USB_NotSupported) && (status2 == 
                  kStatus_USB_NotSupported))
            {
                status = kStatus_USB_NotSupported;
            }
            break;

        case kUSB_HostEventNotSupported:
            usb_echo("Device not supported.\r\n");
            break;

        case kUSB_HostEventEnumerationDone:
            status1 = USB_HostInterface0CicVcomEvent(deviceHandle, 
                      configurationHandle, eventCode, processedInterfaces);
            status2 = USB_HostInterface0HidMouseEvent(deviceHandle, 
                      configurationHandle, eventCode, processedInterfaces);
            if ((status1 != kStatus_USB_Success) && (status2 != kStatus_USB_Success))
            {
                status = kStatus_USB_Error;
            }
            break;

        case kUSB_HostEventDetach:
            status1 = USB_HostInterface0CicVcomEvent(deviceHandle, 
                      configurationHandle, eventCode, processedInterfaces);
            status2 = USB_HostInterface0HidMouseEvent(deviceHandle, 
                      configurationHandle, eventCode, processedInterfaces);
            if ((status1 != kStatus_USB_Success) && (status2 != 
                 kStatus_USB_Success))
            {
                status = kStatus_USB_Error;
            }
            break;

        case kUSB_HostEventEnumerationFail:
            usb_echo("Enumeration failed\r\n");
            break;

        default:
            break;
    }
    return status;
}

USB_HostTasks() is used to deal with all the USB messages in the main loop. At last, HID work should also be added in this function.

void USB_HostTasks(void)
{
    USB_HostTaskFn(g_HostHandle[0]);
    USB_HostTaskFn(g_HostHandle[1]);

    USB_HostInterface0CicVcomTask();
    USB_HostInterface0HidMouseTask();
}

 

After all these steps, the dual USB function is ready. User can insert USB mouse and USB CDC device into any of the two USB port simultaneously.

Conclusion

All the RT/LPC/Kinetis devices with two OTG or HOST can support dual USB host. With the help of MCUXpresso Config Tool, it is easy to implement this function.

Labels (2)
Attachments
Comments

Hello @jingpan ,

 

Customer trying to use USB examp0le to set the USB#1 as host and USB#2 as device. While selecting the components in the Step 1, choose FreeRTOS instead of bare metal. In step 2 while choosing the preset its showing only the HID keyboard(baremetal) option and there is no option to choose the preset with the FreeRTOS support. Is it designed that way? How do to change  to support FreeRTOS?

Also, while selecting the clock in step 1, when I enable the clock for USBPHY2_CLK, it gets set to 24 MHz. Is that ok?

 

Appreciate your advice.

 

Regards,

Audrey

 

 

Hi,

I took a try. It seems no problem...   IDE11.4 + SDK2.9.1

USBPHY2_CLK should also be 480M.

Regards,

Jing

Version history
Revision #:
2 of 2
Last update:
‎08-10-2021 07:23 PM
Updated by: