Author Topic: STM32F411 USB module step by step  (Read 7439 times)

0 Members and 4 Guests are viewing this topic.

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
STM32F411 USB module step by step
« on: February 26, 2025, 06:22:20 pm »
Hi all,
After takling a little the USB module in the STM32F103, I want to play with that of the big brother the STM32F411. It's a complicated beast but I project to start with the device mode only.
I've taken a look at the provided ST library but I found it very difficult alas! So I'm studying the RM 0383, but I couldn't grasp some things:
1- Since the RX fifo is shared, is there one POP register for all EPs? If yes, which one?
If not, are the POP and PUSH registers for an EP the same? If different which is which?
2- What's the minimal initialization needed to start the module aside from enabling clocks, configuring PA11 and PA12 pins to alt-func push-pull outputs with AF10 and enabling the OTG_FS interrupt Nr 67 in the NVIC?
3- What to do when these interrupts fire: RESET and ENUM DONE?
Please help and be indulgent with me.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 5755
  • Country: dk
Re: STM32F411 USB module step by step
« Reply #1 on: February 26, 2025, 06:26:51 pm »
just install stm cube ide  ....
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #2 on: February 26, 2025, 06:32:04 pm »
just install stm cube ide  ....
I prefer going the bare metal way to undersatand what's hapenning under the hood.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 5755
  • Country: dk
Re: STM32F411 USB module step by step
« Reply #3 on: February 26, 2025, 06:41:53 pm »
just install stm cube ide  ....
I prefer going the bare metal way to undersatand what's hapenning under the hood.

so install stm cube ide and look at what it does, unless of course the idea is to make it as complicated and time consuming as possible
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #4 on: February 26, 2025, 06:58:10 pm »
so install stm cube ide and look at what it does.
stm cube ide uses the libraries provided by ST which I've already tried to dig into without success.
I've some spare time to spent in order to understand this module.
After reading the RM, here's a part of the initialization process I'll try:
Code: [Select]
// Force Device mode
OTG_FS->GUSBCFG |= 1<<30;
// Enable O_EP, I_EP, ENUM, RESET and RXLVL Interrupts
OTG_FS->GINTMSK = 1<<19 | 1<<18 |  1<<13 | 1<<12 | 1<<4;
// Turn on the global interrupt switch
OTG_FS->GAHBCFG |= 1<<0;
// enable OTG_FS interrupt (Nr 67) in NVIC
NVIC->ISER[67 >> 5]  = 1 << (67 & 0x1F);
// deactivate power down and disable Vbus sensing
OTG_FS->GCCFG = 1<<21 | 1<<16;
We have to configure the clock to 48MHz and enable it in RCC_AHB2ENR before.
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3741
  • Country: gb
Re: STM32F411 USB module step by step
« Reply #5 on: February 26, 2025, 07:11:52 pm »
I've been meaning to try porting Alex's usb implementation from samd to stm32, just for fun. And I always find Alex's code very clear and concise.

https://github.com/ataradov/vcp/tree/master/samd11
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #6 on: February 26, 2025, 07:27:31 pm »
Thanks volisandjolts for the link, I'll take a look into ASAP.
Is the SAMD11 using the same USB controller as the STM32F4XX??
« Last Edit: February 26, 2025, 07:33:20 pm by DELTA67 »
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #7 on: February 26, 2025, 07:56:43 pm »
and here's the interrupt handler.
Code: [Select]
void OTG_FS_handler(){

unsigned int intflags = OTG_FS->GINTSTS;

if (intflags & 1<<19 ) {
    printf ( "Int -- OUT EP\n");
}

if (intflags & 1<<18 ){
    printf ( "Int -- IN EP\n");
}

if (intflags & 1<<13 ) {
    printf ( "Int -- Enumeration done\n");
}

if (intflags & 1<<12 ) {
    printf ( "Int -- RESET\n");
}

if (intflags & 1<<4 ) {
    printf ("Int - Rx FIFO not empty\n");
}

OTG_FS->GINTSTS = 0xffffffff; // clear all
}
 

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #8 on: February 26, 2025, 08:18:40 pm »
Tested the code above.
I'm getting "Int - Rx FIFO not empty" continously at an astonishing speed!!!
It seems that writing 1 to it's flag in OTG_FS_GINTSTS don't clear it!
But it's a good start, at least the USB module is working and sending interrupts to us.
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3741
  • Country: gb
Re: STM32F411 USB module step by step
« Reply #9 on: February 26, 2025, 08:59:56 pm »
Is the SAMD11 using the same USB controller as the STM32F4XX??

I haven't checked but I expect they are quite different.
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #10 on: February 27, 2025, 02:02:01 pm »
Well, I'm experimenting with this excellent notes (thanks Tom):
http://cholla.mmto.org/computers/usb/hydra/
The test code:
https://github.com/trebisky/stm32-hydra/blob/master/usb_411.c
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: sk
Re: STM32F411 USB module step by step
« Reply #11 on: March 01, 2025, 11:30:33 am »
> 1- Since the RX fifo is shared, is there one POP register for all EPs? If yes, which one?

The FIFO scheme in the Synopsys OTG module is bizarre (and probably tries to cater for memcpy() or similarly working DMAs in mcus other than STM32). There is no single PUSH or POP register, instead, a whole address range functions as such register - 4kB each endpoint's Tx, and, as you've noted, Rx is shared, so probably reading from any of these address ranges would work; but according to  Data FIFO (DFIFO) access register map table you are supposed to read from the same range for given endpoint as you write to.

Note, that anything related to FIFO is word-based - you must access it as aligned words, and every register/bitfield related to FIFO size or occupancy is in words (whereas data-transfer registers are in bytes).

And finally, mind the erratum which mandates a packet's worth of FIFO being read/written at once, without being interrupted by accesses to some other OTG registers.

> 2- What's the minimal initialization needed to start the module aside from enabling clocks, configuring PA11 and PA12 pins to alt-func push-pull outputs with AF10 and enabling the OTG_FS interrupt Nr 67 in the NVIC?

You probably figured that out already - clocks have to be set up in RCC and running, beforehand. start by disabling the integrated pullup by setting USB_OTG_DCTL.SDIS,  you need to enable PHY by setting USB_OTG_GCCFG.PWRDWN (very weirdly named bit, btw.) and you probably want to force the device mode by setting USB_OTG_GUSBCFG.FDMOD. You'd also need to set up the FIFO sizes.  Finally you enable interrupts and the integrated pullup by clearing USB_OTG_DCTL.SDIS.

For a more generic startup you may want to do things like resetting the module beforehand, in some "higher" STM32 model you may need to select FS/HS etc.

> 3- What to do when these interrupts fire: RESET and ENUM DONE?
You may want to read the USB (v2.0) specification. It's quite badly written and not an easy read, but at least skim it through. In this particular case, you may want to look at 7.1.7.3 Connect and Disconnect Signaling and 7.1.7.5 Reset Signaling.
From firmware perspective, the USBRST interrupt is a good place to reset the whole software stack (i.e. remove/reset any outstanding status from previous communications) and to enable EP0 to listen to SETUP packets. The ENUMDNE fire when the FS/HS chirp handshake is over; but in 'F411 is irrelevant as the device speed is there fixed to FS.

> I'm getting "Int - Rx FIFO not empty" continously at an astonishing speed!!!

The mechanism behind RXFLVL interrupt is weird, more complicated than it would appear at first glance (for reasons both historical and to cater for various configurations of the module, e.g. using the internal DMA (which is not present in 'F411's incarnation of this module)), and the main problem is that it's very inadequately described in the documentation.

This interrupt does not indicate "Rx *data* FIFO level". Rather, between the USB core and registers there is a small FIFO conveying events from the Rx portion of USB core to the processor. This interrupt indicates, that this FIFO has some event in it, and you pop these events from this FIFO by reading OTG_FS_GRXSTSP. Read description of this register for Device mode. Popping some of the events triggers other interrupts, see description of the PKTSTS field of this register - for example, popping OUT transaction completed triggers the respective OTG_FS_DOEPINTx.XFCR interrupt.

JW
 
The following users thanked this post: harerod, DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #12 on: March 01, 2025, 02:46:26 pm »
WOW!
Thanks wek for your detailed reply. If you have some bare metal code to share, please, it would be a great help.
I'm studying the RM while trying the code from the given link above.
There are many interrupts and many flags to play with.
 

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 322
  • Country: ua
Re: STM32F411 USB module step by step
« Reply #13 on: March 01, 2025, 05:33:46 pm »
Code: [Select]
// Force Device mode
OTG_FS->GUSBCFG |= 1<<30;

Don't do this. It is unreadable, and unmaintainable.

Use ST's cmsis header with registers and bits definittions, e.g.
https://github.com/STMicroelectronics/cmsis-device-f4/blob/1777d8832e57ec2974afaa9f24dc3ac56bb4cffb/Include/stm32f411xe.h#L7172
Open source embedded network library https://mongoose.ws
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 
The following users thanked this post: SiliconWizard, DELTA67

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 322
  • Country: ua
Open source embedded network library https://mongoose.ws
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #15 on: March 01, 2025, 06:04:49 pm »
Don't do this. It is unreadable, and unmaintainable.
Use ST's cmsis header with registers and bits definittions, e.g.
Thanks tellurium for the remark and the links.
Yes, you are right, my writing style is horrible, but I prefer doing so when learning.
when writing "OTG_FS->GUSBCFG |= 1<<30; ", later I know immediatly that it's bit30 in OTG_FS_GUSBCFG register.
When using a header file the same bit is defined some thing like:
#define OTG_FS_GUSBCFG_FDMOD 1<<30;
In the 2 cases consulting the RM is necessary. I don't see the difference.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 5755
  • Country: dk
Re: STM32F411 USB module step by step
« Reply #16 on: March 01, 2025, 06:22:35 pm »
Don't do this. It is unreadable, and unmaintainable.
Use ST's cmsis header with registers and bits definittions, e.g.
Thanks tellurium for the remark and the links.
Yes, you are right, my writing style is horrible, but I prefer doing so when learning.
when writing "OTG_FS->GUSBCFG |= 1<<30; ", later I know immediatly that it's bit30 in OTG_FS_GUSBCFG register.
When using a header file the same bit is defined some thing like:
#define OTG_FS_GUSBCFG_FDMOD 1<<30;
In the 2 cases consulting the RM is necessary. I don't see the difference.

with the former you have no idea what bit 30 does, with the latter you get the name of the bit and in a sane editor hovering over the constant with show you that is it bit 30 .. 

 
The following users thanked this post: DELTA67

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3741
  • Country: gb
Re: STM32F411 USB module step by step
« Reply #17 on: March 01, 2025, 06:30:34 pm »
I know immediatly that it's bit30 in OTG_FS_GUSBCFG register.

Nobody cares what bit it is, because we can't remember what each bit does (and neither will you in a few weeks).
Reading and understanding firmware with hardcoded bits is a nightmare.
The defined name for that bit gives some information as to the function of it, and in a click you can find the bit number if you so wish.
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #18 on: March 01, 2025, 06:52:52 pm »
voltsandjolts, langwadt and tellurium, sure you are right. My coding style is bad.
some times I put more comments like this:
Code: [Select]
RCC->CFGR &= ~(1<<23);  // I2SSRC (Bit23) = 0 => PLLI2S used as I2S clock 
But it  still a bad habit!!
 

Offline tellurium

  • Frequent Contributor
  • **
  • Posts: 322
  • Country: ua
Re: STM32F411 USB module step by step
« Reply #19 on: March 01, 2025, 10:39:21 pm »
Code: [Select]
// Force Device mode
OTG_FS->GUSBCFG |= 1<<30;

It is quite easy to adopt. For the above example:

Code: [Select]
  #include <stm32f411xx.h>

  ...
  OTG_FS->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;  // Force Device mode

- More readable
- Reduced chances of mistaking bit / shift count
- Reduced changes of making a mistake with bit operations, cause CMSIS bit names are properly parenthesised

Those CMSIS headers exists specifically for that reason, to spare people from writing "1 << 30" things. But maybe you think those bit shifts look sexy, then yeah, the more the merrier
« Last Edit: March 01, 2025, 10:44:53 pm by tellurium »
Open source embedded network library https://mongoose.ws
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 
The following users thanked this post: DELTA67

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 5962
  • Country: gb
  • Doing electronics since the 1960s...
Re: STM32F411 USB module step by step
« Reply #20 on: March 03, 2025, 07:39:30 am »
Nothing wrong with using bit 30 etc so long as you comment it - which you should be doing anyway!
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 
The following users thanked this post: DELTA67

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3741
  • Country: gb
Re: STM32F411 USB module step by step
« Reply #21 on: March 03, 2025, 09:34:45 am »
 :palm:
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 591
  • Country: sk
Re: STM32F411 USB module step by step
« Reply #22 on: March 03, 2025, 03:37:27 pm »
> If you have some bare metal code to share

I write most code for money, so I can't "share" it. But there's code galore out there, except that rarely is it in depth explained/commented (mine is not, either, btw.) So, what you should/can do is, to pick any and try to comprehend. Experiment a lot. If in doubts with the details, ask. Don't be afraid to make errors.

A USB protocol analyzer is a very instructional tool in such endeavour, I urge you to get some if you mean it seriously. There are cheap LAs and/or scopes with USB analyzer option around; I believe there is a related thread somewhere here.

And be prepared to read a lot, even if you won't understand most of that initially, so you are going to re-read it multiple times. Start with the USB chapter in RM and the USB specification.

JW
 
The following users thanked this post: DELTA67

Offline DELTA67Topic starter

  • Regular Contributor
  • *
  • Posts: 138
  • Country: fr
Re: STM32F411 USB module step by step
« Reply #23 on: March 03, 2025, 04:11:36 pm »
what you should/can do is, to pick any and try to comprehend. Experiment a lot. If in doubts with the details, ask. Don't be afraid to make errors.
Thanks wek for the encouragement . I started looking at the code here:
https://github.com/trebisky/stm32-hydra/tree/master/usbF4

A USB protocol analyzer is a very instructional tool.
I'm simulating the STM32F401CE in PROTEUS which has a decent USB protocol analyzer.

And be prepared to read a lot,  you are going to re-read it multiple times. Start with the USB chapter in RM and the USB specification.
I'm reading the RM and taking notes.
« Last Edit: March 03, 2025, 09:18:09 pm by DELTA67 »
 

Offline grantb5

  • Regular Contributor
  • *
  • Posts: 159
  • Country: ca
Re: STM32F411 USB module step by step
« Reply #24 on: July 24, 2025, 04:31:21 pm »
I've used stm32_libusb on STM32F103 with good success. I plan on trying it out on STm32F411 as well, since it is also supported.

https://github.com/dmitrystu/libusb_stm32



 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf