MSP430 - Packing Structure

From Texas Instruments Wiki
Jump to: navigation, search

This wiki describes a small guide to do structure packing on several MSP430 compilers.

CCS v5.x

The CCS v5.x comes with the compiler (Code Generation Tools) version 4.x which supports GCC extensions variable "packed" attributes. This variable attributes can be used to do structure packing.

Activating GCC Extensions Support

In order to be able to use the GCC extensions, the compiler option which is per default disabled shall be first activated. Check the "Enable support for GCC extensions" under Project->Properties->Build->MSP430 Compiler->Advanced Optons->Language Options.

Ccs v5 msp430 enable gcc extensions.PNG


Using The "packed" Variable Attributes

The following example code shows how to use the "packed" attributes to do data structure packing:

#include <msp430.h>
 
// packed struct
struct __attribute__((__packed__)) my_struct_1
{
  unsigned char port1_bits;
  unsigned int delay;
  unsigned char port2_bits;
};
 
// normal struct
struct my_struct_2
{
  unsigned char port3_bits;
  unsigned int delay;
  unsigned char port4_bits;
};
 
struct my_struct_1 my_data_1;
struct my_struct_2 my_data_2;
volatile unsigned int delay;
 
void main(void)
{
 
  // stop WDT
  WDTCTL = WDTPW + WDTHOLD;
 
  // initialize structures
  my_data_1.port1_bits = BIT0;
  my_data_1.delay = 100;
  my_data_1.port2_bits = BIT1;
 
  my_data_2.port3_bits = BIT2;
  my_data_2.delay = 200;
  my_data_2.port4_bits = BIT3;
 
  // initialize hardware using data structure
  P1DIR = my_data_1.port1_bits;
  P2DIR = my_data_1.port2_bits;
  P3DIR = my_data_2.port3_bits;
  P4DIR = my_data_2.port4_bits;
 
  while(1)
  {
    P1OUT ^= my_data_1.port1_bits;
    P2OUT ^= my_data_1.port2_bits;
    for(delay=my_data_1.delay;delay;delay--);
 
    P3OUT ^= my_data_2.port3_bits;
    P4OUT ^= my_data_2.port4_bits;
    for(delay=my_data_2.delay;delay;delay--);
  }
}

The example code above shows two type of struct definitions my_struct_1 and my_struct_2. Both structure are similar that they have two unsigned char (8 bit) fields with one unsigned int (16 bit) field in between.The only difference is that for my_struct_1 the "packed" variable attribute is used.

After compilation, the following information is generated in the map file:

GLOBAL SYMBOLS: SORTED BY Symbol Address

address    name
--------   ----
00000001   __TI_args_main
00000001   __TI_exit
00000050   __STACK_SIZE

....................

00001c00   my_data_1
00001c04   my_data_2
00001c0a   delay

....................

As can be seen above, the my_data_1 variable which has packed structure takes 4 bytes (address 0x1C00-0x1C03) which means that the structure is packed, while the my_data_2 variable takes 6 bytes (address 0x1C04-0x1C09) since it is not packed. This result shows that without the "packed" attribute like the my_struct_2, internal padding bytes will be added by the compiler.


IAR v5.50

Using the pack pragma

IAR compiler supports pack pragma which can be used to pack the structure. The following same example for IAR as the one for CCS is shown as follows:

#include <msp430.h>
 
// packed struct
#pragma pack(push, 1)
struct my_struct_1
{
  unsigned char port1_bits;
  unsigned int delay;
  unsigned char port2_bits;
};
#pragma pack(pop)
 
// normal struct
struct my_struct_2
{
  unsigned char port3_bits;
  unsigned int delay;
  unsigned char port4_bits;
};
 
struct my_struct_1 my_data_1;
struct my_struct_2 my_data_2;
volatile unsigned int delay;
 
void main(void)
{
 
  // stop WDT
  WDTCTL = WDTPW + WDTHOLD;
 
  // initialize structures
  my_data_1.port1_bits = BIT0;
  my_data_1.delay = 100;
  my_data_1.port2_bits = BIT1;
 
  my_data_2.port3_bits = BIT2;
  my_data_2.delay = 200;
  my_data_2.port4_bits = BIT3;
 
  // initialize hardware using data structure
  P1DIR = my_data_1.port1_bits;
  P2DIR = my_data_1.port2_bits;
  P3DIR = my_data_2.port3_bits;
  P4DIR = my_data_2.port4_bits;
 
  while(1)
  {
    P1OUT ^= my_data_1.port1_bits;
    P2OUT ^= my_data_1.port2_bits;
    for(delay=my_data_1.delay;delay;delay--);
 
    P3OUT ^= my_data_2.port3_bits;
    P4OUT ^= my_data_2.port4_bits;
    for(delay=my_data_2.delay;delay;delay--);
  }
}

The generated map file content:

.....................
    -------------------------------------------------------------------------
DATA16_Z
  Relative segment, address: 1C08 - 1C0B (0x4 bytes), align: 0
  Segment part 7.             Intra module refs:   main
           ENTRY                   ADDRESS         REF BY
           =====                   =======         ======
           my_data_1               1C08
    -------------------------------------------------------------------------
DATA16_Z
  Relative segment, address: 1C00 - 1C05 (0x6 bytes), align: 1
  Segment part 8.             Intra module refs:   main
           ENTRY                   ADDRESS         REF BY
           =====                   =======         ======
           my_data_2               1C00
    -------------------------------------------------------------------------
.....................