cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeIDE and C++ support

mattias norlander
ST Employee
Hi C++ Developers,
 
As you may know, developers downliading Cube tools from st.com will receive an e-mail asking them to provide feedback. From this feedback we see some complaints vs the C++ support in STM32CubeIDE. The complaints are however lacking details. We are aware of several C++ topics which could be improved. But without detail, it is hard to tell what is seen as the highest priority... Here is where we need your help!
 
Brainstorming on the main C++ issues in STM32CubeIDE (and Cube ecosystem) I arrive at this list of issues::
 

 

What is your main concern related to C++ support in CubeIDE? You may have issues not even listed... Please share your opinions!
 
Kind regards, Mattias
 
12 REPLIES 12
mfgkw
Senior III

Hi Mattias,

 

thanks for addressing this theme. I did not see any interest from ST in the past and had very low expectations up to now.

 

My main concern is that CubeMX does not create a C++ main file.

It should be not a big deal to have a check mark somewhere and write/read/change main.cpp instead of main.c.

In case of C++ the generated C funktions for initialization, interrupts, call backs and so on need to be declared extern "C".

 

Changing HAL or LL functions makes no sense IMO.

For longer editing I change to EMACS anyway, so I'm not particulalry interested in other CubeIDE issues.

 

(I am much more interested having all tools available on Linux, since Windows is more and more no option for many companies, especially outside USA.)

 

 

 

try to use "-x c++" with .c files you want to compile as c++.

c -x c++.png

 

 

I don't mind mixing C and C++. You can always wrap C drivers with a C++ interface. Though it would be nice if there is a native C++ driver interface. The downside is that if there is only a C++ implementation there might be too much overhead or the interface may not be suited for your specific needs. My preference is to have C++ friendly definitions and functions that can easily be wrapped and integrated in C++.

When I use C++ I want to use constexpr as much as possible to do many checks and calculations at compile time instead of run time. Unfortunately constexpr cannot work with pointers, even fixed address pointers. So predefined peripheral addresses such as defined GPIO ports cannot be used unless defined as an integer. I made a topic for this:
https://community.st.com/t5/stm32cubemx-mcus/option-to-not-have-a-gpio-port-typecasted-to-a-pointer/td-p/887164

 

Another thing that would help is user defined context in HAL callback functions. This way object references can be put in user context allowing static methods to be used as callback functions. There is a topic on this:
https://community.st.com/t5/stm32-mcus-embedded-software/user-defined-context-in-hal-callbacks/m-p/783093
It looks like the feature request on github has been closed and it won't be added to HAL v1. It looks like it is present in HAL V2: https://github.com/STMicroelectronics/STM32CubeU5-V2-Preview/blob/0cf320046f0147a87c5db327c4d7e67e7b75eb27/stm32u5xx_drivers/hal/stm32u5xx_hal_dac.h#L353

Advantage of C++ is function overloading. You can overload functions that use a pointer and a size to a buffer with std::span. Such as transmit functions e.g. HAL_SPI_Transmit().

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.
TDK
Super User

The C++ support is fine as is. Things compile fine, autocomplete works, expressions display correctly. The bigger issues are fixing the annoyances, like a random file opening every time you debug.

If you feel a post has answered your question, please click "Accept as Solution".
richmit
Associate II

 

I think CubeMX not creating a C++ main file is the biggest concern.

I don't think we need "native c++" HAL or LL -- just make sure everything that needs to be extern C is.

 

-mitch

 

WillieVisagie
Associate

Hi Mattias

 

I have succesfully created my own C++ environment.  I generate a C makefile project with CubeMX and then edit the makefile to compile both C and C++ according to it's extension.  The challenge was also to go over to C++ 'domain' due to name mangling.  But I solved that too.  C functions can be called from C++, but the other way around you need to solve the name mangling issue.  So I let the CubeMX generated code do all the initialisations etc.  Then before the main function hits the while loop, I return and call the C++ main (AppMain) from the startup assembly file.  Thereafter it's C++.  I developed a few necessary wrappers because now you want the FreeRTOS task to be a class.  That was my approach.  I hope that helps.

BTW, I code ONLY in VSCode and compile from there and debug from there.

 

Kind regards

Pavel A.
Super User

To all C++ users here: C++ is not a perfect superset of C (unless maybe few very recent versions). So requiring that all ST-provided libraries build perfectly in C++ mode is IMHO not feasible currently. The same applies to the generated initialization code. So please don't skip your C++ lectures and recall the extern "C" thing.

@mattias norlander Maybe you could implement "express C++ mode" in CubeMX, where the project is created with C++ nature from the beginning, and the main file is "main.cpp". Rename the previous main file to c_main.c (or whatever) where main() renamed to c_main(). The new file can look like this:

// generated main.cpp

extern "C" int c_main(void);

// USER CODE here....

[[noreturn]]
auto main() ->int {
  // USER CODE here....
  (void)c_main();
  // USER CODE here....
  while(1) {}
  // USER CODE here....
}

// USER CODE here....
// generated c_main.c

#ifdef __cplusplus
#error
#endif

#include "main.h"
.......

int c_main(void)
{
   HAL_Init()...
   .......
}

 

... and proudly call this a feature ;)

Andrew Neil
Super User

Please can we have the "main" file not called just main.cpp (or main.c) ?

When working with multiple projects, it gets confusing with multiple files all call main !

Better would be <project>.cpp or <project>_main.cpp 

 

Similarly for plain C projects.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
bbee
Associate III

To be able to build a correct C++ Wrapper around the HAL C-Funktions you should extend the Handle-Typedefs with some sort of User Data Pointer like

/**
  * @brief  UART handle Structure definition
  */
typedef struct __UART_HandleTypeDef
{
  void                     *pUserData;       /*!< User Data Pointer */
  USART_TypeDef            *Instance;        /*!< UART registers base address */
  UART_InitTypeDef         Init;             /*!< UART communication parameters */

This has been a feature request some time ago, but was declined. See [Feature Request] Pass arbitrary data pointer in callbacks · Issue #23 · STMicroelectronics/STM32CubeG4 and Solved: Feature request: Pass arbitrary data pointer in HA... - STMicroelectronics Community

We can then use the pointer to point back to the C++ Instance in the callbacks like:

#if ((BSP_USE_UART == 1) && defined(HAL_UART_MODULE_ENABLED))
/**
  * @brief  Tx Transfer completed callbacks.
  * @PAram  huart  Pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @attention Overrides HAL_UART_TxCpltCallback from HAL
  * @attention Executed in interrupt
  */
extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  BspUart* pUart = reinterpret_cast<BspUart*>(huart->pUserData);
  if (pUart)
  {
    pUart->OnTxComplete();
  }
}
#endif