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

26 REPLIES 26

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

Hi Hans,

Congratulations for your baby boy and thank you very much for sharing your experience.

My board is also a custom made board with STM32F103VET6

The USB circuit

0693W000001sTnnQAE.png

The clock circuit

0693W000001sTnsQAE.png

The clock config.

0693W000001sTmaQAE.png

I knew that the demo has no PA8 for pull up, so I added that in "usb_device.c" in "void MX_USB_DEVICE_Init(void)" before "if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)" but not stable, sometimes (normally nothing happened) I managed to see the flash drive after running the debug mode several time but it gone after 1 or 2 sec.

I will look into the USB_CoreReset() and see what I have found.

Thank you very much again for your help.

Simon

Hi Hans,

What a story! Thanks for sharing it.

Please select your post as Best so that the thread is marked as solved.

And all the best to the baby and his parents!

Jan

Hi Simon

I am sure I have very inferior STM32 knowledge compared to many here. As far as I can see your clock configuration looks OK to me, for USB FS because you have 48MHz for the USB peripheral which is good. There are TWO things which I can immediately think of which may be causing your problem.

  1. The USB FS spec requires a 1.5K pull-up to 3.3V on the USB D+ signal. You did not provide that. On some members of the STM32 device family, the USB FS pull-up resistor is provided by the STM32 internally. On other members, it is not. I am using the STM32F401RBT6 and on this device there is an internal 1.5K pull-up resistor and so an external resistor is NOT required. However on the STM32F103 there is no internal pull-up resistor in the USB peripheral and therefore you must provide it externally. I have been bitten by this too, on a different project, that used STM32F103 on my own custom board! I was pondering that for a long time and found the answer with a bit of Googling. As soon as I added the 1.5K pullup to 3.3V, my problems disappeared. In your case you have a transistor switching it, which itself will cause a ~0.6V voltage drop from 3.3V; AND you are using a 10K resistor. I would recommend deleting that whole circuit and just use a 1.5K pullup to +3.3V. Do you really need to be able to switch it? If you really do, perhaps use a P-channel MOSFET to avoid the voltage drop (I don't know if the voltage drop causes a problem or not). But either way 10K is wrong, it should be 1.5K.
  2. You mentioned running in debug mode. One thing about USB is that you CANNOT run the firmware in debug mode, as far as I know. Not over the SWD interface anyway. This is because the USB protocol has communication events every 1 millisecond. As soon as you set a breakpoint or are stepping through the code, you will miss those 1 millisecond communication events and the USB host will decide your device is faulty and drop the USB connection. This is why some helpful members of this forum recommended that I set up a USART and add some serial debug using that. This works because it just dumps text to the serial port, at locations in the code you specify, and this does not stop the processor so it does not interfere with the USB interrupts.

Good luck

Hans

Thanks Jan

And done! I selected my post as Best. I do consider the problem solved as far as I am concerned. I completed my USB bootloader firmware update project and it works beautifully.

Regards, Hans

Hi Hans,

Thank you very much your advice.

Eventually I got that work perfectly.

I had changed the value of the resistor and switched on the pull up pin but it didn't work. However, I noticed that when I deleted the customized contents in "STORAGE_Init_FS", "STORAGE_GetCapacity_FS", "STORAGE_Read_FS" and "STORAGE_Write_FS" under "usbd_storage_if.c", my pc could detect the USB drive but it asked me to format the drive, then I understand the drive didn't show up because of the problems of my custom code ! I did some google search again and found one example to the drive perfectly. I can have a good sleep tonight.:D

reference link:

https://controllerstech.com/stm32-usb-msc/

Thank you so much for you help again!

Simon

avenk.1
Associate II

I able to see the stmboard RAM as storage in pc.

I need to transfer the data from RAM storage to pc in the form of files and buffer. how to transfer i unable to find it which function we need to use. can send me demo.

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

{

 /* USER CODE BEGIN 6 */

memcpy(buf, &buffer1[blk_addr*STORAGE_BLK_SIZ], blk_len*STORAGE_BLK_SIZ);

 return (USBD_OK);

 /* USER CODE END 6 */

}

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)

{

 /* USER CODE BEGIN 7 */

memcpy(&buffer1[blk_addr*STORAGE_BLK_SIZ],buf,blk_len*STORAGE_BLK_SIZ);

 return (USBD_OK);

 /* USER CODE END 7 */

}