cancel
Showing results for 
Search instead for 
Did you mean: 

Bug with getting power profiles from Source after reset.

ADoro.2
Associate III

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.

0693W000007ESB3QAO.jpgBut 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.

0693W000007ESBDQA4.jpgIs 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?

1 ACCEPTED SOLUTION

Accepted Solutions
Yohann M.
ST Employee

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

View solution in original post

3 REPLIES 3
Yohann M.
ST Employee

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

ADoro.2
Associate III

@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.

Nicolas P.
ST Employee

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