Using C++ on Bare Metal

Description of your first forum.

Using C++ on Bare Metal

Postby carrigan » January 5th, 2013, 11:31 am

Hey all-

I have been doing more and more research on using C++ for microcontrollers (Cortex M's mainly, since their compilers support it) and was wondering if anyone has worked with C++ before other than MBed/Arduino. I have tried a few easy projects using an LPC1114 and they seemed to work great without any significant code bloat or performance drop, but I was wondering what others thought.

The blog article I wrote on my findings recently can be found at: http://www.microcontrollercentral.com/author.asp?section_id=2379&doc_id=256858&
carrigan
 
Posts: 5
Joined: August 17th, 2012, 11:06 am

Re: Using C++ on Bare Metal

Postby UAirLtd » January 5th, 2013, 7:58 pm

I have used C and C++ for the LPC1769. I wrote a hardware abstraction library for the chip, and the board that I created for it (a control and telemetry board for a small electric vehicle, including stuff like motor control, CANbus, and LCD screen). I wrote the library using objects thinking: hey, I can make each hardware peripheral an object, for example allowing me to use the same class for each SSP port, and mapping the control registers via an index value, allowing the same initialisation, and read/write functions to be reused.

Well turns out that's really neat on paper, but generates code that is bigger and slower than if I had just written things in C without objects.

Prior to this, I wrote theForebrain function library for the LPC1343 dev board Forebrain that we sell. And that was in good old C, so I did have a good benchmark for code size and speed to compare against. I'm now porting that to our new LPC1347 boards, and am sticking to C.

My experience of this is that you won't notice a difference between C and C++ if you're coding in C-style. But as soon as you start using OOP, you'll start getting larger and slower code. I honestly think you should stick with C for the majority of tasks you might want to accomplish on a microcontroller. If you have a massive project that can really benefit from OOP, then you could consider C++, but you'd want to make sure you have a microcontroller with sufficient storage space or external memory controller (and therefore neither the LPC1114 nor the LPC1768/9 as found on the MBed).
User avatar
UAirLtd
 
Posts: 629
Joined: July 19th, 2011, 10:32 pm

Re: Using C++ on Bare Metal

Postby carrigan » January 8th, 2013, 9:44 am

Thanks for the reply UAirLtd. What you did is exactly the topic I am exploring: making each peripheral an object.

I plan on doing some experiments with code size and program performance coming up. I expect that the code will be bigger and slower than the same code written in C, but I want to see by how much. Using a conservative subset of C++ shouldn't increase hurt performance or memory by a considerable amount- for the small electric vehicle you speak of I'm sure it would not hurt but maybe for something more timing critical like a quadcopter I would stick with C.

Chips are getting cheaper, but engineering hours are not. Even if the code isn't quite as efficient or compact, it is more readable and safe for the engineers developing.

Do you have any numbers as to how damaging the language switch is to performance? Also what compiler did you use?
carrigan
 
Posts: 5
Joined: August 17th, 2012, 11:06 am

Re: Using C++ on Bare Metal

Postby UAirLtd » January 8th, 2013, 12:50 pm

I wouldn't say it's necessarily safer - with so many pointers flying around; I think you have about as much, if not more, chance of doing Something Bad. The old joke about C++ being more difficult to shoot yourself in the foot, but blowing away your whole leg when you do, has some truth in it.

What you're saying about timing-critical is spot on. On the vehicle we had two boards, both using the same chip. The one that powered the in-dash LCD display was written using the C++ library, while the one that drives the motor was written using C and without any library.

It's hard to compare code size, since I don't have two similar pieces of code to compare, and it would be entirely dependant on how much you access the library. In my case, the code size was almost double, and ran about half the speed I would expect, this was mostly because it was fairly IO-heavy. But the main issue for me was that it's not particularly any more straightforward to write code for it, there's only one main noticeable difference, and that's being able to device drivers that were port-agnostic, for example you could have different instances of a function that accessed an I2C EEPROM chip, each with a pointer to their relevant I2C objects, such as this snippet from my library:

Code: Select all
EEPROMc::EEPROMc(I2Cc * setPort, unsigned char setAddress) {
   I2CPort = setPort;
   deviceAddress = setAddress;
}

void EEPROMc::writeByte(unsigned short address, unsigned char data) {
   unsigned int timeout = 0;
   
   (*I2CPort).autoInit();
   
   (*I2CPort).buffer[0] = deviceAddress;
   (*I2CPort).buffer[1] = (address >> 8) & 0x7f;   // ADDR high
   (*I2CPort).buffer[2] = address & 0xff;   // ADDR low
   (*I2CPort).buffer[3] = data;   // Data
   (*I2CPort).engine((*I2CPort).buffer, 4, 0, 0);

   // Poll until internal write cycle clears
   (*I2CPort).setState(I2C_NACK);
   while(((*I2CPort).getState() == I2C_NACK) && (timeout++ < I2C_TIMEOUT)) {
         (*I2CPort).buffer[0] = deviceAddress;
         (*I2CPort).engine((*I2CPort).buffer, 1, 0, 0);
   }
}


So now all a user has to do to create an EEPROM object is to pass a pointer to the relevant I2C port instance, and the EEPROM's I2C address:

Code: Select all
EEPROMc EEPROM(&I2C1, 0xa0);


Doing this is far neater than if you were to achieve the same thing using C function pointers (it's possible to do the same in C, but your namespace gets really messy very quickly). There are also some caveats: you'll have to throw around some 'extern "C"'s around to deal with the IRQ Handlers within the library, I haven't figured out a way to do this in C++ yet.

I've not come across any microcontroller application that needs to deal with objects, other than it being a neater way of storing information (and most of the time, a few structs would do the same job). So the application code itself does not necessarily benefit from being in C++.

On the balance, from this experience, I don't feel the benefits of C++ for microcontrollers are great enough to justify the lower speed and bigger code size. When you start entering the applications processor/SOC territory, that becomes a different story.

The compilers I have used for this was Keil's ARM MDK, and also YAGARTO (based on GCC), the difference between the output of the two in terms of size and speed appeared to be negligible, Keil perhaps being slightly smaller and faster though I have not done any objective tests.
User avatar
UAirLtd
 
Posts: 629
Joined: July 19th, 2011, 10:32 pm


Return to General Talk

Who is online

Users browsing this forum: No registered users and 4 guests