cancel
Showing results for 
Search instead for 
Did you mean: 

How to make STM32H7 HAL USB driver OS compatible

wildfireheart
Associate II

Hello,

Various CubeMX generated files related to USB, such as "usbh_conf.c" and even "stm32h7xx_ll_usb.c", are littered with HAL_Delay() waiting up to hundreds of milliseconds and therefore halting threaded application execution. Every time I switch USB keys (STM32 is MSC host), everything freezes for up to 200-300 ms.

I'd like to ask if it is me, who is doing something wrong, because I cannot wrap my head around how can something like this make it into official firmware and stay there for so long. Also, how can I replace it with for example osDelay() and keep the changes after project regeneration. I don't want to change HAL_Delay() to use osDelay(), as it is used for some delays in initialisation before scheduler takes over and it generally seems like bad idea.

6 REPLIES 6
Pavel A.
Evangelist III

Note: the USBH/USBD stuff is not quite an "official" firmware. It sits under "Middlewares", collection of various components, possibly useful.

ST haves it there it for their demo projects, it works just good enough for that purpose.

The low-level USB controller drivers under Drivers/STM32xxx_HAL_Driver are the "official firmware". They don't contain any such delays,

-- pa

willcfj
Senior

Hi wildfireheart, Interesting timing, I'm just starting a USB project under FreeRTOS and running into some issues too. I'm using the CDC profile and I haven't seen the delay problem yet, I see #defines mapping to HAL_Delay, but no usage. What profile are you using? I do have another OS-compatibility question to add to the discussion. I want to send a signal to my main USB task whenever some data has been successfully sent to the host and the hardware is ready for some more data. Seems simple enough.

The callback for transmission complete looks to be HAL_PCD_DataOutStageCallback(). There is a__weak definition in stm32h7xx_hal_pcd.c. I tried creating my own function to override it, but it is already being used in usbd_conf.c. Alas it is in an area that doesn't have any USER_CODE slots, so if I ever go back to CubeMX, it is going to be deleted.

When I look at the example CDC application code in the STM32CubeF7 distribution (it is standalone, not RTOS), that code does a polling loop based on a 1ms timer to check and see if the device is busy or not. Polling every 1ms seems horribly inefficient compared to a call-back. Anyone know a reason it should be done this way instead of a callback?

will

"The low-level USB controller drivers under Drivers/STM32xxx_HAL_Driver are the "official firmware". They don't contain any such delays,"

These are from "Drivers/STM32xxx_HAL_Driver/stm32h7xx_ll_usb.c":

HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_OTG_ModeTypeDef mode)
{
  ...
  HAL_Delay(50);
  ...
}
HAL_StatusTypeDef  USB_DevConnect (USB_OTG_GlobalTypeDef *USBx)
{
  ...
  HAL_Delay(3);
  ...
}
HAL_StatusTypeDef  USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx)
{
  ...
  HAL_Delay(3);
  ...
}
HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
{
  ...
  HAL_Delay(200);
  ...
}
HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx)
{
  ...
  HAL_Delay (100);                                /* See Note #1 */
  ...
}

If it wasn't there, I would not be asking this question. I can probably accept HAL_Delay() being used in "usbh_conf.c", but what should I do with this? For now I replaced everything with osDelay() and it works as expected, but after regeneration those changes will be overwritten.

EDIT: I replaced "stm32h7xx_ll_usb.c" with my own and excluded the original one from build, not great solution, but good enough until they fix it in LL library.

I haven't tried if it is a good solution, but you can remove ST USB middleware in CubeMX and add it to project manually, then edit whatever you need. Or exclude "usbd_conf.c" from build (in Eclipse right click on file in Project Manager -> Resource Configuration -> Exclude from Build) and add your own file somewhere with edited implementation from "usbd_conf.c".

WildFireheart: That is weird on the HAL_Delay calls in stm32h7xx_ll_usb.c. At least in the files copied to the user src space they have #defines to map delay calls to your favorite delay function. I will keep those in mind if I run into some strange timing problems as well.

I agree there are ways around the CubeMX-generated code, but like you worry about un-intended consequences. I'm also new enough at this class of programming (I'm stepping up from bare-metal programming), that I also like to ask if maybe there is a reason something is being done a way that doesn't make sense to me. I will spend some more time going over the driver code to see if there is any other weirdness that suggests hijacking that call may not work.

will

Wildfireheart: After a lot more poking around, the call-back isn't going to work. There are lots of other transactions going on besides the particular data I want to send to the host, and that call-back can be for any of them. Once the data is sent, the context of what calling function sent it has been lost. Without huge changes, polling is the only way--ick.

Looks like we each answered our own questions! 🙂

will