Go Down

Topic: [SOLVED] arm-none-eabi-g++ global object declaration inheritance problems (Read 1 time) previous topic - next topic

avik

Hi, the background is that I am working on an Arduino core (approximately) for an STM32F373 I am using, with arm-none-eabi-g++ from https://launchpad.net/gcc-arm-embedded/+download.

Here is a simple C++ source file:
Code: [Select]

class Base {
public:
 virtual int pureVirt() = 0;
 int otherMethod() { return pureVirt() + 1; }
};

class Derived: public Base {
public:
 int pureVirt() { return 2; }
};

// Global declaration
Derived derived;

void setup() {
 Serial1.begin(115200);
}

void loop() {
 // or, local declaration
 // Derived derived;
 Serial1.print(derived.otherMethod());
 delay(100);
}

I am having a strange problem with globally declared objects: The above code hangs and doesn't print anything if "derived" is declared globally, but works fine if it is declared inside loop() (and prints "3"). I am currently using the following CFLAGS and LDFLAGS
Code: [Select]

CFLAGS  = -O2 -Os -Wall -Werror-implicit-function-declaration -Wno-sign-compare -Wno-strict-aliasing -Wdouble-promotion -fno-rtti
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4
CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant
CFLAGS += -fno-common -fno-exceptions -ffunction-sections -fdata-sections -nostartfiles
CFLAGS += -ffast-math
CFLAGS += -DARM_MATH_CM4 -D'__FPU_PRESENT=1'

LDFLAGS  = $(CFLAGS)
LDFLAGS += --static -Wl,--gc-sections -Wl,-Map,$(BUILDDIR)/$(PROJNAME).map -nostartfiles -T$(STM32DIR)/vendor/st/STM32_FLASH.ld -specs=nano.specs -lm -u _printf_float

but I have indeed tried to take out any optimizations or code size reduction options without any seeming difference.

An additional symptom is that if I have a class with a constructor, and I declare an instance global, the constructor seems to not actually be called. I am not much of an expert with C++, any hints at all would be much appreciated! Additionally if this isn't the right forum for this, I'd be glad if it could be moved by a moderator.

avik

The problem was that my startup code (meant for C programs) wasn't calling __init_array_start. A temporary solution was to call them explicitly myself:
Code: [Select]

extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));


int main() {

  // This is basically libc_init_array -- handles global constructors
  unsigned int count;
  unsigned int i;

  count = __preinit_array_end - __preinit_array_start;
  for (i = 0; i < count; i++)
    __preinit_array_start[i] ();

  count = __init_array_end - __init_array_start;
  for (i = 0; i < count; i++)
    __init_array_start[i] ();
 
  // ... OTHER STUFF ...
}

Go Up