Menu Close

Tag / c++

Make your Code Safe and Readable with Flags

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.

To be fair, CMSIS is a hardware abstraction layer standard defined by ARM. It shall standardise the software interfaces across all Cortex-M products. Therefore Atmel had no choice as to follow this standard.

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.

Continue Reading

Lucky World – A jump’n’run game for MeggyJr RGB

Today I release a full featured jump’n’run game for the MeggyJr RGB platform. It has an intro, a level map with more than 16 levels packed with obstacles and even a end scene. This game uses most of the flash of the ATmega328P and it was an interesting challenge to keep everything as compact as possible. In the past, when I learned to develop software, a very limited RAM was normal. Creating this game for this platform brought back a little bit of this nostalgia.

I release all sources of the game under the GPL v2 license. Feel free to create your own fork and improve this game even further. You can download a ZIP with the sources for version 1.0 here:

https://github.com/LuckyResistor/LuckyWorld/archive/v1.0.zip

To give you a quick impression of the gameplay, I created the following video.

Read more about the requirements for the game in the sections below.

Continue Reading

A New Library for Meggy Jr RGB

I planed to create a game as a gift and use the really great Meggy Jr RGB platform for it. See the picture above, it’s a great game machine powered by the ATmega328P (buy it here). You can use the Arduino IDE to program it.

After assembling the device, I played a little bit around with the provided library — but was a bit disappointed by the library. This is a game device after all, but the library lack in my opinion some important things a game library need.

So I wrote a new library from scratch, using the provided schema and documentation (you can see the printed out schema in the background of the picture). Sometimes its better to start from scratch and learn from the mistakes of other libraries.

Today I release the first version of the library at GitHub here: https://github.com/LuckyResistor/LRMeggyJr. It has a proper API documentation and a few examples. I release this early, but hope to improve the documentation and add examples while I develop the actual game.

Download the release v1.2 as a ZIP

Continue Reading

How and Why to Avoid Preprocessor Macros

While most naming conflicts in C++ can be solved using namespaces), this is not true for preprocessor macros.

This post is outdated. You will find an updated version here:
How and Why to Avoid Preprocessor Macros

Macros can not be put into namespaces. If you would try to declare a new class called Stream, but somewhere in a header you include would be a macro called Stream, things would break. While compiling your code, the preprocessor would simply replace the Stream in your class Stream { declaration. You could get a really confusing error message, and it would take time and energy to find the actual problem.

Especially people developing software for controllers, often overuse macros for almost everything. They believe it will save RAM, speed up the code or make it more flexible. Often none of these three things are true. Actually each additional macro is a risk for name conflicts and makes the code less readable. You should reduce the use of macros to the absolute minimum, and especially avoid macros in your header files.

Continue Reading

How and Why to use Namespaces

Namespaces are a feature of C++ which address the problem of name conflicts. There is a “global” namespace, where everything lives which was declared without namespace. Especially the Arduino environment declares a huge amount of variables and constants there, so it is a good practice to put everything you write in a own namespace. Namespaces are only used while compile time, and they do not use any memory at runtime nor make they run your program slower.

In my case I choose the namespace lr which stands for Lucky Resistor. Everything I declare in this namespace is accessible trough the :: operator which you probably already know from function definitions.

Continue Reading