C++ in AVR Studio 6.1


This week, at work, after upgrading AVR studio to 6.1 I was pleasantly surprised to find that the new project dialogue offered C++ as an option. Although not ever really having used C outside of the world of AVR development, I much prefer the object oriented idioms C++ has to offer, and was eager to to see what the new project options had available.
    avr-g++ is, as far as I can tell, based on g++ 4.7, so modern features such as C++11's auto keyword and range-based for loops are immediately available (assuming the -std=c++11 flag is set). An implementation of the STL is not, however, so those of us (including myself) spoiled by iterators, containers, streams and all the other utilities the STL provides may initially be disappointed. I decided, on the other hand, that this was a perfect diving-in point for experimentation so I set about creating a basic std::unique_ptr style smart pointer class. If you've read my post on self-destruction (or any of the seminal works, for that matter) then there's not too much to explain behind the concept, so I won't cover the code. I did notice when doing this is that there is no support for new or delete, although this could be fixed with my own definitions which wrapped malloc() and free():

#include <stdlib.h>
void* operator new(size_t size)
{
    return malloc(size);
}

void operator delete(void* ptr)
{
    free(ptr);
}


I was pleasantly surprised that this worked (as far as I could tell on an MCU) but after I thought about it I saw no real need for dynamic memory allocation on an 8-bit AVR, which would, in fact, explain the lack of new and delete in the first place. I have, after all, never found myself with the need for malloc() or free() in the past either.

Taking a look at my existing projects, I decided that a more practical application of OO methods would be to write some reusable code. A prime candidate was the timer code which I've used so many times on ATMega 8s to create clocks for various applications. The basic principle is to set up the 16 bit timer to trigger a compare match interrupt once every second. This usually means a bunch of bit-shift patterns on some registries at the top of the main function (although this can be put in its own function for neatness) and *shudder* a global variable. Here, then, was some code in need of encapsulation.
    I decided the design for this class actually met the criteria of the much maligned Singleton pattern - after all the clock only needs to be set once (in this scenario anyway, granted timers can be used for all sorts of applications to which this is not suited) and a sub-class can be used to interface with the clock. This also means that the global variable is nicely encapsulated away, accessible via only a Tick() function called by the compare match interrupt. This was a slight stumbling block, however, as ISRs can't readily be made a member of a class. I did find this article, and another, which claim that ISRs can be given access to private members via friendship, but my experiments seemed to prove not so, unfortunately. Otherwise everything is peachy:

class Clock
{   
public:
    static void Init(){Clock clock;}
    static void Tick(){m_count++;}
   
    class Timer
    {
    public:
        Timer(): m_timer (&m_count){};
        //returns time elapsed since last restart in seconds
        float Elapsed();
        //returns time since last restart in seconds and resets timer
        float Restart();
    private:
        unsigned long m_startTime;
        volatile const unsigned long* m_timer;
    };

private:
    Clock();
    volatile static unsigned long m_count;
};


As the Timer class is a sub-class of Clock the private member m_count can be passed by reference on construction, so that each timer created can keep track of the master clock count. m_count was previously the global variable, so here you can see how it has been nicely tucked away as a private member, where only objects who need to know about it, do. The telltale signature of the Singleton is visible as the private Clock constructor, which performs the initial bit shifting of the AVR timer registers, setting up the timing and compare match interrupts. These are hardware specific and need to be implemented depending on the chip you use - in this case I'm using an ATMega 8 so I have the timer 1 compare match interrupt set to trigger once every millisecond (OCR1A = 500, with a clock prescaler of 1/8 @ 4MHz if you're curious). The reason I have the clock running in milliseconds is that it makes it easier for the Timer class to return the elapsed time in seconds as a float. Optionally the time could, of course, be returned in milliseconds or even minutes. The great thing about C++ is that it doesn't take much to add these extra functions. Using the Clock class is then as straight forward as:

#include <Clock.hpp>

void main()
{
    Clock::Init();
    while(1)
    {
        Clock::Timer timer;
        if(timer.Elapsed() > 5.f)
        {
            doStuff();
        }
    }
}

So this was good. I already had some useful, tidy, encapsulated code which I could drop into more or less any AVR project. What else could I do..? If you're a solid C programmer then you may not wish to read on as this will probably make you wince... but if I could afford the overhead I thought why not; bit set utilities. I know such things do exist in the form of macros, but macros just aren't C++ so it seemed useful (to me anyway) to wrap some commonly used code in a couple of functions and then neaten it up with some name spaces.

namepace IO
{
    enum State
    {
        High,
        Low
    };

    namespace Pin
    {
        //returns whether requested pin / port is high or low
        State Set(uint8_t pin, volatile uint8_t* port)
        {
            return (*port & (1 << pin)) ? High : Low;
        }
    }
   
    namespace Port
    {
        //sets output pin high or low on requested port
        void Set(uint8_t pin, volatile uint8_t* port, State state)
        {
            if(state == High)
            {
                *port |= (1 << pin);
            }
            else
            {
                *port &= ~(1 << pin);
            }
        }
    }
}


These 2 functions make setting and testing pins on specified ports as simple as

IO::Port::Set(2u, &PORTB, IO::High);

which, if anything, makes code more legible to read and more pleasing to the eye in general. If you're wondering why I'm passing the PORT address as a pointer it's because it didn't work when passing by reference. I can't give a technical reason as to why (I've not really looked into it), I can only assume it has something to do with the variable being volatile (but don't quote me on that).

Just for fun, then, I used these classes to (re)create the 'Hello World!' of embedded engineers everywhere - the blinking LED. I won't post the full code (figuring it out can be considered an academic exercise if you like) but the nub of it looks like:

while(1)
{
    if(timer.Elapsed() > frequency)
    {
        if(flip)
            IO::Port::Set(pin, port, IO::High);
        else
            IO::Port::Set(pin, port, IO::Low);

        flip = !flip;
        timer.Restart();
    }
}



So from now on I'm probably going to use C++ when programming AVRs whenever I can. Granted a lot of it is just wrapping C functions in classes at the cost of overhead, but I find the idioms just more... agreeable. It is, of course, a matter of opinion. If you're an experienced C programmer and don't really see the need for the extra ground work and apparently unnecessary overhead then you're likely to want to stick with what you're used to, likewise C++ programmers may be deterred by the lack of features - but if, like me, you're a fan of anything object oriented and always up for interesting experiences then using C++ with AVRs  is just plain fun.

Comments

Popular Posts