EmbeddedRelated.com
Forums

C language tools to use with MSP430 or ...

Started by Ing. Morra Antonio December 1, 2003
Jon,

> >Some compilers can *reorder* a structure to
better use 
> memory *without* 
> >a compromise in code quality.  So, for instance:
> >
> >struct { char x; int y; char z; }
> >
> >would be reordered to
> >
> >struct { char x, z; int y; }
> >
> >removing two padding bytes, but having no size increase on compiled 
> >code size.
> 
> But it cannot change it to:
> 
>   struct { char z, x; int y; }
> 
> can it?
> 
> My memory may be wrong about this.  I do believe I know that 
> padding may not be inserted at the beginning of a structure, 
> under 6.7.2.1 (13).  But is it possible to move the first 
> item from being the "first?"  The reason I ask this is:  If 
> no padding is allowed at the beginning and if it is also true 
> that the first item named in a structure declaration must 
> remain the logically first in terms of memory addressing, 
> then it follows that a pointer to the structure will compare 
> equal to a pointer to the first member of the structure, 
> suitably cast.
> 
> Just curious if you recall the chapter and verse on this.

I believe MIX C used to be able to do this.  You are, however, correct
that it is beyond the scope of the ANSI standard.  Well, MIX C was never
ANSI anyway, but it's one of those features ("extensions") that
get
bulleted as a "we do this, the competition doesn't".  Section
6.2.7.1
para 13 of the C99 standard describes allocation order for structures.

Bit OT, but in the spirit of C99, I like the restrict qualifier, but I
fear it'll be used indiscriminantly.  Electricity & water don't
mix and,
when a compiler does something the user doesn't expect, the compiler is
declared "broken".  It happens all the time--"My program compiles
and
runs correctly on hardware X with compiler Y but doesn't run on hardware
Z with your compiler!  My code is correct by example!"  A compiler that
ignores restrict will generate correct code given a restrict-broken
program, but a compiler that doesn't ignore restrict when fed with that
same program may generate code the user sees as wrong.  C'est la vie.
Give a user a sharp tool and he's bound to cut himself and blame the
tool maker.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for MSP430 and ARM processors 

Beginning Microcontrollers with the MSP430

Seems Micro$oft is on the money grab again

http://www.microsoft.com/mscorp/ip/tech/fat.asp

It seems they want to now start charging for use of their FAT file system.

Not good news...

Matthew 


"...the ANSI standard is not clear at that point..."

I disagree.  The standard >>is<< clear; it is up to the compiler.

To one of your further points:  the packing may produce slower code, 
as has been pointed out.  Someone else could crusade that packing 
makes it slower and the compiler is not providing proper value.

Two sides of the coin.

Lee
--- In msp430@msp4..., r f <nobodyo@w...> wrote:
> Hi,
> 
> > The rationale is that the ANSI standard *only* specifies bit 
packing
> > with unsigned int and signed int types,
nothing else.  
> 
> Ok, the ANSI standard is not clear at that point and does not 
specifies 
> things like little endian or IEEE 754 format or
the radix in which 
> numbers are represented but usually the same C source code is used 
on 
> PCs and MCs and therefore you usually expect that
you can 
read/write 
> data produced from a MC with a PC. From a high
price compiler like 
the 
> icc430 i do expect the same behaivior or a
warning! Why else should 
> someone pay so much money?
> 
> Maybe some other Compiler are not better at that point but the 
icc430 
> has some other bugs which are showing that he is
no ANSI compiler. 
One 
> of these bugs is than in sprintf the conversion
specifier u does 
not 
> work; the compiled code simply prints the
specifier (and the 
preceding 
> %) insted of the number although the conversion
specifier u is in 
the 
> ANSI C standard!
> As a working workaroung i use the specifier d insted of u.
> 
> I#039;m sure i would find dozens of other bugs with a compiler test 
suite.
> 
> Rolf F.


"...Some compilers can *reorder* a structure to better use memory 
*without* a compromise in code quality. ..."

... and thus violate the ANSI requirement that structure fields be 
allocated in order.

Lee

--- In msp430@msp4..., "Paul Curtis" <plc@r...> wrote:
> Jon,
> 
> I'll cut the agreed bits; Anders has covered this more than a 
little.
> Perhaps he's cursing the day he decided to
join or stop 
trolling... ;-)
> 
> 
> > >Thus, you could argue that a structure is allocated like this:
> > >
> > >struct {
> > >  TUINT8 lP;     // byte 0
> > >  TUINT8 lW;     // byte 1
> > >  TUINT8 lT;     // byte 2
> > >  TUINT16 te:5;  // bits 7-3 of byte 3
> > >  TUINT16 de:3;  // bits 2-0 of byte 3
> > >  TUINT16 ct;    // bytes 4 and 5
> > >};
> > 
> > Yes, except my query wasn't about that.  It was about 
> > aligning on even address boundaries, as in the VAX where you 
> > often found 4-byte objects aligned on 4-byte boundaries, 
> > 2-byte objects aligned on 2-byte boundaries, 8-byte objects 
> > aligned on 8-byte boundaries, and so on.  So I was wondering 
> > about the possibility that the 8 bytes arrived from:
> > 
> > >// structure assumed to always start on even addresses, as 
it's // 
> > >largest atom is a 2-byte object....
struct {
> > >  TUINT8 lP;     // byte 0         1-byte alignment rule
> > >  TUINT8 lW;     // byte 1         1-byte alignment rule
> > >  TUINT8 lT;     // byte 2         1-byte alignment rule
> > >                 // byte 3 "pad"   forced
'.even' alignment
> > >  TUINT16 te:5;  // part of byte 4..5
> > >  TUINT16 de:3;  // part of byte 4..5
> > >  TUINT16 ct;    // byte 6..7
> > >};
> > 
> > I'd considered a smaller packing, too, as you seem to be 
> > addressing... but that wasn't my question.  I was only 
> > curious if it were possible that the compiler in question was 
> > using some kind of VAX-like alignment rules and, if so, if 
> > there was logic to that.
> 
> Hmm, I thought the VAX didn't require alignment but would benefit 
from
> alignment if aligned at runtime.
> 
> > In other words, I was only trying to explain the 8-byte 
> > finding in my own mind.  Not trying to argue that it should 
> > have been 6.
> 
> Most (if not all) compilers by default allocate fields read
> top-to-bottom (lexical order) as low-to-high data in memory order.
> Anders correctly points out that a field that requires alignment may
> lead to padding if not aligned at the point it's seen.  On the 
MSP430 an
> int requires word alignment (even address).  In
the example, the int
> fields aren't word aligned hence the forced alignment and consequent
> padding bytes.  Anders also points out the possibility 
of "rounding" the
> structure by adding extra padding bytes *after*
the last member as 
the
> alignment of the structure as a whole is equal to
the maximal 
alignment
> required by any of its members.  This neatly deals
with allocating 
array
> elements correctly so their members are all
aligned correctly.
> 
> Some compilers can *reorder* a structure to better use memory 
*without*
> a compromise in code quality.  So, for instance:
> 
> struct { char x; int y; char z; }
> 
> would be reordered to
> 
> struct { char x, z; int y; }
> 
> removing two padding bytes, but having no size increase on compiled 
code
> size.
> 
> Some compilers implement packing (ahh, the infamous PACKED 
structures of
> Pascal, the bane of my life) which will reduce the
overall data 
size for
> a program by packing data and disregarding its
natural alignment
> requirement, but this forces the compiler to generate much more 
code to
> access the packed structures.  The 68020 have
BFEXTU and BFEXTS to 
do
> bitfield extraction, which helped, but many other
processors use
> shifting and masking.  The MSP430 isn't well endowed in the shift 
and
> rotate department, rather unlike the 68K.  I wish
the MSP430 had a
> barrel shifter and instructions to use it.
> 
> --
> Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
> CrossWorks for MSP430 and ARM processors


Clyde,

> On Fri, Dec 05, 2003 at 02:39:32PM -0800, Jonathan
Kirwan wrote:
> > On Fri, 5 Dec 2003 21:29:15 -0000, Paul wrote:
> > >would be reordered to
> > >
> > >struct { char x, z; int y; }
> > >
> > >removing two padding bytes, but having no size increase on 
> compiled 
> > >code size.
> > 
> > But it cannot change it to:
> > 
> >   struct { char z, x; int y; }
> > 
> > can it?
> 
> Quite right Jon, the ordering of structure members is 
> guaranteed by the standard to be the same as the lexical 
> order. Not so with scalar variables, whose memory address 
> need bear no relationship with order in the source file.

The fact remains that some compilers can reorder (MIX C); but these are
not ANSI compilers.  IAR's packed structures pretty much go against the
grain of the ANSI/ISO standard, yet are a useful addition in a
RAM-limited, FLASH-rich micro (such as the MSP430) where an app teeters
on the edge of available RAM memory.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for MSP430 and ARM processors 

microbit wrote:
> Hi Paul,
> 
> I have noticed such behaviour, but I am talking specifically
reading/writing processed
> 16/32 bit stuff from/into char based arrays, which then can be written to
another buffer
> yet again (eg. for RF transfer). 
> This is totally dynamic, and depending on the user's program input can
land in even 
> or odd addresses after tokenising.
> Once it's done it's not so bad, but the initial
"trapping" at various points in runtime
> is woeful... !  I have no other choice there, not does the compiler/linker
used.
> 
> Cheers,
> Kris
> 
> 

ASM makes life easy in these circumstances, I do it all the time, mixing 
types, and taking advantage of the ability to do this. Could you not 
handle these difficult areas in asm?

Al

>>Actually, the linker *can* know whether an
access will be to a
>>word-aligned address or not in some cases.
>>
>>Consider the absolute, symbolic, and register-offset addressing mode on
>>the stack using word addressing:
>>
>>(a) Absolute, coded as x(R0).  x must be divisible by 2 to maintain word
>>alignment of data.  The linker can check this.
>>
>>(b) Symbolic, coded as x(PC).  The PC is always word aligned, so x must
>>be divisible by two to maintain word alignment.  The linker can check
>>this.
>>
>>(c) Stack-relative, coded as x(SP).  The SP is always word aligned, so x
>>must be divisible by two to maintain word alignment.  The linker can
>>check this.
>>
>>In many cases the linker can't check for problems as it
doesn't know, at
>>any given instance, whether a register value will be aligned correctly
>>or not.
>>
>>Regards,
>>
>>--
>>Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
>>CrossWorks for MSP430 and ARM processors 
>>
>>      
>>           
>>     
>>     
>>
>>.
>>
>>
>>
>>">http://docs.yahoo.com/info/terms/ 
> 
> 
> 


Lee,

> "...Some compilers can *reorder* a structure
to better use memory 
> *without* a compromise in code quality. ..."
> 
> ... and thus violate the ANSI requirement that structure fields be 
> allocated in order.

Just to reiterate, I did not state that this behaviour was found in an
ANSI compiler.  However, an ANSI compiler might just consider a remark
or note when compiling that reordering will bring down the size of the
structure...

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for MSP430 and ARM processors 


Al wrote :

> ASM makes life easy in these circumstances, I do
it all the time, mixing
> types, and taking advantage of the ability to do this. Could you not
> handle these difficult areas in asm?

Hi Al,

Ouch !
There comes the dreaded thorn.

Strangely, no, not in _my_ particular application because I'm already
"breaching"
ISO anyway, by giving a char array datatypes that are larger (int, long,
float), thus
I'm left high and dry.
But there is simply __no other__ way around it given the byte-based token
scheme.
Storing 16/32 bits anywhere in MSP430 memory incurs this problem.

ASM will not help, *maybe* if it is painstakingly optimised to run faster
with 8 bit operations
than the C 16-bit LIB code (which will run much faster anyway, and is also
ASM hand written)

BUT, I'll go on a limb here, and volunteer that in fact the whole project
would be
slightly more RAM efficient in ASM, but it was specifically intended to be
very portable.
(where actually 60% of the work was :-)
It must be stressed though that is a very _unusual_ exception.
(the RAM savings are only 30-40 bytes though !)

So, basically this is finally "the exception to the rule", and in fact
I
will admit that if
you started the full scope of the task in ASM while I started in C,
you'd probably finish it 3 times faster than me !!
___BUT___ after that it will take me 30 seconds to land it on any 8 bit MCU,
it will take
you much longer than that on a new MCU ....

I hope I haven't started up another Pandora's box, but actually have
closed
one
vis-a-vis ASM vs. C ....
But I'm forthcoming too, and will grant you your _salient_ point Al !!!

Best regards,
Kris


On Sat, 6 Dec 2003 08:58:27 +1000, Clyde wrote:

>On Fri, Dec 05, 2003 at 02:39:32PM -0800, Jonathan
Kirwan wrote:
>> On Fri, 5 Dec 2003 21:29:15 -0000, Paul wrote:
>> >would be reordered to
>> >
>> >struct { char x, z; int y; }
>> >
>> >removing two padding bytes, but having no size increase on compiled
code
>> >size.
>> 
>> But it cannot change it to:
>> 
>>   struct { char z, x; int y; }
>> 
>> can it?
>
>Quite right Jon, the ordering of structure members is guaranteed
>by the standard to be the same as the lexical order. Not so with
>scalar variables, whose memory address need bear no relationship
>with order in the source file.

Yes, or even function parameter values which do not have to be
placed in some specific packing on the stack.  If this weren't
the case, then (granting me a little room here):

 void xy0 (int a, int b, int c) { auto int* c= &a; /* ... */ }
 void xy1 (int a, int b, int c) { auto int c= a; /* ... */ }

If the compiler chooses to implement function calls like this
with register passing, then xy0() code will need to "spill" the
'a' parameter value into the local stack frame so that an
address can be taken.  But no way will this address likely be
next to the address of 'b' which is still in a register and not
in memory at all.

Also, my reading of 6.7.2.1 (13):

  "Within a structure object, the non-bit-field members and
   the units in which bit-fields reside have addresses that
   increase in the order in which they are declared. A pointer
   to a structure object, suitably converted, points to its
   initial member (or if that member is a bit-field, then to
   the unit in which it resides), and vice versa. There may be
   unnamed padding within a structure object, but not at its
   beginning."

Says to me that a pointer to the structure also points to its
initial member, precluding the possibility of moving the first
element anywhere else.  Also, that members have addresses which
are in increasing magnitude (as regards >, I suppose) in the
order in which they were declared, adding yet another
restriction on what a compiler can do with a structure.

So all this together tells me that a structure must not start
with padding, must order the members with increasing addresses
in cases where taking an address of them is valid at all, and
that the address of the first member of a structure must also be
the address of the structure itself.  I think.

>As far as padding goes, it may be inserted anywhere
except at
>the beginning. On the msp430 it is *necessary* to word-align 
>structure members, and to pad structure sizes to even numbers
>of bytes.
>
>Trust me on this, I've been doing it for 25 years.

Just curious, and it's probably "unspecified" behavior in C, but
what happens when you cast a char* to an int* and then use it?
I'm guessing that no MSP430 compiler even attempts to deal with
this as forcing a pointer adjustment to an even address would
seem problematic and so would causing the code generator to
decide to generate byte-mode access code for accessing the
integers.  It's just left as a "bad thing to do."

It would be interesting to see if there could be a valid
combination of union and struct which could cause problems,
while at the same time having _specified_ behavior under the C
standards.  Nothing comes immediately to mind, though.

>Anyone who expects to be able to transfer data from
one
>architecture to another just by copying structures is in for
>a nasty surprise, sooner or later.

Yup.

Jon

On Fri, 5 Dec 2003 23:17:44 -0000, Paul wrote:

>Jon,
>
>> >Some compilers can *reorder* a structure to better use 
>> memory *without* 
>> >a compromise in code quality.  So, for instance:
>> >
>> >struct { char x; int y; char z; }
>> >
>> >would be reordered to
>> >
>> >struct { char x, z; int y; }
>> >
>> >removing two padding bytes, but having no size increase on compiled

>> >code size.
>> 
>> But it cannot change it to:
>> 
>>   struct { char z, x; int y; }
>> 
>> can it?
>> 
>> My memory may be wrong about this.  I do believe I know that 
>> padding may not be inserted at the beginning of a structure, 
>> under 6.7.2.1 (13).  But is it possible to move the first 
>> item from being the "first?"  The reason I ask this is:  If 
>> no padding is allowed at the beginning and if it is also true 
>> that the first item named in a structure declaration must 
>> remain the logically first in terms of memory addressing, 
>> then it follows that a pointer to the structure will compare 
>> equal to a pointer to the first member of the structure, 
>> suitably cast.
>> 
>> Just curious if you recall the chapter and verse on this.
>
>I believe MIX C used to be able to do this.  You are, however, correct
>that it is beyond the scope of the ANSI standard.  Well, MIX C was never
>ANSI anyway, but it's one of those features ("extensions")
that get
>bulleted as a "we do this, the competition doesn't".  Section
6.2.7.1
>para 13 of the C99 standard describes allocation order for structures.
>
>Bit OT, but in the spirit of C99, I like the restrict qualifier, but I
>fear it'll be used indiscriminantly.  Electricity & water
don't mix and,
>when a compiler does something the user doesn't expect, the compiler is
>declared "broken".  It happens all the time--"My program
compiles and
>runs correctly on hardware X with compiler Y but doesn't run on
hardware
>Z with your compiler!  My code is correct by example!"  A compiler that
>ignores restrict will generate correct code given a restrict-broken
>program, but a compiler that doesn't ignore restrict when fed with that
>same program may generate code the user sees as wrong.  C'est la vie.
>Give a user a sharp tool and he's bound to cut himself and blame the
>tool maker.

Well, it would be nice if you could require all your customers
to be well-trained and knowledgeable.  But then, you'd probably
not be happy with the size of your customer base.  So, if you
write for the common denominator of least skill I imagine you'll
write "blunt" tools where it's hard for your customers to hurt
themselves.

Meanwhile... do you think you could make good use of restrict on
an embedded target like the MSP430?  If so, can you provide an
example?

Jon