Skip to main content
TDJ
Senior III
August 21, 2023
Solved

UCPD activation crashes STM32U5 MCUs - hardware bug?

Using Nucleo-U575ZI-Q (rev X) board I try to do a PoC - a very simple UCPD source app providing default USB 5V and 0.5A max. With undocumented onboard SB8-10 shorten this probably can be accomplished. I know this board does not provide output current control, but that is OK, it is just a simple UCPD test to check if I am able to control CC lines state and receive line state change events, no BMC communication.
At first, I tried to use CubeMX middleware. Generated application requires two DMA channels, one advanced timer, uses proprietary ST library and crashes MCU so badly that probably no fault handler is even being called.

So I tried to activate UCPD and monitor CC lines with my simple code. As soon as I activate the Rp resistor MCU crashes, debug communication is lost. Sample code below. Please Advise.
Firmware package version: 1.3.0

Update: I got success, but with Nucleo-H563ZI Rev W. Using the same code (w/o trimming) I was able to correctly read SR.TYPEC_VSTATE_CCn, UCPD1_IRQn seems to fire as expected.
Then I tried with another U5 board (B-U585I-IOT02A, Rev X) and the result was consistent with the first one - MCU crash.

The question: what is so different between H5 and U5 MCUs with respect to UCPD?
Or maybe what matters it is MCU revision? I am stacked and clueless.
What is the correct UCPD activation routine for SM32U5 MCU?
No sample code seems to be available, CubeMX uses ST proprietary library.

 

// Precondition: MX_UCPD1_Init() called

#include "stm32u5xx.h"
#include "stm32u5xx_ll_ucpd.h"

#define SET_REG_FIELD(reg, mask, value) reg = ((reg) & ~mask) | (((value) << mask##_Pos) & mask)

// Table 766. UCPD software trim data
#define _3A0_CC1 ((*(uint8_t*)0x0BFA0545) & 0x0f)
#define _3A0_CC2 ((*(uint8_t*)0x0BFA0547) & 0x0f)
#define _1A5_CC1 ((*(uint8_t*)0x0BFA07A7) & 0x0f)
#define _1A5_CC2 ((*(uint8_t*)0x0BFA07A8) & 0x0f)
#define _Rd_CC1 ((*(uint8_t*)0x0BFA0544) & 0x0f)
#define _Rd_CC2 ((*(uint8_t*)0x0BFA0546) & 0x0f)

UCPD_TypeDef* UCPD = UCPD1;

// Note: Writing to CFG1-CFG3 registers is only effective when UCPD is disabled (UCPDEN = 0)
SET_REG_FIELD(UCPD->CFG1, UCPD_CFG1_PSC_UCPDCLK, 0x01); // set the ucpd_clk divider to 2 since 6-9 MHz range is recommended (16/2=8MHz)
SET_REG_FIELD(UCPD->CFG1, UCPD_CFG1_TRANSWIN, 0x09); // recommended value
SET_REG_FIELD(UCPD->CFG1, UCPD_CFG1_IFRGAP, 0x0E); // 15 - USB PD 2.0 nominal value
SET_REG_FIELD(UCPD->CFG1, UCPD_CFG1_HBITCLKDIV, 0x1A); // ? or 0x00 bypass

// 74.5.5 UCPD software trimming - required for Rev X
SET_REG_FIELD(UCPD->CFG3, UCPD_CFG3_TRIM_CC1_RP, _3A0_CC1);
SET_REG_FIELD(UCPD->CFG3, UCPD_CFG3_TRIM_CC2_RP, _3A0_CC2);
SET_REG_FIELD(UCPD->CFG3, UCPD_CFG3_TRIM_CC1_RD, _Rd_CC1);
SET_REG_FIELD(UCPD->CFG3, UCPD_CFG3_TRIM_CC2_RD, _Rd_CC2);

LL_UCPD_RxAnalogFilterEnable(UCPD);

LL_UCPD_Enable(UCPD);

// Writing to CR & IMR registers is only effective when the peripheral is enabled (UCPDEN = 1)
LL_UCPD_EnableIT_TypeCEventCC1(UCPD);
LL_UCPD_EnableIT_TypeCEventCC2(UCPD);

LL_UCPD_SetSRCRole(UCPD);
LL_UCPD_SetRpResistor(UCPD, LL_UCPD_RESISTOR_DEFAULT); // this line crashes MCU
LL_UCPD_SetccEnable(UCPD, LL_UCPD_CCENABLE_CC1CC2);

 

This topic has been closed for replies.
OlivierR
OlivierRBest answer
ST Employee
August 25, 2023

Without update, I'm able to reproduce this issue. Some Ips clocks setup seems missing (DMA??, ADC??).

I made a quick test with my system clock settings in your environment, and now I observe no hang.

I have no time today to go deeper, but here is the wa:

 

DB TCPP01 setup is missing in your latest change, add this:

// Set TCPP01 DB inactive
HAL_GPIO_WritePin(UCPD_DBn_GPIO_Port, UCPD_DBn_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_SET);

 

Regarding system clocks:

 

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 

/** Configure the main internal regulator output voltage

*/

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

 

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI

|RCC_OSCILLATORTYPE_MSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.MSIState = RCC_MSI_ON;

RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;

RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;

RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 80;

RCC_OscInitStruct.PLL.PLLP = 2;

RCC_OscInitStruct.PLL.PLLQ = 2;

RCC_OscInitStruct.PLL.PLLR = 2;

RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_0;

RCC_OscInitStruct.PLL.PLLFRACN = 0;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != 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_CLOCKTYPE_PCLK3;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

 

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)

{

Error_Handler();

}

}

Have a nice we.

Olivier

20 replies

TDJ
TDJAuthor
Senior III
August 25, 2023

@OlivierR The prj is shared here. Many thanks for looking into it.
https://drive.google.com/file/d/1BMSVf1gMVvKlC68eiJ1xVRCIvA6GgbeG/view?usp=sharing
It is 99% CubeMX generated, besides the code in USER CODE sections, IOC file included.

OlivierR
OlivierRBest answer
ST Employee
August 25, 2023

Without update, I'm able to reproduce this issue. Some Ips clocks setup seems missing (DMA??, ADC??).

I made a quick test with my system clock settings in your environment, and now I observe no hang.

I have no time today to go deeper, but here is the wa:

 

DB TCPP01 setup is missing in your latest change, add this:

// Set TCPP01 DB inactive
HAL_GPIO_WritePin(UCPD_DBn_GPIO_Port, UCPD_DBn_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_SET);

 

Regarding system clocks:

 

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 

/** Configure the main internal regulator output voltage

*/

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

 

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI

|RCC_OSCILLATORTYPE_MSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.MSIState = RCC_MSI_ON;

RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;

RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;

RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV1;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 80;

RCC_OscInitStruct.PLL.PLLP = 2;

RCC_OscInitStruct.PLL.PLLQ = 2;

RCC_OscInitStruct.PLL.PLLR = 2;

RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_0;

RCC_OscInitStruct.PLL.PLLFRACN = 0;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != 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_CLOCKTYPE_PCLK3;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

 

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)

{

Error_Handler();

}

}

Have a nice we.

Olivier

TDJ
TDJAuthor
Senior III
August 26, 2023

@OlivierR Problem solved! What was missing was HSI clock activation - UCPD depends on it.
I believe it is a CubeMX bug. STM32U5 UCPD is clearly enabled, but CubeMX does not think it is enabled and probably for that reason it does not configure HCI clock. This does not happen with STM32H5. It indicates that CubeMX QA process may still have space for improvement.
Thank you for your help.

TDJ_0-1693034363428.png

TDJ_1-1693034429119.png

 

OlivierR
ST Employee
August 28, 2023

Thanks, I will fw this information to relevant peoples.

Olivier