USB re-enumeration

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

USB re-enumeration

Jump to solution
4,001 Views
emblink182
Contributor III

Hi, I have a question about USB HS enumeration on LPC54605J512 MCU.

I need to change the polling rate of the USB device in runtime. In order to do that I need to force the host to re-enumerate the device. I have tried to call USB_DeviceStop() and USB_DeviceRun() right after, but most of the time device fails to enumerate. Reboot MCU and start with a new configuration is not an option for my particular case.

Is there any way to do that with USB stack functions or maybe manual registers settings?

Labels (3)
0 Kudos
1 Solution
3,806 Views
emblink182
Contributor III

Solved this problem by adding a custom notification and device event.

notification.png

event.png

Add a case kUSB_DeviceNotifyRestart in USB_DeviceNotification and call 

USB_DeviceRestartNotification from there.
device callback.png

Eventually, USB_DeviceCallback gets called with event param kUSB_DeviceEventRestart from USB task context.

device callback event.png
usb restart.png
 
sendUsbRestartCommand  called manually from other task context and pushes re-enumeration notification to the internal queue.

func.png

This code is not breaking the internal queue of the driver.

Re enumeration worked fine after that. 

View solution in original post

0 Kudos
6 Replies
3,807 Views
emblink182
Contributor III

Solved this problem by adding a custom notification and device event.

notification.png

event.png

Add a case kUSB_DeviceNotifyRestart in USB_DeviceNotification and call 

USB_DeviceRestartNotification from there.
device callback.png

Eventually, USB_DeviceCallback gets called with event param kUSB_DeviceEventRestart from USB task context.

device callback event.png
usb restart.png
 
sendUsbRestartCommand  called manually from other task context and pushes re-enumeration notification to the internal queue.

func.png

This code is not breaking the internal queue of the driver.

Re enumeration worked fine after that. 

0 Kudos
3,946 Views
belmontbob59
Contributor IV

The call to NVIC_ClearPendingIRQ(USB1_IRQn);  is invalid after the call to USB_DeviceClassInit() because you are messing up with lpcip3511.c workflow at that point.

0 Kudos
3,938 Views
emblink182
Contributor III

And what's really strange that usb_echo("usbReEnumerate\r\n"); line fixes this issue. I can't explain this phenomenon.

0 Kudos
3,941 Views
emblink182
Contributor III

I ran this code on a non-RTOS example and it works fine. I also tried not to call NVIC_ClearPendingIRQ(USB1_IRQn); in the RTOS example but the behavior didn't change.

0 Kudos
3,960 Views
belmontbob59
Contributor IV

What I do to re-enumerate w/o MCU reset (USB0 or USB1):

To bring the stack up:

a)call USB_DeviceInit()

b)enable USB's IRQ

c)call USB_DeviceRun()

to bring the stack down:

a)call USB_DeviceStop()

b)disable USB's IRQ

c)call USB_DeviceDeinit()

0 Kudos
3,954 Views
emblink182
Contributor III

Hi, thanks for your suggestion and sorry for the late response.

I figured out that this method is working well on non-RTOS examples. But unfortunately, it doesn't with the FreeRTOS example. If I call usbReEnumerate() from other contexts, such as the timer task, the USB fails to enumerate. And I'm struggling to answer why that happening. I used  lpcxpresso54628_dev_hid_mouse_freertos project with minor modifications as an experimental ground.

#define USB_DEVICE_CONFIG_LPCIP3511HS (1U)

#define USB_DEVICE_CONFIG_USE_TASK (1U)

#define USB_DEVICE_CONFIG_COMPLIANCE_TEST (1U)

#define USB_DEVICE_CONFIG_DETACH_ENABLE (1U)

In mouse.c I have added // TEST_CODE comment in places where example was modified. Basically I created a one shot 1 sec software timer, starting it after usb got configured and call usbReEnumerate() in timer callback. Modified files are in attachment.

static void usbReEnumerate(TimerHandle_t xTimer) // TEST_CODE
{
    (void) xTimer;
    usb_status_t res = kStatus_USB_Success;
    // usb_echo("usbReEnumerate\r\n");

    if (g_UsbDeviceHidMouse.attach) {
        USB_DeviceStop(g_UsbDeviceHidMouse.deviceHandle); // always returns kStatus_USB_Error
        g_UsbDeviceHidMouse.attach = 0; // allows ignoring suspend event after re-enable.
        NVIC_DisableIRQ(USB1_IRQn);
        usb_status_t res = USB_DeviceClassDeinit(CONTROLLER_ID);
        // usb_status_t res = USB_DeviceDeinit(g_UsbDeviceHidMouse.deviceHandle);

        // res |= USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback,        &g_UsbDeviceHidMouse.deviceHandle);
         res |= USB_DeviceClassInit(CONTROLLER_ID, &g_UsbDeviceHidConfigList,         &g_UsbDeviceHidMouse.deviceHandle);
         NVIC_ClearPendingIRQ(USB1_IRQn);
         NVIC_EnableIRQ(USB1_IRQn);
         USB_DeviceRun(g_UsbDeviceHidMouse.deviceHandle); // always returns kStatus_USB_Error
    }
    assert(kStatus_USB_Success == res);
}

I also tried to use directly USB_DeviceInit() and USB_DeviceDeinit() but that didn't work also. USB_DeviceClassInit and USB_DeviceClassDeinit eventually call those functions so I think it's not a big deal here. Strange thing happens if uncomment // usb_echo("usbReEnumerate\r\n"); After that usb re-enumerates succesfully. And that's confusing.

0 Kudos