C++ and STM32

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: C++ and STM32

Post by colin »

Actually I found that the right way to solve the problem is to disable C++ exception support in gcc:

Code: Select all

  USE_CPPOPT = -fno-rtti -fno-exceptions

The g++ exception handling support uses abort() and friends to handle uncaught exceptions.

I have a Hello, World demo for the STM32VLDISCOVERY board in both C and C++ flavors. The compiled and linked firmware binary is identical in size down to the byte between C and C++ versions! The only difference was I replaced use of 'static' for module-scope symbols with C++ anonymous namespace usage, and replaced 'void foo(void);' with 'void foo();', then built using C++.

If you want to try it, get my ChibiOS/RT C++ STM32VLDISCOVERY Hello, World demo source here.
noether
Posts: 91
Joined: Wed Nov 16, 2011 3:18 pm

Re: C++ and STM32

Post by noether »

colin wrote:Actually I found that the right way to solve the problem is to disable C++ exception support in gcc:

Code: Select all

  USE_CPPOPT = -fno-rtti -fno-exceptions

The g++ exception handling support uses abort() and friends to handle uncaught exceptions.

I have a Hello, World demo for the STM32VLDISCOVERY board in both C and C++ flavors. The compiled and linked firmware binary is identical in size down to the byte between C and C++ versions! The only difference was I replaced use of 'static' for module-scope symbols with C++ anonymous namespace usage, and replaced 'void foo(void);' with 'void foo();', then built using C++.

If you want to try it, get my ChibiOS/RT C++ STM32VLDISCOVERY Hello, World demo source here.


Hello Colin, thanks for your response. I am 90% sure that II have this flag for C++ code, but not for the C code (I have them mixed). As I can read on gcc website:

Code: Select all

-fexceptions
    Enable exception handling. Generates extra code needed to propagate exceptions. For some targets, this implies GCC will generate frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution. If you do not specify this option, GCC will enable it by default for languages like C++ which normally require exception handling, and disable it for languages like C that do not normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++. You may also wish to disable this option if you are compiling older C++ programs that don't use exception handling.


My problem arises when I link to the Eigen C++ library, if I do not use this library, everything compiles fine, no matter what -Ox level I employ.

I will check my code and compiler options this night in detail, maybe if you have more experience with the g++ options flags, you can help me :P

Many thanks
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: C++ and STM32

Post by colin »

noether wrote:
colin wrote:Actually I found that the right way to solve the problem is to disable C++ exception support in gcc:

Code: Select all

  USE_CPPOPT = -fno-rtti -fno-exceptions

The g++ exception handling support uses abort() and friends to handle uncaught exceptions.

My problem arises when I link to the Eigen C++ library, if I do not use this library, everything compiles fine, no matter what -Ox level I employ.


Are you building Eigen from source? I think the same -f(no-)exceptions flag setting must be used for all linked code in a program. Can Eigen be compiled without exception support, or is it required?
noether
Posts: 91
Joined: Wed Nov 16, 2011 3:18 pm

Re: C++ and STM32

Post by noether »

sorry, repeated
Last edited by noether on Thu Jan 12, 2012 9:31 pm, edited 1 time in total.
noether
Posts: 91
Joined: Wed Nov 16, 2011 3:18 pm

Re: C++ and STM32

Post by noether »

colin wrote:
noether wrote:
colin wrote:Actually I found that the right way to solve the problem is to disable C++ exception support in gcc:

Code: Select all

  USE_CPPOPT = -fno-rtti -fno-exceptions

The g++ exception handling support uses abort() and friends to handle uncaught exceptions.

My problem arises when I link to the Eigen C++ library, if I do not use this library, everything compiles fine, no matter what -Ox level I employ.


Are you building Eigen from source? I think the same -f(no-)exceptions flag setting must be used for all linked code in a program. Can Eigen be compiled without exception support, or is it required?



Hello colin,
Eigen is a C++ template library for linear algebra, is all headers .hh. So it is not compiled before.

I have attached the project. Take a look to the Makefile and swap -O2 by -O0 and the linker error triggers. As you wrote earlier, the same error triggers if you do not put the -fno-exceptions flag.
Fill the DINCDIR variable with the Eigen directory, if you are using Linux, Eigen should be included in your official repository, in my machine is ' /usr/include/eigen3/ ' .

I have spent all the afternoon, and preprocessing (gcc -E) the main.cpp with -O0, there is any call to abort... I do not know where is magically invoked u_U.

If you remove Eigen from the main.cpp, the project compiles fine.

EDIT:
it seems there is a problem uploading the project and the post appears empty after attaching it.

The project is very simple, just take the c++ example, and put this main.cpp

Code: Select all

#include "ch.h"
#include "hal.h"

#include "Eigen/Dense"

using namespace Eigen;

static WORKING_AREA(waThread1, 128);
static msg_t Thread1(void *arg) {

   (void)arg;
   chRegSetThreadName("blinker");

   int i = 1;
    Matrix<float, 13, 13> A, L;
   A = Matrix<float, 13, 13>::Identity(13, 13) +
   Matrix<float, 13, 13>::Constant(1);

   while (TRUE)
   {
      i++;
      L = A.llt().matrixL();
      A(0, 0) += i;

      palSetPad(GPIOD, GPIOD_LED3);       /* Orange.  */
      chThdSleepMilliseconds(500);
      palClearPad(GPIOD, GPIOD_LED3);     /* Orange.  */
      chThdSleepMilliseconds(500);
   }

}

int main(void) {

   halInit();
   chSysInit();

   chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);

   while (TRUE) {
      chThdSleepMilliseconds(500);
   }
}


The Makefile for flags is:

Code: Select all

# Compiler options here.
ifeq ($(USE_OPT),)
  USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16 -mhard-float -mfpu=fpv4-sp-d16 -fsingle-precision-constant -DNDEBUG -fno-exceptions
endif

# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
  USE_COPT =
endif

# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
  USE_CPPOPT = -fno-rtti
endif

DINCDIR = /usr/include/eigen3/ <- put where Eigen is installed

colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: C++ and STM32

Post by colin »

I don't know how to directly find out what code is causing a reference to abort(), but you might look at eigen's src/Core/util/Macros.h around lines 176 through 218 for stuff relating to assertions. If you define NDEBUG, the assertions and abort() references should be cut out by the preprocessor.

It may still be something related to exception handling support, or it may be some other reference to abort() causing the problem. Maybe there is another library function that eigen calls which may reference abort()? Some math library function? What if you try to use some floating point arithmetic and math library functions such as pow(), exp(), atan2(), and maybe refer to errno those sorts of things.

I hope you can solve it.
noether
Posts: 91
Joined: Wed Nov 16, 2011 3:18 pm

Re: C++ and STM32

Post by noether »

colin wrote:I don't know how to directly find out what code is causing a reference to abort(), but you might look at eigen's src/Core/util/Macros.h around lines 176 through 218 for stuff relating to assertions. If you define NDEBUG, the assertions and abort() references should be cut out by the preprocessor.

It may still be something related to exception handling support, or it may be some other reference to abort() causing the problem. Maybe there is another library function that eigen calls which may reference abort()? Some math library function? What if you try to use some floating point arithmetic and math library functions such as pow(), exp(), atan2(), and maybe refer to errno those sorts of things.

I hope you can solve it.


so, could you reproduce the linker error with -O0?

Many thanks for your tips. Actually the pre processor cuts off the section where abort lays in Eigen.

This is my output after:

Code: Select all

arm-none-eabi-g++ -E -c -mcpu=cortex-m4 -O0 -ggdb -fomit-frame-pointer -falign-functions=16 -mhard-float -mfpu=fpv4-sp-d16 -fsingle-precision-constant -DNDEBUG -fno-exceptions -ffunction-sections -fdata-sections -fno-common -fno-rtti -Wall -Wextra -Wa,-alms=build/lst/main.lst   -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -MD -MP -MF .dep/main.o.d -mthumb -DTHUMB -I. -I./os/ports/common/ARMCMx/CMSIS/include -I./os/ports/common/ARMCMx -I./os/ports/GCC/ARMCMx -I./os/ports/GCC/ARMCMx/STM32F4xx -I./os/kernel/include -I./os/hal/include -I./os/hal/platforms/STM32F4xx -I./os/hal/platforms/STM32 -I./os/hal/platforms/STM32/GPIOv2 -I./os/hal/platforms/STM32/RTCv2 -I./board -I./os/various -I/usr/include/eigen3/ main.cpp | grep abort


void abort (void) __attribute__ ((noreturn));
using ::abort;

I suspect that maybe is a bug of g++?

I tried out with -O1,2,3,s and the linker error is not triggered. In theory, the optimization level makes no difference about calling an abort, but actually it is u_U

If I only try with "math.h" functions, everything is fine as well. Actually, the error starts when I do an operation with matrices, like A+B for instance. Everything is fine just declaring them.
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: C++ and STM32

Post by colin »

I haven't tried to build with Eigen, haven't had time. But here's an idea to track down the source of the 'abort' reference. What if you build a simple test program using C++ and Eigen that just declares those matrices A and B and evaluates A+B. Build it with g++ for your PC architecture (i386 or amd64) using -fno-rtti and -fno-exceptions as well as -O0 and -ggdb. Then you may be able to examine the compiled program using 'objdump' and 'nm' to find references to abort. Even maybe run it in gdb and set a breakpoint on the 'abort()' function?

Just some quick thoughts!

Or, another idea is for you to try and define some stub implementations of the abort(), etc. functions that the GNU linker is complaining about on the ARM build. Make the stub for abort() hang with a while(1){} or trigger a debug trap or something in case it gets called. Then build and disassemble using 'arm-none-eabi-objdump -dS PROGRAM.elf' to find out what code references it.
colin
Posts: 149
Joined: Thu Dec 22, 2011 7:44 pm

Re: C++ and STM32

Post by colin »

Is is really a problem for you to build with -O1 for debugging? Does it cause that much trouble?
noether
Posts: 91
Joined: Wed Nov 16, 2011 3:18 pm

Re: C++ and STM32

Post by noether »

Thanks a lot for you hints,

I've got around the problem in the past (with another RTOS) implementing the abort function in 'syscalls.c', as you said with a while(1).
I will do it again for seeing where is called. I will do as well the same in my laptop and use objdump to locate it.

About -O1, I really haven't use it for debugging yet, but the output code size is the same as with -O2, so I guess that the debugging with gdb maybe is as messy as with -O2.

I will be out until Sunday afternoon, I will keep you posted with progresses :P, thanks again.
Post Reply