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.

Structure Alignment



I need a way to align a structure with CCSv4; I'm performing a large code port with structure that have been defined using a place holder that will allow me to byte align on the structure. For example,

typedef struct {

unsigned int a;

char b;

} BYTE_ALIGNMENT_PLACE_HOLDER my_struct_t;

where BYTE_ALIGNMENT_PLACE_HOLDER can be defined based on the specfic platform/compiler used.

DATA_ALIGN appears to work only on the variable instance of the structure; is there another command or a simple #pragma that can be used, rather than having to update 100's of files that use the structures?

-meb

  • David,

    The short answer to your question is no, you cannot get the C compiler in code composer to accomplish what you want to do.  The long answer is yes it is possible but you have to be willing to move to C++.  Explanation follows...

    Every compiler (or implementation in the terms of the C99 standard) is required to document its implementation of the C standard.  This is because there are several  (many) freedoms identified by the standard which are left to the implementation to choose how to implement.  For CCS, these are documents named "<processor family> C/C++ Optimizing Compiler Guide" and in this case the MSP430 C/C++ Optimizing Compiler Guide can be found here http://focus.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=slau132e&fileType=pdf.

    Section 5.9.4 of this document explains the DATA_ALIGN pragma and it states that the alignment will be...

    "The alignment boundary is the maximum of the symbol's default alighment value or the value of the constant in bytes."

    and in section 6.2.1 gives the default alighment for an unsigned int to be "aligned to 16 bit (word) boundary".  Thus, the default alignment is on even byte addresses and that is greater than the value of 1 you may supply to the DATA_ALIGN pragma so the alignment defaults to 2 as a minimum.

    The choice for this is mainly because the MSP430 processor does not seperate word accesses that cross word boundaries into multiple accesses (i.e. like the ARM can).  Thus if you make a word access to an odd memory address, the second half of the word comes from the previous address instead of the following address.  For example, I created the following code

    Thus, t0 and t1 read words out of the array with t0 reading the word aligned value and t1 reading the byte aligned value (we know that test starts on a word boundary as it is on the stack and the stack is forced to word aligned values).  The transfer of t0 and t1 to t3 and t4 merely forces the compiler to do the accesses and make them available to the debugger.

    The generated code is

    The code at address 812A loads from an address that is an even number of bytes offset from the stack pointer so we know this is a word address as we expected.  The code at address 8130 loads an address that is an odd number of bytes offset from the stack pointer so we know this is not a word address, again as we expected.  However, take a look at what the cpu loaded into the respective variables

    Since the MSP430 stores variables in little endian format, the value read into t0 is correct as 0x00 was in the addressed byte and 0xAA was in the  following byte.  However, the value loaded into t1 should have been 0x55AA but it is the same as that of t0.  This is because the MSP430 forces the LSB of an adddress to zero for word accesses so the attempt to read a word starting at address 0x2BF5 resulted in a word read of address 0x2BF4 which is the same address that was used to load t0.

    Now it is true that the word starting at 0x2BF5 could be read using two byte reads with proper shifting and such, the reason the compiler writers didn't provide for this is because it cannot be managed without dynamically looking at every pointer access.  This would cause very poor performance code not to mention the nightmare of trying to optimize the valid accesses to simple word accesses.  So the compiler writers simply require you to work within reasonable limits of the underlying architecture.

    This is one of those hard lessons when writing code.  You have to choose when you write it if you may ever need to port it and if so, to what type of machine you might port it to.

    All is not lost though, you could write a class in C++ to access non-word aligned words using byte accesses, overload all of the operators, provide appropriate conversion operators and then use this class type as your 16bit words within your structure.  As long as the only data member of your class is the array of chars, you can align it on a byte boundary.  It's not a difficult as it sounds but if your not familiar with C++, it may be faster to change your existing code.

    Note that if you do this, you will probably have to compile all of your project as C++ in order to get the class to take in all the files it is accessed from.  You could possibly only compile a couple of files as C++ but you will need to create linkage specifications for all of your header files that compile in both C and C++ formats.  Although C++ is considered a superset of C, not all constructs are compatible (such as the value 0 being promoted to void* type in pointer assignments, most pragmas also change in form slightly) so you may need to tweek your code in a couple of places with casts to compile without warnings and errors.  Shouldn't be too difficult though.

    Jim

     

  • I had a similar problem when doing our projects:

    I was using structs which were to be sent in a binary stream through RF to an access point. The amount of data had to be as small as possible. So some of the structs weren't even-sized. This meant that the beginning of a struct inside the received data stream/pachakge was not aloigned too. It caused me some grey hairs since the geenrated binary code was 100% correct.

    Normally, the mspgcc compiler automatically does pdata padding inside and at the end of a struct, so the size of the struct is even as well as the offset ot any non-byte-sized member inside the struct. Since the structs had to be small (no size padding) and its content was historically non-optimized (backwards compatibility to older devices based on PIC and the access point base on ATMega, which does not do 16bit data access anyway, except for data access from code flash, which is implicitely 16bit), I 'packed' the structs (using GCCs __packed attribute) and ran into trouble.

    It was a tiny sentence in the mspgcc documentation that brought me on the right track: 'in instructions with word access, the LSB of the address is silently ignored by the MSP"
    So the MSP effectively applies an implicit & 0xFFFE to the address before reading the word value.

    In newer versions of the mspgcc, the compiler did not generate word access to struct members if the struct had been packed or its address was given through a pointer parameter not known at compile-time. So the issue was solved at the cost of additional execution time and code even IF the struct were aligned (but the pointer to the struct passed as parameter to a function)

    Since I had to resolve this before the compielr was patched, I reorganized m structs so they only contained byte-sized members. All ints or longs (or 64bit long longs) were defined as arrays of unsigned char. I then created a set of macros which put the values together from the array elements or split the values when writing to the struct.

    It's only marginally slower (if at all, the compiler does good optimization where possible) and has an additional advantage: I don't have to care for little or big endianess on the source and target systems. Sicne the macros read and write the data always in the same order on both sides of the conection, any conversion between the two 'variants' of storing data >1 byte is implicitely resolved during the read/write. It allowed me  to use the same source files for structure definition as well as data access for different systems without caring for the native byte order.

  • Thanks to you (and Jim N.) for your thorough responses.  We are in the middle of a code-port project, from an older, no longer supported compilier to the CCSv4 IDE.  It looks like we have some code mods to make . . .

     

     

**Attention** This is a public forum