Skip to main content
Associate II
March 17, 2026
Solved

USB PD SINK application with APDO

  • March 17, 2026
  • 2 replies
  • 146 views

Hello everybody

I'm building the device with power delivery sink function. I need the 21V (PPS). I done the configuration with STM32CubeMX and wrote some code in STM32CubeIDE. Unfortunately, after about 14 s of estabilishing connection, the source send hardware reset. What is the problem? In the attached file is the trase from STM32CubeMonitor-UCPD. I use STM32CubeIDE v. 2.1.1 and STM32CubeMX v. 6.17.0.

void USBPD_DPM_SNK_EvaluateCapabilities(uint8_t PortNum, uint32_t *PtrRequestData, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObjectType)
{
/* USER CODE BEGIN USBPD_DPM_SNK_EvaluateCapabilities */
 //DPM_USER_DEBUG_TRACE(PortNum, "ADVICE: update USBPD_DPM_SNK_EvaluateCapabilities");
	USBPD_SNKRDO_TypeDef rdo;

	rdo.d32=0U;
	rdo.ProgRDO.ObjectPosition=6U;
	rdo.ProgRDO.OutputVoltageIn20mV=1050U; //21V
	rdo.ProgRDO.OperatingCurrentIn50mAunits=60U; //3A
	rdo.ProgRDO.NoUSBSuspend=USBPD_ENABLE;
	rdo.ProgRDO.USBCommunicationsCapable=USBPD_ENABLE;

	*PtrPowerObjectType=USBPD_CORE_PDO_TYPE_APDO;
	*PtrRequestData=rdo.d32;

/* USER CODE END USBPD_DPM_SNK_EvaluateCapabilities */
}

 

Best regards 

Best answer by Jaroslaw_T

I solved this problem (with AI help ;) )

In file main.c I added the tas, which periodically send request, as below:

void StartPeriodTask1(void const * argument)
{
 /* USER CODE BEGIN StartPeriodTask1 */
 /* Infinite loop */
 for(;;)
 {

	 USBPD_PE_Send_Request(USBPD_PORT_0, PDO_Parameters, APDO_Position);
	 osDelay(12000);
 }
 /* USER CODE END StartPeriodTask1 */
}

 

In main.h:

extern uint32_t PDO_Parameters;
extern uint8_t APDO_Position;

 

And in usbpd_dpm_user.c:

uint8_t If_APDO=1U;
uint32_t PDO_Parameters=0U;
uint8_t APDO_Position=0U;

And:

void USBPD_DPM_SNK_EvaluateCapabilities(uint8_t PortNum, uint32_t *PtrRequestData, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObjectType)
{
/* USER CODE BEGIN USBPD_DPM_SNK_EvaluateCapabilities */
 //DPM_USER_DEBUG_TRACE(PortNum, "ADVICE: update USBPD_DPM_SNK_EvaluateCapabilities");
	USBPD_SNKRDO_TypeDef rdo;

	if(If_APDO==1)
	{
		rdo.d32=0U;
		rdo.ProgRDO.ObjectPosition=6U;
		rdo.ProgRDO.OutputVoltageIn20mV=1050U; //24V
		rdo.ProgRDO.OperatingCurrentIn50mAunits=60U; //3A
		rdo.ProgRDO.NoUSBSuspend=USBPD_ENABLE;
		rdo.ProgRDO.USBCommunicationsCapable=USBPD_ENABLE;

		*PtrPowerObjectType=USBPD_CORE_PDO_TYPE_APDO;
		*PtrRequestData=rdo.d32;
		PDO_Parameters=rdo.d32;
		APDO_Position=rdo.ProgRDO.ObjectPosition;
	}
	else
	{
		rdo.d32=0U;
		rdo.FixedVariableRDO.ObjectPosition=5U;
		rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits=300U;
		rdo.FixedVariableRDO.OperatingCurrentIn10mAunits=300U;
		rdo.FixedVariableRDO.USBCommunicationsCapable=USBPD_ENABLE;
		rdo.FixedVariableRDO.NoUSBSuspend=USBPD_ENABLE;
		rdo.FixedVariableRDO.CapabilityMismatch=USBPD_DISABLE;

		*PtrPowerObjectType=USBPD_CORE_PDO_TYPE_FIXED;
		*PtrRequestData=rdo.d32;
	}

/* USER CODE END USBPD_DPM_SNK_EvaluateCapabilities */
}

 

Maybe it will help someone :)

2 replies

Jaroslaw_TAuthorBest answer
Associate II
March 18, 2026

I solved this problem (with AI help ;) )

In file main.c I added the tas, which periodically send request, as below:

void StartPeriodTask1(void const * argument)
{
 /* USER CODE BEGIN StartPeriodTask1 */
 /* Infinite loop */
 for(;;)
 {

	 USBPD_PE_Send_Request(USBPD_PORT_0, PDO_Parameters, APDO_Position);
	 osDelay(12000);
 }
 /* USER CODE END StartPeriodTask1 */
}

 

In main.h:

extern uint32_t PDO_Parameters;
extern uint8_t APDO_Position;

 

And in usbpd_dpm_user.c:

uint8_t If_APDO=1U;
uint32_t PDO_Parameters=0U;
uint8_t APDO_Position=0U;

And:

void USBPD_DPM_SNK_EvaluateCapabilities(uint8_t PortNum, uint32_t *PtrRequestData, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObjectType)
{
/* USER CODE BEGIN USBPD_DPM_SNK_EvaluateCapabilities */
 //DPM_USER_DEBUG_TRACE(PortNum, "ADVICE: update USBPD_DPM_SNK_EvaluateCapabilities");
	USBPD_SNKRDO_TypeDef rdo;

	if(If_APDO==1)
	{
		rdo.d32=0U;
		rdo.ProgRDO.ObjectPosition=6U;
		rdo.ProgRDO.OutputVoltageIn20mV=1050U; //24V
		rdo.ProgRDO.OperatingCurrentIn50mAunits=60U; //3A
		rdo.ProgRDO.NoUSBSuspend=USBPD_ENABLE;
		rdo.ProgRDO.USBCommunicationsCapable=USBPD_ENABLE;

		*PtrPowerObjectType=USBPD_CORE_PDO_TYPE_APDO;
		*PtrRequestData=rdo.d32;
		PDO_Parameters=rdo.d32;
		APDO_Position=rdo.ProgRDO.ObjectPosition;
	}
	else
	{
		rdo.d32=0U;
		rdo.FixedVariableRDO.ObjectPosition=5U;
		rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits=300U;
		rdo.FixedVariableRDO.OperatingCurrentIn10mAunits=300U;
		rdo.FixedVariableRDO.USBCommunicationsCapable=USBPD_ENABLE;
		rdo.FixedVariableRDO.NoUSBSuspend=USBPD_ENABLE;
		rdo.FixedVariableRDO.CapabilityMismatch=USBPD_DISABLE;

		*PtrPowerObjectType=USBPD_CORE_PDO_TYPE_FIXED;
		*PtrRequestData=rdo.d32;
	}

/* USER CODE END USBPD_DPM_SNK_EvaluateCapabilities */
}

 

Maybe it will help someone :)

Technical Moderator
March 18, 2026

Hi @Jaroslaw_T,

Thanks for sharing your findings and workaround, this is very valuable for others.

Calling USBPD_PE_Send_Request() from your own task bypass the PD policy engine and lead to requests to be sent out of sequence. In general, it’s better to let the PD stack drive the protocol and decide when to send requests, using USBPD_DPM_SNK_EvaluateCapabilities() to build the RDO when the core asks for it.

Your solution will definitely help others avoid the same pitfall.

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.Best regards,FBL