cancel
Showing results for 
Search instead for 
Did you mean: 

[OTG USB] Delay needed between selecting PHY and softreset

In STM32F427 OTG_HS used with its internal FS PHY, the following sequence is used to initialize the OTG module (with all settings in RCC, i.e. setting up the 48MHz clock from PLL's Q tap, and enabling the clock in respective RCC_AHBxENR, performed far before this sequence):

usb->c->u->global.GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;     // disable interrupts
  usb->c->u->global.GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;    // select (built-in) FS PHY  
  while ((usb->c->u->global.GRSTCTL AND USB_OTG_GRSTCTL_AHBIDL) == 0);  // Wait for AHB master IDLE state
  usb->c->u->global.GRSTCTL |= USB_OTG_GRSTCTL_CSRST;  // core soft reset
  while ((usb->c->u->global.GRSTCTL AND USB_OTG_GRSTCTL_CSRST) != 0);

where usb->c->u points to OTG_HS. This worked well, until I tried to use a newer version of gcc, with presumably more aggressive optimization. This resulted in the following binary (I don't have the older version's disasm at hand):

0803d46c <USBD_Init>:
    usb->c->u->global.GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
 803d46c:	6803      	ldr	r3, [r0, #0]
 803d46e:	681b      	ldr	r3, [r3, #0]
 803d470:	689a      	ldr	r2, [r3, #8]
 803d472:	f022 0201 	bic.w	r2, r2, #1
  void USBD_Init(TUsbDeviceStruct * usb) {
 803d476:	b570      	push	{r4, r5, r6, lr}
    usb->c->u->global.GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
 803d478:	609a      	str	r2, [r3, #8]
    usb->c->u->global.GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;    // select (built-in) FS PHY  
 803d47a:	68da      	ldr	r2, [r3, #12]
 803d47c:	f042 0240 	orr.w	r2, r2, #64	; 0x40
  void USBD_Init(TUsbDeviceStruct * usb) {
 803d480:	4604      	mov	r4, r0
    usb->c->u->global.GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;    // select (built-in) FS PHY  
 803d482:	60da      	str	r2, [r3, #12]
    while ((usb->c->u->global.GRSTCTL AND USB_OTG_GRSTCTL_AHBIDL) == 0);  // Wait for AHB master IDLE state
 803d484:	691a      	ldr	r2, [r3, #16]
 803d486:	2a00      	cmp	r2, #0
 803d488:	dafc      	bge.n	803d484 <USBD_Init+0x18>
    usb->c->u->global.GRSTCTL |= USB_OTG_GRSTCTL_CSRST;  // core soft reset
 803d48a:	691a      	ldr	r2, [r3, #16]
 803d48c:	f042 0201 	orr.w	r2, r2, #1
 803d490:	611a      	str	r2, [r3, #16]
    while ((usb->c->u->global.GRSTCTL AND USB_OTG_GRSTCTL_CSRST) != 0);
 803d492:	691a      	ldr	r2, [r3, #16]
 803d494:	07d1      	lsls	r1, r2, #31
 803d496:	d4fc      	bmi.n	803d492 <USBD_Init+0x26>

This hung with cca 50% probability on the last while, where GRSTCTL.CSRST bit did not autoclear as it is supposed to.

It appears that adding delay (a single NOP) between setting GUSBCFG.PHYSEL and GRSTCTL.CSRST results in 100% working code. Adding delay anywhere else did not help. As there is no documentation for this and I am tired of digging deep into the Synopsys's mess, I just added

while ((usb->c->u->global.GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) == 0);

after setting GUSBCFG.PHYSEL and threw in some hope.

JW

[EDIT] It appears that objdump which came with the newer gcc choked on the .elf generated by older gcc... it took more than 10 minutes until it produced the disasm, but here it is, at the left-hand side in comparison with the new one

 803cd54:  b5f8        push  {r3, r4, r5, r6, r7, lr}      
 803cd56:  6803        ldr  r3, [r0, #0]                         803d46c:  6803        ldr  r3, [r0, #0]
 803cd58:  681a        ldr  r2, [r3, #0]                         803d46e:  681b        ldr  r3, [r3, #0]
 803cd5a:  6893        ldr  r3, [r2, #8]                         803d470:  689a        ldr  r2, [r3, #8]
 803cd5c:  f023 0301   bic.w  r3, r3, #1                         803d472:  f022 0201   bic.w  r2, r2, #1
                                                                 803d476:  b570        push  {r4, r5, r6, lr}
usb->c->u->global.GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;                                                               
 803cd60:  6093        str  r3, [r2, #8]                         803d478:  609a        str  r2, [r3, #8]                                    
 803cd62:  6803        ldr  r3, [r0, #0]
 803cd64:  681a        ldr  r2, [r3, #0]
 803cd66:  68d3        ldr  r3, [r2, #12]                        803d47a:  68da        ldr  r2, [r3, #12]       
 803cd68:  f043 0340   orr.w  r3, r3, #64  ; 0x40                803d47c:  f042 0240   orr.w  r2, r2, #64  ; 0x40
                                                                 803d480:  4604        mov  r4, r0
        usb->c->u->global.GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;    // select (built-in) FS PHY  
 803cd6c:  60d3        str  r3, [r2, #12]                        803d482:  60da        str  r2, [r3, #12]
 803cd6e:  6803        ldr  r3, [r0, #0]
 803cd70:  681a        ldr  r2, [r3, #0]
 803cd72:  4604        mov  r4, r0
        while ((usb->c->u->global.GRSTCTL AND USB_OTG_GRSTCTL_AHBIDL) == 0);  // Wait for AHB master IDLE state
 803cd74:  6913        ldr  r3, [r2, #16]                        803d484:  691a        ldr  r2, [r3, #16]             
 803cd76:  2b00        cmp  r3, #0                               803d486:  2a00        cmp  r2, #0                    
 803cd78:  dafc        bge.n  803cd74 <USBD_Init+0x20>           803d488:  dafc        bge.n  803d484 <USBD_Init+0x18>
        usb->c->u->global.GRSTCTL |= USB_OTG_GRSTCTL_CSRST;  // core soft reset
 803cd7a:  6913        ldr  r3, [r2, #16]                        803d48a:  691a        ldr  r2, [r3, #16]                                                           
 803cd7c:  f043 0301   orr.w  r3, r3, #1                         803d48c:  f042 0201   orr.w  r2, r2, #1 
 803cd80:  6113        str  r3, [r2, #16]                        803d490:  611a        str  r2, [r3, #16]
        while ((usb->c->u->global.GRSTCTL AND USB_OTG_GRSTCTL_CSRST) != 0);
 803cd82:  6823        ldr  r3, [r4, #0]                                                              
 803cd84:  681a        ldr  r2, [r3, #0]
 803cd86:  6913        ldr  r3, [r2, #16]                        803d492:  691a        ldr  r2, [r3, #16]                  
 803cd88:  07d9        lsls  r1, r3, #31                         803d494:  07d1        lsls  r1, r2, #31              
 803cd8a:  d4fc        bmi.n  803cd86 <USBD_Init+0x32>           803d496:  d4fc        bmi.n  803d492 <USBD_Init+0x26>
 

0 REPLIES 0