Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 23:30 07 May 2026 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : STM32H7xxx with Cherry USB and mouse failure

Author Message
rrroonn

Newbie

Joined: 08/02/2026
Location: Australia
Posts: 12
Posted: 06:40am 07 May 2026
Copy link to clipboard 
Print this post

Given the pain this problem caused me, I am posting here in the off chance that if someone else has the same issue, it can be solved.

The Cherry USB is not well adapted to USB_FS and needed two changes to make a mouse work.

Change 1: usb_hc_dwc2.c


#if 0 // TODO: AI

This fix worked:

The STM32H7 internal FS PHY requires a strict configuration that generic DWC2
drivers often break when handling Low-Speed devices. The final working state
relies on three explicit hardware overrides:

Bit-Rate Throttling: Forcing LSDEV = 1 physically throttles the hardware to
send 1.5 Mbps pulses instead of 12 Mbps.

PHY Timebase: Locking FSLSPCLKSEL to 48 MHz (Selection 1) ensures the internal
digital sampling logic remains synchronized with the H7's core USB clock domain.

Frame Boundaries: Locking HFIR to 48000 prevents the driver from
incorrectly calculating an 8ms frame. It guarantees the hardware scheduler
maintains strict 1ms periodic boundaries for the Interrupt pipe.

The Host Controller is now firing the End-of-Frame Keep-Alives and
sampling the mouse's response at the correct frequency.

Correct code in ELSE block


       if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) {
           regval = USB_OTG_HOST->HFIR;
           regval &= ~USB_OTG_HFIR_FRIVL;
           regval |= dwc2_calc_frame_interval(bus) & USB_OTG_HFIR_FRIVL;
           USB_OTG_HOST->HFIR = regval;


           if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
               if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) {
                   if ((USB_OTG_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCLKSEL_6_MHZ) {
                       regval = USB_OTG_HOST->HCFG;
                       regval &= ~USB_OTG_HCFG_FSLSPCS;
                       regval |= USB_OTG_HCFG_FSLSPCLKSEL_6_MHZ;
                       USB_OTG_HOST->HCFG = regval;
                   }
               }
               else {
                   if ((USB_OTG_HOST->HCFG & USB_OTG_HCFG_FSLSPCS) != USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ) {
                       regval = USB_OTG_HOST->HCFG;
                       regval &= ~USB_OTG_HCFG_FSLSPCS;
                       regval |= USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ;
                       USB_OTG_HOST->HCFG = regval;
                   }
               }
                 
           }
       }
#else
       if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) {
           
           if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
               if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) {
                   /* Low Speed: 6 MHz clock requires exactly 6000 ticks for a 1ms frame */
                   regval = USB_OTG_HOST->HCFG;
                   regval &= ~USB_OTG_HCFG_FSLSPCS;
                   regval |= USB_OTG_HCFG_FSLSPCLKSEL_6_MHZ;
                   USB_OTG_HOST->HCFG = regval;
                   
                   USB_OTG_HOST->HFIR = 6000;
               } else {
                   /* Full Speed: 48 MHz clock requires exactly 48000 ticks for a 1ms frame */
                   regval = USB_OTG_HOST->HCFG;
                   regval &= ~USB_OTG_HCFG_FSLSPCS;
                   regval |= USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ;
                   USB_OTG_HOST->HCFG = regval;
                   
                   USB_OTG_HOST->HFIR = 48000;
               }
           } else {
               /* Non-FS PHY fallback logic */
               regval = USB_OTG_HOST->HFIR;
               regval &= ~USB_OTG_HFIR_FRIVL;
               regval |= dwc2_calc_frame_interval(bus) & USB_OTG_HFIR_FRIVL;
               USB_OTG_HOST->HFIR = regval;
           }
       }


#endif

Change 2: same file in dwc2_chan_char_init


   /* LS device plugged to HUB */
   if ((speed == USB_SPEED_LOW) && (usbh_get_port_speed(bus, 0) != USB_SPEED_LOW)) {
       regval |= USB_OTG_HCCHAR_LSDEV;
   }

   // TODO:  (over-ride above code)
   if (speed == USB_SPEED_LOW) {
       regval |= USB_OTG_HCCHAR_LSDEV;
       }



Getting keyboards to work on the STM32H743 was not too much of a problem, but mouse was a bitch.  Anyway hope this helps someone.

And yes, I used AI to help work this out but sometimes I wonder if AI is more trouble than its worth.
If all else fails, remain flexible and maintain a sense of humour
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2026