Skip to main content
S.Cross
Associate II
August 17, 2020
Solved

Nucleo-G474 and X-Nucleo-USBPDM1 sink setup for continuous changement of PDOs and APDOs

  • August 17, 2020
  • 12 replies
  • 7689 views

Hey there,

since a few weeks i am setting up a USB-PD sink with the Nuc-USBPDM1 and Nuc-G474.

In this special case i want to:

1. Read out charger PDOs

2. Set up Fixed PDOs (e.g. 15V@3A) and switching during runtime

3. Set up APDOs according to PPS (variable voltage and current) and switching during runtime

My project files are generated by CubeMX with firmware package 1.2.0 for the G4 series (with 1.3.0 i couldn't get this work). I am using non RTOS mode.

For now it is possible for me to select fixed PDOs and switching them during runtime (by USBPD_DPM_RequestMessageRequest). But when i want to set up an APDO (by requesting continuously every 100ms) i can't get this work.

Only the first request is sent by the stack (proved with Cypres USB-PD protocol analyser) and after this i only get a "USBPD_BUSY" or "USBPD_ERROR" by the request function and the stack goes crazy (hard resetting every few seconds). The whole board has to be reset, that USB-PD stack works stable again.

Is there any possibility to get PPS working properly with my setup. Or do i have to make special changes in CubeMX, "usbpd_dpm_user" or "usbpd_dpm_core"?

Best regards

This topic has been closed for replies.
Best answer by Guenael Cadier

Dear @S.Cross​ 

Thanks for your attachments.

Libraries provided in USBPD Middleware could be used on several targets. Depending on Cortex M core used inside the STM32xx device, several libs for same IDE/USBPD feature configuration, exist. For STM32G4xx, libs with ***_CM4*** are ok.

Regarding the Hard Reset issue, could you try to use updated lib (as attached to this post, please remove"_update" suffix), rebuild you binary, and check if issue still present ?

Thanks

Guenael

12 replies

Guenael Cadier
ST Employee
August 18, 2020

Dear @S.Cross​ 

Have you checked content of SW delivery that is available for X-CUBE-USBPDM1 package ?

(available at https://my.st.com/content/my_st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32cube-expansion-packages/x-cube-usbpdm1.license=1597743165145.product=X-CUBE-USBPDM1.version=2.0.2.html)

This package includes USBPD applications examples designed for STM32G071RB and STM32G474RE Nucleo boards. In both applications you could content of applicative usbpd_dpm_user and dpm_core files.

Regarding PPS aspect, please check content of the files available in the Projects\NUCLEO-G071RB\Applications\USB_PD\TCPP01_Consumer_PPS applications, as it seems to correspond to your application.

If not solving your issue, could you record a PD log on your board (using STM32CubeMonitorUCPD) ?

Regards

Guenael

S.Cross
S.CrossAuthor
Associate II
August 24, 2020

Dear Guenael,

thank you for your reply. I was trying your referenced hints, but i still can't establish a stable PPS connection. But i already realized, that my 100ms request interval was wrong and now i set it up to 10s according to tPPSRequest.

But is an automatic request every 9/10 seconds generated by default from the stack, or should i do this manually? Actually there is no automatic request generated by the stack.

Thank you and best regards.

S.Cross
S.CrossAuthor
Associate II
August 24, 2020

I also recorded a log file with UCPD monitor. There you can see, that there is no automatic request after 9/10 seconds generated by the stack

Guenael Cadier
ST Employee
August 24, 2020

Dear @S.Cross​ 

I was just having a look at latest logs and code you attached, but lost them (maybe you remove attachements). Indeed in case of PPS (i.e. when a APDO is selected by SINK, Request messgae should be sent on a regular basis (10 sec max).

This should be handled by the USBPD Core stack.

In order to select an APDO, (example PDO5), application could use USBPD_PE_Send_Request() API. (an example is provided in X-Cube-USBPDM1 package, in USBPD_DPM_RequestMessageRequest() function in usbpd_dpm_user.c file).

An argument of the USBPD_PE_Send_Request() function is the type of power object (Fixed PDO, Variable, ...). This parameter informs the stack of the type of PDO that is selected : if APDO is selected, USBPD stack should normally manage the tPPSRequest timer.

Could you check that when you execute USBPD_PE_Send_Request() for selecting an APDO, last parameter (type USBPD_CORE_PDO_Type_TypeDef) is properly set to USBPD_CORE_PDO_TYPE_APDO (i.e. 3) ?

Please also notice that fields of RDO object are slightly different when Fixed PDO or APDO are selected :

  • 0x2104B12C for a Fixed PDO indicates PDO2, Operation current 3A, Max current 3A (300 * 10 mA)
  • 0x5104B12C for an APDO indicates PDO5, Operation Voltage 6V (300*20mV), Operational current 15A (300 * 50 mA)

Regards

Guenael

S.Cross
S.CrossAuthor
Associate II
August 24, 2020

Dear Guenael,

thank you for your reply! I just checked my code again, and everything seems right. For example i am requesting USBPD_PE_Send_Request(0, 0x5103203C, 0x03), which means i want on port 0 pdo number 5, which is USBPD_CORE_PDO_TYPE_APDO with (8V@3A), right ?. But when i do this i can see the first request coming from the sink, but after 10 seconds i get a HardReset initiated from the source. Could it be some timing issue?

Best regards

Guenael Cadier
ST Employee
August 24, 2020

Dear @S.Cross​ 

I wonder if difference between your app and X-CUBE-USBPDM1 project could be linked to use of RTOS or not.

Actually, if request is properly sent to USBPD stack, I guess timer should be started. Next question is to know if it is properly decremented afterwards.

Could you confirm your Systick_Handler() is called and include execution of USBPD_DPM_TimerCounter() ?

Is it possible to try your applicationin RTOS mode ?

Regards

S.Cross
S.CrossAuthor
Associate II
August 24, 2020

Dear @Guenael Cadier​ 

actually i am using RTOS now. I put a seperate timer (TIM20) as timebase source (interrupt routine called every 1ms). And as you already mentioned i forgot putting some code into my timer interrupt handler ... after adding the code snippets from the example files i get:

void TIM20_UP_IRQHandler(void)
{
 /* USER CODE BEGIN TIM20_UP_IRQn 0 */
 USBPD_DPM_TimerCounter();
 
#if defined(_GUI_INTERFACE)
 GUI_TimerCounter();
#endif /* _GUI_INTERFACE */
 
  HAL_GPIO_TogglePin(PD2_GPIO_Port, PD2_Pin);
 HAL_IncTick();
 /* USER CODE END TIM20_UP_IRQn 0 */
 HAL_TIM_IRQHandler(&htim20);
 /* USER CODE BEGIN TIM20_UP_IRQn 1 */
 
 /* USER CODE END TIM20_UP_IRQn 1 */
}

When i select an APDO now, i can see one or two automatic generated requests after 9/10 seconds. But after this the PE causes a HardReset like described in the log file attached. Selection of normal PDOs causes sometimes a HardReset, especially, when i switch the USB-C cable between two different chargers. In FreeRTOS i am using CMSIS_v2 actually.

Do you have an idea what causes this instability ?

Best regards

2753 OUT 5411006 1 REQUEST DATA: 28400661 / ObjectPosition:6 / 
 GiveBack:0 / CapabilityMismatch:0 / 
 USBCommunicationCapable:0 / NoUSBSuspend:1 / 
 UnchunkedExtendedMessagesSupported:0 SOP PD3	H:0x1482 
2754 IN 5411008 1 GOODCRC	 SOP		 H:0x05A1 
2755 PE 5411008	1 PE_SNK_SELECT_CAPABILITY
2756 IN 5411016	1 ACCEPT	 SOP PD3	H:0x0BA3 
2757 OUT	 5411016	1 GOODCRC	 SOP		 H:0x0A01 
2758 NOTIF	5411016	1	POWER_STATE_CHANGE
2759 NOTIF	5411016	1	REQUEST_ACCEPTED
2760 PE	 411016	1	PE_SNK_TRANSITION_SNK
2761 IN	 5411308	1	PS_RDY	 SOP PD3 H:0x0DA6 
2762 OUT	 5411308	1	GOODCRC	 SOP H:0x0C01 
2763 NOTIF	5411310	1	POWER_STATE_CHANGE
2764 NOTIF	5411310	1	POWER_EXPLICIT_CONTRACT
2765 PE	 5411310	1	PE_STATE_READY
2766 NOTIF	5411310	1	STATE_SNK_READY
2767 PE	 5411310	1	PE_STATE_READY_WAIT
2768 PE	 5429310	1	PE_SNK_SEND_REQUEST
2769 OUT	 5429310	1	REQUEST DATA: 28400661 / ObjectPosition:6 / 
 GiveBack:0 / CapabilityMismatch:0 / 
 USBCommunicationCapable:0 / NoUSBSuspend:1 / 
 UnchunkedExtendedMessagesSupported:0	SOP	 PD3 H:0x1682 
2770	IN	 5429312	1	GOODCRC	 SOP		 H:0x07A1 
2771	PE	 5429312	1	PE_SNK_SELECT_CAPABILITY
2772	IN	 5429320	1	ACCEPT	 SOP	 PD3 H:0x0FA3 
2773	OUT	 5429320	1	GOODCRC	 SOP		 H:0x0E01 
2774	NOTIF	5429320	1	POWER_STATE_CHANGE
2775	NOTIF	5429320	1	REQUEST_ACCEPTED
2776	PE	 5429320	1	PE_SNK_TRANSITION_SNK
2777	IN	 5429322	1	PS_RDY	 SOP	 PD3 H:0x01A6 
2778	OUT	 5429322	1	GOODCRC	 SOP		 H:0x0001 
2779	NOTIF	5429324	1	POWER_STATE_CHANGE
2780	NOTIF	5429324	1	POWER_EXPLICIT_CONTRACT
2781	PE	 5429324	1	PE_STATE_READY
2782	NOTIF	5429324	1	STATE_SNK_READY
2783	PE	 5429324	1	PE_STATE_READY_WAIT
2784	PE	 5447324	1	PE_SNK_SEND_REQUEST
2785	OUT	 5447324	1	REQUEST DATA: 28400661 / ObjectPosition:6 / 
 GiveBack:0 / CapabilityMismatch:0 / 
 USBCommunicationCapable:0 / NoUSBSuspend:1 / 
 UnchunkedExtendedMessagesSupported:0	SOP	 PD3 H:0x1882 
2786	IN	 5447326	1	GOODCRC	 SOP		 H:0x09A1 
2787	PE	 5447326	1	PE_SNK_SELECT_CAPABILITY
2788	IN	 5447334	1	ACCEPT	 SOP	 PD3 H:0x03A3 
2789	OUT	 5447334	1	GOODCRC	 SOP		 H:0x0201 
2790	NOTIF	5447334	1	POWER_STATE_CHANGE
2791	NOTIF	5447334	1	REQUEST_ACCEPTED
2792	PE	 5447334	1	PE_SNK_TRANSITION_SNK
2793	IN	 5447338	1	PS_RDY	 SOP	 PD3 H:0x05A6 
2794	OUT	 5447338	1	GOODCRC	 SOP		 H:0x0401 
2795	NOTIF	5447338	1	POWER_STATE_CHANGE
2796	NOTIF	5447338	1	POWER_EXPLICIT_CONTRACT
2797	PE	 5447338	1	PE_STATE_READY
2798	NOTIF	5447338	1	STATE_SNK_READY
2799	PE	 5447338	1	PE_STATE_READY_WAIT
2800	PE	 5447746	1	PE_STATE_HARD_RESET
2801	NOTIF	5447746	1	POWER_STATE_CHANGE
2802	NOTIF	5447746	1	HARDRESET_TX
2803	OUT	 5447746	1	HRST
2804	DEBUG	5447746	1	USBPD_DPM_HardReset - Current Role: 1 - Status: 1
2805	PE	 5447746	1	PE_SNK_HARD_RESET_WAIT_VSAFE_0V
2806	NOTIF	5447834	1	POWER_SNK_STOP
2807	PE	 5447834	1	PE_SNK_HARD_RESET_WAIT
2808	DEBUG	5449498	1	USBPD_DPM_HardReset - Current Role: 0 - Status: 5
2809	NOTIF	5449498	1	POWER_STATE_CHANGE
2810	PE	 5449498	1	PE_SNK_WAIT_FOR_CAPABILITIES
2811	IN	 5449720	1	SRC_CAPABILITIES DATA:2C9101082CD102002CC103002CB10400E14006003C2140C1 / 5V - 3A / 9V - 3A / 12V - 3A / 15V - 3A / 20V - 2.25A / [3.3V - 16V] - 3A	SOP	 PD3	 H:0x61A1 

S.Cross
S.CrossAuthor
Associate II
August 26, 2020

Dear @Guenael Cadier​ 

maybe there could also be some issue with the generation of my RDOs. I put my creation code below. I tried to combine all information from the Nucleo-G071 and Nucleo-G474 example code. But maybe i produced some error with that ... The function USER_DPM_SRC_PDO_Request() is called externally with PdoPosition, RequestedVoltage and RequestedCurrent.

/**
 * @brief Build RDO for request
 * @param PortNum : the current port number
 * PdoPosition : PDO object position starting at 1
 * Voltage : requested voltage in mV
 * Current : requested current in mA
 * prdo : pointer to USBPD_SNKRDO_TypeDef
 * PtrPowerObject: pointer to USBPD_CORE_PDO_Type_TypeDef
 * @retval none
 */
void USER_DPM_SNKRDO_Builder(uint8_t PortNum, uint8_t PdoPosition, uint16_t Voltage_mV, uint16_t Current_mA, USBPD_SNKRDO_TypeDef* prdo, USBPD_CORE_PDO_Type_TypeDef* PtrPowerObject)
{
 USBPD_PDO_TypeDef pdo;
 USBPD_SNKRDO_TypeDef rdo;
 
 USBPD_HandleTypeDef *pdhandle = &DPM_Ports[PortNum];
 
 /* Initialize RDO */
 rdo.d32 = 0;
 rdo.GenericRDO.ObjectPosition = PdoPosition;
 rdo.GenericRDO.USBCommunicationsCapable = 0;
 rdo.GenericRDO.NoUSBSuspend = 1;
 
 /* Initialize PDO */
 pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[PdoPosition - 1];
 *PtrPowerObject = pdo.GenericPDO.PowerObject;
 
 switch (pdo.GenericPDO.PowerObject)
 {
 case USBPD_CORE_PDO_TYPE_FIXED:
 case USBPD_CORE_PDO_TYPE_VARIABLE:
 { 
 rdo.FixedVariableRDO.ObjectPosition = PdoPosition;
 rdo.FixedVariableRDO.OperatingCurrentIn10mAunits = Current_mA / 10;
 rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = Current_mA / 10;
 }
 break;
 case USBPD_CORE_PDO_TYPE_APDO:
 {
 rdo.ProgRDO.ObjectPosition = PdoPosition;
 rdo.ProgRDO.OperatingCurrentIn50mAunits = Current_mA / 50;
 rdo.ProgRDO.OutputVoltageIn20mV = Voltage_mV / 20;
 }
 break;
 }
 
 pdhandle->DPM_RequestDOMsg = rdo.d32;
 pdhandle->DPM_RDOPosition = PdoPosition;
 pdhandle->DPM_RequestedCurrent = Current_mA; 
 pdhandle->DPM_RequestedVoltage = Voltage_mV;
 
 prdo->d32 = rdo.d32;
}
 
/**
 * @brief Request a PDO/APDO from given index, voltage and current
 * @param PortNum : the current port number
 * PdoPosition : PDO object position starting at 1
 * RequestedVoltage: requested voltage in mV
 * RequestedCurrent: requested current in mA
 * @retval USBPD_StatusTypeDef
 */
USBPD_StatusTypeDef USER_DPM_SRC_PDO_Request(uint8_t PortNum, uint8_t PdoPosition, uint16_t RequestedVoltage, uint16_t RequestedCurrent)
{
 USBPD_StatusTypeDef _status = USBPD_ERROR;
 
 USBPD_SNKRDO_TypeDef rdo;
 USBPD_CORE_PDO_Type_TypeDef pdo_object;
 
 /* Initialize RDO */
 rdo.d32 = 0;
 
 USER_DPM_SNKRDO_Builder(PortNum, PdoPosition, RequestedVoltage, RequestedCurrent, &rdo, &pdo_object);
 USER_DPM_Set_Request_Details(PortNum, PdoPosition, RequestedVoltage, RequestedCurrent);
 
 _status = USBPD_PE_Send_Request(PortNum, rdo.d32, pdo_object);
 
 if (_status != USBPD_OK)
 {
 DPM_USER_DEBUG_TRACE(PortNum, "USER_DPM_SRC_PDO_Request status %d", (uint8_t) _status);
 }
 return _status;
}

Best regards

Guenael Cadier
ST Employee
August 26, 2020

Dear @S.Cross​ 

No issue found at reading your code. Moreover, your previous log was showing that you are reaching Explicit contract as expected, is already a good starting point.

Do you still experience same issue, i.e. APDO Request sent for some times, and then Hard reset occuring ?

Could you check if your code is properly executing following function calls sequence at startup :

Main()
 |---> MX_USBPD_Init();
 |---> USBPD_HW_IF_GlobalHwInit();
 |---> 
 {
 /* PWR register access (for disabling dead battery feature) */
 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
 LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_CRC);
 }
 
 

Regards

Guenael

S.Cross
S.CrossAuthor
Associate II
August 27, 2020

Dear @Guenael Cadier​ ,

i'm happy that my code seems right! I checked your code snippet and this code is executed correctly in my setup.

On my X-NUCLEO-USBPDM1 i checked the jumper settings of JP2 and recognized, that i configured [VCC-3.3V] and [DB-3.3V] because i don't want low power mode. So i disabled USBPDM1_VCC_FEATURE_ENABLED and USBPDM1_DB_OUT_FEATURE_ENABLED in usbpdm1_usbpd_pwr.h.

But the same error is still occurring. Is there any possibility to debug why the stack on my sink sends the HardReset? Or do you have any idea how to detect the fault?

Again i attached my log file; but it's similar to the previous file. Best regards

Guenael Cadier
ST Employee
August 27, 2020

Dear @S.Cross​ ,

Just a question on your last log : time spent between 2 REQUEST from Sink, in PPS mode, is expected to be around 9 sec (max is 10 sec). You mentioned it is what you observe. But looking at counter, it looks like around 18000 units occurred between 2 requests. I would have expected to see something around 9000.

Do you confirm time between Requests is around 9 seconds ?

Guenael

S.Cross
S.CrossAuthor
Associate II
August 31, 2020

Dear @Guenael Cadier​ ,

the request was sent in the right time delta of 9-10 seconds. I just recognized, that an HAL_IncTick() is already executed by the interrupt handler of TIM20. So i removed my inserted HAL_IncTick() and the timebase is correct now . But error is still the same.

Guenael Cadier
ST Employee
August 31, 2020

OK, Thanks for clarification.

By the way, is the Hard Reset always occurring after the 3rd Request or is it sometimes after the 4th, 5th, ... ?

S.Cross
S.CrossAuthor
Associate II
September 17, 2020

Dear @Guenael Cadier​ ,

after doing some tests i still have the same problem with selecting PPS profiles. The reset seems to relate to the charger i connect my sink with. So in some cases i get an HardReset after the 3rd request, and sometimes already after the 2nd request. If i select an APDO and there is a HardReset caused by the sink i get sometimes up to 10 HardResets after this before the regular 5V profile is selected correctly by the sink. This behaviour is shown in the attached file. But every time the sink goes to status "POWER_EXPLICIT_CONTRACT". I also checked the voltage level of VBus, if something changes, which causes the sink to do an HardReset, but everything was stable. So i assume, that the HardReset is caused by the stack, which i can't monitor.

S.Cross
S.CrossAuthor
Associate II
September 18, 2020