Shop OBEX P1 Docs P2 Docs Learn Events
C++. Perfect for small embedded systems. — Parallax Forums

C++. Perfect for small embedded systems.

Heater.Heater. Posts: 21,230
edited 2011-10-20 20:07 in General Discussion
It is a commonly held belief that C++ is not suitable for space and/or performance constrained systems. It is often said that C++ has no place in programming micro-controllers for example. Mostly this opinion is stated with out any supporting evidence, indeed stated out of ignorance because anyone who had looked into the matter would soon come to a different conclusion. I will not state the usual arguments against C++ here, there are enough on the web already.

My intention in this thread is to demonstrate that C++ can be used in such space/time limited systems with zero overhead compared to C whilst at the same time allowing for such things as:
Clearer, more organized, more easily understood code.
Write once, re-usable code.
Less scope for bugs due to the above two items.

Clearly C++ is a big and complicated language which often comes with huge and complex class libraries. This results in the famous "bloat" often referred to when talking about C++ and the view that it does not suit small systems. Obviously multiple inheritance, dynamic creation of objects on the stack and heap, exceptions, etc etc can eat memory and performance.

But who says that just because you have a lot of rope you have to hang yourself? What if we create code using features of C++ that help us with clarity, reuse and maintenance issues but don't contribute to bloat? Is that even possible? Resoundingly yes.

Attached are implementations of FIFO's in C and C++. Each version contains a FIFO for bytes (chars) and a FIFO for integers.

I am making the assumption that our program will need more than one of each such FIFO's therefore in the C++ version the FIFO is defined in a class which can then be instantiated more than once. For the C version the FIFO's are structures and the FIFO functions (put, get etc) take a pointer parameter to the instance of FIFO to operate on (Saves writing the FIFO code multiple times and code space).

Because we want fifo's of integers and fifo's of chars in our program in the C++ version the fifo is defined as a template class from which char, int, or other type fifos can be created from the same fifo definition.
(It is often said templates should be avoided in C++ on small systems, for unspecified reasons). In the C version it is necessary to write the fifo function out twice once for int's and once for chars. (Perhaps could be done with macros though)

As we are talking about space constrained embedded systems I have chosen one of the most space constrained and embedded places I know for this demonstration, the Propeller COG.

Both of these files are compiled down to Propeller native assembler and the resulting files compared. See attached .S files.

The surprising and astounding result is: THE FINAL CODES ARE IDENTICAL, there are some minor variations in label names only.

This amazes even me given that the sources are so different. I think you will all agree that the C++ version looks a lot nicer.

P.S. This is inspired by an ongoing debate with RossH re: C/C++ which we both keep forgetting about:)
P.P.S. I hope the Propeller GCC team don't notice and/or mind I have shown these examples of Prop C code for COGS. Perhaps it will inspire some more to volunteer as alpha testers.

Comments

  • Martin_HMartin_H Posts: 4,051
    edited 2011-10-19 06:12
    You won't get an argument out of me. I love C++ and in another thread I posted a class I wrote which wrapped a compound eye sensor. The class was statically allocated in the consuming program, and the class's methods are inlined. The performance should be nearly the same as equivalent C, but the code was much better organized.

    In some ways Spin isn't that much different from that sort of C++ usage. But after decades of use C++ is my native tongue, while Spin is not.
  • photomankcphotomankc Posts: 943
    edited 2011-10-19 06:35
    No argument here either. I spent a good number of years programming in C++ and despite some of the complexity and never really getting the hang of preprocessor stuff I loved the way you could organize code in it. One of the reasons I could slide into SPIN was it is enough like C++ that it clicked easily for me but it's enough different that I beat my head against the wall at times too. No inheritance, no passing of an object reference to another. I never enjoyed C much but C++, I just sorta naturally took to it. I'd love to see an easy to use and well documented C++ come to the Propeller and I keep watching the development efforts going on with much anticipation. The Prop has so much more capability but sometimes I like to just pick up the Arduino and do something because, as above, we just know how to talk to each other already.

    I guess my only complaints about the language is that if you want to make a real mess of something, boy C++ will let you do it in grand fashion. Memory leaking applications suggest that the tedious management of allocated RAM is often screwed up in larger apps. Lastly, the still confusing (to me) way that includes and defines can muck things up in a large project can be frustrating. Still it's neat that you made the comparison there, and yes, to me the .cpp code is much cleaner.
  • mindrobotsmindrobots Posts: 6,506
    edited 2011-10-19 06:59
    Amen Brothers!! (I'm NOT a C++ programmer)

    Higher-Level language are tools of abstraction to aid the programmer by rapidly creating source code that is understandable and maintainable and support some descriptive features that maps to the world they are creating and manipulating (yes, I love programming because I am the master of each world I create!!) and/or generating target code to exploit the features of the hardware without the programmer having intimate working knowledge of those features.

    I'm currently learning Octave (GNU Matlab) for a machine learning class because it is very well suited to the world of matrix and vector manipulation - it's very impressive for that use. Could my company write their payroll system in it? Yes, but not very likely. That is not the abstract world it maps to. Does it care what hardware it runs on, no, with time and effort, it could be made to run on most anything.

    Back in the old days, there were big mainframes that were used for day to day computing and then there were these amazing vector processors made by Seymour Cray. You could run FORTRAN on either machine, you could do complex numeric calculations on either machine. If you generated code for the Cray in the same manner as your IBM 370, it ran slow, if you generated code to take advantage of the vector processing the speed was astounding. The high-level language was the same, but the way the target code was generated made all the difference. Things like that have been done for ages....still are.

    We have amazing powers on our desktop to transform symbolic code to target code on our desktop today. The good features of a language can be used without the features that don't make sense for a target environment (e.g. a garbage collecting heap on the propeller).

    When I learned IBM360 assembler, I was coming from a micro background. Everything I had worked on had a stack, I liked having a stack. I wrote macros and a library to support stacks on the 360 because I programmed better having a stack. It made sense to me and made my programs better.

    If objectifying can lead to better programmable code and static objects can be implemented at the machine level...COOL!

    ....the ramblings go on.......
  • prof_brainoprof_braino Posts: 4,313
    edited 2011-10-19 07:58
    Amazing stuff. Good example of a tool that is an instrument when used properly.
    photomankc wrote: »
    I guess my only complaints about the language is that if you want to make a real mess of something, boy C++ will let you do it in grand fashion. Memory leaking applications suggest that the tedious management of allocated RAM is often screwed up in larger apps. Lastly, the still confusing (to me) way that includes and defines can muck things up in a large project can be frustrating.

    For me I still have bad feels from being bitten by "mistakes" from those tasked with the work when the masters are not available. As photomank says, C++ allows "grand fashion". If we could but bottle heater....
  • rod1963rod1963 Posts: 752
    edited 2011-10-19 09:35
    Had no idea there is a C++ compiler for the Prop.

    Any links where to download it?
  • jazzedjazzed Posts: 11,803
    edited 2011-10-19 09:52
    rod1963 wrote: »
    Had no idea there is a C++ compiler for the Prop.

    Any links where to download it?
    It's coming. We will probably decide today if it's time to invite Alpha testers.


    Heater I had to check your IDENTICAL claim myself this morning. Amazingly, you're right.
  • Heater.Heater. Posts: 21,230
    edited 2011-10-19 10:06
    Jazzed,
    Sorry for letting the cat out of the bag like that. I thought about it for a while and then thought it looks like alpha testing is close enough that a little leak would be no matter.

    Yep IDENTICAL. I was a little shocked at that myself and had to double check. I had done an experiment like this before with the ZPU compiler where it only managed 99% the same (the C++ code was shorter by a byte or two).

    Seems that Stroustrup guy knew how C coders would tackle the problem and then made C++ do the messy bits for you in the same way.
  • Roy ElthamRoy Eltham Posts: 3,000
    edited 2011-10-19 10:35
    I'm glad you posted this Heater. Now maybe all those C++ haters will quiet down a little? (Probably not.)

    My experiences with CPUs (x86, PPC, etc.) is that well written C++ produces tighter, better, smaller code than well written C. Largely because the compilers have gotten so good, and because it's easier (and often a lot less typing, as in less code) to do "the right thing" in C++ and produce good results. However, it's also easier to do "the wrong thing" and produce very bad code. So you have to be aware...

    Roy
  • rod1963rod1963 Posts: 752
    edited 2011-10-19 12:12
    C++ isn't a fix for poor programming habits and lack of proper planning on the part of the coder.

    As for C++ suitability for smaller micros like the Z-80 or Silabs 805x series remains to be see. It would be interesting to see a rewrite of CP/M in C++ is possible and compare it with the original in terms of performance and code size.
  • LeonLeon Posts: 7,620
    edited 2011-10-19 12:33
    IIRC, CP/M was written in assembler.
  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-10-19 12:41
    > Sorry for letting the cat out of the bag like that. I thought about it for a while and then thought it looks like alpha testing is close enough that a little leak would be no matter.

    I think the correct terminology is "creating buzz". Honestly, that's some some cool stuff. Thanks for the effort, all who are involved.

    Just one question... how much cog memory is used by the PASM?
  • Heater.Heater. Posts: 21,230
    edited 2011-10-19 16:42
    Kevin,
    Great, I don't think I ever created a buz before:)

    As for the size of the PASM you can count the instructions in the *.S files. That's it apart from the fact that they call printf. Yes there is a printf that fits in COG and prints to the serial line. Normally you would not use that. Then the is 8 or so longs used as a C run time.
    Notice that all variables here are in HUB RAM. Which might be reasonable for a FIFO buffer. It is also possible to locate variables in COG space for reduced size size and top speed.
    I have a version of FullDuplexSerial entirely written in C running in a COG and working up to 115200 baud.
  • RossHRossH Posts: 5,519
    edited 2011-10-19 18:37
    Heater. wrote: »
    P.S. This is inspired by an ongoing debate with RossH re: C/C++ which we both keep forgetting about:)

    :) I blame old age.

    I am not a C++ hater. I have used C++ extensively and actually do like some of the things C++ added to C - they really do make life easier. But C++ is also liberally littered with exploding mines that will kill you if you don't tread carefully.

    With C you have to learn what to do - and it is the same whether you are on a microcontroller, a microprocessor or a mainframe. With C++ not only do you have to learn what to do, but you then have to then learn what not to do when working in a highly constrained environment (such as a microcontroller). I won't go through the list of things you have to avoid - this has already been covered in other threads, and people do differ on the precise details (but no-one disagrees with the need to avoid some things!)

    To quote from a very old joke ("how to shoot yourself in the foot"):

    C
    You shoot yourself in the foot.

    C++
    You accidently create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical assistance is impossible since you can't tell which are bitwise copies and which are just pointing at others and saying "That's me, over there."
    But as heater says - this is an old argument, and it has no winners. Use C if you want to. Use C++ if you want to. But whether or not you agree that C++ is suitable for embedded systems, I don't think there is any doubt that C++ is not particularly suitable as a language for beginners to build embedded systems. However, the lesson we can learn from the Arduino is that there is a subset of C++ that is appropriate for this - provided it is also wrapped up in a suitably simple IDE and with suitably simple libraries.

    Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-10-19 18:45
    Strangely enough there is an attempt to formally specify a C++ subset for use in embedded systems. I forget now what it is called or the name of the group doing it. Might be nice if there were some compiler switches to turn off features you don't want.
    Isn't this the same problem that Ada has? The language grows so big and complicated and gross as it develops that someone has to define a subset to make it manageable. The spark Ada subset.
  • RossHRossH Posts: 5,519
    edited 2011-10-19 19:04
    Heater. wrote: »
    Strangely enough there is an attempt to formally specify a C++ subset for use in embedded systems. I forget now what it is called or the name of the group doing it. Might be nice if there were some compiler switches to turn off features you don't want.
    Isn't this the same problem that Ada has? The language grows so big and complicated and gross as it develops that someone has to define a subset to make it manageable. The spark Ada subset.

    You want to talk about C vs C++ myths? How about the "Ada is a big language" myth??? Ada may have been a big language when it was first developed, but compared to most languages today (including C++, C# and Java) Ada is positively "lean and mean" !

    BTW: I don't think the Spark Ada subset is designed to make the language smaller, it is designed to make it formally verifiable using automated tools.

    Ross.
  • localrogerlocalroger Posts: 3,452
    edited 2011-10-19 19:17
    I think the thing with Ada started with a rather infamous essay written by one of its developers grousing about how it had ballooned in scope and become, for its day (its day being around 1980) something of an albatross. In modern terms, of course, the most byzantine and complex software even imaginable in 1980 will run in real time on your phone. I think the Spark Ada thing was meant to return to one of Ada's original goals, which was verifiability, and the impossibility of that was one of the things The Infamous Essay groused about.
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-10-19 19:53
    The problem I see with C++ is that things could get very complicated over time. People who program the Prop range from novices who have never programmed before to professionals who have programmed in many languages. If there were no control over the features used in C++ on the Prop we'd end up with code that would be far beyond the understanding of most Prop programmers. This might be OK if the code is just treated as a black-box, but I think we want code that most programmers can understand. If the code is structured like Heater's example it would be similar to the object approach in Spin, and novices might find it easy to understand.
  • photomankcphotomankc Posts: 943
    edited 2011-10-20 13:55
    RossH wrote: »
    :) I blame old age.
    C You shoot yourself in the foot.

    C++ You accidently create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical assistance is impossible since you can't tell which are bitwise copies and which are just pointing at others and saying "That's me, over there."


    But as heater says - this is an old argument, and it has no winners. Use C if you want to. Use C++ if you want to. But whether or not you agree that C++ is suitable for embedded systems, I don't think there is any doubt that C++ is not particularly suitable as a language for beginners to build embedded systems. However, the lesson we can learn from the Arduino is that there is a subset of C++ that is appropriate for this - provided it is also wrapped up in a suitably simple IDE and with suitably simple libraries.

    Ross.

    Ok, that right there is funny.

    I think the debate is ongoing and every bit is likely to end just as definate as the PC language wars do. Which is to say that they don't ever end. Your last sentance I think is the key. Lots of people want to frame the debate by deciding what they mean by terms and then argue from that platform. So we can argue about how suited the whole boat-anchor of C++ is but there in our face is a small platform running a not so speedy chip using enough C++ to make code encapsulation possible and keep the more elegant items while not getting mired down into the depths of the OOP priesthood. It seems to be selling rather well and people are using it to good effect and not even really contemplating instances and pointers and overloads unless they want to get into it. So as long as the language and environment lets me create what I want, helps make it easier, and it fits on the chip, then it's the right language for my embedded system.

    Then there will always be the people like me that just clicked with the ideas in OOP even if did get made into a labyrinth somewhere along the way but never really liked straight procedural just as there are those that ask why add all that Smile when I can just code the darn thing, globals and all and be done with it. I'm really likeing the middle of the road approach in Spin and the Arduino.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-10-20 15:33
    It seems to me that the world of embedded controllers is changing rapidly. What once was bloatware is now considered normal. Memory chips megabytes in size cost less than ones measured in kilobytes. So where once C++ did not belong, perhaps it does now. I'm hoping to jump one step further and get C# running on an embedded controller (which should arrive in the next week or so).
    The surprising and astounding result is: THE FINAL CODES ARE IDENTICAL, there are some minor variations in label names only.

    That is both surprising, and also encouraging.
  • RossHRossH Posts: 5,519
    edited 2011-10-20 17:56
    Dr_Acula wrote: »
    It seems to me that the world of embedded controllers is changing rapidly. What once was bloatware is now considered normal. Memory chips megabytes in size cost less than ones measured in kilobytes. So where once C++ did not belong, perhaps it does now. I'm hoping to jump one step further and get C# running on an embedded controller (which should arrive in the next week or so).



    That is both surprising, and also encouraging.

    C#? On a microcontroller? Dr_A, that's just crazy talk!

    Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-10-20 20:07
    Dr A,
    To parphrase, "MCUs and embedded systems are getting bigger and faster therefore bloat does not matter."

    Strangely enough I'm currently working with a system where the same code is used in small embedded platforms and on high performance servers with gigs of MIPs, RAM and disk.
    In the embedded space this code is used for real time monitoring and control. In the server space it is used
    for simulations.
    In both cases performance matters and bloat is not tolerable. In the embedded space because performance is limited and in the server space because if you want to run thousands if instances each one had better be efficient.

    Now this thread could well become yet another pointless, meandering debate in the interminable language wars. I'd rather it did so with cold hard facts as per the opening post.

    You must admit that having such wildly different looking source codes compile to exactly the same machine code is pretty amazing and it does very forcefully bust the myth of C++ being unsuitable for small systems due to bloat.
Sign In or Register to comment.