Hi, very sorry if this question should be too picky ... .
I have quite a bit of large "global classes" in my multi-module C++ software. (I mean a class without constructor/destructor, which is used exactly one time in the software - it is defined "globally").
As it is used only one time, I could specify the variables / functions as static or not. I was wondering, which way would create tighter code. According to my investigations I have the following rules now: - Functions should be static, except inline functions - these must NOT be static (otherwise they are not inlined any more). - Public data variables, which are heavily used outside class functions, should preferably be defined static. - Private data variables, which are mainly used inside class functions, should preferably be defined non-static.
Could some C++ expert have a look at these rules and comment them? (ok, quite ok or complete nonsense?)
PS: In some C++ languages, it seems to be possible to define a complete class as static:
static class TestClass{ ... };
As I see, this is NOT possible in Keil C++, or am I wrong?
C++ inline functions are very good to use as accessor functions when interacting with the hardware. Compared to a #define, you still get full type checking etc. But you can hide if a pin is active high or low, or if a pin needs to switch between tristate input for "high" state and actively drive low for "low" state - might be needed for a 3V3 chip using an external pull-up to reach 5V high levels but needing strong sink capability.
When turning on/off a car alarm, there are zero speed needs, so it doesn't matter if the activate_alarm() is a standard function call or an inlined function. If controlling the displayed data of a large LED panel, speed would matter.
Talking about C++ classes, it's possible to have virtual methods that makes use of static data structures too. So instead of having one C++ class with multiple instances for multiple controlled hardware objects, there can be one base class and then several classes that contains virtual methods to access the specific hardware I/O.
One way is to have one mapping layer that defines all I/O - possibly using bit-banding. And then C++ objects that contains the business logic and have action methods that makes use of the bit-banding of the mapping layer.
Hi Mike Kleshov, If you program in C, then there will come a point where you organize your data in structs. Usually then you would arrive at a point, where you would like to create Read-Only Access for some of your struct variable for external modules.
This is not possible in C, but in C++ this is no problem, using such inline-functions (In C this will not work even if you use inline functions, as the multi-module-public inline functions (defined in some h file) of course have no access to static variables defined in a module).
This sounds a simple point, but in fact it is very powerful to enable fail-safe programming. Alone due to this I would strongly recommend C++.
As I told you, to my experience with Keil-ARM C++, C++ gives NO larger code size.
I would clearly say, that C++ is easier in programming than C, and C easier than assembler, but a good microcontroller programmer should be able to use all 3 languages. (If you program C++ together with several people in a team, you should specify, whether it is allowed to use constructors-destructors, new-delete-operators and virtual base classes - for the beginning I would not allow them. Especially no new-delete-operator or virtual base classes, as those things will add quite a bit of internal "ghost code" to your program).
I used to program some other microcontroller family for some years now in C, and I am really VERY impressed by the Keil-ARM compiler, just I miss currently heavily the fast implementation of saturated addition for int64/uint64 variables. This would be a snap to implement if embedded assembler would work, but unfortunately for a Thumb-only processor - as STM32F4 - embedded assembler does not work in the Keil-ARM compiler (in the previous compiler I used, I had to used embedded assembler at many points for interrupt programming - but the code generated by Keil ARM C++ is so impressively nice, that currently my only issue crying for embedded assembly is the addition for int64/uint64 with high-speed saturation checking - just this unfortunately currently is quite urgent for me).
[If some Keil support team member is reading this, I would be VERY grateful for an estimate, whether in near future Keil ARM C++ will support inline assembly for Thumb mode, or whether at least in some near future I could expect an intrinsic compiler function for the saturated addition/subtraction of int64/uint64 (alternatively, I would be even more happy for an intrinsic for the branch commands B{cond} (best for any available condition EQ, NE, ...LE) - but I think unfortunately a branch command is not suitable to define by function mnemonics in C - further for saturation control it would be necessary to somehow force the compiler to use the signify versions of ADD and SUB previously to this intrinsic branch command) (if possible, please also insert an intrinsic for __vcvt int16/uint16, or support VCVT.S16/U16 for conversion from float to int16/uint16).]