Callbacks 01/09/2017

I have recently been returning to programming microcontrollers. Had an idea of creating a client for the SerialNet to STM32F4 microcontrollers and immediately got side-tracked into the issue of callbacks in C++.

In C++11 and later we have std::function. It works very well in normal environments. You can throw a bunch of different callable types at it and it allows you to call them uniformly. It does have some drawbacks though. For microcontrollers the most grave one is the need for heap allocation. When you assign e.g. a function object that can be arbitrarily large this is a neccessity. But is does make it unsuitable for many MCU:s. Other issues are using virtual dispatch which forces us to have vtables and std::function can be a bit on the large side. (e.g. gcc uses 24 bytes on 64 bit architectures.)

Coming from MCU and C programming, a traditional way to implement callbacks are to use normal function pointers. You store a pointer to a free function and later call it in some other context. This works well in C style procedural programs.

It is common to supply a void* pointer as first argument to distinguish a data object to operate on in these callbacks. For example, interrupt service routines can be thought of a callbacks. The STM32 MCU family can have 5-10 USART hardware devices on one chip. Each of these have one ISR being called.

Using OO techiques one might want to write one class called 'UsartDriver' implementing a driver and instantiate one object for each hardware module. Assume one member function called 'UsartDriver::isr()' is supposed to be called during IRQ calls. In practice that means each ISR should call the same member function but use a different object in the call. It boils down to traditional function callbacks needs an additional pointer and it uses the the void* to point out the object to operate on.

I started to hack away on this and got a really neat solution usable for microcontrollers. The details and code are at github. Go to the github repository to continue reading.