cancel
Showing results for 
Search instead for 
Did you mean: 

Couldn't make ULPI work with STM32F446.

YashJ
Associate III

Dear Experts,

I am using a USB3300 chip as an external HS 480Mbit/s USB PHY  with STM32F446 MCU. Using CubeMX to generate code and add USB CDC Middleware. As I connect the USB Cable from the PC to the USB3300 chip no COM port is detected. 

Didn't find any official document related ULPI Interface. I need your help to resolve this issue.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t wave[32768] = {0};
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
  uint16_t j = 0x0;
  for(int i = 0;i<32768;i++,j+=0x01){
	  wave[i] = (uint8_t)(j & 0xFF);
	  i++;
	  wave[i] = (uint8_t)((j >> 😎 & 0xFF);
  }
  uint8_t *ptr = wave;

  HAL_Delay(3000);
  CDC_Transmit_HS(ptr,32768);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
//	  CDC_Transmit_HS(ptr,32768);
//	  HAL_Delay (1000);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 180;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @PAram  file: pointer to the source file name
  * @PAram  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

1 ACCEPTED SOLUTION

Accepted Solutions
FBL
ST Employee

Hello @YashJ 

First let me thank you for the effort and details. Indeed, the USB3300 does not support using an external 60MHz clock input.

According to design guide, section 5 Timing and Protocol, it is mentioned: ULPI interface can accept external 60MHz clock. Also, see 5.1.2 ULPI Input Clock Mode. You may need to consider this to select your PHY.

The second point, based on the waveform, I guess it is confirmed that CLK is not operating accurately. You can measure duty cycle and oscillation frequency drift PPM .. Link cannot drive low STP.

Finally, once you disconnect CLK pin, the code is expected to hang because core will no longer receive the CLK signal it needs to operate and without that clock the hardware cannot perform any operations including CRST.

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.

View solution in original post

8 REPLIES 8
FBL
ST Employee

Hello @YashJ 

You can find more about ULPI in the reference manual. Check Table 223. OTG_HS input/output pins detailing ULPI interface signals. Also, you can find timing diagram and characteristics of ULPI in datasheet.

 

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.

YashJ
Associate III

Hello @FBL 

I have checked that there is no activity on DIR, STP, NXT, and Data pins of ULPI.

I am getting the Clock signal of 60MHz from the USB3300 Chip but it's not the proper squarewave. When I connect it on the PC the USB Device is detected but with an error of no descriptor found.

There is nowhere mentioned how the data will be written to ULPI Pins.

PFA of Clock signal and CubeMx.ULPI.jpgCLK.jpg

FBL
ST Employee

Hello @YashJ 

It seems like the issue is more likely linked to transceiver. According to ULPI spec, the clock direction can be reversed, the link can provide the 60MHz as an input to the PHY. The crystal pins can be removed from the PHY.

Duty cycle must always be within 5% if the 4-bit bus implementation option is used.

Could you check VDD? It should be in range [2.7V, 3.6V] with CL = 20 pF

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.

YashJ
Associate III

Hello @FBL 

According to the datasheet of USB3300, the CLK pin is only an Output pin. The Vdd voltage is 3.3v.

I have attached the waveforms of CLK(Yellow), DIR(Purple), NXT(Blue), STP(Green). This time I used a 10x probe and my scope is 100MHz. Here before CLK the state of DIR is High and after CLK the state of DIR is Low, but the state of STP is the same HIGH as it should also go Low after the DIR pin goes Low according to the document ULPI Design Guide https://ww1.microchip.com/downloads/en/AppNotes/en562704.pdf.

If I disconnect the CLK Pin my code hangs on line 33 while loop:-WaveFormsWaveFormsULPIDesignG.jpgPinsPins

/**
  * @brief  Reset the USB Core (needed after USB clock settings change)
  * @param  USBx  Selected device
  * @retval HAL status
  */
static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)
{
  __IO uint32_t count = 0U;

  /* Wait for AHB master IDLE state. */
  do
  {
    count++;

    if (count > HAL_USB_TIMEOUT)
    {
      return HAL_TIMEOUT;
    }
  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);

  /* Core Soft Reset */
  count = 0U;
  USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;

  do
  {
    count++;

    if (count > HAL_USB_TIMEOUT)
    {
      return HAL_TIMEOUT;
    }
  } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);

  return HAL_OK;
}

 

FBL
ST Employee

Hello @YashJ 

First let me thank you for the effort and details. Indeed, the USB3300 does not support using an external 60MHz clock input.

According to design guide, section 5 Timing and Protocol, it is mentioned: ULPI interface can accept external 60MHz clock. Also, see 5.1.2 ULPI Input Clock Mode. You may need to consider this to select your PHY.

The second point, based on the waveform, I guess it is confirmed that CLK is not operating accurately. You can measure duty cycle and oscillation frequency drift PPM .. Link cannot drive low STP.

Finally, once you disconnect CLK pin, the code is expected to hang because core will no longer receive the CLK signal it needs to operate and without that clock the hardware cannot perform any operations including CRST.

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.

YashJ
Associate III

Hello @FBL 

I couldnt understand how clock is not operating accurately. I took measurements of clock it is 60MHz and with nearly 50% duty cycle. As my oscilloscope bandwidht is 100MHz it can't measure accurately. 

So, what is the option now?

Hi @YashJ 

I guess USB3300 is not the best option in this case. Maybe, consulting the transceiver manufacturer will help!

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.

FBL
ST Employee

Hi @YashJ 

Would you please share your schematics for further investigation?

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.