Indeed, one of the least recognized senctences somewhere in the MSPGCC 
documentation is that  the LSB on word access commands 'is silently ignored' by 
the processor. Which leads to a read or write access 
one address LESS than expected (possibly overwriting a length counter or such 
right before the misaligned data/array/struct)

While this makes the MSP cpu extremely fast compared to the clock frequency, it 
makes (in conjunction with low RAM ressources) complex data handling a pain in 
the ass.

We have several machines with different processor types (MSP, ATMega, x86-PC) 
exchanging measurement data. The data is transmitted by network, radio, RS485 
and it needs to be as short as possible. Padding 
any byte value in a datagram to word size would be a waste of space and 
decrease throughput extremely. We put a datagram together by a datagram header 
and several chunks of data with its own header and 
different data size.
All this is lined-up into a bytestream. I ended up defining everything as 
either char or array of char. Each word or long (or long long) datafield in the 
package is just treated as an array of char and written to and 
extracted by macros.
This might be slow but has severtal advantages: 
first, it makes no difference whether the machine is little- or big-endian, the 
data is always the same (the extraction macro handles the endianess 
automatically)
then any data structure will not encounter any padding and may reside anywhere 
in RAM where it fits.
And it allows nice handling of header/payload structs just by simple pointer 
arithmetic. And not only the data inside the struct, even the structs 
themselves may be misaligned without problems.

e.g.:

#define PACKED __attribute__ ((__packed__)) // maybe required by some compilers 
to pack structs

typedef struct Frame{
  unsigned char  src;                      // sender of this VFrame (required 
for bounce detection)
  unsigned char  len;                      // size of the payload
  unsigned char  crc[2];                   // crc16 of payload (not including 
this header)
  unsigned char  pld[0];                   // start of payload (offset to array 
of variable size VPacks
} Frame PACKED;

// VISTAGON Pakettyp
typedef struct Pack{
        unsigned char dst;                       // final recipient of this 
VPack
        unsigned char src;                       // Origin of this VPack
        unsigned char len;                       // Size of payload (NOT 
including this header)
        unsigned char pc;                        // internal (origin) packet 
number (for detecting packet loss)
        unsigned char cmd;                       // command defining the packet 
type of the payload (may be more than one payload packet of same type)
        unsigned char pld[0];                    // start of payload (offset)
}Pack PACKED;


so the start address of the first Pack in the frame is Frame.pld, the start of 
the data in the first pack is Frame.pld.pld, the start of the next Pack is 
Frame.pld+Frame.pld.len (which can be casted to Pack) and the data 
itself can be casted to any struct you need (or array of structs), based on 
Frame.pld.cmd.

It's important to pack the structs, so the compiler won't padd them to an even 
total size. If you only have 256 bytes, every byte counts and there is no space 
for 'unpacking' the streamed data into aligned structs.

All the time-critical stuff is of course done using 'real' ints, aligned and 
fast.

JMGross

----- Ursprüngliche Nachricht -----
Von: Roberto Padovani
An: GCC for MSP430 - http://mspgcc.sf.net
Gesendet am: 24 Jul 2009 08:46:27
Betreff: Re: [Mspgcc-users] ... iomacros.h, -fpack-struct

In packing the structure, just beware of ALWAYS aligning a word
variable to an even address, otherwise you'll end up in a mess.
As a matter of fact, if you call a word instruction (like mov.w) with
a word argument aligned at an odd address, the msp430 will zero out
the most significant byte of the word.


Reply via email to