[F103] USB_RAW: Assertion "already receiving" after PC sleep and resume Topic is solved

Report here problems in any of ChibiOS components. This forum is NOT for support.
l0ud
Posts: 8
Joined: Thu Nov 30, 2017 12:55 am
Been thanked: 3 times

[F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by l0ud »

Hi,
I've build USB-MIDI adapter with two endpoints based on USB-RAW example. I have 2 threads for USB processing: one for receiving data in a loop, one for sending when there is a need to do that.
Everything works without problems until I put the computer to sleep while the device is connected. It crashes right away after resuming from sleep (I made a led blink thread to catch the moment of crash).
MCU used: stm32f103c8t6.
My OS is Linux Manjaro, I didn't test that on Windows.

Assertion happens in receiving thread, inside usbStartReceiveI function:

Code: Select all

osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving");

In fact, usbp->receiving is equal to 2.

Beginning of thread loop:

Code: Select all

THD_FUNCTION(usb_out_thread_loop, p)
{
    (void)p;

    while (!chThdShouldTerminateX())
    {
        //get free item from jack queue
        midi_packet_s transaction_packets[16]; //64 bytes in endpoint / sizeof packet(4) = 16
        msg_t size;
        //receive from usb
        while ((size = usbReceive(&USBD1, 1, (uint8_t*)transaction_packets, sizeof(transaction_packets))) <= 0)
        {
            //todo: sleep?
            chThdSleepMilliseconds(100);
        }
        ... packet processing...


USB event callback is similar to one in USB_RAW example.

Code: Select all


static const USBEndpointConfig ep1config = {
    USB_EP_MODE_TYPE_BULK, // Bulk EP
    NULL,                  // SETUP packet notification callback
    NULL,                  // IN notification callback
    NULL,                  // OUT notification callback
    0x0040,                // IN maximum packet size
    0x0040,                // OUT maximum packet size
    &ep1instate,           // IN Endpoint state
    &ep1outstate,          // OUT endpoint state
    1,                     // Reserved?
    NULL                   // SETUP buffer (not a SETUP endpoint)
};

static void usb_event_cb(USBDriver* usbp, usbevent_t event)
{
    (void)usbp;
    switch (event)
    {
        case USB_EVENT_RESET:
            return;

        case USB_EVENT_ADDRESS:
            return;

        case USB_EVENT_CONFIGURED:

            chSysLockFromISR();
            usbInitEndpointI(usbp, 1, &ep1config);
            chSysUnlockFromISR();
            return;

        case USB_EVENT_SUSPEND:
            return;

        case USB_EVENT_WAKEUP:
            return;

        case USB_EVENT_STALLED:
            return;

        case USB_EVENT_UNCONFIGURED:
            return;
    }
}


I suspect there is a bug inside HAL, or at least USB_RAW example. What may be causing this?

Thank you for your help
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by Giovanni »

Apparently the USB driver is in the middle of a receive operation when the host goes to sleep. Does the USB device get a reset when the host wakes up?

Giovanni
l0ud
Posts: 8
Joined: Thu Nov 30, 2017 12:55 am
Been thanked: 3 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by l0ud »

There is no USB_EVENT_RESET after host sleep nor after resume. The only reset event I got happens directly after connecting USB cable first time. Maybe there is reset after wakeup, but firmware is already crashed on assertion so I couldn't catch it.
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by Giovanni »

When the host exits sleep does it re-enumerate devices? enumeration should reset the device.

Anyway, wow can I reproduce this? can I use one of the existing demos?

Giovanni
l0ud
Posts: 8
Joined: Thu Nov 30, 2017 12:55 am
Been thanked: 3 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by l0ud »

It doesn't seem to reenumerate any devices at all. I can leave openocd st-link session open and after resume it just go on like it was before sleep. Also, I don't see any dmesg messages about reenumeration, except when my device is connected. In that case I see multiple URB errors and then failed enumeration triggered by that errors (I think) and it is of course failed because firmware is already crashed.

To be honest I don't know how to reproduce problem on your side without much effort. I think USB_RAW demo is sufficient, keeping in mind I'm running it on STM32F1 mcu. I would connect board with that demo to PC, then put that PC to sleep (not hibernate) and resume. If it doesn't trigger problem I would download Linux Manjaro (which I'm using right now) and then try to do the same. Maybe it's some incompatibility between newest linux releases and chibios?
l0ud
Posts: 8
Joined: Thu Nov 30, 2017 12:55 am
Been thanked: 3 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by l0ud »

I connected my board at work to a PC with windows 10 with USB analyzer between. It crashed after resume too. I'm not sure about exact reason, because I don't have a debugger here.

However, on analyzer I can see there is ongoing IN transaction (with corresponding NAK-s because there are no midi events) and then Suspend, some time later Resume and Resume EOP. Then there is immediately continuation of IN transaction (again, with NAK-s) but I suspect firmware is crashed here.

So I think that USB Suspend and Resume events are a problem here.
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by Giovanni »

I understood the scenario, thanks. I need to understand how to reset the transaction on the device side, there is no reset event to do that.

Moving this topic in "bug reports" for processing.

Giovanni
l0ud
Posts: 8
Joined: Thu Nov 30, 2017 12:55 am
Been thanked: 3 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by l0ud »

Thanks for confirming issue. I've made a quick workaround in _usb_suspend function.

Code: Select all

    for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
      if (usbp->epc[i] != NULL) {
        osalSysLockFromISR();
        if (usbp->epc[i]->in_state != NULL) {
          usbp->transmitting &= ~(1 << (i));
          osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
        }
        if (usbp->epc[i]->out_state != NULL) {
          usbp->receiving &= ~(1 << (i));
          osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
        }
        osalSysUnlockFromISR();
      }
    }


With this I have no longer any issue with sleep on my Linux PC, after resume it just works like it worked before.
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by Giovanni »

Hi,

I have committed a slightly different fix in trunk, could you verify this fixes the problem on your side?

In general, about the suspend state, I wonder if the LLD should also reset the state of endpoints in order to terminate ongoing transactions, perhaps this is on required for USBv1 on the F103 but the matter is more complex on OTGv1 (there are FIFOs to be considered).

To be checked.

Giovanni
l0ud
Posts: 8
Joined: Thu Nov 30, 2017 12:55 am
Been thanked: 3 times

Re: [F103] USB_RAW: Assertion "already receiving" after PC sleep and resume

Post by l0ud »

Now it seems to be working correctly without any modifications in ChibiOS source on master branch.
Post Reply