cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G071 hardfault in USBPD middleware when configured with 1 source and 1 sink port

NathanWolcott
Associate III

I'm trying to get the USBPD middleware running with 2 ports: 1 source and 1 sink. I already followed the tutorial to get 1 port working as a sink. When I add the second port as a source, the chip immediately hits a hardfault after starting. I traced it back and the problem is on line 1013 of usbpd_cad_hw_if.c, where _handle->CAD_PtrStateMachine(PortNum, pEvent, pCCXX) is run. The problem is that for some reason, _handle->CAD_PtrStateMachine is never initialized and is actually a NULL pointer. Naturally, this hardfaults immediately.

The problem with the init seems to be around line 296 to 358. There are a number of #if defined (***) macros that control which functions are assigned to _handle->CAD_PtrStateMachine depending on whether _SNK, _SRC, or _DRP are defined in the project. It looks like CubeMx is defining _DRP when one of the ports is a sink and the other is a source even though neither port is actually configured for dual role. This activates the code path at line 298 but then, since neither port is actually dual role, the it fails the check on 299 and so CAD_PtrStateMachine is never set.

After the init finishes, a cable detech event is fired for both ports, which eventually causes _handle->CAD_PtrStateMachine() to be executed unconditionally.

I've pasted the snippet from usbpd_cad_hw_if.c below (note that the line numbers won't match).

Yes, it works just fine with both ports configured as sinks.

I'm using firmware V1.4.1 and CubeIDE 1.6 (although the same problem exists in CubeIDE 1.5).

 /* Set the state machine according the SW configuration */
#if !defined(USBPDCORE_LIB_NO_PD)
#if defined(_DRP)
  if (Ports[PortNum].settings->CAD_RoleToggle == USBPD_TRUE)
  {
    _handle->CAD_PtrStateMachine = CAD_StateMachine_DRP;
    _handle->CAD_Accessory_SRC = Ports[PortNum].settings->CAD_AccesorySupport;
#if defined(USBPDCORE_VPD)
    _handle->CAD_VPD_SRC = Ports[PortNum].settings->CAD_VPDSupport;
#endif /* USBPDCORE_VPD */
  }
  else
#endif /* !USBPDCORE_LIB_NO_PD */
  {
#if defined(_SRC)
    if (USBPD_PORTPOWERROLE_SRC == Ports[PortNum].settings->PE_DefaultRole)
    {
      _handle->CAD_PtrStateMachine = CAD_StateMachine_SRC;
      _handle->CAD_Accessory_SRC = Ports[PortNum].settings->CAD_AccesorySupport;
#if defined(USBPDCORE_VPD)
      _handle->CAD_VPD_SRC = Ports[PortNum].settings->CAD_VPDSupport;
#endif /* USBPDCORE_VPD */
    }
    else
#endif /* _SRC */
    {
#if defined(_SNK)
      _handle->CAD_PtrStateMachine = CAD_StateMachine_SNK;
      _handle->CAD_Accessory_SNK = Ports[PortNum].settings->CAD_AccesorySupport;
#if defined(USBPDCORE_VPD)
      _handle->CAD_VPD_SNK = Ports[PortNum].settings->VPDSupport;
#endif /* USBPDCORE_VPD */
#endif /* _SNK */
    }
  }
#else  /* USBPDCORE_LIB_NO_PD */
#if defined(USBPD_TYPE_STATE_MACHINE)
#if defined(_SRC)
    if (USBPD_PORTPOWERROLE_SRC == Ports[PortNum].settings->PE_DefaultRole)
    {
      _handle->CAD_PtrStateMachine = CAD_StateMachine_SRC;
#if !defined(USBPDCORE_LIB_NO_PD)
      _handle->CAD_Accessory_SRC = Ports[PortNum].settings->CAD_AccesorySupport;
#endif /* !USBPDCORE_LIB_NO_PD */
#if defined(USBPDCORE_VPD)
      _handle->CAD_VPD_SRC = Ports[PortNum].settings->CAD_VPDSupport;
#endif /* USBPDCORE_VPD */
    }
    else
#endif /* _SRC */
    {
#if defined(_SNK)
      _handle->CAD_PtrStateMachine = CAD_StateMachine_SNK;
#if !defined(USBPDCORE_LIB_NO_PD)
      _handle->CAD_Accessory_SNK = Ports[PortNum].settings->CAD_AccesorySupport;
#endif /* !USBPDCORE_LIB_NO_PD */
#if defined(USBPDCORE_VPD)
      _handle->CAD_VPD_SNK = Ports[PortNum].settings->CAD_VPDSupport;
#endif /* USBPDCORE_VPD */
#endif /* _SNK */
    }
#endif  /* USBPD_TYPE_STATE_MACHINE */
#endif  /* USBPDCORE_LIB_NO_PD */

1 ACCEPTED SOLUTION

Accepted Solutions
Yohann M.
ST Employee

Hi @NathanWolcott​ 

I reproduced your setup and I confirm the same problem.

Unfortunately, we should enable also _DRP switch with _SRC and _SNK switches. In case of _DRP is not enabled, in your configuration, ANAMODE is set to 1 in both configuration linked to this code:

void CAD_Init(uint8_t PortNum, USBPD_SettingsTypeDef *pSettings, USBPD_ParamsTypeDef *pParams,  void (*WakeUp)(void))
{
(...)
#if defined(_SRC) || defined(_DRP)
  /* Initialize usbpd interrupt */
  if (USBPD_PORTPOWERROLE_SRC == Ports[PortNum].params->PE_PowerRole)
  {
    USBPDM1_AssertRp(PortNum);
  }
#endif /* _SRC || _DRP */
#if defined(_DRP)
  else
#endif /* _DRP */
#if defined(_SNK) || defined(_DRP)
  {
    USBPDM1_AssertRd(PortNum);
  }
#endif /* _SNK || _DRP */

Apologize again regarding this constraint :(

In meanwhile, if you want a reference to source application, we have the following one (based on STM32G081B-EVAL board in STM32CubeG0 package):

https://github.com/STMicroelectronics/STM32CubeG0/tree/master/Projects/STM32G081B-EVAL/Applications/USB-PD/USB-PD_Provider_1port

There are no STM32CubeMx application for dual role but demonstration of STM32G081B-EVAL board shows this configuration on port_1 DRP:

https://github.com/STMicroelectronics/STM32CubeG0/tree/master/Projects/STM32G081B-EVAL/Demonstrations/DemoUCPD

Regards,

Yohann

View solution in original post

11 REPLIES 11
Yohann M.
ST Employee

Dear @NathanWolcott​ 

We may have an issue with code generation done by CubeMx.

Can you try to enable _SRC and _SNK compilation switches in your STM32CubeIDE project? And remove the compilation switch _DRP.

regards,

Yohann

NathanWolcott
Associate III

Hi @Yohann M.​ 

I made the change as you suggested and this appears to work. The code no longer hardfaults at startup and I am able to attach the CubeMonitorUCPD app to the board and see the trace on the sink port.

I have not yet actually tested the source port, so I don't know if it works, but it is at least stable while running idle.

Thanks for the help. I will add the results of the source port test once I run it.

Hi @Yohann M.​ ,

I can't seem to get the USBPD middleware to work with both a sink and a source port enabled at the same time. While the app no longer crashes with your fix, when I test the Source functionality, it doesn't work correctly. There is still some kind of configuration error because when I check the configuration register, the port is configured as a Sink and not a Source. In my configuration, UCPD1 is a sink and UCPD2 is a source (although I have tried the other way and it doesn't change anything). If I start debugging and then halt and check the registers, UCPD2->CR->ANAMODE is set to 1 (Sink) for both ports. I tracked this problem down after noticing that both CC1 and CC2 lines on the Source port were at 0V, instead of being pulled up.

If I configure the project for only 1 port in Source mode, it works properly, the GUI shows a power contract if I connect to another Sink, etc.

I have also tried running the X-CUBE-TCPP project SNK1M1_Sink as you suggested and just adding a source port to the cube config and regenerating, but this fails too. In this case, the code generator isn't working correctly because the Preprocessor symbols only have _SNK defined and USBPD_PORT_COUNT=1, so the code for the second port is not generated at all.

It doesn't look like is any support in the examples and tutorials for Source, or Dual Role mode. Has any of this stuff been tested?

Thanks,

Nathan

Yohann M.
ST Employee

Hi @NathanWolcott​ 

I reproduced your setup and I confirm the same problem.

Unfortunately, we should enable also _DRP switch with _SRC and _SNK switches. In case of _DRP is not enabled, in your configuration, ANAMODE is set to 1 in both configuration linked to this code:

void CAD_Init(uint8_t PortNum, USBPD_SettingsTypeDef *pSettings, USBPD_ParamsTypeDef *pParams,  void (*WakeUp)(void))
{
(...)
#if defined(_SRC) || defined(_DRP)
  /* Initialize usbpd interrupt */
  if (USBPD_PORTPOWERROLE_SRC == Ports[PortNum].params->PE_PowerRole)
  {
    USBPDM1_AssertRp(PortNum);
  }
#endif /* _SRC || _DRP */
#if defined(_DRP)
  else
#endif /* _DRP */
#if defined(_SNK) || defined(_DRP)
  {
    USBPDM1_AssertRd(PortNum);
  }
#endif /* _SNK || _DRP */

Apologize again regarding this constraint :(

In meanwhile, if you want a reference to source application, we have the following one (based on STM32G081B-EVAL board in STM32CubeG0 package):

https://github.com/STMicroelectronics/STM32CubeG0/tree/master/Projects/STM32G081B-EVAL/Applications/USB-PD/USB-PD_Provider_1port

There are no STM32CubeMx application for dual role but demonstration of STM32G081B-EVAL board shows this configuration on port_1 DRP:

https://github.com/STMicroelectronics/STM32CubeG0/tree/master/Projects/STM32G081B-EVAL/Demonstrations/DemoUCPD

Regards,

Yohann

Thanks for the update @Yohann M.​ .

Unfortunately, I've run into a weird problem and haven't been able to test your fix.

After regenerating the code, I now get a bunch of undefined reference errors when trying to compile.

I actually started a brand new project, configured it the same as usual (1 sink and 1 source port, trace, gui, etc) and I get the same error. Does this have anything to do with importing that other project from the X-CUBE_TCPP package? I wouldn't think that would have any impact on the other projects in the workspace.

This is the error. When I do a global search, I can't find the function definitions in the firmware repo folder at all. Very strange.

c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: Middlewares/ST/STM32_USBPD_Library/Core/src/usbpd_trace.o: in function `USBPD_TRACE_Init':
C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../Middlewares/ST/STM32_USBPD_Library/Core/src/usbpd_trace.c:113: undefined reference to `USBPD_PE_SetTrace'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: USBPD/usbpd_dpm_core.o: in function `PE_Task':
C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:368: undefined reference to `USBPD_PE_StateMachine_DRP'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: USBPD/usbpd_dpm_core.o: in function `USBPD_CAD_Task':
C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:391: undefined reference to `USBPD_CAD_Process'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: USBPD/usbpd_dpm_core.o: in function `DPM_ManageAttachedState':
C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:464: undefined reference to `USBPD_PE_IsCableConnected'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: USBPD/usbpd_dpm_core.o: in function `USBPD_DPM_CADCallback':
C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:427: undefined reference to `USBPD_PE_IsCableConnected'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: USBPD/usbpd_dpm_core.o: in function `USBPD_DPM_InitCore':
C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:167: undefined reference to `USBPD_PE_CheckLIB'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:175: undefined reference to `USBPD_PE_GetMemoryConsumption'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:197: undefined reference to `USBPD_CAD_Init'
c:\st\stm32cubeide_1.6.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_1.5.0.202011040924\tools\arm-none-eabi\bin\ld.exe: C:/Users/D-Rock/STM32CubeIDE/workspace_1.6.0/stm32g071_nucleo_usbCC_test3/Debug/../USBPD/usbpd_dpm_core.c:201: undefined reference to `USBPD_PE_Init'
<snipped...>

Dear @NathanWolcott​ 

All these functions are included in the USB-PD stack library.

Can you check that the library is well included in your project?

0693W000008y83oQAA.jpg 

Regards,

Yohann

@Yohann M.​ 

Yes, that was the problem. Both the library search path and the libraries section were empty.

For some reason, CubeMX no longer adds these settings to the project configuration file when regenerating the code. Worse still, the libraries setting is cleared each time the code is regenerated, even if it was previously set. Oddly enough, the library search path is not cleared after regenerating.

This is also a problem for newly created projects, which is very strange because CubeMX used to add this setting to new projects automatically, at least it did a few weeks ago.

Anyway, after getting the project to compile, I confirmed that both stacks now seem to work.

Any estimate for when a new release will come out patching these bugs? It is very annoying to have a long list of edits that I have to make to the code every time I regenerate the project.

Thanks,

Nathan

Dear @NathanWolcott​ 

Again sorry if you faced a new issue :(

For this problem, I tried to reproduce it with CubeMX V6.2.0 but it works in my side (libraries section is well filled with the stack library name).

To investigate it, could you attach the associated IOC and confirm the CubeMX version you are using?

Regards,

Yohann

Good afternoon @Yohann M.​ 

Here is my IOC file. I am using CubeIDE 1.6. I have not tried generating the project with the standalone CubeMX (the version on my system is also 6.2.0). It's a very strange error because it was working fine for the last couple weeks. It only started erasing the library from the linking configuration after I played around with the X-CUBE_TCPP project; although that's probably just a coincidence.

My project is very simple: it's just starting with a Nucleo-G071RB dev board template and turning on enough stuff to get the USB PD ports up and running. More or less just following the USB-PD tutorial video.

Thanks for all your help.