cancel
Showing results for 
Search instead for 
Did you mean: 

UCPD activation crashes STM32U5 MCUs - hardware bug?

TDJ
Lead

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);

 

20 REPLIES 20

Thanks, I will fw this information to relevant peoples.

Olivier