Best way to perform USB reset in Zephyr 3.0?

For reasons that are complicated, I need to be able to perform a USB reset on the device I'm developing triggered by firmware events. (I'm working around a problem with host sotware - this is not a permanent fix, but will be needed to unblock some additional development over the next 3-4 months.)  The device has an nrf52840 and is currently using Zephyr 3.0; My initial thought was simply to call `usb_dc_reset()` to do it - and this DOES work (in that it causes the reset to happen), but then immediately thereafter I get a hard fault:

```

[00:00:04.446,411] <err> os: ***** USAGE FAULT *****
[00:00:04.446,411] <err> os: Illegal use of the EPSR
[00:00:04.446,441] <err> os: r0/a1: 0x00000000 r1/a2: 0x00000000 r2/a3: 0x2000e798
[00:00:04.446,472] <err> os: r3/a4: 0x00000000 r12/ip: 0x20009948 r14/lr: 0x00033c63
[00:00:04.446,472] <err> os: xpsr: 0x60000000
[00:00:04.446,472] <err> os: Faulting instruction address (r15/pc): 0x00000000
[00:00:04.446,502] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
[00:00:04.446,533] <err> os: Current thread: 0x20009968 (unknown)
[00:00:04.553,955] <err> os: Halting system

```

Admittedly, I'm being pretty naive here, and just calling `usb_dc_reset()` from within the main execution thread.  What is the recommended way to achieve this?  Admittedly, I'm no USB guru, but it seems like it should be straightforward...

  • Hi,

    A couple questions so that we are on the same page:

    The device has an nrf52840 and is currently using Zephyr 3.0;

    So you are not using the nRF Connect SDK then, right?

    Which code are you running on the nRF52840?
    I am asking for either the sample you are running or the API you are using in your custom code.

    Which code are you running on your host?
    Is the host a compute or another microcontroller?

    Regards,
    Sigurd Hellesvik

  • No, not using the nRF Connect SDK - it's stock Zephyr 3.0.  Since the SDK includes Zephyr, and this is fairly basic functionality, I was hoping I could gain some insight as to whether I'm missing something simple.

    The code I am running on the nrf52840 is written with the Zephyr 3.0 API, and there is an MCUBoot bootloader (in case it matters, but I'm not dealing with the bootloader at this stage).  The host is any one of a number of computers - Windows, MacOS, or Linux.  What I am asking, though, is how to do a USB reset from the _device_ side.

     Mostly what I'm curious about is whether there is any special setup required to call `usb_dc_reset()` or whether I am expected to be able to call it from the main thread (ie, NOT in interrupt context) and have things work.  It DOES reset USB - I see the device detach and reattach, but then I get a hard fault afterwards - and debugging those is painful enough that I'm checking my assumptions first.

  • Hi Jeff,

    Admittedly, I'm being pretty naive here, and just calling `usb_dc_reset()` from within the main execution thread.  What is the recommended way to achieve this?  Admittedly, I'm no USB guru, but it seems like it should be straightforward...

    I agree with you here, it should be just to call the function.

    To test if this is the case, I did the following:

    For later reference, I used:
    nRF Connect SDK v2.2.0
    nRF52840DK

    Trying to reproduce your issue in the nRF Connect SDK (I have not zephyr set up so this is fastert for me), I added the following to the end of the main loop of the USB HID Sample Application:

        while(1){
            k_sleep(K_SECONDS(5));
            printk("AAAA\n");
            usb_dc_reset();
    

    In this case, my sample does not crash, and my PC gets repeated disconnect/connect warning on the journalctl command suggested in the docs.

    Can you try this to see if you get the same error with that sample?

    Regards,
    Sigurd Hellesvik

  • Took me a bit to get it configured for my board, but yeah- that example seems to work OK with the reset.  clearly I have some other issues to find.

    I do get one warning log on console:

    [00:00:15.684,570] <wrn> main: IN endpoint callback without preceding buffer write

    ...which probably isn't anything of import.

    Thanks for your followup.

  • Interesting - after a couple days playing around, I discovered that I wasn't actually building against the version of Zephyr I thought I was for the sample - I had been using 3.2 when I thought I was using 3.0.

    When I fixed this - that is, when I built the sample with your changes against Zephyr 3.0, I do in fact see the problem:

    *** Booting Zephyr OS build zephyr-v3.0.0-13-g6f1d4aeb81ee ***
    [00:00:00.397,155] <inf> main: HID Device: dev 0xab74
    [00:00:00.397,186] <inf> main: Starting application
    [00:00:00.398,315] <inf> usb_hid: Device connected
    [00:00:00.401,428] <inf> usb_hid: Device suspended
    [00:00:00.730,133] <inf> usb_hid: Device reset detected
    [00:00:00.730,163] <inf> usb_hid: Device resumed
    [00:00:00.791,320] <inf> usb_hid: Device configured
    AAAA
    [00:00:05.399,169] <inf> usb_hid: Device connected
    [00:00:05.402,282] <inf> usb_hid: Device suspended
    [00:00:05.594,329] <inf> usb_hid: Device reset detected
    [00:00:05.594,329] <inf> usb_hid: Device resumed
    [00:00:05.644,256] <err> os: ***** USAGE FAULT *****
    [00:00:05.644,256] <err> os: Illegal use of the EPSR
    [00:00:05.644,287] <err> os: r0/a1: 0x00000000 r1/a2: 0x00000000 r2/a3: 0x20001050
    [00:00:05.644,287] <err> os: r3/a4: 0x00000000 r12/ip: 0x20000878 r14/lr: 0x0000447f
    [00:00:05.644,287] <err> os: xpsr: 0x60000000
    [00:00:05.644,317] <err> os: Faulting instruction address (r15/pc): 0x00000000
    [00:00:05.644,348] <err> os: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
    [00:00:05.644,378] <err> os: Current thread: 0x20000720 (unknown)
    [00:00:06.584,686] <err> os: Halting system

    ...I'd love any insight on what might be different between 3.0 and 3.2 which would cause this.  I'm sure I could patch my code.

Related