2020-10-06 09:38 AM
We are designing a USB PD LiPo charger that can receive power from a variety of USB PD sources. It is based around a charger IC designed to handle a wide range of input voltages with internal control of the current draw. For example, our design can draw 3A at 20V if the USB PD Source can handle it. However, our design can also just pull 1.5A at 12V if that's all the USB PD Source can supply. We are using the STM32G071RB with integrated USB PD peripheral and the USB PD stack provided by ST. How should we configure the PORT0_PDO_ListSNK[] array so the stack will always ask for the highest voltage and current available from the source (we can easily handle 20V 5A, but our device will accept 5V 1A if that's all the source can provide)? Also, where is the best location to configure this array. We are currently hard coding the values in the USBPD_PWR_IF_Init() function.
Here is a snippet of code we have been testing with:
USBPD_StatusTypeDef USBPD_PWR_IF_Init(void)
{
/* USER CODE BEGIN USBPD_PWR_IF_Init */
USBPD_StatusTypeDef _status = USBPD_OK;
/* Set links to PDO values and number for Port 0 (defined in PDO arrays in H file).
*/
PWR_Port_PDO_Storage[USBPD_PORT_0].SinkPDO.ListOfPDO = (uint32_t *)PORT0_PDO_ListSNK;
PWR_Port_PDO_Storage[USBPD_PORT_0].SinkPDO.NumberOfPDO = &USBPD_NbPDO[0];
//Hard coded config values
PORT0_PDO_ListSNK[0] = _PWR_SNKFixedPDO(1.5,5,1,0,0,0,0);
PORT0_PDO_ListSNK[1] = _PWR_SNKVariablePDO(20,5,1.25);
PORT0_PDO_ListSNK[2] = _PWR_SNKVariablePDO(20,5,1.5);
PORT0_PDO_ListSNK[3] = _PWR_SNKVariablePDO(20,5,2);
PORT0_PDO_ListSNK[4] = _PWR_SNKVariablePDO(20,5,2.25);
PORT0_PDO_ListSNK[5] = _PWR_SNKVariablePDO(20,5,2.5);
PORT0_PDO_ListSNK[6] = _PWR_SNKVariablePDO(20,5,3);
USBPD_NbPDO[0]=7;
This works fine (successfully establishes a contract with the highest power available from the source) if we plug our device into a 100W or 60W USB PD charger, but it doesn't work if we plug into a USB PD charger that is only 18W (12V @ 1.5A).
Below is the request that gets made to the 18W charger, but the request gets rejected.
Thank you in advance for any help you can provide.
2020-10-06 10:10 AM
Hello Tim,
It seems your request is not correct. You request too much current ? (the bit "Capability mismatch" is set)
Can you have a look at our wiki ? There is a specific section about this kind of error.
Then, instead of sharing the picture of the trace, can you share the .cpd file ? (The trace files are saved in c:\Users\%username%\AppData\Local\Temp\STM32CubeMonitor-UCPD\Acquisition\ with ".cpd" extension.)
See also this wiki section related to PDO building policy.
Thanks.
Nicolas
2020-10-06 10:24 AM
2020-10-06 01:00 PM
I believe the capabilities mismatch may be caused by this section of code in usbpd_dpm_conf.h
USBPD_USER_SettingsTypeDef DPM_USER_Settings[USBPD_PORT_COUNT] =
{
{
.PE_VconnSwap = USBPD_FALSE, /* support VCONN swap */
.DPM_SNKRequestedPower = /*!< Requested Power by the sink board */
{
.MaxOperatingCurrentInmAunits = USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT,
.OperatingVoltageInmVunits = USBPD_BOARD_REQUESTED_VOLTAGE_MV,
.MaxOperatingVoltageInmVunits = USBPD_BOARD_MAX_VOLTAGE_MV,
.MinOperatingVoltageInmVunits = USBPD_BOARD_MIN_VOLTAGE_MV,
.OperatingPowerInmWunits = (USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT * USBPD_BOARD_REQUESTED_VOLTAGE_MV)/1000,
.MaxOperatingPowerInmWunits = (USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT * USBPD_BOARD_MAX_VOLTAGE_MV)/1000
},
#if defined(USBPDCORE_SNK_CAPA_EXT)
.DPM_SNKExtendedCapa = /*!< SRC Extended Capability */
{
.VID = USBPD_VID, /*!< Vendor ID (assigned by the USB-IF) */
.PID = USBPD_PID, /*!< Product ID (assigned by the manufacturer) */
.XID = USBPD_XID, /*!< Value provided by the USB-IF assigned to the product */
.FW_revision = 1, /*!< Firmware version number */
.HW_revision = 2, /*!< Hardware version number */
.SKEDB_Version = USBPD_SKEDB_VERSION_1P0, /*!< SKEDB Version (not the specification Version)
based on @ref USBPD_SKEDB_VERSION */
.LoadStep = USBPD_SKEDB_LOADSTEP_150MA, /*!< Load Step based on @ref USBPD_SKEDB_LOADSTEP */
.SinkLoadCharac.b = /*!< Sink Load Characteristics */
{
.PercentOverload = 0, /*!< Percent overload in 10% increments Values higher than 25
(11001b) are clipped to 250%. 00000b is the default. */
.OverloadPeriod = 0, /*!< Overload period in 20ms when bits 0-4 non-zero. */
.DutyCycle = 0, /*!< Duty cycle in 5% increments when bits 0-4 are non-zero. */
.VBusVoltageDrop = 0, /*!< Can tolerate VBUS Voltage drop. */
},
.Compliance = 0, /*!< Compliance based on combination of @ref USBPD_SKEDB_COMPLIANCE */
.Touchtemp = USBPD_SKEDB_TOUCHTEMP_NA, /*!< Touch Temp based on @ref USBPD_SKEDB_TOUCHTEMP */
.BatteryInfo = 0, /*!< Battery info */
.SinkModes = 0, /*!< Sink Modes based on combination of @ref USBPD_SKEDB_SINKMODES */
.SinkMinimumPDP = 0, /*!< The Minimum PDP required by the Sink to operate without
consuming any power from its Battery(s) should it have one */
.SinkOperationalPDP = 0, /*!< The PDP the Sink requires to operate normally. For Sinks with
a Battery, it is the PDP Rating of the charger supplied with
it or recommended for it. */
.SinkMaximumPDP = 0, /*!< The Maximum PDP the Sink can consume to operate and
charge its Battery(s) should it have one. */
},
#endif /* USBPDCORE_SNK_CAPA_EXT */
" .OperatingPowerInmWunits = (USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT * USBPD_BOARD_REQUESTED_VOLTAGE_MV)/1000" is assuming the board draws constant power. But our device can draw dynamic power based on what is available from the source. Should we just set this to a low value (18W for example)?
2020-10-07 12:42 AM
Dear @Tim
USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT has been fixed to 5A and it seems that your power supply does not accept our request with a max current to 5A:
---> 0000008915 P0 SOP s:006 PD3 H:0x1082 REQUEST DATA:f4b10414
PDO position :(1)
NoUSBSuspend : 0
USB Capable : 0
GiveBack : 0
Capa Mismatch : 1
Operating current : 3000 mA
Maxi Operating current: 5000 mA
UnchunkMode Support : 0
<--- 0000008918 P0 SOP s:002 PD3 H:0x03a4 REJECT
Can you just try to sent this defined to 3A?
(usbpd_pdo_def.h)
#define USBPD_CORE_PDO_SNK_FIXED_MAX_CURRENT 3000
Yohann
2020-10-07 09:12 AM
Hi Yohann, I made the change you suggested and the request was accepted. This seems to fix the problem. Thank you for your help.
Do you agree with the following SNK configuration? We are trying to ensure it will always select the highest available power from the USB PD Source?
//located in USBPD_PWR_IF_Init
PORT0_PDO_ListSNK[0] = _PWR_SNKFixedPDO(3,5,1,0,0,0,0);
PORT0_PDO_ListSNK[1] = _PWR_SNKVariablePDO(20,5,1.25);
PORT0_PDO_ListSNK[2] = _PWR_SNKVariablePDO(20,5,1.5);
PORT0_PDO_ListSNK[3] = _PWR_SNKVariablePDO(20,5,2);
PORT0_PDO_ListSNK[4] = _PWR_SNKVariablePDO(20,5,2.25);
PORT0_PDO_ListSNK[5] = _PWR_SNKVariablePDO(20,5,2.5);
PORT0_PDO_ListSNK[6] = _PWR_SNKVariablePDO(20,5,3);
USBPD_NbPDO[0]=7;
2020-10-07 01:09 PM
Hi Tim,
As described in the wiki page, the construction of the request is done through the 'USBPD_DPM_SNK_EvaluateMatchWithSRCPDO' function.
According to our PDO selection algorithm, variable Sink PDO will be selected only if the source provides in its list a variable PDO, which matches with our sink capabilities.
Up to you to change this algorithm to match with your needs.
Yohann