cancel
Showing results for 
Search instead for 
Did you mean: 

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

S.Cross
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

20 REPLIES 20
Guenael Cadier
ST Employee

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
Associate II

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
Associate II

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

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
Associate II

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

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

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
Associate II

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

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