2020-08-17 01:07 AM
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
Solved! Go to Solution.
2020-09-22 03:31 AM
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
2020-08-18 05:21 AM
Dear @S.Cross
Have you checked content of SW delivery that is available for X-CUBE-USBPDM1 package ?
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
2020-08-24 01:04 AM
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.
2020-08-24 05:43 AM
2020-08-24 05:44 AM
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 :
Regards
Guenael
2020-08-24 07:14 AM
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
2020-08-24 07:46 AM
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
2020-08-24 08:25 AM
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
2020-08-26 07:21 AM
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
2020-08-26 08:45 AM
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