cancel
Showing results for 
Search instead for 
Did you mean: 

Lowlevel USB programming

kiv
Associate II
Posted on November 17, 2015 at 10:01

I'm trying to understand low-level (without third-party libraries) programming of USB module of STM32F103 MCU and have encountered a problem.

My sequence of actions:

1) I have an external crystal of 8 MHz. PLL setup to output 72 MHz (multiplication factor of 9, divider 3 USB). Of course, this process consists of several stages, however, the result in register RCC-> CFGR is 0x001DC40A (which among other things means that the PLL is successfully selected as the system frequency source). USART and SysTick works normally (frequency exactly true).

2) Enable USB clock via RCC. Clear PWDN bit in USB->CNTR. Waiting 1 microsecond (as datasheet says it need to stabilize the reference voltage), write zeros to CNTR, BTABLE and ISTR registers. Enable USB_FS_WKUP and CAN1_RX0 IRQs. Then write USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_CTRM value to the USB->CNTR.

3) USB initialization is done. Next comes first USB interrupt. Interrupt reason from USB->ISTR is RESET. Yes, this is what should happen, everything is ok. I cleared this flag.

4) Setup endpoint 0. As a result, USB-> EP0R value is 0x3220. At address USB_PMA_BASE + 0 placed value 64 (TXADDR for EP0 == 64), at the address USB_PMA_BASE + 8 placed value 128 (RXADDR for EP0 == 128), at the address USB_PMA_BASE + 12 placed value 0x8400 (receiving buffer size for EP0 - 64 bytes).

5) Enable USB operation - write in the USB->DADDR value 0x80.

6) Return from the interrupt handler.

7) I expect that I will have to received the first SETUP-packet, what will be indicated by flag CTR in register USB->ISTR. And it does not come. But comes a bunch of interrupts due WKUP (I reset this the flag, but it comes again). Sometimes I have receive USB RESET interrupt (device address setting timeout exceed and host perfromed bus reset), but after that I receiving WKUP events again. In the end, the host give up and no more interrupts occurs. In addition ESOF condition is happens before WKUP.

My theory: USB-module does not run properly and is not able to understand what is coming on the bus except RESET. Data transfer is seen as an WKUP event (which is in fact caused by any activity on the line).

Maybe I forgot to initialize something or do it wrong.

The hardware part is OK - USB works properly with ChibiOS or libopencm3 on same board.

Any ideas?

#usb #stm32f103
2 REPLIES 2
manuel239955
Associate II
Posted on November 18, 2015 at 12:37

Doesn't the USB Hardware need 48MHz (instead of 72MHz?)

I use CubeMX to configure the Clock paths and let it generate Code, then I copy&paste what i want from that to my own clock init. Makes it much easier as setting up all clocks can be quite challenging.

Maybe do that and compare the output to your own code to be sure USB has 48 MHz.
kiv
Associate II
Posted on November 20, 2015 at 02:24

I solved this problem now. Need to disable WKUP interrupt when USB is not in sleep mode. WKUP must be enabled only when SUSP interrupt happens and disabled after WKUP. WKUP always triggered on any bus activity.

RESET

SETUP (request device descriptor)

Send the first 8 bytes of descriptor

EP0 OUT (zero length)

Comes CTR of EP0 IN

RESET

SETUP (set address)

Send ZLP and save address to variable

Comes CTR of EP0 IN

Writing address to DADDR

SETUP (request device descriptor)

Send the first 8 bytes (18 total) of the descriptor

Comes CTR of EP0 IN

Send the following 8 bytes of descriptor

Comes CTR of EP0 IN

Send the last 2 bytes of the descriptor

EP0 OUT (zero length)

Set EP0 IN and OUT to STALL state

Comes CTR of EP0 IN

Set EP0 IN to NAK state

Nothing else comes

Host successfully gets a device descriptor, but does not try to get the configuration descriptor even. I think I did not finish correctly the transfer of the device descriptor.