Skip to main content
Visitor 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
  • 7678 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

    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.CrossAuthor
    Visitor 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.CrossAuthor
    Visitor 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

    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.CrossAuthor
    Visitor 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

    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.CrossAuthor
    Visitor 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.CrossAuthor
    Visitor 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

    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.CrossAuthor
    Visitor 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

    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.CrossAuthor
    Visitor 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.

    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.CrossAuthor
    Visitor 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.CrossAuthor
    Visitor II
    September 18, 2020

    .