Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add STM32H7 Series USB Device Support #33365

Closed
JeremyBCD opened this issue Mar 16, 2021 · 9 comments · Fixed by #33686
Closed

Add STM32H7 Series USB Device Support #33365

JeremyBCD opened this issue Mar 16, 2021 · 9 comments · Fixed by #33686
Assignees
Labels
area: USB Universal Serial Bus platform: STM32 ST Micro STM32

Comments

@JeremyBCD
Copy link
Contributor

Is this request related to a missing driver support for a particular hardware platform, SoC or board? Please describe.
This request addresses USB device driver support on the STM32H7 series. It is not currently supported by Zephyr.

Describe why you are asking for this support?
I have attempted to bring up USB device support myself (see below), but need help understanding where some of the pieces belong (clock and peripheral config) as well as hoping to get support from people more expert in the STM USB implementation.

I am willing, to the best of my abilities, to support this functionality if it makes it into Zephyr.

Additional context
STM32H7 Overview
USB hardware and PCB guidelines using STM32 MCUs - Application note

My Efforts So Far
I have started work in this development branch. I started with trying to bring up the USB FS peripheral on the NUCLEO-H753. I added it to the stm32h7.dtsi and to nucleo_h753zi.dts. (One area where I need help is in understanding how to populate some of the values in the DTS entry for this peripheral, how to find all of the appropriate register values).

With these changes, the samples/subsys/usb/hid sample would compile, but the peripheral failed to initialize.

[00:00:05.006,000] <dbg> main.main: Enabling usb...
[00:00:05.006,000] <dbg> usb_device.usb_enable: lock usb_enable_lock mutex
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_set_status_callback: 
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_attach: 
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_stm32_init: Pinctrl signals configuration
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_stm32_init: HAL_PCD_Init
[00:00:05.025,000] <err> usb_dc_stm32: PCD_Init failed, 1
[00:00:05.025,000] <dbg> usb_device.usb_enable: unlock usb_enable_lock mutex
[00:00:05.025,000] <err> main: Failed to enable USB

Comparing the init and config in Zephyr to a working USB STM32H7 project in STM32CubeIDE, I tried adding some USB peripheral config that seemed to be missing for H7.

With these changes, the device will now initialize! There is even different behavior on startup if a USB host is attached. Specifically, the device is suspended.

[00:00:00.006,000] <dbg> main.main: Starting application
[00:00:05.006,000] <dbg> main.main: Enabling usb...
[00:00:05.006,000] <dbg> usb_device.usb_enable: lock usb_enable_lock mutex
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_set_status_callback: 
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_attach: 
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_stm32_init: Pinctrl signals configuration
[00:00:05.006,000] <dbg> usb_dc_stm32.usb_dc_stm32_init: HAL_PCD_Init
[00:00:05.059,000] <dbg> usb_dc_stm32.usb_dc_stm32_init: HAL_PCD_Start
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_configure: ep 0x00, previous ep_mps 64, ep_mps 64, ep_type 0
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_configure: ep 0x80, previous ep_mps 64, ep_mps 64, ep_type 0
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_set_callback: ep 0x00
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_set_callback: ep 0x80
[00:00:05.062,000] <dbg> usb_device.composite_setup_ep_cb: set cb, ep: 0x81
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_set_callback: ep 0x81
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_enable: ep 0x00
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_enable: HAL_PCD_EP_Open(0x00, 64, 0)
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_enable: ep 0x80
[00:00:05.062,000] <dbg> usb_dc_stm32.usb_dc_ep_enable: HAL_PCD_EP_Open(0x80, 64, 0)
[00:00:05.062,000] <dbg> usb_device.usb_enable: unlock usb_enable_lock mutex
[00:00:05.068,000] <dbg> usb_dc_stm32.HAL_PCD_SuspendCallback: 
[00:00:05.068,000] <inf> usb_hid: Device suspended
[00:00:05.068,000] <dbg> main.status_cb: status 5 unhandled

Unsurprisingly, the device does not enumerate.

At this point I'm not sure what's missing. Some fundamental incompatibility of the H7 USB device that's not obvious from looking at their header and example files, or something with the configuration of the Zephyr stack in terms of device registers, interrupts, and pinouts.

@erwango erwango added area: USB Universal Serial Bus platform: STM32 ST Micro STM32 labels Mar 16, 2021
@erwango erwango self-assigned this Mar 16, 2021
@shlomow
Copy link
Contributor

shlomow commented Mar 16, 2021

I am planning to contribute this next week, but I don't want to promise anything. So here are the steps you need:

  1. In the device tree you should write clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x8000000>; instead of clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>;.
  2. Enable HSI48 clock: in the line that starts with #if defined(RCC_HSI48_SUPPORT) || defined(CONFIG_SOC_SERIES_STM32WBX) add also the CONFIG_SOC_SERIES_STM32H7X.
  3. Disable ulpi clock using: __HAL_RCC_USB2_OTG_FS_ULPI_CLK_DISABLE.
  4. In the end of the function usb_dc_stm32_init call HAL_PWREx_EnableUSBVoltageDetector

@JeremyBCD
Copy link
Contributor Author

JeremyBCD commented Mar 16, 2021

@shlomow Thank you for this—I've applied these changes to my dev branch, and now the device will enumerate on my MacBook! 🎉

Unfortunately, the device gets suspended shortly after enumeration:

[00:00:00.314,000] <inf> usb_hid: Device configured
[00:00:00.314,000] <dbg> main.status_cb: USB_DC_CONFIGURED
[00:00:00.314,000] <dbg> usb_dc_stm32.usb_dc_ep_write: ep 0x80, len 0
[00:00:00.314,000] <dbg> usb_dc_stm32.HAL_PCD_DataInStageCallback: epnum 0x00
[00:00:00.314,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x80, status 0x02
[00:00:00.333,000] <dbg> usb_dc_stm32.HAL_PCD_SetupStageCallback: 
[00:00:00.333,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x00, status 0x00
[00:00:00.333,000] <dbg> usb_dc_stm32.usb_dc_ep_read_wait: ep 0x00, 8 bytes, 0+8, 0x24002288
[00:00:00.333,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x00, len 64
[00:00:00.333,000] <dbg> usb_device.custom_handler: bRequest 0x06, wIndex 0x0000
[00:00:00.333,000] <dbg> usb_dc_stm32.usb_dc_ep_write: ep 0x80, len 32
[00:00:00.333,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x80, len 0
[00:00:00.333,000] <dbg> usb_dc_stm32.HAL_PCD_DataInStageCallback: epnum 0x00
[00:00:00.333,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x80, status 0x02
[00:00:00.333,000] <dbg> usb_dc_stm32.HAL_PCD_DataOutStageCallback: epnum 0x00, rx_count 0
[00:00:00.333,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x00, status 0x01
[00:00:00.333,000] <dbg> usb_dc_stm32.usb_dc_ep_read_wait: ep 0x00, 0 bytes, 0+0, 0x800a0e6
[00:00:00.333,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x00, len 64
[00:00:00.334,000] <dbg> usb_dc_stm32.HAL_PCD_SetupStageCallback: 
[00:00:00.334,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x00, status 0x00
[00:00:00.334,000] <dbg> usb_dc_stm32.usb_dc_ep_read_wait: ep 0x00, 8 bytes, 0+8, 0x24002288
[00:00:00.334,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x00, len 64
[00:00:00.334,000] <dbg> usb_device.class_handler: bRequest 0x0b, wIndex 0x0000
[00:00:00.334,000] <dbg> usb_dc_stm32.usb_dc_ep_write: ep 0x80, len 0
[00:00:00.334,000] <dbg> usb_dc_stm32.HAL_PCD_DataInStageCallback: epnum 0x00
[00:00:00.334,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x80, status 0x02
[00:00:00.338,000] <dbg> usb_dc_stm32.HAL_PCD_SetupStageCallback: 
[00:00:00.338,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x00, status 0x00
[00:00:00.338,000] <dbg> usb_dc_stm32.usb_dc_ep_read_wait: ep 0x00, 8 bytes, 0+8, 0x24002288
[00:00:00.338,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x00, len 64
[00:00:00.338,000] <dbg> usb_device.custom_handler: bRequest 0x06, wIndex 0x0000
[00:00:00.338,000] <dbg> usb_device.usb_handle_std_device_req: REQ_GET_DESCRIPTOR
[00:00:00.338,000] <dbg> usb_dc_stm32.usb_dc_ep_write: ep 0x80, len 4
[00:00:00.338,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x80, len 0
[00:00:00.338,000] <dbg> usb_dc_stm32.HAL_PCD_DataInStageCallback: epnum 0x00
[00:00:00.338,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x80, status 0x02
[00:00:00.338,000] <dbg> usb_dc_stm32.HAL_PCD_DataOutStageCallback: epnum 0x00, rx_count 0
[00:00:00.338,000] <dbg> usb_device.usb_handle_control_transfer: ep 0x00, status 0x01
[00:00:00.338,000] <dbg> usb_dc_stm32.usb_dc_ep_read_wait: ep 0x00, 0 bytes, 0+0, 0x24000220
[00:00:00.338,000] <dbg> usb_dc_stm32.usb_dc_ep_start_read: ep 0x00, len 64
[00:00:02.314,000] <dbg> usb_dc_stm32.usb_dc_ep_write: ep 0x81, len 2
[00:00:02.314,000] <dbg> main.send_report: Wrote 2 bytes with ret 0
[00:00:03.320,000] <dbg> usb_dc_stm32.HAL_PCD_SuspendCallback: 
[00:00:03.320,000] <inf> usb_hid: Device suspended
[00:00:03.320,000] <dbg> main.status_cb: status 5 unhandled

I'm updated my development branch with your suggested changes.

@shlomow
Copy link
Contributor

shlomow commented Mar 16, 2021

I made a mistake in what I wrote before. Enable voltage detector in the end of usb_dc_attach instead of usb_dc_stm32_init. I am not sure if it matters but this is what I did. Can you check also the cdc acm class? This is the class I am using.

@JeremyBCD
Copy link
Contributor Author

@shlomow Moved the voltage detector enable to usb_dc_attach, does look like that's a more appropriate place for it. The hid sample still doesn't stay connected, still gets suspended.

However, the cdc_acm example does stay connected!

@JeremyBCD
Copy link
Contributor Author

JeremyBCD commented Mar 16, 2021

Continuing testing with the cdc_acm example, I found that it works and stays connected (doesn't get suspended) if the USB cable is connected on power-up or reset. However, hot-plugging the USB cable leaves the STM32H753 disconnected. Is that expected? Since I'm testing with a NUCLEO-H753, power is not provided by the device USB connection.

I tried setting CONFIG_USB_SELF_POWERED=y, but that didn't make a difference.

@JeremyBCD
Copy link
Contributor Author

Realized that I hadn't tried to send data through the cdc_acm example. Tried doing that—nothing comes through. So, while it will stay connected, it's not fully functional.

@JeremyBCD
Copy link
Contributor Author

@shlomow Did you have more success than this?

@shlomow
Copy link
Contributor

shlomow commented Mar 18, 2021

Sorry,. I am on holiday now

@JeremyBCD
Copy link
Contributor Author

Thanks to work from my colleague @IvoBCD, we have a solution to this issue. I've just made a pull request with our changes here: #33686

Thanks @shlomow, your suggestions were very helpful in moving this forward!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: USB Universal Serial Bus platform: STM32 ST Micro STM32
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants