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

1 ACCEPTED SOLUTION

Accepted Solutions
crwper
Senior

Hi all--

I believe I've found a solution to this problem with the help of ST technical support. The underling issue is that CPU2 uses the USB clock to run the RNG. When it's done with the RNG, it will shut down the USB clock unless you've told it not to. The relevant code that solved the issue for me is this:

void PeriphClock_Config(void)
{
#if (CFG_USB_INTERFACE_ENABLE != 0)
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
  RCC_CRSInitTypeDef RCC_CRSInitStruct = { 0 };
 
  /**
    * This prevents the CPU2 to disable the HSI48 oscillator when
    * it does not use anymore the RNG IP
    */
 
  LL_HSEM_1StepLock( HSEM, 5 );
 
  LL_RCC_HSI48_Enable();
 
  while(!LL_RCC_HSI48_IsReady());
 
  /* Select HSI48 as USB clock source */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
 
  /**
    * Configure the clock recovery system (CRS)
    */
 
  /* Enable CRS Clock */
  __HAL_RCC_CRS_CLK_ENABLE();
 
  /* Default Synchro Signal division factor (not divided) */
  RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
 
  /* Set the SYNCSRC[1:0] bits according to CRS_Source value */
  RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;
 
  /* HSI48 is synchronized with USB SOF at 1KHz rate */
  RCC_CRSInitStruct.ReloadValue = RCC_CRS_RELOADVALUE_DEFAULT;
  RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT;
 
  RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;
 
  /* Set the TRIM[5:0] to the default value*/
  RCC_CRSInitStruct.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT;
 
  /* Start automatic synchronization */
  HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);
#endif
 
  return;
}

This is placed in the "USER CODE BEGIN 4" block in main.c, and called from the "USER CODE BEGIN SysInit" block. The top half of the function prevents CPU2 from shutting down the USB clock. The second half is unrelated to the problem.

Michael

View solution in original post

22 REPLIES 22
crwper
Senior

I'm just taking another look at AN5289, and noticed in Table 2 (page 19) that USB is not listed as a shared peripheral. Am I wrong in assuming that USB is shared between CPU1 and CPU2?

Michael

crwper
Senior

I'm still working on this issue, and have been looking at USB initialization with and without the BLE stack started. If we don't start the BLE stack, the USB mass storage device enumerates normally and we see the following sequence of calls to HAL_PCD_IRQHandler:

HAL_PCD_IRQHandler:                          RESET                0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                          RESET                0 0
HAL_PCD_IRQHandler:                                SOF ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                SOF ESOF       0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                          RESET                0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                SOF ESOF       0 0
HAL_PCD_IRQHandler:                                SOF ESOF       0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler: CTR                                           1 0
HAL_PCD_IRQHandler: CTR                                           0 1
HAL_PCD_IRQHandler: CTR                                           0 1
HAL_PCD_IRQHandler: CTR                                           0 1
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                SOF            0 0
... then more of this

Here, for each call to HAL_PCD_IRQHandler, I show the result of USB_ReadInterrupts, i.e., what flags are set in USB_ISTR. The last two fields show the value of DIR and EP_ID.

(continued...)

crwper
Senior

(...continued)

If, instead, we allow the BLE stack to start by calling SHCI_C2_BLE_Init, here is the result:

HAL_PCD_IRQHandler:                          RESET                0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                          RESET                0 0
HAL_PCD_IRQHandler:                                SOF            0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                                    ESOF       0 0
HAL_PCD_IRQHandler:                     SUSP           ESOF       0 0
HAL_PCD_IRQHandler:                WKUP                           0 0
... then more of this

In this case, the mass storage device goes into a sequence of suspending after 3 ESOF interrupts, then waking up, receiving 3 more ESOF interrupts, suspending, etc.

This is a very simple application. I've just built a minimal BLE server and USB mass storage device using the ST middleware. Individually, each one works fine. But if the BLE stack is allowed to start, the USB mass storage device fails to enumerate.

At this point, I'm trying to understand what might cause the BLE + MS version to go into a loop of suspending and waking up. I'm hoping some of the information above might mean more to one of you.

Any ideas would be greatly appreciated. Thanks for your help!

Michael

~Amit~
Associate III

Hi Michael,

I am facing the same issue here...

took me about a few hours just to understand there is a correlatrion between the USB and the BLE :weary_face:

did u solve it?

~Amit~
Associate III

tried to replace the initialization order, that helped once but not stable

crwper
Senior

Hi Amit--

I haven't figured it out yet, but am still exploring the problem. I'll post any progress I make here. Please let me know if you learn anything new.

Michael

crwper
Senior

Hi all--

I believe I've found a solution to this problem with the help of ST technical support. The underling issue is that CPU2 uses the USB clock to run the RNG. When it's done with the RNG, it will shut down the USB clock unless you've told it not to. The relevant code that solved the issue for me is this:

void PeriphClock_Config(void)
{
#if (CFG_USB_INTERFACE_ENABLE != 0)
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
  RCC_CRSInitTypeDef RCC_CRSInitStruct = { 0 };
 
  /**
    * This prevents the CPU2 to disable the HSI48 oscillator when
    * it does not use anymore the RNG IP
    */
 
  LL_HSEM_1StepLock( HSEM, 5 );
 
  LL_RCC_HSI48_Enable();
 
  while(!LL_RCC_HSI48_IsReady());
 
  /* Select HSI48 as USB clock source */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
 
  /**
    * Configure the clock recovery system (CRS)
    */
 
  /* Enable CRS Clock */
  __HAL_RCC_CRS_CLK_ENABLE();
 
  /* Default Synchro Signal division factor (not divided) */
  RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
 
  /* Set the SYNCSRC[1:0] bits according to CRS_Source value */
  RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;
 
  /* HSI48 is synchronized with USB SOF at 1KHz rate */
  RCC_CRSInitStruct.ReloadValue = RCC_CRS_RELOADVALUE_DEFAULT;
  RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT;
 
  RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;
 
  /* Set the TRIM[5:0] to the default value*/
  RCC_CRSInitStruct.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT;
 
  /* Start automatic synchronization */
  HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);
#endif
 
  return;
}

This is placed in the "USER CODE BEGIN 4" block in main.c, and called from the "USER CODE BEGIN SysInit" block. The top half of the function prevents CPU2 from shutting down the USB clock. The second half is unrelated to the problem.

Michael

I had the same problem. I want to access the MCU over USBserialCOM-Port or BLE. After the scheduler was called, the controller is not reachable over USB anymore. I added the code you provided and it works perfectly fine again. I did not experience this problem with the Nucleo-Board. Maybe because I used a different BLE-Stack-Firmware back then.

Thank you very much. :)

BNist.1
Associate II

Hello! I know this is not really related to your issue, but I've noticed that you managed to make an microSD work with SPI on STM32WB55.

Would you mind sharing the code that allowed you to do this? I am literally doing the same functions as you did, but I don't seem to make the SD card work by any means... It always returns FR_NOT_READY..

Thanks!