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.