Hello. I'm struggling with just starting enumeration of USB FS on the STM32H7 part. Several years ago I've done CDC On F4 part and it was already a major PITA. Now I need a specific composite device, so trying to port some old code. I didn't expect any less carnage, so here it comes:
the USB core refuses to acknowledge VBUS active level at plug-in event, so the device cannot signal Powered state to host by pulling data line. Basically, no core state/flag change at all when VBUS turns active; never get the a/b session valid.
This issue is only similar to this
one, but his core raised SRQINT flag, mine doesn't. Though I investigated SDIS "soft disconnect" bit and it seems it is past my issue.
Potential evaluated suspects:
- pins configuration: data lines are PP AF, VBUS is "digital" input - I think VBUS pin required configuration still isn't mentioned anywhere on docs... during plug-in event VBUS is detected by port; zero activity on data lines though.
- core instance number: the device has two physical ips, yet in docs and CMSIS they are using "OTG_HS..", "OTG_FS.." mnemonics, which are ambiguous, as both cores can run FS on internal PHY and they state somehere else that both ips are HS but one ip lacks ULPI... Point is it isn't clear which core uses which set of DP, DM, VBUS... pins. In the end I checked EVAL boards and assumed that pins on port A are tied to "OTG_FS.." (Cube output conforms too). Even did the same config on both ips, but they both behave the same.
- clock: PLL3 Q output required. HSI48 also evaluated, no difference. Although cannot route PLL3-Q onto the MCO, but I have mirrored the pll config to another pll which could be put on mco pin, and have measured required 48 MHz. But when I put different than 48 MHz bogus freq onto the usb core, it still behaves the same way. Only when I don't route any clock, the system crashes on GRSTCTL CSRST bit. At least some other response.
- Cube generated example - I followed configuration sequence, with no avail. Still couldn't manage to run complete generated example on Keil, I never got it.
- AHB frequency - seems 200 MHz (docs require at least 30 MHz).
My issues during intialization; I have no idea if this is valid behaviour:
- GUSBCFG PHYSEL bit behaves like write-only bit, dunno if it ever apply; can't read it either. Is this bit supposed to persist after setting? In docs it is marked "rw"...
- "setting" PHYSEL causes to core to switch to HOST mode (GINTSTS CMOD bit turns 1).
Code:
#define USB2_OTG_FS_DEVICE ((USB_OTG_DeviceTypeDef *) 0x40080800)
/*48 mhz na PLL Q, assumed 8 mhz input*/
RCC->PLLCFGR &= ~RCC_PLLCFGR_PLL3FRACEN; /*integer pll*/
RCC->PLLCFGR |= RCC_PLLCFGR_PLL3VCOSEL; /*narrow range vco output:150-400mhz*/
RCC->PLLCFGR |= RCC_PLLCFGR_PLL3RGE_2; /*range ck in: 4-8Mhz (8Mhz input) */
RCC->PLLCKSELR |= RCC_PLLCKSELR_DIVM3_0; /*input prescaler = 1*/
RCC->PLL3DIVR = ((0x00000003)<<16)|(0x00000017); /*0x17 = 23; 8*(23+1) = 192 Mhz; Q divider: 3+1; output: 192/divider =48mhz*/
RCC->PLLCFGR |= RCC_PLLCFGR_DIVQ3EN;
RCC->CR |= RCC_CR_PLL3ON;
while(!(RCC->CR & RCC_CR_PLL3RDY));
RCC->D2CCIP2R |= RCC_D2CCIP2R_USBSEL_1; /*clock source selection - PLL3-Q*/
RCC->AHB1ENR |= RCC_AHB1ENR_USB2OTGHSEN; /*peripheral enable*/
RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN;
__DSB();
/*PA11-DM, PA12-DP*/
GPIOA->MODER |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER12_1; /*AF PP*/
GPIOA->MODER &= ~(GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0);
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12; /*SPEED max*/
GPIOA->AFR[1] |= (0x0000000A<<12)|(0x0000000A<<16); /*AF10 (0x0A) - USB DM DP datasheet p82*/
GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR11 | GPIO_PUPDR_PUPDR12); /*no pull ups*/
/*PA9 - VBUS*/
GPIOA->MODER &= ~GPIO_MODER_MODER9; /*input*/
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR9; /*no pull ups*/
USB2_OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; /*USB 1.1 full-speed serial transceiver*/
delayMs(100);
USB2_OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; /*force device mode*/
delayMs(100);
USB2_OTG_FS->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; /*Core Soft Reset*/
while((USB2_OTG_FS->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
delayMs(100);
USB2_OTG_FS_DEVICE->DCFG |= USB_OTG_DCFG_DSPD; /*Full speed using internal FS PHY*/
USB2_OTG_FS_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS; /*soft disconnect release*/
USB2_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; /*VBUS detection enable*/
USB2_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; /*USB FS transceiver enabled*/
At this moment core should response at plug in with pulling up data line.
I'm using STM32H743 from Nucleo board, 750 part is the final target, though the board isn't done yet.
Have you ever meet such behaviour, or have any other ideas?