Skip to main content
Visitor II
February 9, 2021
Solved

Bug with getting power profiles from Source after reset.

  • February 9, 2021
  • 3 replies
  • 1357 views

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?

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

    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

    3 replies

    Yohann M.Answer
    ST Employee
    March 1, 2021

    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.2Author
    Visitor II
    March 1, 2021

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

    ST Employee
    March 1, 2021

    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