In any event I'd really appreciate some quick pointers on C++ for the stm32 should you have any. Thanks in advance!
Sorry, I wasn't paying attention...
Well, the key thing is use C++ in an embedded environment. STM32 is the same as Stellaris, is the same as everyone else's ARM, etc. I recommend yagarto's arm-none-eabi gcc, but I think any C++ will do.
Here are the compiler switches I use (currently):
-fno-rtti -fno-exceptions -fms-extensions -Wno-pmf-conversions -Wno-unused-parameter -Wno-psabi -std=gnu++0x
1) -fno-rtti turns off run time type information. You probably won't need it and it leads to code bloat.
2) -fno-exceptions does what you think. Exception handling is a good thing, but it also bloats the code because the compiler has to generate two exits for each basic block. Embedded apps generally do without.
3) -Wno-pmf-conversion allows the compiler to convert a pointer to a member function like void (A::*fn)() to something like void (*fn)(A*). This is obscure, but I've used it for object-oriented callbacks.
4) -Wno-unused-parameter turns off complaints about unused parameters in function definitions.
5) -Wno-psabi turns of warnings related to varargs.
6) std=gnu++0x enables GNU extensions to C++
Your environment will need to have some way of taking control once the CPU comes out of reset. This isn't necessarily a C++ thing, but C++ does add a requirement to call all of the compiler-generated static initialization code. The linker strings together all the compiled constructors for each file/module and creates an array of function pointers. After the CPU comes out of reset and before the call to main(), somebody needs to call those functions. This is might be already handled by your environment, but if not, you'll have to write a little loop. Technically, you should also call destructors after main() exits, but that basically never happens for an embedded app.
Occasionally you may run into situations where the compiler generates a call to some strange function that you have to stub out. For instance, you'll see references to __cxa_pure_virtual() are generated if you declare pure virtual functions. I'm not sure why this isn't part of the standard library, but I had to stub it out like this:
extern "C" {
void __cxa_pure_virtual() {
for(;;);
}
void *__dso_handle = NULL;
};
The main thing with C or C++ is to avoid dynamic memory allocation, since there probably isn't enough free memory to effectively use a heap. In the C world, this leads to lots of global variables. With C++, it's much better since you can put everything in objects (i.e., compiler managed structs) and then declare a handful of global objects which represent the entire state of your program.