TI's Code Composer does not clear bss data

I have taken over a project for the msp430 that has been built with TI's Code Composer Studio IDE and compiler. One thing that I have noticed in the documentation is the following paragraph:

In ANSI/ISO C, global and static variables that are not explicitly initialized must be set to 0 before program execution. The C/C++ compiler does not perform any preinitialization of uninitialized variables. Explicitly initialize any variable that must have an initial value of 0.

Is it just me, or do others think that this goes against C behaviour since the term "C standard" was first coined, and is likely to cause all sorts of hard-to-find bugs in code that is written with the assumption that "static int x" is the same as "static int x = 0" ?

I have never heard of any toolchain that does not clear the bss at startup (unless you specifically write your own non-standard startup code) - I have only seen it before in CCS for the TMS320 DSP's that I had to work with some 10-12 years ago. At the time, when I finally figured out the cause of my problems, I assumed it was either a bug in the toolset or that I somehow had an odd option set that disabled clearing the bss.

People here in c.a.e. have used a wide variety of compilers - and some here have written compilers. Is this a "feature" that anyone has seen elsewhere? Is it something that would catch you out, because you write code assuming that the bss is cleared? I'd like to know if my stunned reaction here is justified.

mvh.,

David

Reply to
David Brown
Loading thread data ...

The more experienced I get, the less assuming I do.

** I think that it is a "good thing" that they told you that they did not initialize BSS. ** There are times when you do NOT want want the BSS scrubbed at reset.

I think stunned is over-reacting.

Reply to
d_s_klein

The few cases where you don't want variables cleared are easily solved by creating custom initialization code, and/or adding another type of segment where you can put those variables in.

Writing code that depends on the fact that BSS is not cleared makes an even bigger assumption, and will most likely fail when you port it to a different toolchain.

Reply to
Arlet Ottens

I've never seen a _compiler_ that did pre-initialization of static variables. That's always been the responsibility of the startup code, the linker/loader, or whatever it is that runs before the C program is started.

Are you saying that the TI's CC tool suite includes startup code that doesn't clear the "bss" section? If so, then yes, that's broken. It's no wonder that nobody (TI FAEs included) ever recommends CC for MSP430 development.

TI Code Composer has a pretty bad reputation. I too was forced to use for TMS320 development and I was unimpressed. The only thing I've heard about CC on the '430 plaform is "don't use it, use IAR or Gnu."

Yes, shipping startup code that doesn't clear bss seems pretty broken to me.

--
Grant Edwards               grant.b.edwards        Yow! I am NOT a nut....
                                  at               
                              gmail.com
Reply to
Grant Edwards

Yes, it's a good thing that they told him about it. It's a bad thing that they didn't clear bss.

If you don't want them cleared, you put them _in_a_different_section_.

I'm not stunned, but that's becuase it's Code Composer. I'd be stunned if it were IAR or mspgcc that wasn't following the rules.

--
Grant Edwards               grant.b.edwards        Yow! What's the MATTER
                                  at               Sid? ... Is your BEVERAGE
                              gmail.com            unsatisfactory?
Reply to
Grant Edwards

There's a reason I refer to it as "code composter".

I've seen tool chains (not the compiler, as has been pointed out) that fail at this task. Most of them just lack decent start up code, some of them do not support a bss segment or do not support letting the startup code know where the bss segment starts and ends.

One of the joys of embedded programming is working around crappy tools.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

Yes. But it's certainly the responsibility of the compiler to tell the other parts of the tool chain about those static variables that aren't initialized explicitly. To this extent, compiler do pre-initialize statics.

And of course, "the compiler" as mentioned in the text quoted by the OP was rather certainly meant to refer to the entire toolchain, not just the compiler proper.

ACK. Startup code can usefully support a configurable _option_ that turns off BSS clearing. But it's brutally dumb to ship start-up code with that option active by default.

Reply to
Hans-Bernhard Bröker

TI has never been accused of being smart about anything relating to support for their parts. The parts themselves are often impressive enough, but the toolchains, refusal to disclose debug info, and so on all seem seem to be intended to annoy as many customers as possible.

Vendors like Microchip and Atmel do a much better job at support.

--
Grant Edwards               grant.b.edwards        Yow! Life is a POPULARITY
                                  at               CONTEST!  I'm REFRESHINGLY
                              gmail.com            CANDID!!
Reply to
Grant Edwards

When I buy a C compiler, I assume it conforms at least roughly to the C standards. I don't assume a perfect match, but I assume uninitialised variables will be cleared in the same way that I assume it will generate correct code for simple arithmetic.

No, it is a good thing that I happened to notice this information when reading through the manual. How many people actually /read/ these manuals cover to cover? Myself and about a dozen other people the world over - other people are going to read the relevant paragraphs after wasting hours, days, or more trying to debug non-reproducrable problems.

Reply to
David Brown

Yes, I know technically that it is the startup code rather than the compiler itself that clears the bss. But there are two sorts of libraries that come as part of any C toolchain - the C standard library (containing things like "printf" and "strlen", as required by the standards), and the compiler support library (containing things like software floating point routines and other code that supports the C language itself). The C startup code is part of that support library, and thus much more tightly integrated with the compiler than the standard library, which may often be swapped out. Still, it would have been more accurate for me to say it is a flaw in the toolchain rather than the compiler itself.

I can understand crappy tools. I've used many tools, with many flaws, bugs, failures, and missing parts. I can understand the reasons for providing such tools - small markets, lack of time, lack of money, shipping something "good enough", etc. I've seen C compilers that can't work with nested arrays, or which have 16-bit longs, or which don't support function pointers. I can appreciate the reasons for that (even if I don't like it), and I can work around them.

But this is something different - it is a concious decision to make the tool incompatible and non-standard in a surprising way that must surely have caused developers a great deal of wasted time and effort, as well as causing people to ship buggy products if they have not noticed this issue. Clearing the bss is not exactly rocket science - it needs a couple of marker symbols in the linker file, and a short loop in the startup code. It would take much less time to write the code than it did to document the flaw in the manual.

Reply to
David Brown

If I wrote code which assumed that .bss was cleared at startup then I would certainly be caught by this as I consider it part of the standard that .bss is cleared to 0x00 at startup.

However, I have a policy that I always initialise at startup _all_ variables whose first use within the code is something other than to be assigned a value, even when I am just initialising that variable to it's implictly assigned value.

I do this because I do not like implictly assigned variables and I like to make it explicit within the code that the following code which accesses that variable assumes a starting value of zero.

Also, at various warning levels, some C compilers will throw warnings about uninitialised variables and I also have a policy of actively eliminating compiler warnings in my code when possible.

I am also influenced by the fact that I write code in other languages and the rules are sometimes different in those languages.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Reply to
Simon Clubley

TI did the same thing with the JTAG interface. They made a conscious decision to violate the spec in ways that make it impossible to use in a JTAG chain. I was never too crazy about the AVR architecture when compared with the MSP430, but at least the AVR JTAG interface worked right.

Yep, it's a total of maybe 5 lines of assembly code.

Having the startup code behave according to the standard (and possibly providing an option to "optimize" it) is obviously the right thing to do -- obvious to everybody except TI.

--
Grant Edwards               grant.b.edwards        Yow! Is something VIOLENT
                                  at               going to happen to a
                              gmail.com            GARBAGE CAN?
Reply to
Grant Edwards

I write code that assumes the same thing -- but I also always confirm that the startup code does it.

One might assume that a decent compiler would place all variables that are initialized to 0 into the bss section so that explicitly initializing a variable to 0 doesn't create extra overhead. That said, we all know there are a lot of bad compilers around.

A compliant compiler should never warn about a static variable being "uninitialized" since according to the C standards all static variables are, by definition, initialized.

--
Grant Edwards               grant.b.edwards        Yow! HAIR TONICS, please!!
                                  at               
                              gmail.com
Reply to
Grant Edwards

Close, but not quite correct. Compliancy has nothing to do with that. Now, sanity, or quality of implementation, that's a totally different kettle of fish.

A compliant compiler is entitled to warn ("emit diagnostics") about whatever it bloody well pleases. A diagnostic like

Oh, puleeze! Come on, mon, you know perfectly well that 13-letter variable names are not allowed in line 5 of a source file!

can be emitted without in any way risking your compiler's compliancy level.

Reply to
Hans-Bernhard Bröker

I guess compilers do issue warnings about all sorts of "legal" things such as

if (i = foobar()) { }

That's perfectly legal, yet I do appreciate being warned about it.

I guess that's true as long as the correct code is generated.

--
Grant Edwards               grant.b.edwards        Yow! I know things about
                                  at               TROY DONAHUE that can't
                              gmail.com            even be PRINTED!!
Reply to
Grant Edwards

Indeed. :-)

The gcc Ada front end has successfully compiled a number of my Ada programs while still telling me _exactly_ why they were going to then fail at runtime.

I was sure I had seen this uninitialised warning in the distant past, but I just compiled a test C program (which didn't explictly initialise a static variable before using it) with a gcc 4.x compiler and I didn't get a warning.

However, my main reason for initialising zero valued variables in the code is that I don't like implictly assigned variables.

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Reply to
Simon Clubley

That's just crazy. :-(

Was this some attempt at vendor lock in (ie: was there a need to buy a TI approved JTAG interface device) or was there another reason ?

Simon.

--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
Reply to
Simon Clubley

les

I could not agree with your post more completely. Today I might be writing code on an elegant, well-tested compiler fully compliant with the standards of the day. Tomorrow I might want to import that sourcecode into a hellhole of a broken, buggy compiler (Microchip targets come to mind), and my best defense is to make sure that my code assumes as little as possible about the quality of the compiler.

Yeah, I know .bss ought to be zero. When I write startup code, I zero it. I have absolutely no faith in RandomCRTLibraryProviderXYZ to obey any kind of laws or best practices, so I don't rely on anyone else's implementation for this. Anyone who has ever tried to use an Atmel app note will realize that even code that comes direct from chip manufacturers is frequently of hideous quality.

Reply to
larwe

I don't know the details in this case (I haven't looked at the low-level workings of the msp430 jtag interface). But ultimately, jtag is a silly choice of interface for debugging - it's got a /huge/ overhead if you want to follow all the rules correctly. Most chips that have a jtag debugger interface have some sort of non-standard shortcut to put their jtag interface into "debug" mode rather than testpin mode. Some of these play well with other jtag devices, others only work well if they are the only device on the jtag bus. While the best idea is to have a shortcut technique that works along with other devices on the board, it's usually only the big chips that bother. When you have an FPGA or a processor in a 400 pin bga package, it is conceivable that you will also have a jtag chain for testing pin connections between that package and a bga package memory device. But I expect it is a negligible proportion of msp430 users who will want other jtag devices on the same chain.

In reality therefore, very few people will care if the interface follows jtag standards or is completely different - such as Freescale's BDM, or AVR's debugwire.

What people /do/ care about, are several other points:

The interface should be standard across the family. Different msp430 devices have slightly different jtag interface arrangements - some need hardware reset pins, others don't. Some need clock pins, others don't.

The full debug interface should be documented, and those documents available to anyone who wants them. /That/ is the big problem, and the vendor lockin mechanism. Atmel AVR's are just as bad - in both cases, you can get limited information so that you can re-program the devices over the jtag interface, but you cannot get full information about debugging them. Freescale and ARM both give full information (AFAIK).

The interface should be a straightforward synchronous serial interface transferring all data and commands in blocks of 8 bits (or multiples of

8 bits), and work well with long blocks of transfer data. In other words, it should be easy to make a cheap and fairly fast interface using devices like the FTDI2322 USB chip. As far as I know, TI's jtag interface works like that. Examples of debug interfaces that don't fit that model well are Freescale's Coldfire BDM - it uses 17-bit transfers, with one bit in the reply being a "ready/busy" bit that is supposed to pause the transfers. If you follow those rules precisely, you get a download speed of about 1K per second using an FTDI 2232 interface.

Finally, if you want to sell USB based jtag interfaces, you should be consistent about the chips used and the drivers needed. Both TI and Olimex (who make cheap TI jtag interfaces) have been a serious pain here

- they have regularly come out with new revisions of their interfaces that have no changes in functionality, but require new drivers and library files on the PC. It's stupid and unnecessary, and breaks third-party software to save a couple of cents on production - customers would not complain if the purchase price was a couple of cents more for a guarantee of backwards compatibility.

Reply to
David Brown

Good C compilers warn about using uninitialised data. But statically allocated data /is/ initialised - to zero. A complier that warns about global data being uninitialised has a broken warning system (or, like CCS, it is a broken compiler/toolchain). It is a different matter for non-static locals - they must be explicitly initialised, and it is good for the compiler to warn you about them. And in such cases, you are typically not "actively eliminating compiler warnings", you are "actively eliminating code bugs" !

Generally, I agree with you about explicit being better than implicit. I would never write code that uses the implicit "int" that exists in many places in C - to me, "long" is a description and "long int" is the type (actually, I would prefer the more explicit int32_t).

Yes, different languages have different rules - Pascal, for example, does not have implicit initialisation of data. I find it annoying that you can't give an initialisation value when declaring a variable (unless you count the truly bizarre idea of calling it a "constant" so that it can be initialised, and then using it as a variable anyway). And I appreciate the idea of writing a sort of "subset" of the languages - either unconsciously from habit (I used to put an unnecessary semicolon after closing brackets in C, after years of putting a semicolon after an "end" in Pascal) or consciously for consistency or to aid porting.

Reply to
David Brown

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.