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.

CCS Compiler does not clear bss data

This thread is nearly a clone of the thread titled (edit: link was false)

http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/t/90763.aspx

The reason for starting a new thread is the following: the original thread is polluted with many, many (philosophical) discussions.

Problem: The CCS-compiler does not initialise global and static variables to 0, unless these are explicitly zeroed by users.

One contributor complained, that this "anomaly" caused much time spent in finding errors (of course, due to not reading the manual), but I agree: zeroed .bss sections are absolutely standard.

Another contributor says that CCS' bss-section also contains flash constants. Ergo: it seems that modifying startup-code in order to get desired initialisation behaviour is not that trivial.

Complaints of users who fear that the watchdog could trigger during startup code should NOT apply, to my opinion. Clearing a block of 1000 integers to zero in a contiguous .bss block should be a quick job that's done within a ms.

TI seems not interested in getting .bss initialised as all other compiler vendors offer - no TI-employee responded to the thread indicated above.

 

  • Rob Maris said:
    I agree: zeroed .bss sections are absolutely standard.

    Well, may be PC programmers standard, btu not C(++) standard. None of the C(++) standards includes zeroing the area for variables which are not explicitely initialized. (and CSS does not claim to implement any C standard, it only references K&R where it does.)
    Worse, if you ever wondered why some PC program files contain megabytes of empty data - this is the initialization data for some variables and/or arrays, stupidly generated by the compiler and then included into the binary.

    Embedded programming means to be efficient and precise. If you don't say a variable has to be initialized, it won't. As superfluous initialization is inefficient. If you need it to be zero, add a "=0" to the definition.

    Rob Maris said:
    Complaints of users who fear that the watchdog could trigger during startup code should NOT apply, to my opinion.

    Well, it does. On 1611 processor with 10k ram and a default speed of 600kHz (before your code could rise it), it did happen.
    MSPGCC did silently disable the WDT before the init code was executed (and clears bss). My own statup code was changed to trigger the WDT instead. Slower, but safe.

  • It's also not standard if you program C++ under Windows, well sort of, it depends on the compiler or it's settings. Compiling using debug directives gave me uninitialised variables, using the release build it gave me a 0 initialisation. I didn't care as the initialisation to a meaningful value was done inside the program - and that is what everyone should do.

    If your program needs a certain starting value of a variable don't make any assumptions on what the compiler does - it might change with every version. Program in a way that the program runs independently on which compiler is was compiled.

    Of course sometimes you really have to dig into your compiler to get out every ounce of speed and size, but often that is not required and producing safe and bug free code should be a primary goal. And so you have to be aware that the compiler is generally not doing what you expect it to do (that way you will check things thoroughly).

    Of course that is only my view on things.

    Jens-Michael Gross said:
    Well, it does. On 1611 processor with 10k ram and a default speed of 600kHz (before your code could rise it), it did happen.
    MSPGCC did silently disable the WDT before the init code was executed (and clears bss). My own statup code was changed to trigger the WDT instead. Slower, but safe.

    I managed to do that in a 2xx device. Now while I generally don't care on how the variables are initialised, I'd strongly suggest that the startup code initializing variables should be in such a way that the watchdog will not trigger because it takes too long. So there should be some code in the compiler to make it reset the watchdog timer during initialisation.

    As for the standards of the CSS compiler (at least for revision 4):

    The C and C++ language features in the compiler are implemented in conformance with these ISO
    standards:
    • ISO-standard C
    The C/C++ compiler conforms to the C Standard ISO/IEC 9889:1990. The ISO standard supercedes
    and is the same as the ANSI C standard. There is also a 1999 version of the ISO standard, but the TI
    compiler conforms to the 1990 standard, not the 1999 standard. The language is also described in the
    second edition of Kernighan and Ritchie's The C Programming Language (K&R).
    • ISO-standard C++
    The C/C++ compiler conforms to the C++ Standard ISO/IEC 14882:1998. The language is also
    described in Ellis and Stroustrup's The Annotated C++ Reference Manual (ARM), but this is not the
    standard. The compiler also supports embedded C++. For a description of unsupported C++ features,
    see Section 5.2.
    • ISO-standard run-time support
    The compiler tools come with an extensive run-time library. All library functions conform to the ISO
    C/C++ library standard. The library includes functions for standard input and output, string
    manipulation, dynamic memory allocation, data conversion, timekeeping, trigonometry, and exponential
    and hyperbolic functions. Functions for signal handling are not included, because these are
    target-system specific. For more information, see Chapter 7.

     

     

  • Let me summarize the rumours about the CCS compiler, the C standard and not initialized global variables:

    • http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf, chapter 6.7.8/10 states it more or less clearly that static variables which are not explicitely initialized must be setup to zero
    • chapter 5.1 of slau132f states: "The compiler supports the C language as defined by ISO/IEC 9899:1990" - this leaves almost no space for speculations about the conformance of the CCS compiler
    • chapter 5.13 of slau132f tells something of not initializing global variables to zero: "The ANSI/ISO C standard specifies that global (extern) and static variables without explicit initializations must be initialized to 0 before the program begins running...".  There are some more comments about this

     

    Although some very appreciated experts state that init to zero costs valuable space in the very small MSP430 devices, this is almost not true, because init to zero can be done either in a small loop or with a call to memset() at the right place.

    My usual way to clear memory is done like this:

     

    int _system_pre_init( void )
    {
       extern uint8_t __bss__;
       extern uint8_t _stack;

       memset( &__bss__, 0, &_stack - &__bss__ );
       return 1;
    }   // _system_pre_init

     

    I guess, this costs about 20 bytes of flash.

    Hardy

  • Thanks for all replies up to now. One remark: please don't make comparisons with C++. I'm very keen on keeping this thread as compact as possible. I can also start a new page on TI's wiki, where you have a separate page for "discussion" and a main page for any topic-relevant information.

    Regarding the 600 kHz hint. Yes, I am aware of this, but forgot that. That means, in fact, that startup code must lengthen the timeout of the watchdog timer.

    I fully agree with Hardy, regarding the flash space for zeroing variables. I'd guess that from approx. 10 variables on that must be zeroed explicitly, this costs more flash space (where zeroes are NORMALLY part of a table with the other non-zero initializers), that is also copied in RAM from a startup code. At least local statics cannot be initialized in code runtime (unless a flag would be used that says that the variable has not been initialized upon function call).

     

    Well, it is my goal to have modifications in the startup code that make TI's compiler conform to  the vast majority of C-compilers out there. Of course this is a simple taskt, but I guess that it points out to be not that simple. Otherwise, TI would have designed it the common way. I recall the note that .bss apparently is not *only* initvars section (refer to thread as recalled on top of this thread).

    Perhaps, anybody has succeeded in using mspgcc within CCS4, or  even use the debugger plugins of CCS4 into recent eclipse with mspgcc...

    I'd collect any relevant information and ideas when they emerge here, and transfer them over to a new wiki page.

  • It might be that this discussion would better be held in the TI C/C++ Compiler forum, I'm sure more people are reading this forum, but I'm not so sure if the compiler people from TI are reading this forum.

    If you don't want comparisons to C++ then maybe you should have stated this in your opening post, the "CCS compiler" is both.

    But to provide something for the discussion, I searched through the compiler forum and found a thread (Global Variables not Automatically Set to Zero.) in which a hint is given to look on that wiki page.

    From which the  following quote is taken:

    Uninitialized static-storage-duration objects are not initialized to zero by the compiler. The user must do this explicitly in the linker. (Exceptions: ARM EABI and C6000 EABI zero-initialize all such objects.) ... The TI compiler does not do this; this is left up to the user to perform in the linker command file with a fill value for sections representing initializers. This is not technically a violation of the C standard, since the linker is part of the implementation, ....

    So it's not like TI is unaware of that, and it will probably be hard to convince them to change their minds on this item, as they argued their way around it.

    The problem is of course if you initialize using the linker, this will be once during the programming of the device but not after a system reset. So basically this method is just to gain a technical conformance with the standard but leaves the problem completely to the user.

  • Bernhard Weller said:
    As for the standards of the CSS compiler (at least for revision 4):

    IIRC, the issue was clearly stated in the documentation of the 3.x compiler (in CCS4.x). CCS won't init uninitialized variables.
    Personally, I prefer this, as it means I can have variables that survive a reset untouched (with a guard value to ensure that it is no random value from power-up).

    Rob Maris said:
    Regarding the 600 kHz hint. Yes, I am aware of this, but forgot that. That means, in fact, that startup code must lengthen the timeout of the watchdog timer.

    Not possible on the 1x devices. (in fact, the DCO speed was no issue here - since the WDT was running from DCO too. So after 32768 clock cycles the WDT did trigger. Copying a few KB of code was exceeding these 32768 clock cycles in any case).

    HardyGriech said:
    My usual way to clear memory is done like this:


    Except for not using memset but rather using a direct loop of a few assembly instructions, this is what MSPGCC does.
    My own implementation added a write to the WDT on every '0' word written. From a preloaed register, to keep it short.
    However, it doubles the execution tiem for the memory clear process or the memory copy process.

    If you were referring to me with "some very appreciated experts", I mentioned the fact that some PC compilers do add variables with explicitely '0' initialized variables to the initialized variables space, causing their zero init value to be added to the stored binary instead of moving these variables into the egment which is initialized to zero in a loop on program start, causing the binary to be greatly expand.
    Some compilers even do this fo uninitialized variables too. Argh!

    Of course there is no need to store zeroes as init values in flash, if you already have a loop or function that clears the memory for uninitialized variables on startup. But not all compilers (or compiler coders) are as s mart as we are :)

    Bernhard Weller said:
    Uninitialized static-storage-duration objects are not initialized to zero by the compiler. The user must do this explicitly in the linker.

    To be exact, this is true for othe rcompilers too.

    It's the linker that puts objects, placed into a certain segment by the compiler, into the final linker sections. Based on the linker script. So a change in the linekr scrip can put initialized variables in uninitialized object space, code into ram, whatever. The compiler only gives a hint what should be done with them.
    However, most people consider compiler and linker to be an unity. 'the compiler' is 'all software that turns source code into a binary'.

  • OK, it's the start-up code (of course), and that's using section information from the linker. According to exactly http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/t/90763.aspx#315615 post from the original thread, the bss section with CCS has not that narrowed meaning as is standard. I'd believe that it's this, where TI should make (suggested) small changes to the linker.

    In fact, TI: please make a statement!

**Attention** This is a public forum