Loading...
 

SW4STM32 and SW4Linux fully supports the STM32MP1 asymmetric multicore Cortex/A7+M4 MPUs

   With System Workbench for Linux, Embedded Linux on the STM32MP1 family of MPUs from ST was never as simple to build and maintain, even for newcomers in the Linux world. And, if you install System Workbench for Linux in System Workbench for STM32 you can seamlessly develop and debug asymmetric applications running partly on Linux, partly on the Cortex-M4.
You can get more information from the ac6-tools website and download (registration required) various documents highlighting:

System Workbench for STM32


Using classes/objects with CubeMX project

Hi all

I’ve spend countless hours on the internet trying to figure out how to use classes/objects (C++, I guess) with a project coming from CubeMX. I know this question has been asked several times before, but I simply do not understand how to make it work.

I simply want to add C++ files to the CubeMX project, and call a member function of an object from main() in main.c.

I’m on the latest releases of CubeMX and System Workbench, and I have converted the project to C++ using “Convert to C++” in System Workbench. I can add .cpp and .hpp files to the project, but how do I call the member function from main()?

I have the following CTerminal.hpp:

#ifndef CTerminal_H_
#define CTerminal_H_

class CTerminal {
	...
};

#endif


Eclipse says: unknown type name ‘class’

But... even if I get the above issue corrected, will the following main.c work (including a C++ file and instantiating an object within a C file)?

main.c

#include "main.h"
#include "stm32f4xx_hal.h"
#include "fatfs.h"
#include "usb_device.h"

/* USER CODE BEGIN Includes */
#include "CTerminal.hpp"

...

int main(void)
{
  /* USER CODE BEGIN 1 */
	CTerminal Terminal;

...
}


Thanks in advance! :-)

Dude :-) I dont think you have C++ here. Only C.

C++ is very “heavy” and is to found only on the bigger ARMs (think Raspberry pi ARMs) etc.

For the “small” devices, like the oneswe have here (not running Linux) etc, you will have to make do with “standard” C.

The modern ubiquity of these ARMs make us forget that sometimes we work with very resource limited embedded devices.

Hope this clears it up (use and go C)


Dude (hardwareguyvw), C++ is C; just better cool Some of us have been using it in embedded code for a while now...

jrhansen : there are a few things you’ll need to brush up on as you are working at a slightly lower level than for example writing a C++ app on Linux.

You need to go and read about “C++ name mangling” and how the C++ compiler creates type safe linkage and how that affects linking to C code. Note in the example below how extern "C" is used to give C linkage to a C++ function and how a combination of that and #ifdef __cplusplus is used to maintain it if a header is included in C++ that has C functions. Note that the HAL libraries all have this construct already.

You should name your files appropriately so you keep everything straight - so that’s “.cpp” for your C++ source and “.c” for the plain C source. Try not to mix those as you’ll be in trouble.
I’m assuming that’s where your Eclipse says: unknown type name ‘class’ error came from.

Also, while not strictly required, name your C++ headers “.hpp” or something - it’ll help to not include C++ headers in C source (the reverse is easily dealt with - see #ifdef __cplusplus).

As for “calling through” to C++ code from (for example) the CubeMX generated output, you’ll need to make C++ functions with C naming conventions - here’s a simple approach that works fine for a project that you’re reworking from CubeMX side regularly and yet using C++.
Basically you have a C header that you include in the CubeMX main which declares C functions to call from there:


/** @file fred.h
* ie: this is a C lang header
*/

#ifndef APP_FRED_H_
#define APP_FRED_H_

#ifdef __cplusplus
extern "C" {
#endif

//! insert call to this function from CubeMX generated init
void Fred_init();
//! insert call to this function from CubeMX generated loop
void Fred_loop();

#ifdef __cplusplus
}
#endif // __cplusplus

#endif /* APP_FRED_H_ */


You have your C++ headers for declaration of your own stuff:
/** @file Fred.private.hpp
* ie: C++ header file
*/

#ifndef APP_FRED_PRIVATE_HPP_
#define APP_FRED_PRIVATE_HPP_

#include <cstdint> // ie: can include std lib headers
#include <cstddef>

#include "main.h" // ie: safe to include CubeMX C code headers
#include "gpio.h"

/** wrapper class for "application"
*
*/
class Fred
{
private:
//! application singleton - be aware of static initialisation timing & limitations in embedded context etc
static Fred instance;
public:
//! bootstrap C code into C++ class instance init method
static inline void call_init() { instance.init(); }
//! bootstrap C code into C++ class instance loop method
static inline void call_loop() { instance.loop(); }

Fred();

//! initialise application
void init();

//! do application superloop
void loop();
};


#endif /* APP_FRED_PRIVATE_HPP_ */


and then you define that function in a C++ source file (where you get C++ linkage):
/** @file Fred.cpp
* ie: a C++ source file
*/

#include "Fred.private.hpp"
#include "Fred.h"

extern "C" void Fred_init() { Fred::call_init(); }
extern "C" void Fred_loop() { Fred::call_loop(); }

//rest of Fred class definitions go here

Be Aware that you really need to understand the C++ object lifecycle, when are where static initialisation occurs and exactly how much stack space you can blow using some of the fancier STL stuff that does a lot of copies.

Learn about all the good keywords like ‘explicit’ and ‘const’ and how they save you extra copies and make life a bit safer in an embedded context.

There are some pretty good resources out there on the generic concepts involved in calling C from C++ or vice versa.

Oh, and the “weak” linkage functions that HAL provides for various things are also usable from the C++ side if you remember to do the extern C dance.