2025-09-04 11:50 PM
Hi ST Community,
once again I have found a USB PD Specification violation, that I can't find the reason for:
Source operation: According to USB PD Spec the order of action is as follows:
1. Detect Sink using CC lines and only if sink is detected continue with the next points
2. Enable VBus to safe5V
3. Once safe5V is applied send source capabilities message
However current implementation of the ST Stack does not care about the state of VBus. It starts immediately sending out source capabilities messages.
I guess the problem is that PE Task is started immediately on Attach event in USBPD_DPM_CADCallback. And it never checks for the bus voltage.
I composed a crude minimal example that does not even do anything when it should enable VBus but still source capabilities message is blown out immediately. Please find the minimal example attached.
Did I miss anything? Will I need to find a workaround or can we get a fixed version of the library?
Best regards,
Adrian
2025-09-07 10:45 PM - edited 2025-09-08 12:09 AM
I don't know if it is related but it might be:
I just found another Problem: When acting as a source the sink sends a request for a specific PDO and the "magic" ST Stack just answers PS RDY exactly 30ms after. According to Spec before the USB C 3.2 Spec 7.3.1.1.1 "Generic Transition Diagram for changing the Source to another (A)PDO" source needs to wait tSrcTransition (25-35ms) before it is even allowed to transition to the new voltage setpoint. That 30ms I measure fits the tSrcTransition time window perfectly, so maybe the stack waits that time window and then immediately sends PS RDY?
But why does it not check voltage Levels? Am I missing something?
Putting a breakpoint in BSP_USBPD_PWR_VBUSGetVoltage is not triggered when before transitioning. USBPD_PWR_IF_SupplyReady is not called either....
Hope you can help me on this. Unfortunately the stack documentation is quite weak and as it is a black box where you can't look into I can't find further places I can dig into. Sometimes I feel like I am the first one to test it for specification compliance....
Best Regards,
Adrian
Edit: when looking at the example at https://github.com/STMicroelectronics/STM32CubeH5/blob/main/Projects/STM32H573I-DK/Applications/USBPD/USBPD_SRC/USBPD/App/usbpd_pwr_if.c
I can see vbus_transition is set to different voltage levels, but that variable is never used? Where should it have been used?
2025-09-08 3:48 AM
Hi @abtq
We need to control periodically VBUS as specified in UM2552 after USBPD_DPM_CADCallback, we need to launch the PE task and we control periodically VBUS.. Our documentation clearly explains how it should work !
I couldn't reproduce the behavior using H5 disco board and your firmware! Would you attach .cpd trace using Cube Monitor UCPD for quick check?
About your second point, I assume vbus_transition is not used in this example because it initializes the type C port in source mode with only one PDO at 5V.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-09-08 11:59 PM
Hi @FBL ,
thanks for the support!
As I am running on a custom hardware I wasn't easily able to run STM32CubeMonitor-UCPD, but I managed to at least output the trace as text using the "Select Tracer Port" in the top right (however a txt is generated then instead of a .cpd). Hope this helps as well, otherwise I will need to dig deeper into that. Please find the txt attached.
Here you can see the issue as well: At timestamp 19773 VBus is enabled (which just does nothing in the dummy implementation attached to my first post) and immediately after at timestamp 19773 to 19778 three source capabilities messages are sent out. But in between BSP_USBPD_PWR_VBUSGetVoltage is never queried...
In an external trace tool you can see the same: Without VBus enabling (obviously as in this minimal example I am doing nothing to enable VBus) Source Capabilities are spammed out on CC lines...
Regarding your first point: I don't really get your point. In my example I am source and not sink. So I guess the relevant timing diagram from UM2552 would be this?
In this diagram there is also nowhere mentioned, that actually for USB PD Compliance you would want to wait between VBUS-ON and probably the launch of the PE Task (or you would need to wait in the launched PE Task) until VBus really is there. So I would expect something like this:
or alternatively the waiting part in the PE Task.
What am I missing?
I can see that the headline of the implementation in my picture is "User Application". Here I have just been using the default generated code by CubeMX:
void USBPD_DPM_CADCallback(uint8_t PortNum, USBPD_CAD_EVENT State, CCxPin_TypeDef Cc)
{
/* _TRACE */
(void)(Cc);
switch (State)
{
case USBPD_CAD_EVENT_ATTEMC :
{
#if defined(_VCONN_SUPPORT)
DPM_Params[PortNum].VconnStatus = USBPD_TRUE;
#endif /* _VCONN_SUPPORT */
USBPD_DPM_UserCableDetection(PortNum, USBPD_CAD_EVENT_ATTEMC);
DPM_StartPETask(PortNum);
break;
}
case USBPD_CAD_EVENT_ATTACHED :
USBPD_DPM_UserCableDetection(PortNum, USBPD_CAD_EVENT_ATTACHED);
DPM_StartPETask(PortNum);
break;
// .......
}
VBus is enabled in USBPD_DPM_UserCableDetection and immediately after DPM_StartPETask starts the PE Task. Do I have to add a wait manually in here? (actually you don't want to pause the execution in a callback so I guess I would have to do some state machine magic here and remember to start the PE Task once VBus is on...)
Would a handling inside PE Task (or somewhere else where there is already a state machine) not be more elegant?
Looking forward to your response! I feel like I am heading in the wrong direction here...
2025-09-09 4:27 AM
Hi @abtq
To clarify some points:
Regarding VBUS checking before starting the PE task:
The USB PD stack relies on the CAD state machine to monitor VBUS presence through the power interface functions like BSP_USBPD_PWR_VBUSGetVoltage(). The PE task is triggered by the CAD callback on attach events, but internally the CAD state machine verifies VBUS status before allowing the PE state machine to proceed. This means the stack does not block or wait explicitly before starting PE; instead, it depends on accurate VBUS detection in the CAD layer.
Your observation about missing VBUS voltage queries:
From your trace and description, it appears that USBPD_PWR_IF_ReadVA() and related power interface functions are not implemented since your code is generated with CubeMX. Without a proper VBUS voltage measurement, the CAD state machine cannot detect VBUS presence correctly. This leads to the PE task starting immediately and Source Capabilities messages being sent prematurely, as you observed.
On the figure 11 in UM2552 and compliance:
In my understanding, USB PD specification does not explicitly require a delay between enabling VBUS and starting the PE task. Instead, it expects the CAD layer to handle VBUS detection asynchronously. Blocking inside the CAD callback to wait for VBUS is not recommended and would complicate the state machine.
So what is the recommended approach?
You should implement the power interface functions properly so that BSP_USBPD_PWR_VBUSGetVoltage() returns the actual VBUS voltage. This enables the CAD state machine to detect VBUS presence correctly and only then start the PE task. This approach is cleaner and aligns with the stack’s design.
The USBPD example firmware you already mentioned for STM32H573I-DK fully implements these power interface functions and integrates with STM32CubeMonitor-UCPD for trace and debugging. I recommend reviewing that example to understand how VBUS detection and PE task triggering are coordinated. Also, this wiki STM32StepByStep:Getting started with USB-Power Delivery Source - stm32mcu and Introduction to USB Power Delivery with STM32 - stm32mcu can help you understand better the stack.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-09-10 8:43 AM - edited 2025-09-10 8:44 AM
Hi @FBL ,
thanks for the explanations, however to me it looks like it is behaving differently than you describe it should behave.
I have also implemented all the PWR functions (which I already had in my base project and just didn't bother to do for the minimal example as it already shows the problem) without any difference, but lets walk through it slowly:
Breakpoints in most of the new ones also never hit. Obviously the implementations are stubs but when VBus does not turn on and VBUSGetVoltage always return 0V then it should never send SRC Capabilities, right? Even if it would magically just not show the call to VBUSGetVoltage in the trace. Or is there a different function that I need to change that is used to determine VBus voltage?
You are saying "Without a proper VBUS voltage measurement, the CAD state machine cannot detect VBUS presence correctly" - I have always had a "propper" voltage measurement. It does always return BSP_ERROR_NONE and put 0V to where pVoltage points, which is correct as I am never really enabling any voltage. Or does the stack implement something like "oh if voltage is exactly 0V all the time, measurement must be faulty, lets just asume VBus is on"?
As you also advise against blocking or adding a state machine I think I should fix this issue, but I don't see the solution yet.
Looking at the reference https://github.com/STMicroelectronics/STM32CubeH5/blob/main/Projects/STM32H573I-DK/Applications/USBPD/USBPD_SRC/USBPD/Target/usbpd_pwr_user.c BSP_USBPD_PWR_VBUSOn(uint32_t Instance) function it doesn't even turn on VBus (and even returns BSP_ERROR_FEATURE_NOT_SUPPORTED)?! Where does turning on happen? Searching for PG0, GPIOG, UCPD_PWR does not bring any result for project https://github.com/STMicroelectronics/STM32CubeH5/tree/main/Projects/STM32H573I-DK/Applications/USBPD/USBPD_SRC
To sum up:
Even with PWR Interfaces implemented nothing has changed (maybe I missed a function, that's why I added the diff images)
So what's next?
Can you provide your log of it working?
If you confirm it is working for you I will probably have to get one of the USB PD reference boards to check if it works there... (but still I can't expect it to - see point 2 in "To sum up")
I am looking forward to your hints, but I am not in office the next two weeks so please apologise a late response from my side.