Introduction to USB Power Delivery with STM32

On this page you will find applications examples, document, tips and tricks,... related to STM32 USB Type-C Power Delivery.

1 What is USB Power Delivery

USB Type-C® Power Delivery technology coming with the new reversible USB Type-C™ connector simplifies the consumers' daily life. The technology offers a single platform connector carrying all the necessary lines : USB 2.0, USB 3.x, and power.

The USB Type-C® connector provides native support of up to 15 W (5 V @ 3 A), extendable to 100 W (up to 20 V @ 5 A) with the optional USB Power Delivery feature.

Using the power delivery protocol allows negotiation of up to 100 W power delivery to supply or charge equipment connected to a USB port, the objective being fewer cables and connectors, as well as universal chargers.

The power delivery part extends the previous power specifications (USB 2.0, BC 1.2...) as we see below :

USB 2.0 5 V 500 mA Default Current, based on definitions in the base specifications
USB 3.1 5 V 900 mA Default Current, based on definitions in the base specifications
USB BC 1.2 5 V Up to 1.5 A Legacy charging
USB Type-C @ 1.5 A 5 V 1.5 A Supports high power devices
USB Type-C @ 3.0 A 5 V 3 A Supports higher power devices
USB-PD Configurable up to 20 V Configurable up to 5 A Directional control and power level management

The type C interface brings one new signal comparing to previous USB cables : the CC line. (Control channel). On this line, at 300 Kbits/s the power delivery protocol will give the possibility to exchange messages between the 2 connected partners.

The Power Delivery feature comes with a protocol that brings real time possibilities :

  • change the power role. To change dynamically who provides VBUS, independently of the USB data role.
  • change the USB data role dynamically. This replaces the OTG from the previous USB specifications
  • carry authentication messages to authenticate the connected partner.
  • select an "Alternate Mode" to use the USB 3.0 super speed lines to carry video information (Display port or HDMI)
  • firmware update
  • exchange battery information

To determine the power delivery role, a pull up/down resistor has to be presented on the CC lines. so if the power role change is reflected by the updated resistor on the CC line. Whenever you have a "legacy cable" (type A to type C for example), to comply with the specification, it has an integrated resistor. As the type A/B doesn't have a CC line in the connector, the power role is determined by the pull up/down resistor in the plug.

Frequent acronyms :

Acronym Definition
AM Alternate Mode : to specify the use of the super speed lines for Video for example
APDO Augmented power data object. It is a PDO in the case of PPS
DFP Downstream Facing Port
DRP Dual Role Power : the ability to change power role dynamically ie : Source or Sink. the device toggles the pull up / down resistor
GUI Graphical User Interface = STM32CubeMonitor-UCPD
PDO Power Data Object : the definition of a power capability
PPS Programmable Power Supply : option in power delivery specification to be able to specify a voltage with 20mV precision within a range.
SNK Sink = device that will ask for VBUS
SRC Source = device that will provide VBUS
TCPC Type C Port Controller
TCPM Type C port Manager
UCPD USB Type-C Power Delivery Peripheral
UFP Upstream facing port
VDM Vendor Defined Message. Type of message used for Alternate Mode

2 Getting started with STM32 and USB Power Delivery

Depending on the need, using type-C only may be enough, for example if you need only 5A/3A. In that case you do not need a MCU with UCPD inside. See AN5225 for more details.

If you need specific power delivery features, then you need the stack, and you need to manage CC1 and CC2 lines.

Reminder : even if there is only one CC line used for communication, you need to manage both lines, because you can't guess how the cable will be plugged.

USBPD Type-C cable orientation

The Power delivery protocol is provided by ST as a library as below picture :

USBPD stack architecture

The library (light pink box) only includes PE (Policy Engine), PRL (PRotocol Layer), and a part of CAD (CAble Detection). This library is common to all STM32 including the UCPD IP. The device part depends on the STM32 family (STM32G0, STM32G4...) The customer application is located in DPM (Device Policy Manager). This is where the strategy (choose the maximum power...) is coded.

Here is an USBPD project example in IAR :

USBPD IAR Project example

In all our project examples, different folders can be found:

  • The Application/User folder contains the source files that we need to edit to enrich the application. In particular the files *_user.c.
  • The Drivers folder contains the HAL drivers for the STM32.
  • The Middleware folder contains the source files and the libraries for FreeRTOS and USB-PD stack.
  • The Utilities folder contains the GUI (STM32CubeMonitor-UCPD) and tracer embedded source files part.
  • The Output folder contains the compilation result files.

3 Video related to STM32 and USB Power Delivery

STM32G0: Create a USB Power Delivery sink application in less than 10 minutes

4 STM32 compliant with USB Power Delivery

If you are looking for STM32 products that support Power Delivery, you can search in STM32CubeMX for the integration of the UCPD peripheral. STM32G0 is the only family with parts that contains up to 2 UCPD instances.

5 Specific tools

If the GUI responder is not activated in the embedded firmware, but the debug trace is available (UART through VCP of the STLink, and the compilation switch _TRACE activated) you may still see the trace in UCPD monitor by clicking on the Trace button in the bottom right corner.

USBPD UCPD Monitor Trace selection
USBPD UCPD Monitor COM Port Selection

The trace files are saved in c:\Users\your_login\AppData\Local\Temp\STM32CubeMonitor-UCPD\Acquisition\ with extension ".cpd"

Note: the cpd files are a pretty good entry point to report an issue to our support team, it provide helpful debug information of the USB-PD stack behavior.

6 STMicroelectronics Resources

7 Application Examples

You can find a lot of application examples in the STM32G0 firmware package. For example in Projects\STM32G081B-EVAL\Demonstrations\DemoUCPD Or if you have downloaded the package through STM32CubeMx : c:\Users\your_login\STM32Cube\Repository\STM32Cube_FW_G0_V1.3.0\

MCU ref Power role Comment
STM32G071B-Disco Sink UM2546
STM32G081B-Eval Dual port DRP and Sink UM2321

8 FAQ

8.1 How to analyse the failed return by the function USBPD_DPM_InitCore ?

This function is called at the init stage to initialize the USB-PD application (device and stack part)

 /* Check the lib selected */
 if (USBPD_TRUE != USBPD_PE_CheckLIB(_LIB_ID))
 {
   return USBPD_ERROR;
 }

at this stage, software is checking if the LIB files selected to build the project and the compilation switch USBPDCORE_LIB****** are aligned.

Definition available in usbpd_def.h

 /* _LIB_ID definition */
 /*
   _LIB_ID constructs like this: 0xXYVVVWWW
   * X: 3 (PD3.0) or 2 (PD2.0)
   * Y: 0 (CORE) or 1 (TCPM)
   * VVV: Stack version (ex 200 for Stack 2.0.0)
   * WWW: 0 (FULL VERSION) or config_x
 */

For instance, if the lib 'USBPDCORE_PD3_FULL_CM*.*' is selected, user should enable the switch 'USBPDCORE_LIB_PD3_FULL'

8.2 How to know the memory needed by the stack

This is done dynamically in the stack, depending on the linked USBPD library :

 stack_dynamemsize = USBPD_PE_GetMemoryConsumption();

This stage is optional (could be removed) and only present to know how much memory are needed the USB-PD stack to help to define the correct value of the HEAP.

8.3 How to insert my own debug information inside the trace system ?

  • Add Debug trace inside embedded code :

by using the USBPD_TRACE_Add from file usbpd_trace.c, you can print information inside the gui tools

         USBPD_TRACE_Add(6, 0, 0, 'string', 'string size');

example :

Debug trace in STM32CubeMonitor-UCPD when _GUI_INTERFACE is disabled


          USBPD_TRACE_Add(6, 0, 0, "hello world", 11);

Check the line "DEBUG hello world" in grey on the following pictures (Click to enlarge). The numbers indicated in the trace are the TimeStamp and the port number. (TimeStamp can be practical to debug real time issues)

Debug trace in STM32CubeMonitor-UCPD when _GUI_INTERFACE is enabled


  • Add livewatch on CAD_HW_Handles. This variable can be used to check the Type-C attachment or detachment.

See usbpd_cad_hw_if.c:

 #define USBPD_CAD_STATE_RESET 0u /*!< USBPD CAD State Reset */
 #define USBPD_CAD_STATE_DETACHED 1u /*!< USBPD CAD State No cable detected */
 #define USBPD_CAD_STATE_ATTACHED_WAIT 2u /*!< USBPD CAD State Port partner detected */
 #define USBPD_CAD_STATE_ATTACHED 3u /*!< USBPD CAD State Port partner attached */
  • If the CC lines are empty, check that the TCPP is passed through, which means that the active LOW _DB pin is disabled at 3.3 V. This is due to the jumpers or some GPIO settings.

Note: In the current STM32CubeMX for STM32G4, there is an issue with the default GPIO mode for CC2. In usbpd_cad_hw_if.c there must be: LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_4, LL_GPIO_MODE_ANALOG); In STM32G4 versions before FW 1.2.0, the correct compilation switch is not set. An easy way is to correct this issue is to activate the compilation switch MB1367.

  • For further debug, the VBUS measured value can be printed in the trace, using the user button.

8.4 Why a request function returned USBPD_OK but I cannot see the message in the trace?

All the request functions (like USBPD_DPM_RequestDataRoleSwap) will not trig directly the sending of the message to port partner. Idea is to post a request to the stack and when stack is ready, it will consume this request to send it to the port partner.

Note1: only 1 request is possible. Another request sent whereas the previous one has not been consumed will be not taken in account (USBPD_BUSY status will be returned)

Note2: USBPD_BUSY is also returned if there are no connected port partners

8.5 About FreeRTOS in our stack

Tasks creations are done in usbpd_dpm_core.c file. At the initialization, USB-PD creates 2 threads:
- CAD Task: use for Cable detection (higher priority in our system set to osPriorityRealtime)
- TRA_TX: use to evacuate debug trace (set to osPriorityLow priority)

When Type-C is connected, we create a dynamic task for PE_TASK set to priority lower than CAD, osPriorityAboveNormal (done through callback ‘USBPD_DPM_CADCallback’. It allows to start a PD negotiation. Task is killed if a detach is done.

In usbpd_dpm_user.c, we create also a task for DPM set as low priority
- DPM task: used mainly to manage specification to be done after timer expiration like:
o Management of ALERT messages
o Management of SRC_CAPA_EXT messages …

Two different scenarios:
1- No Type-C cable connected:

  • In DRP mode, we have a CAD toggle to switch every 40ms from Source (present Rp) to Sink (present Rd). Then CAD tasks will be wake-up regularly (every 40ms).
  • In SRC or SNK mode, wake-up if an event on CC lines (through ‘USBPD_DPM_CADCallback’ function)

2- Type-C connected:

  • If Power Delivery negotiation is OK, CAD and PE should wait for a new event, and CAD will be woken-up
    • In SRC: due to an event on CC lines (through ‘USBPD_DPM_CADCallback’ function)
    • In SNK: every 10ms or an event on CC line, PE will be woken-up only if a message should be sent or received (through ‘USBPD_PE_TaskWakeUp’ function)
  • Negociation failed:
    • In SNK, CAD will be woken-up every 10ms or an event on CC line
    • In SRC, if no answer from port partner:
      • PE_CapscounterSupport = 0: PE wake up every 150ms
      • PE_CapscounterSupport = 1: system will be wake-up only in change in CC lines

Normally, during CAD/PE sleep, FreeRTOS should provide the hand to other tasks having lower priority (thanks to osDelay function for instance). There are no real reasons than another tasks with less priority can take the hand!