cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with USB Mass Storage Device class on STM32F401RBT6

HSumm.1
Associate III

Hi

My board has, among other things, an STM32F401RBT6 and a full-size USB B (device) connector. System clock is an external 25MHz TCXO.

I have verified that the hardware is working correctly, because I have already implemented a compound device class containing USB Audio device and Communications Device class and that all works perfectly.

When I try to flash a project containing a very simple MSC Device class with a 16K RAM Disk, nothing happens. Specifically I followed this ST Video tutorial: https://www.youtube.com/watch?v=GjQqZd1keBo which is very clear and he literally only writes/changes 5 lines of code. Yet when I plug in the USB cable to the PC I see nothing at all on the PC. I have tried on Linux, nothing shows up, even on an lsusb command typed in a terminal. I have tried on the only Windows machine I have, which is a WinXP Laptop. Again, nothing...

The video tutorial is written for a STM32F446 on a Nucleo board; the only changes I made compared to the video were:

1) Reduce the RAM disk size from 64K to 16K because my F401 processor has less memory than the F446

2) Different clock configuration as my processor is max 84MHz and my external clock TCXO is 25MHz. However the USB peripheral is correctly configured at 48MHz and processor clock at 84MHz etc so I do not believe there are any issues here.

I used "min heap size" 0x2000 and "min stack size" 0x400 as in the video.

Any help would be very much appreciated, I have googled and YouTubed for days and got nowhere, and all my hair is almost torn out...

Thanks in advance

Hans Summers

1 ACCEPTED SOLUTION

Accepted Solutions

Hello Simon

Apologies for the delayed reply, we have a new baby boy in the family, born 1 week ago... and things have been rather hectic since then...

Eventually I think I have concluded that the problems I had were not any fault in the ST libraries. My application project worked, but not my sample demo project which was to become my bootloader. I believe that in the end, this is my fault, for forgetting about a specific detail of my hardware.

Specifically: my PCB (this is not an ST Dev board, it is my own PCB design) originally had a 25MHz crystal as the system clock, in a push-pull oscillator composed of an NPN and PNP transistor. It was done this way since the oscillator also acts as reference for an Si5351A PLL Synth chip. I did NOT choose to configure a MCO output of the STM32 since these have various low level spurii which would have been a problem in my application. Then I manufactured a batch of boards. AND THEN, I found I needed greater frequency stability. I replaced the crystal with a 25MHz TCXO which then has excellent stability; to do this I had to make a tiny daughterboard containing three connections (3.3V power, Gnd, and 25MHz output). The way it worked out, the only way to conveniently install this daughterboard was to make use of a spare I/O pin pad of the processor which happened to have been provided in my PCB layout, at a 0.1-inch header strip and was not in use. This spare I/O pin supplies 3.3V at 1.25mA for the TCXO. The I/O pin must be configured as GPIO output and set High by the GPIO_Init() before the system clock init is done. So that the TCXO is powered up. It's an inconvenient arrangement, obviously it would be much nicer to power the TCXO from the 3.3V supply rail but physically that did not work on my already-manufactured batch of 500 PCB Assemblies... that was why I opted to use the I/O pin which was conveniently placed.

I believe my error was that in setting up the Mass Storage Device class according to the ST tutorial YouTube video, I followed the steps precisely; I even configured some other I/O pins which I knew I needed, to disable some parts of my hardware for the demo; BUT, I failed to remember that I needed to configure that I/O pin high, which powers my TCXO. Big doh.

What I *ought* to have done of course, is try again the ST demo video, and this time remember to add the config to power up that I/O pin... but by the time I had it working and realized my error, after several frustrating weeks, I was so excited to continue and make progress that I just continued on with my next steps in my bootloader development!

In the end then I have big fat piles of rotten eggs on my face... thanks to all who responded in this thread kindly, and actually on the plus side, all the debugging I did, I did learn a lot from. All the debugging showed a failure in the USB Core Reset function, a timeout of the command to the STM32 core to reset the USB peripheral; someone further up this thread suggested that would be likely due to incorrect clock configuration. In the end they are CORRECT, the ST library is not any longer under suspicion, it was, I believe, my own fault!

So I progressed further and finished my USB Bootloader with a bit more blood, sweat and tears but no major blockages. What I have now is a bootloader which fits in the lowest 16K Flash sector of the STM32F401RBT6. When the bootloader is run in firmware update mode, my PCB appears to the host computer as a USB Flash drive, containing two files: the firmware binary, and an EEPROM file - which is read from the onboard I2C EEPROM chip. These two files can be read and written from/to the PCB exactly as one would read/write to a USB Flash drive; by copying files in File Manager. It works on Linux, Windows (I tested both) and presumably Mac, without any drivers, without any special software, etc. Because USB Flash drive MSC is already supported inherently by all Operating Systems. In the event that the user copies a new firmware file onto the board, the bootloader erases the upper Flash blocks (112K) and writes in the new binary, then boots into the newly updated application firmware. 256-bit AES encryption is also included which secures the firmware and board such that use of the firmware files on cloned PCBs is not possible, and installation of other firmware on my PCB is also not possible.

All in all I am very pleased with the result.

BUT, Simon, I am not sure that this helps at all with your problem. As I mentioned, in my own case after adding a 38400 baud USART and adding debug statements all over the place, I finally found the failure occurred in the USB_CoreReset() function. This should have been an indicator that the clock configuration was incorrect. You may have this problem, you may have others... I think there are a million ways to fail, and only one way to succeed... but this is not a life philosophy topic...

Everything the kind members of this forum said was good advice and I would suggest you to also follow it; try adding debug statements to see what is going on inside the code. If it so happens that the USB_CoreReset() function is where it fails, just the same as in my case, then it would be worth examining the clock configuration to make sure you really do have 48MHz on the USB clock.

Regards

Hans

View solution in original post

26 REPLIES 26

Make sure HSE_VALUE is set correctly in stm32f4xx_hal_conf.h

Add telemetry via a UART so you can understand the internal interactions, USB queries/responses, disk reads/writes, etc.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

nm

If you feel a post has answered your question, please click "Accept as Solution".

Thanks Clive.

HSE_Value is correctly set to 25MHz in stm23f4xx_hal_conf.h

I will add telemetry as you suggest, and let you know if I can find anything...

FYI the code generation used STCubeMX version 5.2.1. I believe that's a fairly recent version.

Regards

Hans

Hi...

An update...

I implemented telemetry USART debugging at 38400 baud. I put a debug trace in EVERY function in all the USB source code files: usb_device.c, usbd_conf.c, usbd_desc.c, usbd_storage_if.c, usbd_msc_bot.c, usbd_msc_data.c, usbd_msc_scsi.c, usbd_msc.c, usbd_core.c, usbd_ctlreq.c, usbd_ioreq.c. as well as some additional status information in some functions, such as whether they return a success or fail.

On booting the application, the following log is generated on the terminal, all of which occurs in the call to function MX_USB_DEVICE_Init(); in main().

MX_USB_DEVICE_Init entry

USBD_Init entry

USBD_LL_Init entry

HAL_PCD_MspInit entry

HAL_PCD_MspInit exit

USBD_LL_Init exit

USBD_Init exit: OK

USBD_RegisterClass entry

USBD_RegisterClass exit

USBD_MSC_RegisterStorage Entry

USBD_MSC_RegisterStorage Exit

USBD_Start entry

USBD_LL_Start entry

USBD_Get_USB_Status 0 OK 

USBD_LL_Start exit

USBD_Start exit OK

MX_USB_DEVICE_Init exit

On plugging in the USB cable to a PC, nothing at all happens. No new entries on the terminal. It feels like something very fundamental is wrong! But what? Until all this was added, the code was exactly like the ST training video except for the smaller number of blocks (to fit my smaller memory, 64K). As far as I know, NVIC interrupts are enabled properly. The physical connections are OK, it is not something silly like a defective USB cable, because if I load in my other application (with the compound USB device class containing audio and CDC) the computer recognizes it normally. There is not a hardfault because I am also flashing a LED in the main while loop at 1Hz. Nothing hangs up.

Any suggestions would be very welcome

Regards

Hans

TDK
Guru

If you probe the DM/DP lines, does one of them get pulled up to 3.3V?

If you feel a post has answered your question, please click "Accept as Solution".
HSumm.1
Associate III

That's a very good point. I have not fitted a 1.5K pull-up resistor to D+ because the STM32F401 has this internally. I did actually leave a space on the PCB for one because I wasn't totally 100% convinced 🙂 BUT - the other (main) application works fine. So that means there has to be something incorrect in the library set-up here, that has not enabled the STM32F401 internal pull-up...

OK great, this narrows down the problem significantly... I will report back... thanks

Hans

Have you clicked in VBUS support? If yes, is VBUS (PA9) connected?

I don't Cube.

JW

JW... VBUS support is not clicked...

Hi...

Further update... I found that in the function USB_CoreReset() in stm32f4xx_ll_usb.c this code:

 do

 {

  if (++count > 200000U)

  {

   return HAL_TIMEOUT;

  }

 }

 while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);

produces a HAL_TIMEOUT.

In other words the Core Reset bit of the GRSTCTL register is set by this function to cause a USB core reset, but the reset is not considered to have executed successfully.

This error passes back up the call stack and prevents the proper initialization of the USB peripheral.

Has anyone any idea, what could cause this?

Thanks, Hans