Showing results for 
Search instead for 
Did you mean: 

how to manage USB with a bare-metal application ?



I want to make a bare-metal application (without Linux OS) on a STM32MP157C-DK2 Board.

I need to use the usb host controller from this board (that why I choose it: multiples USB socket) but in the projects created with CubeIde, I can only assign USBH_HS1 or USB_OTG_HS with the A7 runtime context and my application C code is under the folder project_CM4 wich seem related to only M4 context and not with A7 context

So, my question is simple: could we use a USB mass storage device with a bare-metal application on STM32MP157C-DK2 Board  without a Linux distrib?

I am wondering because I can’t find either a HAL USB module as expected in the “stm32mp1xx_hal�?  list as if the only appropriate way to manage usb was with an OS attached to cortec A7

Thanks in advance for any help


0693W000003Qj3lQAC.jpgYou can done this task by using USB_OTG based stack from STM32H7 CPUs.

STM32MP1 hardware very similar in this case.

I am use in my project this codebase, For access to USB_HS2 port you need initialize USBPHYC peripheral.

All of these (including DDR3 and TZC initialization) you can find at my repo here:

Note! Use branch "develop". In stm32mp1 target I use only A7 core.


Thanks for your reply. It's a good starting point.

I will try to manage USB and SDMMC with gpio and hopefully it will work.


ST Employee

There is no ST support of bare-metal SW on Cortex-A7.

HAL provided by CubeMx or CubeIDE only cover Cortex-M4, which does not support neither USBH nor OTG for STM32MP15 family.

Nevertheless, some third-party might offer support of bare-metal on STM32MP157.

As stated by @Genadi Zawidowski​ , OTG could fly using other STM32 HAL code as HW is very similar.

In case you absolutely want to support USBH (e.g. to support external USB Hub or get better host performances than OTG), as USBH is not present on any other STM32, you might think about starting from an EHCI/OHCI standard SW (as this is a standard way to control the USBH IP, you might found example on the web). You might need also some OpenSTLinux driver code analysis.

But as this is not the supported SW and tools, ST could only provide basic help on that subject.


In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

Latest bare-metal Cortex-A7 news:

Added EHCI controller support (trough slightly modified for speed ST USB HOST Middleware).

No HUB support now.

Results of write speed on directly connected USB storages, exFAT, 128 kB blocks in one minute run:

USB FLASH 8GB: Write speed 5332 kB/S

SATA HDD (old 120 GB 5400 rpm Hitachi HTS542512K9SA00 on USB->SATA converter): Write speed 38637 kB/S

Source codes in my GitHub repo

Associate III

@Genadi Zawidowski​ Thank you for sharing your project! I've played with it a bit, and copied some of the changes you made to the CubeH7 drivers to get USB working in a bare-metal context on the STM32MP1. Here's the project (it's a series of examples of bare metal projects for educational purposes):

Let me know if I gave you credit properly or if you would prefer I do something different. I didn't see anything for MSC device mode in the hftrx project, is that something you've experimented with?



MSC device in my current project not ported from original ST files. Only mass changes for successful compilation as part of sources tree.

In my framework sripped out descriptor functionality in USBD_ClassTypeDef.

This because I support compound USB devices.

Existing ST MSC support code can be simply added (ported to my base)..

Associate III

Ok, I managed to port the MSC driver to your base. Here's my work:

There were a few things to change from ST's MSC Device implementation, besides converting the USBD_ClassTypeDef. I used the fops function pointer struct directly, since we don't have pUserData anymore. Also pClassData became a static global, instead of being "malloc"ed. Setting up the descriptors, strings, and the TXFIFO size I think that was all.

A question for you: In USBD_LL_Transmit(), there is this block:

// if (hpcd_USB_OTG.Init.dma_enable == 1U)
  if (pbuf != NULL && size != 0)
    ASSERT(((uintptr_t) pbuf % DCACHEROWSIZE) == 0);
    arm_hardware_flush((uintptr_t) pbuf, size);

You had the `if` commented out, meaning it would always require transmitted data to be aligned to DCACHE lines. For DMA usage, it makes sense because the cache would need to be flushed (cleaned) before the USB core reads it. But, for non-DMA usage, why is it required to flush the buffer from the cache?

Is it just for performance, or is it required for some uses?



As you can see, all cache manipulation functions in this file independent from hpcd_USB_OTG.Init.dma_enable.

 Some of implemented in my project targets (like Renesas RZA1) may not use dma_enable field, but use DMA transfers.

 For non-DMA usages these arm_hardware_*** not required.


I think, ST implned placing DMA-related stuff in non-cached regions.

Can I integrate your work?