cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750 + USB3300 | No signals on ULPI

Albi G.
Senior

Hi guys, i am at a complete loss; even with describing the problem.

  • I have a 6-layer board with the USB3300 directly underneath the H750(100Pin LQFP), so traces are short and basically optimal.
  • I use CubeMX to generate an example -> I use MCO2 as 24MHz source for the USB3300, eveything in the H750 is working at 96MHz. The clocks are derived from PLL fed by HSE.
  • After enabling MCO2 i wait for several milliseconds in order to let the PLL of the USB3300 stabilize and generate the 60MHz ULPI clock.
  • the Reset-pin of the USB3300 is low.

My main problem (initially) was, that the USB-Lines are not becoming active after a call to USB_DevConnect - i would have expected to see the PullUp on the D+ line (using Fullspeed as a start).

Now, everthing with the USB3300 seems touchy as hell. Cant put words to it...

Within the USB_CoreInit function there is a call to USB_CoreReset. Sometimes this locks up the USB3300 completely (the 60MHz clock stops) and sometimes it works. Sometimes if I call USB_CoreReset twice, then it works.. whatever.

Then i try the basics. Reading a register from the USB3300. I found those functions mentioned here in the forum USB_ULPI_Write and USB_ULPI_Read. Disregarding the fact that they are completely undocumented, i cannot get them to work anywhere in the code.

#define USBULPI_PHYCR     ((uint32_t)(0x40040000 + 0x034))
#define USBULPI_D07       ((uint32_t)0x000000FF)
#define USBULPI_New       ((uint32_t)0x02000000)
#define USBULPI_RW        ((uint32_t)0x00400000)
#define USBULPI_S_BUSY    ((uint32_t)0x04000000)
#define USBULPI_S_DONE    ((uint32_t)0x08000000)
 
#define USB_OTG_READ_REG32(reg)  (*(__IO uint32_t *)(reg))
#define USB_OTG_WRITE_REG32(reg,value) (*(__IO uint32_t *)(reg) = (value))
 
uint32_t USB_ULPI_Read(uint32_t Addr)
{
	__IO uint32_t val = 0;
	__IO uint32_t timeout = 1000; /* Can be tuned based on the Clock or etc... */
	__IO uint32_t bussy = 0;
	USB_OTG_WRITE_REG32(USBULPI_PHYCR, USBULPI_New | (Addr << 16));
	val = USB_OTG_READ_REG32(USBULPI_PHYCR);
	while (((val & USBULPI_S_DONE) == 0) && (timeout--))
	{
		val = USB_OTG_READ_REG32(USBULPI_PHYCR);
		bussy = val & USBULPI_S_BUSY;
	}
	val = USB_OTG_READ_REG32(USBULPI_PHYCR);
	return  (val & 0x000000ff);
}
 
/**
  * @brief  Write CR value
  * @param  Addr the Address of the ULPI Register
  * @param  Data Data to write
  * @retval Returns value of PHY CR register
  */
uint32_t USB_ULPI_Write(uint32_t Addr, uint32_t Data)   /* Parameter is the Address of the ULPI Register & Date to write */
{
	__IO uint32_t val;
	__IO uint32_t timeout = 100;   /* Can be tuned based on the Clock or etc... */
	__IO uint32_t bussy = 0;
 
	USB_OTG_WRITE_REG32(USBULPI_PHYCR, USBULPI_New | USBULPI_RW | (Addr << 16) | (Data & 0x000000ff));
	val = USB_OTG_READ_REG32(USBULPI_PHYCR);
	while (((val & USBULPI_S_DONE) == 0) && (timeout--))
	{
		val = USB_OTG_READ_REG32(USBULPI_PHYCR);
		bussy = val & USBULPI_S_BUSY;
	}
 
	val = USB_OTG_READ_REG32(USBULPI_PHYCR);
	return 0;
}

I added a check for the Busy-Bit for the purpose of debugging. Well.. this bit never is cleared once.

The only time i see something on my oscilloscope is when USB_CoreReset is called. (and the signals look fine in my optinion)

However when I use the fact that i see life for a short moment:

//...in USB_CoreInit	
ret = USB_CoreReset(USBx);
	
volatile unsigned read = 0;
while(1)
{
	USB_ULPI_Write(0x16, 0x55); //USB3300 scratch register
	read = USB_ULPI_Read(0x16);
	HAL_Delay(1);
}
//...

Exactly NOTHING happens at the ULPI-Pins. Not a single pins toggles.

And yes, for the ULPI-gurus among you, the DIR-signal is LOW, so the USB3300 should be able to handle requests.

I tried the Write-Read-Loop else where in the code, no success either.

As said, i am at a complete loss. This is nothing more than pure CubeMX-Code with an additional delay for USB3300-Clock-Startup and then my debugging stuff in between.

I dont know why the ULPI-Interface is not even trying. I am not even complaining about no enumeration.. it is much more fundamentally broken.

And i also dont understand why the most basic functions, like reading PHY-Registers, arent properly documented. But thats another topic. And yes, i tried reading different registers (like product ID) but it always return busy.

Any ideas what to check next?

1 ACCEPTED SOLUTION

Accepted Solutions
Albi G.
Senior

So... good news: i ordered new parts, replaced both the USB3300 and the H750 and it works on first try. Amazing.

What did i learn?

  • That, like other threads in this forum, when the USB3300 does not run out of the box, it always is a hardware issue
  • ST-documentation regarding the USB-stuff is not thought through. [My ability to diagnose the hardware failure was plagued by a huge uncertainty regarding my expectations]
  • I honestly think that the IO-structure of the Pxx_C-pins is fundamentally flawed.
  • That ST does not care or respond nor do they even read.
  • Money solves a lot of problems.

View solution in original post

9 REPLIES 9
Albi G.
Senior

I reimplemented things myself out of desperation. Nothing works. But this is a condensed minimal implementation that should work. I adhered to the Datasheet to the letter. What is wrong?

Its C++ syntax. I hope to those who are unfamiliar with it, that it makes some contextual sense.

WTF. Cant paste my code. The forum does remove my template parameters...

https://pastebin.com/uvR4rv9t

For those who dont trust pastebin :D

0693W000004GikpQAC.png

Why cant i do the most basic thing. The ULPI bus is completely silent. Not a single line toggles.

Albi G.
Senior

Ok. The STP-Pin is high all the time as soon as the periphery is active. According to what i read, STP is only supposed to be a pulse indicating a transfer end.

Since STP is µC-driven, that is a problem with the H750.

Again, i am not sure what to actually expect. Everything is just conjecture. The documentation is pretty much garbage and there are no resources that help to debug this issue. People here in the forum also seem to report that "it just works" or "it doesnt" but there is never an actual fault mechanism mentioned. Its either bad Cube-Code (so i cant trust the reference implementation) nor can i implement it myself due to the state of the documentation.

I am still lost. How is this supposed to work? Can an ST-Employee please give a straight answer what concept is behind this situation?

Albi G.
Senior

Another update. As frustration grows, more and more basics are questioned.

According to the Datasheet one can read the digital input state of a pin even if it is connected to an alternate function input. Basicall GPIO->IDR always reflects the pin state except in analog mode.

0693W000004Gp30QAC.pngNow, after every register write i just sample the GPIOs and save them in a history.

AND LOOK AT THAT!

The DIR pin is always sampled as HIGH in the IDR-register. (that means the ULPI-Bus is not open for communication)

Well, the truth is, DIR is LOW on the oscilloscope!

Now, ULPI_DIR is "PC2_C" on my package (H750 in LQFP100) which is somewhat a weird pin.

Lets have a look:

0693W000004Gp8sQAC.png

Ok. Whats annotation (6)?

0693W000004Gp9CQAS.png

Fair enough. So the switch must be closed. Which register? => SYSCFG_PMCR

0693W000004GpAAQA0.png

Ok... So lets see.

0693W000004GpBwQAK.pngSo... everything should be OK.

WHYYYY is the pin reading HIGH when its LOW??

What could be a reason the analog switches arent working?

  • VDDA is good.
  • VREF+ is 0 (internal reference not enabled) Tying it to VDDA has no consequence.
  • VSSA is 0. (successfully connected to GND)

Just a double check: reading back the PC2 gpio settings: 0693W000004GpXsQAK.png(everything is ok here, except IDR)

Albi G.
Senior

I am assuming a damaged chip for now.

Can anyone explain to me how the ESD-protection on the PCx_C pins work when the device is not powered? (like during soldering!)

0693W000004GtLvQAK.pngI still dont see how any mild ESD could reach into the IDR-register to be honest. I would expect the ADC the only thing to be affected. Yet the digital input is stuck at 1.

Maybe the analog switch is toast. Open on one side and the inward side is fused to VCC.

I will happily continue this thread on my own, as I hope others will find it 🙂 Thank you for reading. For now i need to wait for new chips.

Good strategy ST! You successfully consume my time AND my money.

USB is ALWAYS such a pain. I wanted High Speed, now i have extreme delay.

Albi G.
Senior

So... good news: i ordered new parts, replaced both the USB3300 and the H750 and it works on first try. Amazing.

What did i learn?

  • That, like other threads in this forum, when the USB3300 does not run out of the box, it always is a hardware issue
  • ST-documentation regarding the USB-stuff is not thought through. [My ability to diagnose the hardware failure was plagued by a huge uncertainty regarding my expectations]
  • I honestly think that the IO-structure of the Pxx_C-pins is fundamentally flawed.
  • That ST does not care or respond nor do they even read.
  • Money solves a lot of problems.
timistof
Associate III

I just wanted to say that I've ported the USB_ULPI_Read and USB_ULPI_Write functions to my project that uses a STM32F429 and a USB3320 Phy.. the code works! I can access the various registers and they return expected values.. How bizarre that this isn't documented!

AGord.2
Associate II

Meet with same problem again. One year ago i make prototype on the wires, where connect STM32H750VBT6 devboard with weshare USB3300. was a may headache, but not know it start working on the UGLY wires and works well over than one year.

Now goes to prepare for mass production of this device, use same firmware, but 4 layers PCBA with very accurate routing between H750VBT6 and USB3300 ic.

At first i try use H7 as clock generator, all looks great, but nothing works. I see clocking, 24mhz, 60mhz. see all control signals.

Then i take weshare USB3300 board, resoldering IC (i sure it works well "on wires"), by short wires (3-5mm) connect its oscillator to my board.

What i fount FW 1.10 in the MX_USB_DEVICE_Init(); generate empty function. maybe i some not understood with CubeIDE, but i think it initially not should work.

Init in the FW 1.9 a little bigger

void MX_USB_DEVICE_Init(void)

{

 /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */

 /* USER CODE END USB_DEVICE_Init_PreTreatment */

 /* Init Device Library, add supported class and start the library. */

 if (USBD_Init(&hUsbDeviceHS, &HS_Desc, DEVICE_HS) != USBD_OK)

 {

   Error_Handler();

 }

 if (USBD_RegisterClass(&hUsbDeviceHS, &USBD_CDC) != USBD_OK)

 {

   Error_Handler();

 }

 if (USBD_CDC_RegisterInterface(&hUsbDeviceHS, &USBD_Interface_fops_HS) != USBD_OK)

 {

   Error_Handler();

 }

 if (USBD_Start(&hUsbDeviceHS) != USBD_OK)

 {

   Error_Handler();

 }

 /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */

 HAL_PWREx_EnableUSBVoltageDetector();

 /* USER CODE END USB_DEVICE_Init_PostTreatment */

}

and its working on the prototype.

but not working on the normal PCB.

i try use code from first message, it doest work.

when system power on, until MX_USB_DEVICE_Init() STP are hight, when function works i can see by oscilloscope some activity on data bus and STP, then STP stay low level.

In the normal operations, oscillator stopped, 60mhz dissapear, D+ stay hight. Once i connect USB cable, all stay awake again.

On the PCBA version, all keeps generate, but D+ very rare goes up. and if connect to computer only "unknow device". responce after init "USBD_OK"!

I think, I can directly assign functions to pins and manually send receive data with USB3300.

But have very big doubt about STM32 software works properly. Like IC with one revision works, with another revision stuck. but no any actual problem inside, just mistake.

How check and debug exactly in the ULPI mode?

AGord.2
Associate II

I think mainly problem with levels and delay of CLK from USB3300 to H7. maybe a little bit shifter phase, maybe recognize of ramps not well, because of it synchronization not well. I sure some capacitor of any other delay element can fine adjust sync between IC.

but how look on H7 response?

In the USB3300 has version where it can be sourced by 60mhz (reverse direction), How H7 ULPI engine switch to this mode?

0693W00000VOFLfQAP.png 

AGord.2
Associate II

so problem was solved same.

i check all ULPI pin in the GPIO IN and OUT mode - all works fine, but ULPI doesn`t work.

Then I change H7 to another from same batch - ULPI starts work, sample from first message also.

Then i meet with same problem with timers output.

for example set TIM8_CH3 as PWM output, input circuit after H7 have small capacitor (when touch by probe it charge/discharge). And what i found - PC8 pin float or in the input mode!

If sent out as PP, no any response on the pin. If set as OD, has response pull up or pull down.

Ok, change to GPIO OUT, in loop send open close - it working in PP and OD modes.

Then change TIM1_CH1, TIM2_CH1, TIM4_CH1 PWM outputs - with same code all working.

Looks like mistakes in the CubeIDE/HWP/STM32 pin assignment.