2021-02-08 11:34 PM
I am studying USB PD. I am using the demo board B-G474E-DPOW1 and the project from the STM32CubeG4 examples.
When I connect the USB-C cable to the charger, after the ATTACH event, I receive a list of possible profiles from Source.
But when the cable is already connected to the charger and I reset the board, then after the ATTACH event, the list of profiles from Source does not come.
Is this normal behavior? Should source power profiles come only after cable connection?
How can I fix it so that after resetting the board, everything works same as on cable connection?
Solved! Go to Solution.
2021-03-01 01:45 AM
Dear @ADoro.2
when cable is already connected, source port is not able to detect that CC connection has been lost.
Then sink should send a hard reset to reset VBUS on source side and wait for new source capabilities.
Unfortunately, in the code you are using, there are no code to check that VBUS goes lower than Vsafe0V (around 750mV)
Can you add the following user code in the function 'USBPD_PWR_IF_SupplyReady'?
/**
* @brief Checks if the power on a specified port is ready
* @param PortNum Port number
* @param Vsafe Vsafe status based on @ref USBPD_VSAFE_StatusTypeDef
* @retval USBPD status
*/
USBPD_StatusTypeDef USBPD_PWR_IF_SupplyReady(uint8_t PortNum, USBPD_VSAFE_StatusTypeDef Vsafe)
{
/* USER CODE BEGIN USBPD_PWR_IF_SupplyReady */
USBPD_StatusTypeDef status = USBPD_ERROR;
uint32_t _voltage;
/* check for valid port */
if (!USBPD_PORT_IsValid(PortNum))
{
return USBPD_ERROR;
}
BSP_USBPD_PWR_VBUSGetVoltage(PortNum, &_voltage);
if (USBPD_VSAFE_0V == Vsafe)
{
/* Vsafe0V */
status = ((_voltage < USBPD_PWR_LOW_VBUS_THRESHOLD) ? USBPD_OK : USBPD_ERROR);
}
else
{
/* Vsafe5V */
status = ((_voltage > USBPD_PWR_HIGH_VBUS_THRESHOLD) ? USBPD_OK : USBPD_ERROR);
}
return status;
/* USER CODE END USBPD_PWR_IF_SupplyReady */
}
In meanwhile, I detected with few chargers, that VBUS value by the disco board does not reach Vsafe0V. In my case lowest value was 1350mV.
Then, I needed to increase the threshold of 'USBPD_PWR_LOW_VBUS_THRESHOLD' to 1500mV.
#define USBPD_PWR_LOW_VBUS_THRESHOLD (1500U)
In this case, I was able to receive correctly the new SRC capabilities after the hard reset:
84 PE 1787 1 PE_STATE_READY_WAIT
(board reset with attached cable)
86 CAD 4 1 USBPD_CAD_STATE_ATTACHED_WAIT
87 CAD 123 1 USBPD_CAD_STATE_ATTACHED
88 EVENT 123 1 EVENT_ATTACHED
93 PE 123 1 PE_SNK_STARTUP
94 PE 123 1 PE_SNK_WAIT_FOR_CAPABILITIES
95 PE 623 1 PE_STATE_HARD_RESET
96 NOTIF 623 1 POWER_STATE_CHANGE
97 NOTIF 623 1 HARDRESET_TX
98 OUT 623 1 HRST
101 PE 623 1 PE_SNK_HARD_RESET_WAIT_VSAFE_0V
(vSafe0V detected after 711ms, timeout set to 1s)
102 NOTIF 1334 1 POWER_STATE_CHANGE
106 NOTIF 1334 1 POWER_SNK_STOP
107 PE 1334 1 PE_SNK_HARD_RESET_WAIT
109 PE 1423 1 PE_SNK_WAIT_FOR_CAPABILITIES
110 IN 1573 1 SRC_CAPABILITIES DATA:2C9101082CD10200FAC00300C8B0040096400600 / 5V - 3A / 9V - 3A / 12V - 2.5A / 15V - 2A / 20V - 1.5A SOP PD3 H:0x51A1
I advice you to trace the VBUS value to confirm the vSafe0V:
/**
* @brief Get actual voltage level measured on the VBUS line.
* @param Instance Type-C port identifier
* This parameter can be take one of the following values:
* @arg @ref USBPD_PWR_TYPE_C_PORT_1
* @param pVoltage Pointer on measured voltage level (in mV)
* @retval BSP status
*/
__weak int32_t BSP_USBPD_PWR_VBUSGetVoltage(uint32_t Instance, uint32_t *pVoltage)
{
/* USER CODE BEGIN BSP_USBPD_PWR_VBUSGetVoltage */
/* Check if instance is valid */
int32_t ret = BSP_ERROR_NONE;
if ((Instance >= USBPD_PWR_INSTANCES_NBR) || (NULL == pVoltage))
{
ret = BSP_ERROR_WRONG_PARAM;
}
else
{
uint32_t voltage;
voltage = __LL_ADC_CALC_DATA_TO_VOLTAGE(VDDA_APPLI, ((uint32_t)LL_ADC_REG_ReadConversionData12(VSENSE_ADC_INSTANCE)), LL_ADC_RESOLUTION_12B); /* mV */
/* STM32G474E_EVAL board is used */
/* Value is multiplied by 7.030 according to board measurements.
Theorically, it should have been 7.613 (Divider R323/R244 (49.9K/330K) for VSENSE */
voltage *= 7030U;
voltage /= 1000U;
*pVoltage = voltage;
#if defined(_TRACE)
char _str[20u];
sprintf(_str,"==%d", voltage);
USBPD_TRACE_Add(USBPD_TRACE_DEBUG,0,0,(uint8_t*)_str, strlen(_str));
#endif
}
return ret;
/* USER CODE END BSP_USBPD_PWR_VBUSGetVoltage */
}
Regards,
Yohann
2021-03-01 01:45 AM
Dear @ADoro.2
when cable is already connected, source port is not able to detect that CC connection has been lost.
Then sink should send a hard reset to reset VBUS on source side and wait for new source capabilities.
Unfortunately, in the code you are using, there are no code to check that VBUS goes lower than Vsafe0V (around 750mV)
Can you add the following user code in the function 'USBPD_PWR_IF_SupplyReady'?
/**
* @brief Checks if the power on a specified port is ready
* @param PortNum Port number
* @param Vsafe Vsafe status based on @ref USBPD_VSAFE_StatusTypeDef
* @retval USBPD status
*/
USBPD_StatusTypeDef USBPD_PWR_IF_SupplyReady(uint8_t PortNum, USBPD_VSAFE_StatusTypeDef Vsafe)
{
/* USER CODE BEGIN USBPD_PWR_IF_SupplyReady */
USBPD_StatusTypeDef status = USBPD_ERROR;
uint32_t _voltage;
/* check for valid port */
if (!USBPD_PORT_IsValid(PortNum))
{
return USBPD_ERROR;
}
BSP_USBPD_PWR_VBUSGetVoltage(PortNum, &_voltage);
if (USBPD_VSAFE_0V == Vsafe)
{
/* Vsafe0V */
status = ((_voltage < USBPD_PWR_LOW_VBUS_THRESHOLD) ? USBPD_OK : USBPD_ERROR);
}
else
{
/* Vsafe5V */
status = ((_voltage > USBPD_PWR_HIGH_VBUS_THRESHOLD) ? USBPD_OK : USBPD_ERROR);
}
return status;
/* USER CODE END USBPD_PWR_IF_SupplyReady */
}
In meanwhile, I detected with few chargers, that VBUS value by the disco board does not reach Vsafe0V. In my case lowest value was 1350mV.
Then, I needed to increase the threshold of 'USBPD_PWR_LOW_VBUS_THRESHOLD' to 1500mV.
#define USBPD_PWR_LOW_VBUS_THRESHOLD (1500U)
In this case, I was able to receive correctly the new SRC capabilities after the hard reset:
84 PE 1787 1 PE_STATE_READY_WAIT
(board reset with attached cable)
86 CAD 4 1 USBPD_CAD_STATE_ATTACHED_WAIT
87 CAD 123 1 USBPD_CAD_STATE_ATTACHED
88 EVENT 123 1 EVENT_ATTACHED
93 PE 123 1 PE_SNK_STARTUP
94 PE 123 1 PE_SNK_WAIT_FOR_CAPABILITIES
95 PE 623 1 PE_STATE_HARD_RESET
96 NOTIF 623 1 POWER_STATE_CHANGE
97 NOTIF 623 1 HARDRESET_TX
98 OUT 623 1 HRST
101 PE 623 1 PE_SNK_HARD_RESET_WAIT_VSAFE_0V
(vSafe0V detected after 711ms, timeout set to 1s)
102 NOTIF 1334 1 POWER_STATE_CHANGE
106 NOTIF 1334 1 POWER_SNK_STOP
107 PE 1334 1 PE_SNK_HARD_RESET_WAIT
109 PE 1423 1 PE_SNK_WAIT_FOR_CAPABILITIES
110 IN 1573 1 SRC_CAPABILITIES DATA:2C9101082CD10200FAC00300C8B0040096400600 / 5V - 3A / 9V - 3A / 12V - 2.5A / 15V - 2A / 20V - 1.5A SOP PD3 H:0x51A1
I advice you to trace the VBUS value to confirm the vSafe0V:
/**
* @brief Get actual voltage level measured on the VBUS line.
* @param Instance Type-C port identifier
* This parameter can be take one of the following values:
* @arg @ref USBPD_PWR_TYPE_C_PORT_1
* @param pVoltage Pointer on measured voltage level (in mV)
* @retval BSP status
*/
__weak int32_t BSP_USBPD_PWR_VBUSGetVoltage(uint32_t Instance, uint32_t *pVoltage)
{
/* USER CODE BEGIN BSP_USBPD_PWR_VBUSGetVoltage */
/* Check if instance is valid */
int32_t ret = BSP_ERROR_NONE;
if ((Instance >= USBPD_PWR_INSTANCES_NBR) || (NULL == pVoltage))
{
ret = BSP_ERROR_WRONG_PARAM;
}
else
{
uint32_t voltage;
voltage = __LL_ADC_CALC_DATA_TO_VOLTAGE(VDDA_APPLI, ((uint32_t)LL_ADC_REG_ReadConversionData12(VSENSE_ADC_INSTANCE)), LL_ADC_RESOLUTION_12B); /* mV */
/* STM32G474E_EVAL board is used */
/* Value is multiplied by 7.030 according to board measurements.
Theorically, it should have been 7.613 (Divider R323/R244 (49.9K/330K) for VSENSE */
voltage *= 7030U;
voltage /= 1000U;
*pVoltage = voltage;
#if defined(_TRACE)
char _str[20u];
sprintf(_str,"==%d", voltage);
USBPD_TRACE_Add(USBPD_TRACE_DEBUG,0,0,(uint8_t*)_str, strlen(_str));
#endif
}
return ret;
/* USER CODE END BSP_USBPD_PWR_VBUSGetVoltage */
}
Regards,
Yohann
2021-03-01 02:29 AM
@Yohann M., thank you for your answer.
Your advice were very useful. Everything works fine now.
There is only one small bug.
When I press reset button on the board, i get a message in CubeMonitor
42 GUI 0 EXCEPTIONS DETECTED
Then Monitor stucks and repairs only after I disconnect board in Monitor and connect it again.
2021-03-01 09:33 AM
Hello @ADoro.2
The behaviour you are describing (GUI exceptions) is the one we have chosen on purpose.
When the UCPD monitor detects that the timestamp is reset (which happens in case of board reset), you need to go through all the connections steps.
This has been done, to be sure that all the data displayed in the UCPD monitor windows are aligned with the internal values in the board.
Because most of the values are sent by the board from the moment the computer connection is detected.
Regards,
Nicolas