Skip to main content
Visitor II
August 26, 2020
Solved

PDO initialization Problem

  • August 26, 2020
  • 15 replies
  • 6976 views

Hi STteam,

my name is Himavanth, working as an Embedded Engineer at Supralax Electronics Pvt.Ltd. please have a look at the problem.

@brief : We are working PD source solution(i.e. 60Watt (20V @ 3A max)) using STM32G081RBT6. We are taking USB-PD_Provider_1port as an Base reference project.

@Reference : I have gone through each and every line of UM2552 reference manual I found really good information to setup the USBPD stack.

@context:

  1. I am not able to find the PDO initialization Even for provided example (i.e USB-PD_Provider_1port )from the STM.
  2. I found the code template(attached below)regarding PDO definition and initialization of PDO. But I couldn't find any initialization process for PORT0_PDO_ListSRC(As control going to #ifndef __USBPD_PWR_IF_C loop not to else loop)

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file usbpd_pdo_defs.h
 * @author MCD Application Team
 * @brief Header file for definition of PDO/APDO values for 2 ports(DRP/SNK) configuration
 ******************************************************************************
 *
 * Copyright (c) 2018 STMicroelectronics. All rights reserved.
 *
 * This software component is licensed by ST under Ultimate Liberty license
 * SLA0044, the "License"; You may not use this file except in compliance with
 * the License. You may obtain a copy of the License at:
 * www.st.com/SLA0044
 *
 ******************************************************************************
 */
/* USER CODE END Header */
 
#ifndef __USBPD_PDO_DEF_H_
#define __USBPD_PDO_DEF_H_
 
#ifdef __cplusplus
 extern "C" {
#endif 
 
/* Includes ------------------------------------------------------------------*/
 
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Define ------------------------------------------------------------------*/
 
/* USER CODE BEGIN Define */
 
/* USER CODE END Define */
 
/* Exported typedef ----------------------------------------------------------*/
 
/* USER CODE BEGIN typedef */
 
/**
 * @brief USBPD Port PDO Structure definition
 *
 */
 
/* USER CODE END typedef */
 
/* Exported define -----------------------------------------------------------*/
 
/* USER CODE BEGIN Exported_Define */
 
#define USBPD_CORE_PDO_SRC_FIXED_MAX_CURRENT 3
#define USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT 1500
 
/* USER CODE END Exported_Define */
 
/* Exported constants --------------------------------------------------------*/
 
/* USER CODE BEGIN constants */
 
/* USER CODE END constants */
 
/* Exported macro ------------------------------------------------------------*/
 
/* USER CODE BEGIN macro */
 
/* USER CODE END macro */
 
/* Exported variables --------------------------------------------------------*/
 
/* USER CODE BEGIN variables */
 
/* USER CODE END variables */
 
#ifndef __USBPD_PWR_IF_C
extern const uint32_t PORT0_PDO_ListSRC[USBPD_MAX_NB_PDO];
extern const uint32_t PORT0_PDO_ListSNK[USBPD_MAX_NB_PDO];
extern const uint32_t PORT1_PDO_ListSRC[USBPD_MAX_NB_PDO];
extern const uint32_t PORT1_PDO_ListSNK[USBPD_MAX_NB_PDO];
#else
/* Definition of Source PDO for Port 0 */
const uint32_t PORT0_PDO_ListSRC[USBPD_MAX_NB_PDO] =
{
 /* PDO 1 */
 (0x0201912CU),
 /* PDO 2 */
 (0x00000000U),
 /* PDO 3 */
 (0x00000000U),
 /* PDO 4 */
 (0x00000000U),
 /* PDO 5 */
 (0x00000000U),
 /* PDO 6 */
 (0x00000000U),
 /* PDO 7 */
 (0x00000000U)
};
 
/* Definition of Sink PDO for Port 0 */
const uint32_t PORT0_PDO_ListSNK[USBPD_MAX_NB_PDO] = 
{
 /* PDO 1 */
 (0x00000000U),
 /* PDO 2 */
 (0x00000000U),
 /* PDO 3 */
 (0x00000000U),
 /* PDO 4 */
 (0x00000000U),
 /* PDO 5 */
 (0x00000000U),
 /* PDO 6 */
 (0x00000000U),
 /* PDO 7 */
 (0x00000000U)
};
 
#endif
 
/* Exported functions --------------------------------------------------------*/
 
/* USER CODE BEGIN functions */
 
/* USER CODE END functions */
 
#ifdef __cplusplus
}
#endif
 
#endif /* __USBPD_PDO_DEF_H_ */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

@Quetions :

  1. I am not able to find the PDO initialization. please let me know How I can initialize the PDO's?
  2. I have gone through the numbered steps stated in UM2552 page No. 14. I compared with code from PD example code(USB-PD_Provider_1port ) I found step 2, 4 and 5 are initialized properly. Even I am done with changes mentioned in the UM2552 reference manual for step 3.
  3. I couldn't under stand how to initialize the USBPD_StatusTypeDef USBPD_PWR_IF_Init(void). please help me out to initialize the function stated above. please help me out to get out of this problem.

Note : I couldn't initialize the PDO's as stated in UM2552 page No. 21

Thanks & Regards

Himavanth

    This topic has been closed for replies.
    Best answer by Yohann M.

    I found 2 missing codes in your environment:

    (usbpd_dpm_user.c)
    USBPD_StatusTypeDef USBPD_DPM_UserInit(void)
    {
    /* USER CODE BEGIN USBPD_DPM_UserInit */
     /* PWR SET UP */
     if(USBPD_OK != USBPD_PWR_IF_Init())
     {
     return USBPD_ERROR;
     }
     return USBPD_OK;
    /* USER CODE END USBPD_DPM_UserInit */
    }
     
    (usbpd_pwr_if.c)
    USBPD_StatusTypeDef USBPD_PWR_IF_SearchRequestedPDO(uint8_t PortNum, uint32_t RdoPosition, uint32_t *Pdo)
    {
    /* USER CODE BEGIN USBPD_PWR_IF_SearchRequestedPDO */
     if((RdoPosition == 0) || (RdoPosition > *PWR_Port_PDO_Storage[PortNum].SourcePDO.NumberOfPDO))
     {
     /* Invalid PDO index */
     return USBPD_FAIL;
     }
     
     *Pdo = PWR_Port_PDO_Storage[PortNum].SourcePDO.ListOfPDO[RdoPosition - 1];
     return USBPD_OK;
    /* USER CODE END USBPD_PWR_IF_SearchRequestedPDO */
    }
     

    15 replies

    HGorl.1Author
    Visitor II
    August 27, 2020

    Please Kindly someone help me out to get out of this problem. any help will be greatly appreciated. Thank you.

    Please let me know if need more info about the project to get better understanding.

    ST Employee
    August 31, 2020

    Dear @HGorl.1​ ,

    Power negociation follows the AMS described in UM2552 in 'Figure 24. SRC power negotiation':

    0693W000002lkiVQAQ.png

    You should update your function ''

    /**
     * @brief Allow PDO data reading from PWR_IF storage.
     * @param PortNum Port number
     * @param DataId Type of data to be read from PWR_IF
     * This parameter can be one of the following values:
     * @arg @ref USBPD_CORE_DATATYPE_SRC_PDO Source PDO reading requested
     * @arg @ref USBPD_CORE_DATATYPE_SNK_PDO Sink PDO reading requested
     * @param Ptr Pointer on address where PDO values should be written (u8 pointer)
     * @param Size Pointer on nb of u32 written by PWR_IF (nb of PDOs)
     * @retval None
     */
    void USBPD_PWR_IF_GetPortPDOs(uint8_t PortNum, USBPD_CORE_DataInfoType_TypeDef DataId, uint8_t *Ptr, uint32_t *Size)
    {
     if (DataId == USBPD_CORE_DATATYPE_SRC_PDO)
     {
     *Size = PORT0_NB_SOURCEPDO;
     memcpy(Ptr,PORT0_PDO_ListSRC, sizeof(uint32_t) * PORT0_NB_SOURCEPDO);
     }
    /* USER CODE BEGIN USBPD_PWR_IF_GetPortPDOs */
     *Size = 0;
     switch(DataId)
     {
     case USBPD_CORE_DATATYPE_SRC_PDO :
     {
     *Size = PORT0_NB_SOURCEPDO;
     memcpy(Ptr,PORT0_PDO_ListSRC, sizeof(uint32_t) * PORT0_NB_SOURCEPDO);
     }
     break;
     default :
     break;
     }
    /* USER CODE END USBPD_PWR_IF_GetPortPDOs */
    }

    If you want to have more details, you can refer to the demonstration code available under:

    https://github.com/STMicroelectronics/STM32CubeG0/tree/master/Projects/STM32G081B-EVAL/Demonstrations/DemoUCPD

    Regards,

    Yohann

    HGorl.1Author
    Visitor II
    September 1, 2020

    Hi Yohann,

    It's really good to here from you. Thank you very much for Your reply.

    Please have a look at the picture attached below. This when Discovery kit from ST attached to custom board after programming. (Note : we are working to Develop code from USB-PD_Provider_1port & code changes suggested in previous disscussion have been made, even though thing not working properly)

    0693W000003QQEDQA4.png

    Please have a look at the files by going through the link:

    https://drive.google.com/drive/folders/1enntGvObHZ_xGk3DRsqFqliGJxErmrvz?usp=sharing

    1. please suggest any other changes to files mentioned in the link.
    2. Do USB-PD_Provider_1port example from ST community works by default(with out code changes)?
    3. State of Policy Engine is held at reset(from the figure attached above), if so suggest necessary changes to Header files and C files mentioned in the link to work PD in Source mode PD3.0 PPS version.

    Thanks & Regards

    -Himavanth

    ST Employee
    September 1, 2020

    Answer to your questions:

    1. Please find suggested changes in your files to be able to add new PDO in your SRC profiles (in the attached file, I added 3 fixed PDO to 5V/9V/15V)
    2. I confirm that it works with the application we delivered. By default, only the 5V/3A is provided in the SRC capability (image attached)
    3. Screenshot you attached cannot be done with USB-PD_Provider_1port application because, I can see the GUI interface has been enabled and stack is entered in Sink state and wait for a SRC capability from port partner. To enable, you just need to add a APDO in your usbpd_pdo_def. h file like:
    #define PORT0_NB_SOURCEAPDO 1 /* Number of Source APDOs (applicable for port 0) */
     
     /* PDO 4 */ 
     ( (((PWR_A_50MA(USBPD_PDO_APDO_9VPROG_45W_MAX_CURRENT)) << USBPD_PDO_SRC_APDO_MAX_CURRENT_Pos) & (USBPD_PDO_SRC_APDO_MAX_CURRENT_Msk)) |
     (((PWR_V_100MV(USBPD_PDO_APDO_5VPROG_MIN_VOLTAGE)) << USBPD_PDO_SRC_APDO_MIN_VOLTAGE_Pos) & (USBPD_PDO_SRC_APDO_MIN_VOLTAGE_Msk)) |
     (((PWR_V_100MV(USBPD_PDO_APDO_5VPROG_MAX_VOLTAGE)) << USBPD_PDO_SRC_APDO_MAX_VOLTAGE_Pos) & (USBPD_PDO_SRC_APDO_MAX_VOLTAGE_Msk)) |
     USBPD_PDO_TYPE_APDO
     

    0693W000003QRiyQAG.png

    HGorl.1Author
    Visitor II
    September 1, 2020

    Hi Yohann,

    thank you for the quick reply.

    As you mentioned in the previous post I do fallow the link and I found lot of code changes to from the DemoUCPD to USB-PD_Provider_1port.

    I found changes in the following files usbpd_pwr_if.h&c, usbpd_dpm_core.h&c, usbpd_dpm_user.h&c and usbpd_core.h.

    I suspect should need changes in the above mentioned files as well Kindly suggest changes changes to files mentioned above.

    Explanation to 3rd reply:

    you are right ! we are using Discovery kit as sink and our custom(proprietary board from the organization) board as source, and the image I attached is form sink configuration side one only.

    with the image attached above I found Source is not communicating Properly because of Source PE held at reset set. if my assumption is correct please conform it.

    Thanks & Regards

    • Himavanth

    ST Employee
    September 1, 2020

    Hi @HGorl.1​ ,

    DemoUCPD is the complete application which supports main feature on our stack (dual port with DRP on 1 port and sink on the other one, GUI, PPS...) Idea with simple provider application generated with CubeMx was to provide a very simple SRC application to allow to negotiate a contract to 5V/3A.

    I have no more suggestions to provide to you. It should work as it is. Idea is to add your own code linked to your needs (adding PDO ?) in the basic application (in taking demonstration as code example).

    The image I attached is a EVAL board using the Provider application connected to the G0-DISCO board. There are no issues, just few SRC capability messages re transmission and finally request message sent by the disco.

    Regards,

    Yohann

    HGorl.1Author
    Visitor II
    September 1, 2020

    Hi Yohann,

    I made the code changes as you suggested in previous reply(Note: there is no issue with the code compilation and flashing).

    here is my templates after code change:

    https://drive.google.com/drive/folders/1oEnx2D1jopgg8K7rKq7fLmwjsA7IKEm3?usp=sharing

    I found there is still issue with exchanging source capabilities to sink.

    please have look at the fallowing template :

    /**
     * @brief Initialize DPM (port power role, PWR_IF, CAD and PE Init procedures)
     * @retval USBPD Status
     */
    USBPD_StatusTypeDef USBPD_DPM_UserInit(void)
    {
    /* USER CODE BEGIN USBPD_DPM_UserInit */
     return USBPD_OK;
    /* USER CODE END USBPD_DPM_UserInit */
    }

    Even few functions in usbpd_dpm_user.c are not initialized properl, I made changes to this template Even though nothing is working out.

    Note:

    I found few things during debugging process I hope these might help you to understand problem.

    In my side, I put a breakpoint inUSBPD_PE_TaskWakeUp & USBPD_PE_Task function and it was not raised !

    /**
     * @brief WakeUp PE task
     * @param PortNum port number
     * @retval None
     */
    static void USBPD_PE_TaskWakeUp(uint8_t PortNum)
    {
     osMessagePut(PEQueueId[PortNum], 0xFFFF, 0);
    }
     
    /**
     * @brief Main task for PE layer
     * @param argument Not used
     * @retval None
     */
    void USBPD_PE_Task(void const *argument)
    {
     uint8_t _port = (uint32_t)argument;
     for (;;)
     {
     osMessageGet(PEQueueId[_port], USBPD_PE_StateMachine_SRC(_port));
     
     }
    }

    I put a breakpoint in USBPD_PE_TaskWakeUp & USBPD_CAD_Task and control is encountered both points(before cable attaching itself).

    As of my knowledge USBPD_CAD_Task should be encountered right after cable attaching. if my assumption is correct please revert back with Yes.

    1. please suggest me some changes so that Source capabilities exchange issue to be solved.

    Thanks & regards

    • Himavanth

    ST Employee
    September 1, 2020

    You forgot to enable different UCPD handler and DPM counter in stm32g0it_xx.c:

    void SysTick_Handler(void)
    {
     /* USER CODE BEGIN SysTick_IRQn 0 */
     extern void USBPD_DPM_TimerCounter(void);
     USBPD_DPM_TimerCounter();
     /* USER CODE END SysTick_IRQn 0 */
     
    (...)
     
    /**
     * @brief This function handles UCPD1 and UCPD2 interrupts / UCPD1 and UCPD2 wake-up interrupts through EXTI lines 32 and 33.
     */
    void UCPD1_2_IRQHandler(void)
    {
     /* USER CODE BEGIN UCPD1_2_IRQn 0 */
     extern void USBPD_PORT0_IRQHandler(void);
     USBPD_PORT0_IRQHandler();
     /* USER CODE END UCPD1_2_IRQn 0 */

    Do not hesitate to have a look at our Wiki page. We already highlighted such issues:

    https://wiki.st.com/stm32mcu/wiki/USB_Power_Delivery_overview#Why_is_the_PD_message_not_sent_by_the_stack_-3F

    May I suggest you to enable TRACER_EMB in your environment? It will allow you to get USB-PD debug traces.

    Yohann

    HGorl.1Author
    Visitor II
    September 2, 2020

    Hi Yohann,

    Thank you for the reply.

    I made few code changes suggested by you. Sorry I can't provide TRACER_EMB facility as we are using SWD debugger instead of JTAG debuggers.

    I found JTAG debug facility is necessary for USBPD debug trace so I can't provide you the source side trace.

    please have a look at the responds when I connected STM32G071B-DISCO in stand alone mode.

    0693W000003QY6XQAW.png

    Note: Trace is from Sink device( STM32G071B-DISCO )attached to our Custom board.

    Even after the code changes I couldn't find the source capabilities but I am getting the GoodCRC. I have gone through the wiki link provided by you I found few information relating to previous suggestion made by you.

    Please Do have patience to have a look at debugging observation after cable connection:

    1. I found control is coming to both USBPD_CAD_Task & USBPD_PE_Task now after cable detection.

    Thanks & Regards

    • Himavanth
    Yohann M.Answer
    ST Employee
    September 2, 2020

    I found 2 missing codes in your environment:

    (usbpd_dpm_user.c)
    USBPD_StatusTypeDef USBPD_DPM_UserInit(void)
    {
    /* USER CODE BEGIN USBPD_DPM_UserInit */
     /* PWR SET UP */
     if(USBPD_OK != USBPD_PWR_IF_Init())
     {
     return USBPD_ERROR;
     }
     return USBPD_OK;
    /* USER CODE END USBPD_DPM_UserInit */
    }
     
    (usbpd_pwr_if.c)
    USBPD_StatusTypeDef USBPD_PWR_IF_SearchRequestedPDO(uint8_t PortNum, uint32_t RdoPosition, uint32_t *Pdo)
    {
    /* USER CODE BEGIN USBPD_PWR_IF_SearchRequestedPDO */
     if((RdoPosition == 0) || (RdoPosition > *PWR_Port_PDO_Storage[PortNum].SourcePDO.NumberOfPDO))
     {
     /* Invalid PDO index */
     return USBPD_FAIL;
     }
     
     *Pdo = PWR_Port_PDO_Storage[PortNum].SourcePDO.ListOfPDO[RdoPosition - 1];
     return USBPD_OK;
    /* USER CODE END USBPD_PWR_IF_SearchRequestedPDO */
    }
     

    HGorl.1Author
    Visitor II
    September 2, 2020

    Thank you very much for your reply..... your reply helps us a lot.

    0693W000003QZOlQAO.png

    please have a look at the sink trace when connected to source... seams to be everything proper(only need few changes to manage Power management part.).

    Thanks & Regards

    • himavanth
    HGorl.1Author
    Visitor II
    September 7, 2020

    Hi Yohann,

    please have a look at the fallowing.

    if((_PowerProfileSelected >= *PWR_Port_PDO_Storage[PortNum].SourcePDO.NumberOfPDO))
     {
     	return _ret;
     }
    if((0 == *PWR_Port_PDO_Storage[PortNum].SourcePDO.NumberOfPDO)){
     	return _ret;
     }

    after a lot of time spending in Debugging device I found _PowerProfileSelected initialized with DPM_Ports[PortNum].DPM_RDOPosition is always 0(which shouldn't be).

    I feel DPM_Ports[PortNum].DPM_RDOPosition should be updated after each negotiation... please suggest me some code changes so that RDO position update each time after negotiation.

    0693W000003QvjCQAS.png

    Thanks for your support in building and Initializing PDO's.

    Thanks & regards

    -Himavanth

    ST Employee
    September 7, 2020

    Hello

    You are right, as written in the demonstration, you should save the RDO position in the 'USBPD_DPM_EvaluateRequest' function like this:

    USBPD_StatusTypeDef USBPD_DPM_EvaluateRequest(uint8_t PortNum, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObject)
    {
    /* USER CODE BEGIN USBPD_DPM_EvaluateRequest */
     USBPD_StatusTypeDef _retr = USBPD_REJECT;
     USBPD_PDO_TypeDef pdo;
     USBPD_SNKRDO_TypeDef rdo;
     
     /* read the request value received */
     rdo.d32 = DPM_Ports[PortNum].DPM_RcvRequestDOMsg;
     
     /* Search PDO in Port Source PDO list, that corresponds to Position provided in Request RDO */
     if (USBPD_PWR_IF_SearchRequestedPDO(PortNum, rdo.GenericRDO.ObjectPosition, &pdo.d32) == USBPD_OK)
     {
     
     /* Evaluate the request */
     if(pdo.GenericPDO.PowerObject == USBPD_CORE_PDO_TYPE_FIXED)
     {
     if((rdo.FixedVariableRDO.OperatingCurrentIn10mAunits > pdo.SRCFixedPDO.MaxCurrentIn10mAunits)
     || (rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits > pdo.SRCFixedPDO.MaxCurrentIn10mAunits))
     {
     /* Sink requests too much maximum operating current */
     /* USBPD_DPM_EvaluateRequest: Sink requests too much maximum operating current */
     _retr = USBPD_REJECT;
     }
     else
     {
     /* Save the power object */
     *PtrPowerObject = pdo.GenericPDO.PowerObject;
     /* Set RDO position in DPM port structure */
     DPM_Ports[PortNum].DPM_RDOPosition = rdo.GenericRDO.ObjectPosition;
     _retr = USBPD_ACCEPT;
     }
     }
     }
     
     return _retr;
    /* USER CODE END USBPD_DPM_EvaluateRequest */
    }

    Yohann

    HGorl.1Author
    Visitor II
    September 7, 2020

    Thank you Yohann!. that solves my issue with finding an appropriate position of PDO after negotiation.

    After negotiation I found system Hard Resetting every time and finally I found Route cause is from the function attached below.

    I found Status variable is USBPD_HR_STATUS_START_REQ which cause to Hard Reset. please tell us reasons to get system Hard Reset.

    /**
     * @brief Callback function called by PE layer when HardReset message received from PRL
     * @param PortNum The current port number
     * @param CurrentRole the current role
     * @param Status status on hard reset event
     * @retval None
     */
    void USBPD_DPM_HardReset(uint8_t PortNum, USBPD_PortPowerRole_TypeDef CurrentRole, USBPD_HR_Status_TypeDef Status)
    {
    /* USER CODE BEGIN USBPD_DPM_HardReset */
     switch (Status)
     {
     case USBPD_HR_STATUS_START_ACK:
     case USBPD_HR_STATUS_START_REQ:
     {
     /* Reset the power supply */
     USBPD_PWR_IF_VBUSDisable(PortNum);
     break;
     }
     case USBPD_HR_STATUS_COMPLETED:
     {
     /* Reset the power supply */
     USBPD_PWR_IF_VBUSEnable(PortNum);
     break;
     }
     default:
     break;
     }
    /* USER CODE END USBPD_DPM_HardReset */
    }

    Note: I couldn't find Hard Reset message from attached device.

    ST Employee
    September 7, 2020

    Could you please provide a PD log? With DISCO?

    HGorl.1Author
    Visitor II
    September 7, 2020

    Here is my PD log after I connect Disco board.0693W000003QxfWQAS.png0693W000003QxchQAC.png

    ST Employee
    September 7, 2020

    PDO4 is requested (15V) but after transition to this voltage, we should received a PS_RDY message but a detach is detected by the device.

    Could you confirm that you are able to switch correctly to 15V?