cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f446vet

pingpong999
Associate II

im struggling to get usb fs working on a custom stm32f446vet dev board. im slightly aware that this may be an explored problem but in need of some guidance. 

i suspect the PLLSAI never locks. 

some init code for context 

 

void USB::Init(bool softReset) { volatile uint32_t count = 0; if (!softReset) { GpioPin::Init(GPIOA, 9, GpioPin::Type::Input); // PA9: USB_OTG_HS_VBUS GpioPin::Init(GPIOA, 11, GpioPin::Type::AlternateFunction, 10); // PA11: USB_OTG_HS_DM GpioPin::Init(GPIOA, 12, GpioPin::Type::AlternateFunction, 10); // PA12: USB_OTG_HS_DP RCC->DCKCFGR2 |= RCC_DCKCFGR2_CK48MSEL; // 0 = PLLQ Clock; 1 = PLLSAI_P RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; // USB OTG FS clock enable RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Enable system configuration clock: used to manage external interrupt line connection to GPIOs NVIC_SetPriority(OTG_FS_IRQn, 2); NVIC_EnableIRQ(OTG_FS_IRQn); } USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; // Activate the transceiver in transmission/reception. When reset, the transceiver is kept in power-down. 0 = USB FS transceiver disabled; 1 = USB FS transceiver enabled USB_OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; // Force USB device mode DelayMS(50); // Clear all transmit FIFO address and data lengths - these will be set to correct values below for endpoints 0,1 and 2 for (uint8_t i = 0; i < 15; i++) { USB_OTG_FS->DIEPTXF[i] = 0; } USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; // Enable HW VBUS sensing USBx_DEVICE->DCFG |= USB_OTG_DCFG_DSPD; // 11: Full speed using internal FS PHY USB_OTG_FS->GRSTCTL |= USB_OTG_GRSTCTL_TXFNUM_4; // Select buffers to flush. 10000: Flush all the transmit FIFOs in device or host mode USB_OTG_FS->GRSTCTL |= USB_OTG_GRSTCTL_TXFFLSH; // Flush the TX buffers while (++count < 100000 && (USB_OTG_FS->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH)); USB_OTG_FS->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; // Flush the RX buffers count = 0; while (++count < 100000 && (USB_OTG_FS->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH)); USB_OTG_FS->GINTSTS = 0xBFFFFFFF; // Clear pending interrupts (except SRQINT Session request/new session detected) // Enable interrupts USB_OTG_FS->GINTMSK = 0; // Disable all interrupts USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_USBSUSPM | // Receive FIFO non-empty mask; USB suspend USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | // USB reset; Enumeration done USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_WUIM | // IN endpoint; OUT endpoint; Resume/remote wakeup detected USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT; // Session request/new session detected; OTG interrupt // NB - FIFO Sizes are in words NOT bytes. There is a total size of 320 (320x4 = 1280 bytes) available which is divided up thus: // FIFO Start Size // RX 0 128 // EP0 TX 128 64 // EP1 TX 192 64 // EP2 TX 256 64 USB_OTG_FS->GRXFSIZ = 128; // Rx FIFO depth // Endpoint 0 Transmit FIFO size/address (as in device mode - this is also used as the non-periodic transmit FIFO size in host mode) USB_OTG_FS->DIEPTXF0_HNPTXFSIZ = (64 << USB_OTG_TX0FD_Pos) | // IN Endpoint 0 Tx FIFO depth (128 << USB_OTG_TX0FSA_Pos); // IN Endpoint 0 FIFO transmit RAM start address - this is offset from the RX FIFO (set above to 128) // Endpoint 1 FIFO size/address (address is offset from EP0 address+size above) USB_OTG_FS->DIEPTXF[0] = (64 << USB_OTG_DIEPTXF_INEPTXFD_Pos) | // IN endpoint 1 Tx FIFO depth (192 << USB_OTG_DIEPTXF_INEPTXSA_Pos); // IN endpoint 1 FIFO transmit RAM start address // Endpoint 2 FIFO size/address (address is offset from EP1 address+size above) USB_OTG_FS->DIEPTXF[1] = (64 << USB_OTG_DIEPTXF_INEPTXFD_Pos) | // IN endpoint 2 Tx FIFO depth (256 << USB_OTG_DIEPTXF_INEPTXSA_Pos); // IN endpoint 2 FIFO transmit RAM start address USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS; // Activate USB USB_OTG_FS->GAHBCFG |= USB_OTG_GAHBCFG_GINT; // Activate USB Interrupts transmitting = false; } struct PLLDividers { uint32_t M; uint32_t N; uint32_t P; uint32_t Q; }; const PLLDividers mainPLL {4, 180, 2, 7}; // Clock: 8MHz / 4(M) * 168(N) / 2(P) = 180MHz const PLLDividers saiPLL {6, 144, 4, 0}; // USB: 8MHz / 6(M) * 144(N) / 4(P) = 48MHz void InitClocks() { RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; volatile uint32_t dummy = RCC->APB2ENR & RCC_APB2ENR_SYSCFGEN; RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_VOS_0; SCB->CPACR |= ((3 << 10 * 2) | (3 << 11 * 2)); RCC->CR |= RCC_CR_HSEON; while ((RCC->CR & RCC_CR_HSERDY) == 0); RCC->PLLCFGR = (mainPLL.M << RCC_PLLCFGR_PLLM_Pos) | (mainPLL.N << RCC_PLLCFGR_PLLN_Pos) | (((mainPLL.P >> 1) - 1) << RCC_PLLCFGR_PLLP_Pos) | (mainPLL.Q << RCC_PLLCFGR_PLLQ_Pos) | RCC_PLLCFGR_PLLSRC_HSE; RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV2; RCC->CR |= RCC_CR_PLLON; while ((RCC->CR & RCC_CR_PLLRDY) == 0); RCC->PLLSAICFGR = (saiPLL.M << RCC_PLLSAICFGR_PLLSAIM_Pos) | (saiPLL.N << RCC_PLLSAICFGR_PLLSAIN_Pos) | (((saiPLL.P >> 1) - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos); RCC->CR |= RCC_CR_PLLSAION; FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS; RCC->CFGR &= ~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); FLASH->ACR |= FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN; SystemCoreClockUpdate(); }
View more

 

5 REPLIES 5
Sarra.S
ST Employee

Hello @pingpong999

Could you verify that the PLLSAI is locking by checking the PLLSAIRDY flag?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

thanks for the reply. 

i just ran this block and can confirm it locks which is great. im a little stumped on why im not able to register usb communication. should my d plus line be high? both d- and d+ are low

struct PLLDividers { uint32_t M; uint32_t N; uint32_t P; uint32_t Q; }; const PLLDividers mainPLL {4, 180, 2, 7}; const PLLDividers saiPLL {6, 144, 4, 0}; void InitClocks() { RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; [[maybe_unused]] volatile uint32_t dummy = RCC->APB2ENR & RCC_APB2ENR_SYSCFGEN; RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_VOS_0; SCB->CPACR |= ((3 << 10 * 2) | (3 << 11 * 2)); RCC->CR |= RCC_CR_HSEON; while ((RCC->CR & RCC_CR_HSERDY) == 0); RCC->PLLCFGR = (mainPLL.M << RCC_PLLCFGR_PLLM_Pos) | (mainPLL.N << RCC_PLLCFGR_PLLN_Pos) | (((mainPLL.P >> 1) - 1) << RCC_PLLCFGR_PLLP_Pos) | (mainPLL.Q << RCC_PLLCFGR_PLLQ_Pos) | RCC_PLLCFGR_PLLSRC_HSE; RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_PPRE2_DIV2; RCC->CR |= RCC_CR_PLLON; while ((RCC->CR & RCC_CR_PLLRDY) == 0); RCC->PLLSAICFGR = (saiPLL.M << RCC_PLLSAICFGR_PLLSAIM_Pos) | (saiPLL.N << RCC_PLLSAICFGR_PLLSAIN_Pos) | (((saiPLL.P >> 1) - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos); RCC->CR |= RCC_CR_PLLSAION; while ((RCC->CR & RCC_CR_PLLSAIRDY) == 0); // Check pllsairdy here FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS; RCC->CFGR &= ~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); FLASH->ACR |= FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN; SystemCoreClockUpdate(); } int main() { RCC->CR |= RCC_CR_PLLSAION; while ((RCC->CR & RCC_CR_PLLSAIRDY) == 0); printf("PLLSAI locked and ready\n"); while (1); }
View more

Observe the USB registers in debugger, whether they do have the expected values.

> USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; // Enable HW VBUS sensing

Do you have VBUS-derived voltage connected to given pin? Is GOTGCTL.BSVLD set?

JW

this is my usb register dump, GOTGCTL = 0x03010000 does not have bit 19 set, so BSVLD is not set which makes me think its a hardware issue

GOTGCTL = 0x03010000 GOTGINT = 0x00100000 GAHBCFG = 0x00000001 GUSBCFG = 0x40001440 GRSTCTL = 0x80000000 GINTSTS = 0x04008020 GINTMSK = 0xC00C3814 GRXFSIZ = 0x00000080 DIEPTXF0 = 0x00400080 DIEPTXF1 = 0x004000C0 DIEPTXF2 = 0x00400100 GCCFG = 0x0021FFF0 CID = 0x00002000 DCFG = 0x08200003 DCTL = 0x00000000 DSTS = 0x0007FF06 DIEPMSK = 0x00000000 DOEPMSK = 0x00000000 DAINT = 0x00000000 DAINTMSK = 0x00000000

 

> BSVLD is not set

Do you have VBUS-derived voltage connected to given pin?

You can override VBUS detection by clearing GCCFG.VBDEN and setting GOTGCTL.VBVALOEN and GOTGCTL.BVALOVAL.

JW