Flags play an important role in embedded software development. Microcontrollers and chips are using registers where single bits or combinations of bits play a big role in the configuration. All the bits and their role are described in the specification, but writing the bits directly in the code would be very confusing and hard to read:
AHBMASK.reg = 0x14 // Huh!?
For this reason it makes sense to write an interface to access the registers of a chip. This interface will define identifiers, in the form of constant values, to build bit combinations to write into the registers.
The Outdated and Bad Approach
Chip manufacturers are well known for their extremely bad and outdated interfaces to access chip registers. Let us have a look at the CMSIS implementation from Atmel. This is part of the interface to access registers in one of the microcontrollers. Please ignore the copyright block, it is just added for legal reasons.
Do you feel the dust on this code? There are a vast amount of problems caused by this interface.
First the values are defined as macros instead of constants. All this identifiers will clutter the global namespace of your code and make naming conflicts very likely. Way better would be using simple constants like this:
const uint8_t PM_AHBMASK_DSU_Pos = 3; const uint32_t PM_AHBMASK_DSU = (0x1ul << PM_AHBMASK_DSU_Pos);
This would give the compiler the correct hint about the used data type for the registers. All this constants could be put into a own namespace to prevent any name collisions with the user code. It would still not prevent incorrect assignments.
I can write and compile the following code, which absolutely makes no sense:
CPUSEL.reg = PM_AHBMASK_DSU; // nonsense!
There will be not even a compiler warning about any problems and this is exactly what makes debugging embedded code very difficult.
Use the C++ Language!
I personally think, many software developers writing C++ code for hardware do not make fully use of the language. One reason could be the lack of support of many language features at the beginning or just the lack of experience.
In the the last 10 years, there was a huge progress in the development of the C++ language. Ignoring this progress would be silly in my opinion. Especially the C++11 standard added lots of useful features to the language.
A good support for the C++11, C++14 or even better for C++17 is very important, especially for embedded software development. Many of the introduced features will improve your code, make it simpler and more readable, without adding any additional byte to your firmware.
The features I describe in this article will not increase the size of the final firmware, they will just affect safety, readability and simplicity of your code. At the end, the optimiser in the compiler will resolve all the code and generate small and compact binaries.