This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430 C++ programming

Expert 1125 points
Other Parts Discussed in Thread: MSP430G2303, MSP430F5324

Hi,

 

Is there any document or sample programs on MSP430 C++ programming  using CCSv4 

I found few wiki links Cplusplus but doesnot describe about CCS.

http://processors.wiki.ti.com/index.php/Category:Cplusplus

Please let me know if there are any necessary settings to be done in CCS. 

 

And if possible could you please give a pointer on Pros and Cons about C++ over C.

 

Thankyou.

  • Hi Prad,

    I do all my MSP430 programming in C++ and CCSv4. It works very well if you consider an MCU environment.

    I have not found any disadvantage of C++ compared to C other then the compiler force you to a more accurate and readable code. Not any addtional code is created nor additional  storage space is needed.

    Following hints may help you:

    - Do not create classes which use the heap. This means all functions and variables should be static. Create your own initialization routine (Maybe a static module with constructor could work. I never tried). You can reduce the heap memory to 0.

    - Be aware that unlike IAR the CCS does not initialize static variables. Initialization in your own Init() function allows you to reset a module as often you want.

    Advantages you get by using C++:

    You can publish and protect functions and variables.

    You can even protect interrupt routines(as protected or private function) from unwanted access outside. Within the interrupt function you have full access to all class variables.

    You can created virtual dummy clases and implement code in derived classes.

    and many other advantages on top.

    Regards

    Guenther

  • Guenther Klenner,

    I am using MSP4305324 MCU and am just deciding whether to use C++ or C. Overwhelmingly my preference is C++ however I do not want to take a chance if the support for C++ is flaky or not robust enough. I am using the CCSv5 for development. I was very encouraged after reading your response above. Are the issues you have raised like non initialization of static memory etc. still issues in CCSv5? Is there any good reference blog or article you can refer me to for a sort of checklist when programming MSP430 in C++.

    I also has a specific question about your point about not using the heap.  You say and I quote : "Do not create classes which use the heap. This means all functions and variables should be static. Create your own initialization routine (Maybe a static module with constructor could work. I never tried). You can reduce the heap memory to 0."

    Use of non static functions and variables in classes do not imply use of heap. Only if you allocate it dynamically (by using new operator or malloc) would it be dynamic. Can you elaborate or clarify your statement.

    Thanks in advance.


  • Dear Mohammed,

    I'm using C++ now with V5.2 and like it even more. I use it for many processors like MSP430G2303, ..G2553, ..F2774, ..F5438 and ..F5528. All work fine with C++.

    Refering to your question: The initialisation runs fine if you specifiy it. If you don't initialize a memory then it is not set to a defined value. It forces you to a clean programming and allows you to do your own special initialization.

    I'm sorry I have no article on hand to refer to. But let me know if you find one.

    To use non static functions or variables you need to allocate the refering object of its class. If you allocate such object with " ... = new xyz();" then this new object is located on the heap. On top each call has a hidden pointer as parameter which reference to "this" as object. As RAM is very limited I avoid the use of non static functions or variables.

    A very nice thing I realized is to declare interrupt functions as private function. This avoides misuse and encapsulates the sensitive interrupt function. Here an example:

    In Timer.h

    class Timer
    {
    ...
    private:
      static __interrupt void Timer_B(void);
    };

    In Timer.cpp

    ...
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer::Timer_B (void)
    {
    ...

    Regards

    Guenther

  • Dear Guenther,

    All your points are well taken, however since others may read this discussion, I want to be sure to bring a point out against use of static. Use of static will cause the state of the object to become shared. As a result the class will be reduced to access restriction mechanism only and even defining two instances of the same classes object either on stack (local variable) or globally will not be possible. In other words the concept of object will effectively be eradicated and the class will be just an access boundary. I understand that even that may be of value in itself, but it is not necessary to make things static for achieving it. Non static v/s static would use exactly the same memory if only one object is defined in either case. Addition of the vtable pointer would only come into play if a virtual function is added and that may be avoided if inheritance is not expected to be used.

    I was hoping to define the interrupt routines within the class and your code sample above will prove to be of great value. 

    Thank you, and we can discuss this further. I strongly suggest that you (and I would gladly help) put together an article or blog on this topic if you can spare some time. It would be of great value to others I am sure and it's something completely missing!

  • Hello Mohamed,

    Yes, you are absolutely right. In putting all parts static there is no dynamic allocation with all its pros and cons.

    Maybe an overview on RAM allocation as the linker does helps to understand the issue.

    The whole RAM of an MCU is divided into 3 parts:
    - block storage segment (.bss) and .data segment containing all static variable declaration (also for C and Assembler)
    - heap for dynamic allocation (like new or malloc)
    - stack for local variables

    Only variables, which are known in size at compile time are able to be located in .bss or .data. They do not change size and location.
    Dynamic variables and objects are allocated in heap and it is not easy to guess if heap size is sufficient.

    This is the reason why I avoid dynamic objects on MCUs. I also program in C# on the PC without this limitation and enjoy using objects in heap. At the end you need to know do you play games with elefants (PCs) or with ants (MCUs).

    Regards
    Guenther

  • Guenther Klenner said:

    ... As RAM is very limited I avoid the use of non static functions or variables.

    It's great to hear about others' experiences with C++ for MCUs. I use C++ exclusively, but my work is on ARM, not MSP430.

    How do you avoid using "non-static variables"? Member variables (which aren't static) are the most useful concept in C++, and they don't add any overhead beyond what you'd get with pure C structure references. In fact, references to C++ member variables could even be more efficient than straight C because the "this" pointer isn't allowed to change (where a structure pointer might).

    Regarding virtual functions, the execution overhead should be negligible. I can see where having lots of vtables could blow out your code space, but if you're using virtual functions only when necessary, I'd wager that the vtables + virtual calls will add up to less code than an implementation that uses explicit type information to do the same thing. That's just a conjecture though. :-)

  • One very important question we need to address is what is the cost of enabling exception handling. According to the Compiler User's guide for 4.1. I think exception handling would be a very important feature to have and I do have it enabled but I am concerned after reading the text given below.

    The compiler supports the compilation of embedded C++. In this mode, some features of C++ are
    removed that are of less value or too expensive to support in an embedded system. When compiling for
    embedded C++, the compiler generates diagnostics for the use of omitted features.
    Embedded C++ is enabled by compiling with the --embedded_cpp option.
    Embedded C++ omits these C++ features:
    • Templates
    • Exception handling
    • Run-time type information
    • The new cast syntax
    • The keyword mutable
    • Multiple inheritance
    • Virtual inheritance
    Under the standard definition of embedded C++, namespaces and using-declarations are not supported.
    The MSP430 compiler nevertheless allows these features under embedded C++ because the C++ runtime-support library makes use of them. Furthermore, these features impose no run-time penalty.
    The compiler does not support embedded C++ run-time-support libraries

  • Mohammed Lokhandwala said:
    I think exception handling would be a very important feature to have and I do have it enabled but I am concerned after reading the text given below.

    Someone used to PC programming usually forgets (or doesn't know) that many features that make life convenient for the programmer are paid for by increased code complexity and increased execution times.

    Exception handling is a very convenient thing. And it is a really big thing to handle as it requires complex stack handling and many additional checks at runtime. Even if you do not use it in a function, it might be used by the funciton that is called and handled by the funciton that called the current one. So all support needs to be there everywhere.

    When doing embedded programming, everything that has to be done at runtime should be reduced to the minimum amount, even if this means making the life less easy for the coder.

    In PC software development, the software manufacturer usually isn't the hardware manufacturer. So nobody cares if the user has to buy a new PC to make the program run. All that counts is the development cost of the software. Being faster with more 'powerful' (or rather: convenient) features means less development cost and more profit. Even though the user has to pay the price.

    In embedded development, uually one manufacturer produces both: hardware and firmware. Here a man-week or two more in software developemnt is nothing when it allows you to use a cheaper (because less flash/ram etc.) processor in the 100k products you're producing.

    Sure, if it's just for your personal hobby, you may consider buying one of those new devices Microsoft just presented their 'embedded' .NET framework for (10 years ago I'd wished to have such an 'embedded' device as my main PC)

  • Adding to what Jens-Michael said, exception handling is useful but the main reason to use it is to ensure that heap memory is deallocated on failure. Embedded C++ typically doesn't use the heap very much, so the actual benefit you get from exception handling is much less.

    It basically depends on whether your code does a lot of work in destructors. Most likely, you won't even have many destructors in an embedded application because all your objects will be statically allocated.

  • If you're using GCC, there's a neat trick to override the default exception handling behaviour (which pulls in nearly the entire standard library). Simply add


    namespace __gnu_cxx {

    void __verbose_terminate_handler()
    {
      abort();
    }

    }

    which overrides the default handler in libstdc++. You can replace the abort() call with an infinite loop, or a system call to an RTOS, or other error handling code as appropriate.

    Tony

  • I think it is well understood that exception handling adds run time cost because of stack unwinding requirements. It is however not necessary that it is required when lot of work is done in destructors. Exception handling is really useful to ensure clean coding and bug free coding by virtue of eliminating the need to check the result of every call The though question is determining the cost of exception handing in terms of RAM/Time/Code. Out of the three I would be most concerned with RAM (though in time critical applications time may be more important).  It might in fact be a case for argument that exception handling could reduce code size if used right in comparison to extensive checks in C style function return code validation. Only the run time overhead of carrying the exception to the handler might be the only real cost. 

    One way to check this out might be to check the resulting assembly code and see the difference between the same code with and without exception handling.

  • Mohammed Lokhandwala said:

    Exception handling is really useful to ensure clean coding and bug free coding by virtue of eliminating the need to check the result of every call

    Well, that would be a very bad way of using exceptions. When an exception occurs, something has usually gone very wrong, and unless it's explicitly handled in a try-catch case the application would crash and burn rather ungracefully. Exceptions should be used as a tool to better error handling, rather than as a substitute for explicit error handling.

    See http://ptgmedia.pearsoncmg.com/images/020163371x/supplements/Exception_Handling_Article.html

    Tony

  • Mohammed Lokhandwala said:
    The though question is determining the cost of exception handing in terms of RAM/Time/Code. Out of the three I would be most concerned with RAM (though in time critical applications time may be more important).  It might in fact be a case for argument that exception handling could reduce code size if used right in comparison to extensive checks in C style function return code validation. Only the run time overhead of carrying the exception to the handler might be the only real cost. 

    The C++ exception ABI (http://sourcery.mentor.com/public/cxx-abi/abi-eh.html) is designed to perform basically no work at all on normal function invocation. Instead, it puts off all the expensive stuff off until an exception actually occurs. When an exception is thrown, the code will wind its way backward through stack frames to find catch blocks and destructors that need to be called. That *is* expensive, but it doesn't happen very often.

    The RAM used by all this is minimal because mostly what the runtime needs to know about are stack offsets and entry points--all of which can go into flash. There is some stack overhead for explicit try/catch blocks, but as long as you're not calling such functions recursively, you should be OK.

    The code space overhead can be significant though. In the presence of exceptions, every function can exit two ways: via 'return' and via 'throw', and the compiler will generate code for both branches. The kicker is that each function call (i.e., a "call site") may have to handle two kinds of exits.

    On the other hand, compilers are pretty clever these days, so your best plan is to try compiling chunk of real-world code with exceptions and without and measure the size of the .bin

  • TonyKao said:

    Well, that would be a very bad way of using exceptions. When an exception occurs, something has usually gone very wrong, and unless it's explicitly handled in a try-catch case the application would crash and burn rather ungracefully. Exceptions should be used as a tool to better error handling, rather than as a substitute for explicit error handling.

    I never said otherwise! I meant to say that C style error handling theoretically and ideally requires every statement to be checked for error and especially so for function calls. Since C++ code would inevitably have to interface with C code or assembly, at that point the check requirement still holds true. Within C++ code however every function call would NOT require an explicit check on return because if the called function had detected an error it would have thrown and exception and there would be at least one but possibly more than one exception handler in that call chain to handle it and yet there would be no compromise of stringent error checking despite not explicitly checking every functions return code.

  • andy turk said:

    On the other hand, compilers are pretty clever these days, so your best plan is to try compiling chunk of real-world code with exceptions and without and measure the size of the .bin

    Just as an example, I compiled a real world C++ application using IAR Embedded for ARM (since exceptions are not supported on the MSP430), with an added simple try-catch block, and these are the runtime code added by the linker:

    dl7M_tln.a: [3]
        abort.o                              6
        bsearch.o                           60
        exit.o                               4
        xgetmemchunk.o                      40                 4
        xtls.o                               2
        xxmemxfree.o                       128
        xxmemxmalloc.o                     176                 8
        --------------------------------------------------------
        Total:                             416                12

    dlpp7M_tl_nc.a: [4]
        bad_exception.o                     40       52
        exception.o                         16       44
        rtti.o                             564       40
        rtti2.o                             18        8
        typeinfo.o                          50      392
        xthrow_throw.o                      96       56
        --------------------------------------------------------
        Total:                             784      592

    rt7M_tl.a: [5]
        ABImemcpy.o                         86
        XXexit.o                            12
        arm_exceptions_alloc_c.o            96
        arm_exceptions_begincatch_c.o       76
        arm_exceptions_callterm_c.o         64
        arm_exceptions_callunex_c.o        210       88
        arm_exceptions_cleanup_c.o         124
        arm_exceptions_endcatch_c.o         66        8
        arm_exceptions_foreign_c.o          58
        arm_exceptions_free_c.o             32
        arm_exceptions_globs_c.o            80                 4
        arm_exceptions_mem_c.o              58
        arm_exceptions_rethrow_c.o          60
        arm_exceptions_support_c.o          56
        arm_exceptions_terminate_c.o        32
        arm_exceptions_throw_c.o           438       60
        arm_exceptions_unexpected_c.o       36        8
        cexit.o                             10
        cmain.o                             22
        copy_init3.o                        46
        cstartup_M.o                        12
        data_init3.o                        40
        iar_unwind_asm.o                   148
        unwind_pr.o                      1 566
        unwinder.o                         932
        zero_init3.o                        34
        --------------------------------------------------------
        Total:                           4 394      164        4

    While the same application compiled with exception code removed has only this:

    dl7M_tln.a: [3]
        exit.o                        4
        -------------------------------------------------
        Total:                        4

    rt7M_tl.a: [4]
        XXexit.o                     12
        cexit.o                      10
        cmain.o                      22
        copy_init3.o                 46
        cstartup_M.o                 12
        data_init3.o                 40
        zero_init3.o                 34
        -------------------------------------------------
        Total:                      176

    Fairly significant difference between the two. Of course it would vary across compilers, but I once had a program ballooning from 7kb to 100kb on GCC simply because I used an exception throwing version of operator new.

    Tony

  • Mohammed Lokhandwala said:
    Exception handling is really useful to ensure clean coding and bug free coding by virtue of eliminating the need to check the result of every call

    However, this is only necessary if function that throws an exception is exposed to a caller that may demand things it cannot fulfill.
    Usually this is because the called function is part of a library or a module that tries to handl eeverything in every situation.

    In embedde dprogramming, includign things that are not needed at all for the current project is a bad (but nonetheless common) idea.
    If by design certain conditions cannot happen, there is no need to include them in the final binary. And if certain things can happen by design, there are other, 'cheaper' means to solve them than exception handling.

    But I see people all day carrying around $1000 smartphones just to listen to music and make an occasional phone call. But in times where Microsoft releases an 'embedded .NET' SDK, I've given up shaking my head.

  • Mohammed Lokhandwala said:

    Within C++ code however every function call would NOT require an explicit check on return because if the called function had detected an error it would have thrown and exception and there would be at least one but possibly more than one exception handler in that call chain to handle it and yet there would be no compromise of stringent error checking despite not explicitly checking every functions return code.

    I think you're glossing over and important point. Even though you aren't writing *explicit* error checks in the presence of C++ exceptions, the compiler is essentially doing that for you (in a pervasive and air-tight fashion). So you're not going to save much if any code space by letting C++ generate the error checking.

    The reason to use exceptions, IMO, is to decrease development time and to make the compiled code more reliable. Even so, I turn 'em off for my own work.

  • Mohammed Lokhandwala said:

    Within C++ code however every function call would NOT require an explicit check on return because if the called function had detected an error it would have thrown and exception and there would be at least one but possibly more than one exception handler in that call chain to handle it and yet there would be no compromise of stringent error checking despite not explicitly checking every functions return code.

    I agree it's useful that exceptions do not need to be handled at the source, but it can be both a blessing and a curse. If not handled correctly the exception can propagate down the call chain and wreck havoc on unsuspecting objects (or worse, C functions); you simply cannot except the C++ runtime to automagically guarantee the correct handling of an exception (yes it will eventually be "handled", in the same way that memory access violations are "handled" by the OS as seg faults).

    So what I'm saying is that while exceptions are indeed powerful and useful, they should be handled (no pun intended) with great care, especially in the context of embedded development.

    Tony

  • Hallo Mohammed,

    Just remember your MSP430F5324 MCU has only 6144 Byte (not kByte, MByte, just Byte) of RAM. Depending on the size of your application you should careful pick C++ features or avoid them.

    On all pros and cons what I can tell you is C++ has it's advantages over C and by all these discussions at the end it is you to pick and choose. If you program in C all these options are not there.

    Programming MCUs is like building a race car. All is in your hand but you also be responsible. It's easy to burn a race car as well as it is easy to crash a MCU program, but if you know how to do it you are faster with less cost than others.

    Enjoy riding MSP430
    Guenther

**Attention** This is a public forum