Why arm

I got some evaluation board with uC STM32F405RG , this micro has ARM Cortext M4 core . Please find reference to the uC :

http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1035/PF252144#

I'm using also arm-none-eabi toolchain for linux from below site:

https://launchpad.net/gcc-arm-embedded

After compiling and linking some project I've noticed that linker puts extra padding bytes between mine global variables which are stored in .bss section. Please find short snippet from the map file:

 .bss.variable1
                0x20002d14       0x15 /path/to/application.o
 .bss.variable2
                0x20002d29        0x1 /path/to/application.o
 .bss.variable3
                0x20002d2a        0x1 /path/to/application.o
 .bss.variable4
                0x20002d2b        0x1 /path/to/application.o
 .bss.variable5
                0x20002d2c       0x1c /path/to/application.o
 .bss.variable6
                0x20002d48        0x1 /path/to/application.o
 *fill*         0x20002d49        0x3
 .bss.variable7
                0x20002d4c        0x4 /path/to/application.o
 .bss.variable8
                0x20002d50        0x8 /path/to/application.o
 .bss.variable9
                0x20002d58       0x1c /path/to/application.o
 .bss.variable10
                0x20002d74        0x1 /path/to/application.o

Additionally here is my linker script:

ENTRY(Reset_Handler)

MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000 + 256K, LENGTH = 1M - 256K -(3*128K)
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

_stack_size = 16K;

_estack = ORIGIN(RAM) + LENGTH(RAM);
_sstack = _estack - _stack_size;

SECTIONS
{  
  .text :
  {
    _stext = .;
    KEEP(*(.isr_vector))
    . += 8;
    *(.text)
    *(.text*)
    *(.rodata)
    *(.rodata*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;
  } >FLASH

  .ARM.extab :
  {
    *(.ARM.extab*)
    *(.gnu.linkonce.armextab.*)
  } >FLASH

  .ARM :
  {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH

  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH

  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(.fini_array*))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  _sidata = .;

  .data :
  {
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  } >RAM AT> FLASH

  . = ALIGN(4);

  .bss :
  {
    _sbss = .;
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;
    __bss_end__ = _ebss;
  } >RAM

  .stack :
  {
    . += _stack_size;
  } >RAM

  .memory_b1_text :
  {
    *(.mb1text)        /* .mb1text sections (code) */
    *(.mb1text*)       /* .mb1text* sections (code)  */
    *(.mb1rodata)      /* read-only data (constants) */
    *(.mb1rodata*)
  } >MEMORY_B1

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

Here is type declarations, they're distributed around few header files but I'm putting them here at once:

typedef enum
{
    False=0,
    True=1
} bool;

typedef enum
{
    Unknown,
    Data,
    Crc
} type3_t;

typedef struct
{
    unsigned char data[20];
    unsigned char size;
} __attribute__((packed)) type1_t;

typedef enum
{
    msg1,
    msg2,
    msg3
} msg_type_t

typedef struct
{
    uint8_t msg;
    uint32_t src;
    uint32_t dest;
} header_t;

typedef struct
{
    header_t header;
    uint8_t len;
    uint8_t id;
    uint8_t idx;
    uint8_t type;
} header2_t;

typedef struct
{
    header2_t header;
    uint8_t* data;
} ex_header_t;

typedef struct
{
    msg_type_t type;
    union
    {
        uint8_t * rawData;
        header_t header;
        ex_header_t ex_header;
    } u;
    uint8_t val;
} type5_t;

typedef struct
{
    uint32_t id;
    uint8_t idx;
    uint8_t crc[2];
} type8_t;

and application.c file, I left order like in *.c file:

static type5_t variable5;
static type5_t variable9;
static type8_t variable8;
static type3_t variable3 = Unknown;
static type1_t variable1;
static bool variable10 = False;
static unsigned char variable6 = 0;
static bool variable4;
static unsigned char variable2 = 0;
/* few function definitions here */
static void * variable7;

The question is why arm-none-eabi-ld linker is doing so? Why linker cannot put in place of padding bytes, variables which are one byte big(eg chars) ? Everything is happening in the same translation unit so I think linker should be able to sort them and utilize more RAM memory. Even if one byte (char) or two bytes variables (short) are not present in the same translation unit, why shouldn't linker take them from other *.o files ?

链接地址: http://www.djcxy.com/p/70400.html

上一篇: 未初始化的局部变量是最快的随机数生成器吗?

下一篇: 为什么要武装