cancel
Showing results for 
Search instead for 
Did you mean: 

Problems using USB mass storage middleware with BLE stack on STM32WB55?

crwper
Senior

I'm developing an application which uses both USB mass storage and BLE. I've started by building two separate applications using STM32CubeMX:

  • A USB mass storage application communicating with a microSD card over SPI1
  • A BLE P2P server

Both of these work fine on their own. But if I build an application that includes both components, the USB mass storage device will not enumerate properly.

Initially, I discovered that in the full application, HAL_PCD_IRQHandler got called, but it never fell through to PCD_EP_ISR_Handler. This makes me think the mass storage endpoints have not been configured properly.

I've also tackled the problem a different way--by systematically eliminating parts of the BLE initialization to determine what is interfering with USB mass storage. Using this method, I've been able to determine that if I comment out the call to SHCI_C2_BLE_Init in APP_BLE_Init (in app_ble.c), USB mass storage enumerates properly. If I then uncomment this line, it stops working again.

SHCI_C2_BLE_Init simply sends a message to CPU telling it to start the BLE stack, so this makes me think that the BLE stack on CPU2 is somehow interfering with USB endpoints configured before the call to APPE_Init in main.c.

I believe USB is a shared resource between CPU1 and CPU2, so it seems likely that the BLE stack is also trying to do something with USB. However, I'm at a loss as to how to debug this further or how to avoid the problem.

Any help would be greatly appreciated!

Michael

22 REPLIES 22

Of course! The attached project should work on a P-NUCLEO-WB55 board. The microSD card is connected as shown here:

0693W000000XK3pQAG.png

To build this project, I started with an empty P-NUCLEO-WB55 project, added SPI1 and FATFS, configured both, then added/replaced these files in the FATFS/Target folder:

  • mmc.c
  • mmc.h
  • user_diskio.c

My disk interface (build around ChaN's example) is contained in mmc.* and these functions have been added to the original skeletons in user_diskio.c.

Note that I'm not using SPI very efficiently here. Even for large transfers to the microSD card, I'm using polling HAL functions in mmc.c. To optimize, you should use DMA transfers in the "rcvr_spi_multi" and "xmit_spi_multi" functions.

On the hardware side, you'll need pull-ups on the NSS and MISO lines. I think I'm using 10k.

Michael

Hey! Thank you so much for your answer!

I have some questions for you if you have the time. These are the steps that I took:

  • I used your files and modified the CS pin in order to be the same as mine PA15
  • I added "Hardware NSS output signal" in the SPI section. Here I don't quite understand this and what is a NSS. I have a module SD which has my CS on it, I don't quite get why you suggested using NSS.(or if I even understood it well enough)Then I changed the PIN back to GPIO_OUT. In both cases the program is doing the same thing:
  • I then ran the program with debugging on "f_mount" and "f_open", however when it reaches "f_mount" it does not go further on the the other instructions and it keeps running. When I pause it the first instruction in the thread is the init_spi from "mmc.c" with the timers:
void init_spi (void)
{
	CS_HIGH();			/* Set CS# high */
 
	for (Timer1 = 10; Timer1; ) ;	/* 10ms */
}

I am kind of lost here, there are no errors, no warnings, it just keeps running. (I have a pressure sensor connected as well and the system works as I get data from the sensor, however the SD won't get past the f_mount)

You also said about having pull-ups on the NSS and MISO lines. I have no pull-ups, I thought that the SD module was taking care of all of that. Do I still need to add them? And when you say NSS, you mean the CS pin?

Sorry if all of these sound like basic questions and thanks again!

A couple of things come to mind:

  1. You actually don't want to use hardware NSS. If you look at mmc.c, you'll see we toggle the NSS pin manually. I've just named it SPI1_NSS for consistency with the rest, but we are using it as a GPIO output.
  2. NSS is the SPI CS signal. The SPI bus can attach to several different devices, so the CS signal is used to indicate which device you're talking to. In this case there is only one device, but the microSD card is still expecting to see CS toggled high/low in certain places so it knows data is coming. To get an idea where this is, look for "CS_HIGH" and "CS_LOW" in mmc.c.
  3. ChaN's examples, and my mmc.c code, use a 1 ms "heartbeat" to manage timing. This is handled by calling MMC_timerproc from SysTick_Handler. If you look in my stm32wbxx_it.c, you'll see it. If this isn't called, then the heartbeat never happens, so the system will lock up waiting for the timer to elapse (which is where you're seeing it lock up).
  4. The SD module doesn't take care of pull-ups, as these are specific to the SPI interface. If you don't add pull-ups, the microSD card may not work properly (or may work intermittently). Generally, everyone recommends pull-ups on MISO and NSS (DO and CS on the microSD card).

I hope this helps! I've encountered similar issues to what you're seeing, and the above is how I was able to solve them.

Michael

Hello,

Thank you for these answers! I managed to solve the timer problem and now it is not stuck anymore!

However, I got back to the old problem (that I had after trying the tutorials available on the internet) that I get FR_NOT_READY after doing the "f_mount" function. I also added 2 pull up resistors of 10k each on CS and MISO, but I get the same result with or without the pull-ups...

Do you have any idea on why I might be still getting this?

Thanks!

The first thing I would do is to step through and find out exactly why it's returning FR_NOT_READY. If you have a logic analyzer, I would also take a look at the communications and make sure you can see both parts communicating on the bus. If you don't have a logic analyzer, I'd highly recommend picking one up--otherwise, debugging digital circuits is like playing darts in a room with no light.

Michael

I am gonna check it with a logic analyzer, as you have suggested!

I also notice that from time to time it seems to be working, I get FR_OK, but then when I check for the file, it's not there. Also next time I try I always get again the FR_NOT_READY.

I've seen some posts online that it depends if the SD card is formatted with FAT16. Do you think that matters? I have an SDHC of 16gbs. Nevertheless I formatted it with FAT16, same story. I would also like to ask you, if you have written some data about the card in your code? I've noticed there's a section for the type of the card. Should I be concerned by it?

Than you so much for your time!

The code shouldn't care what kind of card you're using. I've written to cards from 512 MB to 32 GB using the same code.

If you have a P-NUCLEO-WB55 board, have you tried compiling and running the project I sent with no modifications (and with the card connected the same way I've connected it)? This should work the same on your board as on mine, and it would provide a good baseline for testing.

Michael

Yes, I have tried your project as well and it goes into HardFault_Handler() from stm32wbxx_it.c. I've tried it with and without pull-ups.

At this point I think it comes down to a hardware problem as I can't see where should be the issue with the software..

Bogdan

BNist.1
Associate II

Hello again!

I finally figured it out, I had forgotten to write the interrupt for the mmc file and that is why it was not working! I took me a while to get a grip of it, but I am glad I can finally transfer my data to the SD card!

Now I bumped into another problem, as I am trying to advance the project and send the sensor data via BT to my phone, while also registering it at the same time to the SD card.

It is exactly the same issue you've had. Both applications are working perfectly on their own, but after introducing the code for the SD card nothing works anymore.

I don't get this exactly, but I am trying to set the clock to PLLCLK in order to use the peripherals, but at this point the BT is not working anymore (neither does the SD but this is another thing). I have tried introducing your code that you mentioned above, but it doesn't seem to have any effect. I am definitely approaching this from a wrong perspective.

What else did you change in your code in order to be able to receive sensor data by BT while also storing it via SD? Is there any call function to the code you shared?

How do I deal with the clock in this situation, I saw on the Hands On tutorial that the BT uses HSE, however the SD would use PLLCLK (from what I understand), how do I merge them in order to work together.

Let's say the BT works, however I have my UTIL_SEQ_Run(~0); that starts the BT functions. This would be placed in the main.c function, however so is my code for the SD card. How would I get past this in order to access the rest of the code for the SD? Would I write this one in the template_stm? I also seem to have a problem with the MMC_timerproc handler from stm32wbxx_it.c. When I keep this function there, the BT stops working going into some SPI function.

I hope you could help me with this and thank you for your time!

Bogdan

It sounds like there are a few gaps in your understanding which are causing problems here. I would approach it from this angle:

First, check out the STM32WB Workshop here:

https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/STM32WB_workshop_MOOC.html

Don't just read it, though. Follow along with each step, and make sure you understand exactly why they're doing each one, specifically what the code does, etc. It's easy to overlook opportunities to learn if you're just copying and pasting code.

Next, take a look at this application note from ST:

https://www.st.com/content/ccc/resource/technical/document/application_note/group1/43/ea/2f/dc/10/a3/46/e6/DM00598033/files/DM00598033.pdf/jcr:content/translations/en.DM00598033.pdf

Again, if you haven't already done so, carefully read the whole thing. This document does a great job of expanding on what's done in the STM32WB Workshop.

Next, take a close look at the BLE_HeartRate example. Don't just compile it and install it. Notice how simple the main loop is. This example does a lot of what you're trying to do (minus the SD interface). So where are they generating "sensor" data? How are they handling low power modes?

Finally, read the RCC chapter in the Reference Manual. The STM32 has a clock tree which generates a lot of different clocks for different peripherals. It's worth reading closely so you understand how each of these clocks is generated, what peripherals they're associated with, and what happens to each one when you go into a low power mode.

I hope this helps!

Michael