cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U585 USBPD Not Working

cd3361
Associate II

I am currently using the STM32U585 MCU on a custom board and am trying to get the MCU to function as a DRP device in the USB-C PD protocol. Although currently I am just trying to get the device to work as a SNK (with DRP capability enabled). The project I am implementing this in is using ThreadX as the RTOS.

I have followed multiple tutorials for getting USB-C power delivery implemented on ST MCUs and have implemented the needed changes in the CubeMX .ioc file and have also made the necessary changes in the code listed in AN5418.

I have also referenced plenty of example projects including: DemoUCPD, USB-PD_Consumer_1port, USBPD_DRP_UX_DRD_HID, USBPD_SNK, and USBPD_SNK_UX_Device_HID_CDC_ACM.

One thing that is worth noting is our custom PCBs do not have the TCPP IC on our board, contrary to a lot of the examples. Also, a lot of examples also seem to use FreeRTOS, but the rest of our project has been using ThreadX, so didn't want to make the switch.

Here is what I have found so far, using this flow diagram as the expected sequence of events in a Sink Power negotiation:

cd3361_1-1737557282258.png

 

-Device gets through initialization and reads the VBUS voltage correctly.

-When a USB-C cable is plugged in (USB-C to USB-C cable with USBPD capable power source) the program is able to enter the USBPD_DPM_SetDataInfo, but instead of entering with a USBPD_CORE_DataInfoType_TypeDef of USBPD_CORE_DATATYPE_RCV_SRC_PDO, it enters with USBPD_CORE_DATATYPE_RDO_POSITION and then with a subsequent call with USBPD_CORE_DATATYPE_RCV_REQ_PDO. It then repeats this a second time with nothing happening. This doesn't match the flow in the picture above.

-USBPD_DPM_SNK_EvaluateCapabilities is never called.

-I have used both the STM32 UCPD Monitor and a Cypress USB-PD monitor. All I see is that my device only ever sends zeroes back. I can see the USB-C power source sending the correct messages so I can confirm that the power source is working.

-Using a breakpoint in the code I can see that the code enters USBPD_PORT0_IRQHandler and correctly enters UCPD_SR_RXMSGEND when the USB-C cable is plugged in. I can also see a byte being received in my buffer, but can only see one byte at a time since that is the size of the UCPD RX register.

-I tried to look at the memory location where I would expect to see the full message received, but I only ever see zeroes (potentially a DMA issue?).

 

I have looked at multiple example projects and most of them seem to have the same file content between them. Since the SetDataInfo callback is being called with reasonable parameters and the IRQ handler is getting to RXMSGEND, I assume that we are possibly receiving data correctly, but I could be wrong.

I have tried just using the application in SNK mode rather than as a DRP, and I have gotten the same results.

Any help or hints would be greatly appreciated.

 

 

10 REPLIES 10
cd3361
Associate II

Update: Found that the program was entering into USBPD_DPM_SetDataInfo on the two instances listed above, and then it enters PORTx_IRQHandler and enters the RXMSGEND if statement. Still no data in memory.

cd3361
Associate II

Also, noticed that the GPDMA IRQ Handlers (for USBPD TX and RX) have no code generated within them. Although in a lot of the other example projects there is no code generated in the handlers, so maybe this is intentional and not a bug.

FBL
ST Employee

Hi @cd3361 

The GPDMA IRQ handlers are empty, and this is intentional, since the DMA transfer is being handled by HW in pooling mode.

FBL_0-1737987279358.png

When debugging, you can check transfer complete flags in GPDMA_C3CR are all set to zero which means they are not in interrupt mode.

>Also, a lot of examples also seem to use FreeRTOS, but the rest of our project has been using ThreadX, so didn't want to make the switch.

Would you check which example is using FreeRTOS?

USBPD_DPM_SNK_EvaluateCapabilities function evaluates the received capabilities and decides which power profile to request. In your case you may have only one power profile, USBPD_DPM_SNK_EvaluateCapabilities should be added to establish the first contract.

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.


cd3361
Associate II

FBL,

Thanks for the response.

Yes, I have realized your first point since first posting.

Projects I have found that use FreeRTOS:

-USB-PD_Consumer_1port

-AN5418 app note 

-DemoUCPD

So apologies, I misremembered, because the remaining examples I listed do appear to use ThreadX. I don't think the issue lies with my ThreadX setup, but I can look closer at that.

 

As far as USBPD_DPM_SNK_EvaluateCapabilities is concerned, I will eventually need to make use of this function. But it still never is entered at the moment, should I expect it to be entered?

Like I mentioned before, USBPD_DPM_SetDataInfo still never enters with the expected parameter and I still have yet to find the expected received data at the designated DMA destination address (which as far as I can tell, this destination address is chosen by the USBPD core stack). All I see is zeroes at the destination address. Once RXMSGEND hits in the USBPD IRQ, I can see the last byte received in the RXDR, and I can also see that RX_PAYSZR has the correct number of bytes received. So as of now, it really does seem like it is reading the bytes in correctly to the UCPD peripheral.

Unless the USBPD core stack erases the data at these addresses once it completes the transaction, it kind of seems like the DMA isn't working correctly?

 

 

 

FBL
ST Employee

Hi @cd3361 

I couldn't reproduce on our reference board B-U585I-IOT02A - Discovery kit for IoT node with STM32U5 series - STMicroelectronics

Please check your hardware implementation, maybe the TCPP missing is the root cause of this issue. To understand better the issue, would you attach a trace (.cpd file) to analyse further? My first impression the source capabilities are not properly received. To be checked!

In usbpd_dpm_user.c, USBPD_DPM_SNK_EvaluateCapabilities  is meant to evaluate the received capabilities and prepare the request. It seems like something is missing. Would you attach your project? or simply a direct link from github. 

/**
  * @brief  Evaluate received Capabilities Message from Source port and prepare the request message
  * @param  PortNum             Port number
  * @param  PtrRequestData      Pointer on selected request data object
  * @param  PtrPowerObjectType  Pointer on the power data object
  * @retval None
  */
void USBPD_DPM_SNK_EvaluateCapabilities(uint8_t PortNum, uint32_t *PtrRequestData, USBPD_CORE_PDO_Type_TypeDef *PtrPowerObjectType)
{
/* USER CODE BEGIN USBPD_DPM_SNK_EvaluateCapabilities */
  USBPD_PDO_TypeDef  fixed_pdo;
  USBPD_SNKRDO_TypeDef rdo;
  USBPD_HandleTypeDef *pdhandle = &DPM_Ports[PortNum];
  USBPD_USER_SettingsTypeDef *puser = (USBPD_USER_SettingsTypeDef *)&DPM_USER_Settings[PortNum];
  USBPD_DPM_SNKPowerRequestDetails_TypeDef snkpowerrequestdetails;
  uint32_t pdoindex, size;
  uint32_t snkpdolist[USBPD_MAX_NB_PDO];
  USBPD_PDO_TypeDef snk_fixed_pdo;

  /* USBPD_DPM_EvaluateCapabilities: Port Partner Requests Max Voltage */

  /* Find the Pdo index for the requested voltage */
  pdoindex = DPM_FindVoltageIndex(PortNum, &snkpowerrequestdetails);

  /* Initialize RDO */
  rdo.d32 = 0;

  /* If no valid SNK PDO or if no SRC PDO match found (index>=nb of valid received SRC PDOs or function returned DPM_NO_SRC_PDO_FOUND*/
  if (pdoindex >= pdhandle->DPM_NumberOfRcvSRCPDO)
  {
#ifdef _TRACE
    USBPD_TRACE_Add(USBPD_TRACE_DEBUG, PortNum, 0, (uint8_t *) "PE_EvaluateCapability: could not find desired voltage", sizeof("PE_EvaluateCapability: could not find desired voltage"));
#endif /* _TRACE */
    fixed_pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[0];
    /* Read SNK PDO list for retrieving useful data to fill in RDO */
    USBPD_PWR_IF_GetPortPDOs(PortNum, USBPD_CORE_DATATYPE_SNK_PDO, (uint8_t*)&snkpdolist[0], &size);
    /* Store value of 1st SNK PDO (Fixed) in local variable */
    snk_fixed_pdo.d32 = snkpdolist[0];
    rdo.FixedVariableRDO.ObjectPosition = 1;
    rdo.FixedVariableRDO.OperatingCurrentIn10mAunits  =  fixed_pdo.SRCFixedPDO.MaxCurrentIn10mAunits;
    rdo.FixedVariableRDO.MaxOperatingCurrent10mAunits = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits / 10;
    rdo.FixedVariableRDO.CapabilityMismatch = 1;
    rdo.FixedVariableRDO.USBCommunicationsCapable = snk_fixed_pdo.SNKFixedPDO.USBCommunicationsCapable;

    if (USBPD_SPECIFICATION_REV2 < DPM_Params[PortNum].PE_SpecRevision)
    {
      rdo.FixedVariableRDO.UnchunkedExtendedMessage = DPM_Settings[PortNum].PE_PD3_Support.d.PE_UnchunkSupport;
      DPM_Params[PortNum].PE_UnchunkSupport   = USBPD_FALSE;
      /* Set unchuncked bit if supported by port partner;*/
      if (USBPD_TRUE == fixed_pdo.SRCFixedPDO.UnchunkedExtendedMessage)
      {
        DPM_Params[PortNum].PE_UnchunkSupport   = USBPD_TRUE;
      }
    }

    DPM_Ports[PortNum].DPM_RequestedCurrent = puser->DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits;

    pdhandle->DPM_RequestDOMsg = rdo.d32;
    *PtrPowerObjectType = USBPD_CORE_PDO_TYPE_FIXED;
    *PtrRequestData = rdo.d32;
    pdhandle->DPM_RequestedVoltage = 5000;
    return;
  }

  DPM_SNK_BuildRDOfromSelectedPDO(PortNum, pdoindex, &snkpowerrequestdetails,&rdo, PtrPowerObjectType);

  /* Check to send a Get Get_Source_Cap_Extended.
     Can be requested if Peak Current of fixed supply PDOs to 0.
  */
  fixed_pdo.d32 = pdhandle->DPM_ListOfRcvSRCPDO[pdoindex];
  if (USBPD_CORE_PDO_TYPE_FIXED == fixed_pdo.GenericPDO.PowerObject)
  {
    if (USBPD_CORE_PDO_PEAKEQUAL == fixed_pdo.SRCFixedPDO.PeakCurrent)
    {
      DPM_Ports[PortNum].FlagSendGetSrcCapaExtended = 1;
    }
  }

  *PtrRequestData = pdhandle->DPM_RequestDOMsg;
/* USER CODE END USBPD_DPM_SNK_EvaluateCapabilities */
}

 

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.


cd3361
Associate II

@FBL 

Okay thanks for trying that.

I have attached my trace file (although it may not be what you are requesting, I generated this .txt file from the STM32CubeMonitor UCPD). If it isn't what you are looking for, let me know.

 

I likely won't be able to give you the whole project but I may be able to give you particular files or screenshots of some of the code. Are there any particular files that would be useful for you?

Thanks.

cd3361
Associate II

@FBL 

Here is also a screenshot using a different USB-C monitor:

cd3361_0-1738163314686.png

 

FBL
ST Employee

Hi @cd3361 

The source sends its capabilities. However, your sink device sends NOT_SUPPORTED messages and initiates SOFT_RESET. Check your sink PDOs list. The sink device is not properly handling the received SRC_CAP.

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.


cd3361
Associate II

@FBL 

Just double checking, is the NOT_SUPPORTED from the Sink or the Source? It looks to me like it is coming from the Source:

cd3361_0-1738246243046.png

cd3361_1-1738246298662.png