cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F779 USB Endpoint 0 (EP0) interrupts stop after constant deinit and reinit of the USB

APTchassak
Visitor

I'm going to rip my hair out... I mean

 

There has been an issue with rapid disconnect and reconnect of the USB on our product, where the USB stops communicating. We enabled early suspend and when an erratic error (EERR) bit occurs during an early suspend. We plan on deinit and reinit the USB.

 

Our USB device is using a RNDIS (USB Ethernet) and CDC (Virtual Comm) interfaces. Using Device mode full speed (FS). We are not using the HAL library, We do use middleware from SEGGER emUSB. 

 

To test that this is reliable, we added the deinit and reinit code to a one second timer on the device. It works fine until it doesn't. Looking at where it fails, The STM32 microcontroller thinks after onClassRequest, we have a get status request which was never sent from the computer, then the device stalls endpoint 0. Normally what i observed, instantly, the device would clear the stall on endpoint 0, but seems it never responds back. Then we would start the deinit and reinit process after and the peripheral never recovers. The device would never get up to setting the USB address phase. just keep the constant cycle of GetDescriptor request.

 

I tried everything besides ripping my hair out. If you have any ideas on what i can try or where to look, it would help.

 

This isnt the exact deinit, company would make me rip my hair out if i posted their code. This is just an example to show i tried flushing out the FIFO buffers and clearing interrupts to try and fix this issue.

 

void exampleDeinit(void) {
    OTG_DOEPCTL0 &= ~(OTG_DxEPCTLx_STALL); // Ignore, bit can't be cleared, only set, core has to clear
    OTG_DIEPCTL0 &= ~(OTG_DxEPCTLx_STALL);

    // Deinitialize USB
    
    OTG_GINTMSK = 0; // Disable USB Global Interrupt
    OTG_GINTSTS = 0xFFFFFFFF; // Clear pending interrupts
    
    OTG_PCGCCTL |= OTG_PCGCCTL_STOPCLK; // Disable PHY clock
    OTG_GCCFG &= ~OTG_GCCFG_PWRDWN; // Power down the USB transceiver

    // Disable all endpoints
    OTG_DAINTMSK = 0;
    OTG_DOEPMSK = 0;
    OTG_DIEPMSK = 0;

    // Flush transmit FIFO
    OTG_GRSTCTL |= OTG_GRSTCTL_TX_FIFO_FLUSH;
    while (OTG_GRSTCTL & OTG_GRSTCTL_TX_FIFO_FLUSH);

    // Flush receive FIFO
    OTG_GRSTCTL |= OTG_GRSTCTL_RX_FIFO_FLUSH;
    while (OTG_GRSTCTL & OTG_GRSTCTL_RX_FIFO_FLUSH);

    RCC_AHB2ENR &= ~(1 <<  7);  // OTGFSEN: Disable USB OTG FS clock enable

    while (OTG_GRSTCTL & OTG_GRSTCTL_CSRST);  // Wait for reset completion
}

 

 

USB analyzer screenshot:

APTchassak_0-1728305572732.png

USB STM32 print log:

 

635:301 Interrupt - EP0 Interrupt
635:301 Interrupt - _OnRx() Start
635:301 Interrupt - Enter HandleSetup: Setup 21 00 00 00 00 00 20 00
635:301 Interrupt - ENUM: OnClassRequest
635:301 Interrupt - Enter HandleSetup: Setup 00 00 28 01 00 02 25 01
635:301 Interrupt - ENUM: GetStatus
635:301 Interrupt - We got spagetti
635:301 Interrupt - _StallEP0: USB_Setup.c:802
635:301 Interrupt - _OnRx() End
635:303 Interrupt - _OnRx() Start
635:303 Interrupt - _OnRx() End
635:491 Comms - ONESECOND_DEINIT_REINIT
635:507 Interrupt - _OnRx() Start
635:507 Interrupt - _OnRx() End
635:507 Interrupt - USB__EarlySuspend()
635:511 Comms - Activate non-RNDIS interface
635:539 Comms - Config: Adding driver 003D82F0 to stack
635:539 Comms - CDC: Adding CDC interface with ControlInterface = 2, DataInterface = 3
635:539 Comms - USBD_Start
635:539 Comms - DWC2: Controller ID = 2000
635:569 Comms - EP 0 FIFO RAM = 64 bytes, DblBuff = 0
635:569 Comms - EP 1 FIFO RAM = 256 bytes, DblBuff = 1
635:569 Comms - EP 2 FIFO RAM = 64 bytes, DblBuff = 0
635:569 Comms - EP 3 FIFO RAM = 256 bytes, DblBuff = 1
635:569 Comms - EP 4 FIFO RAM = 64 bytes, DblBuff = 0
635:569 Comms - EP 5 FIFO RAM = 0 bytes, DblBuff = 0
635:569 Comms - USB DWC2: 192 bytes unused EP buffer RAM (USB_ENDPOINT_BUFFER_POOL_SIZE / USBD_AssignMemory())
635:575 Interrupt - _OnRx() Start
635:575 Interrupt - _OnRx() End
635:575 Interrupt - USB__EarlySuspend()
635:581 Interrupt - _OnRx() Start
635:581 Interrupt - _OnRx() End
635:581 Interrupt - USB__OnSuspend()
635:581 Interrupt - Activate non-RNDIS interface
637:490 Comms - ONESECOND_DEINIT_REINIT
637:507 Interrupt - _OnRx() Start
637:507 Interrupt - _OnRx() End
637:507 Interrupt - USB__EarlySuspend()
637:513 Comms - Activate non-RNDIS interface
637:533 Comms - Config: Adding driver 003D82F0 to stack
637:533 Comms - CDC: Adding CDC interface with ControlInterface = 2, DataInterface = 3
637:533 Comms - USBD_Start
637:533 Comms - DWC2: Controller ID = 2000
637:563 Comms - EP 0 FIFO RAM = 64 bytes, DblBuff = 0
637:563 Comms - EP 1 FIFO RAM = 256 bytes, DblBuff = 1
637:563 Comms - EP 2 FIFO RAM = 64 bytes, DblBuff = 0
637:563 Comms - EP 3 FIFO RAM = 256 bytes, DblBuff = 1
637:563 Comms - EP 4 FIFO RAM = 64 bytes, DblBuff = 0
637:563 Comms - EP 5 FIFO RAM = 0 bytes, DblBuff = 0
637:563 Comms - USB DWC2: 192 bytes unused EP buffer RAM (USB_ENDPOINT_BUFFER_POOL_SIZE / USBD_AssignMemory())
637:569 Interrupt - _OnRx() Start
637:569 Interrupt - _OnRx() End
637:569 Interrupt - USB__EarlySuspend()
637:575 Interrupt - _OnRx() Start
637:575 Interrupt - _OnRx() End
637:575 Interrupt - USB__OnSuspend()
637:575 Interrupt - Activate non-RNDIS interface
639:478 Comms - ONESECOND_DEINIT_REINIT
639:503 Interrupt - _OnRx() Start
639:503 Interrupt - _OnRx() End
639:503 Interrupt - USB__EarlySuspend()
639:507 Comms - Activate non-RNDIS interface
639:527 Comms - Config: Adding driver 003D82F0 to stack
639:527 Comms - CDC: Adding CDC interface with ControlInterface = 2, DataInterface = 3
639:527 Comms - USBD_Start
639:527 Comms - DWC2: Controller ID = 2000
639:561 Comms - EP 0 FIFO RAM = 64 bytes, DblBuff = 0
639:561 Comms - EP 1 FIFO RAM = 256 bytes, DblBuff = 1
639:561 Comms - EP 2 FIFO RAM = 64 bytes, DblBuff = 0
639:561 Comms - EP 3 FIFO RAM = 256 bytes, DblBuff = 1
639:561 Comms - EP 4 FIFO RAM = 64 bytes, DblBuff = 0
639:561 Comms - EP 5 FIFO RAM = 0 bytes, DblBuff = 0
639:561 Comms - USB DWC2: 192 bytes unused EP buffer RAM (USB_ENDPOINT_BUFFER_POOL_SIZE / USBD_AssignMemory())
639:568 Interrupt - _OnRx() Start
639:568 Interrupt - _OnRx() End
639:568 Interrupt - USB__EarlySuspend()
639:574 Interrupt - _OnRx() Start
639:574 Interrupt - _OnRx() End
639:574 Interrupt - USB__OnSuspend()
639:574 Interrupt - Activate non-RNDIS interface
641:491 Comms - ONESECOND_DEINIT_REINIT
641:507 Interrupt - _OnRx() Start
641:507 Interrupt - _OnRx() End
641:507 Interrupt - USB__EarlySuspend()
641:511 Comms - Activate non-RNDIS interface
641:531 Comms - Config: Adding driver 003D82F0 to stack
641:531 Comms - CDC: Adding CDC interface with ControlInterface = 2, DataInterface = 3
641:531 Comms - USBD_Start
641:531 Comms - DWC2: Controller ID = 2000
641:561 Comms - EP 0 FIFO RAM = 64 bytes, DblBuff = 0
641:561 Comms - EP 1 FIFO RAM = 256 bytes, DblBuff = 1
641:561 Comms - EP 2 FIFO RAM = 64 bytes, DblBuff = 0
641:561 Comms - EP 3 FIFO RAM = 256 bytes, DblBuff = 1
641:561 Comms - EP 4 FIFO RAM = 64 bytes, DblBuff = 0
641:561 Comms - EP 5 FIFO RAM = 0 bytes, DblBuff = 0
641:561 Comms - USB DWC2: 192 bytes unused EP buffer RAM (USB_ENDPOINT_BUFFER_POOL_SIZE / USBD_AssignMemory())
641:567 Interrupt - _OnRx() Start
641:567 Interrupt - _OnRx() End
641:567 Interrupt - USB__EarlySuspend()
641:573 Interrupt - _OnRx() Start
641:573 Interrupt - _OnRx() End
641:573 Interrupt - USB__OnSuspend()
641:573 Interrupt - Activate non-RNDIS interface
643:494 Comms - ONESECOND_DEINIT_REINIT
643:510 Interrupt - _OnRx() Start
643:510 Interrupt - _OnRx() End
643:510 Interrupt - USB__EarlySuspend()
643:514 Comms - Activate non-RNDIS interface
643:539 Comms - Config: Adding driver 003D82F0 to stack
643:539 Comms - CDC: Adding CDC interface with ControlInterface = 2, DataInterface = 3
643:539 Comms - USBD_Start
643:539 Comms - DWC2: Controller ID = 2000
643:569 Comms - EP 0 FIFO RAM = 64 bytes, DblBuff = 0
643:569 Comms - EP 1 FIFO RAM = 256 bytes, DblBuff = 1
643:569 Comms - EP 2 FIFO RAM = 64 bytes, DblBuff = 0
643:569 Comms - EP 3 FIFO RAM = 256 bytes, DblBuff = 1
643:569 Comms - EP 4 FIFO RAM = 64 bytes, DblBuff = 0
643:569 Comms - EP 5 FIFO RAM = 0 bytes, DblBuff = 0
643:569 Comms - USB DWC2: 192 bytes unused EP buffer RAM (USB_ENDPOINT_BUFFER_POOL_SIZE / USBD_AssignMemory())
643:575 Interrupt - _OnRx() Start
643:575 Interrupt - _OnRx() End
643:575 Interrupt - USB__EarlySuspend()
643:581 Interrupt - _OnRx() Start
643:581 Interrupt - _OnRx() End
643:581 Interrupt - USB__OnSuspend()
643:581 Interrupt - Activate non-RNDIS interface
645:333 Interrupt - _OnRx() Start
645:333 Interrupt - _OnRx() End
645:333 Interrupt - _OnBusReset()
645:333 Interrupt - EP 0 FIFO RAM = 64 bytes, DblBuff = 0
645:333 Interrupt - EP 1 FIFO RAM = 256 bytes, DblBuff = 1
645:333 Interrupt - EP 2 FIFO RAM = 64 bytes, DblBuff = 0
645:333 Interrupt - EP 3 FIFO RAM = 256 bytes, DblBuff = 1
645:333 Interrupt - EP 4 FIFO RAM = 64 bytes, DblBuff = 0
645:333 Interrupt - EP 5 FIFO RAM = 0 bytes, DblBuff = 0
645:333 Interrupt - Activate non-RNDIS interface

 

 

1 REPLY 1

> The STM32 microcontroller thinks after onClassRequest, we have a get status request which was never sent from the computer, then the device stalls endpoint 0.

I'm not sure what this means, but I would perhaps try to concentrate on not "getting" requests which were not sent. The rest might be a consequence.

Also, there's IMO no need for "deinitialization" of the USB hardware ever, unless you want to go to some low-power mode. But you definitively need to unwind any changes in software, reset structs etc.

Also, instead of "deinitialization" of the hardware, you may perhaps try to summarily reset it using the respective reset bit in RCC. I've never tried this, though, and I can envisage there may be some devil in the details.

JW