数组部分为空

时间:2018-01-19 09:08:32

标签: c++ arm startup cortex-m3 linker-scripts

我为我的C ++应用程序编写了一个启动和liker脚本,在STM32F407VG上运行。

问题是我有一个结构数组,其中结构字段str始终为零,尽管初始化。结构中的其他字段已正确初始化。我无法理解我做错了什么,我猜想启动脚本中的初始化部分缺失了。

数组声明如下:

struct elem{
    uint32_t str;
    uint32_t value;
    uint32_t value2;
};

const struct elem array[]{
    {(uint32_t)(*(uint32_t*)"CM1"), 1, 1},
    {(uint32_t)(*(uint32_t*)"CM2"), 2, 2},
    {(uint32_t)(*(uint32_t*)"CM3"), 3, 3}
};

启动脚本的相关部分:

inline void static_init()
{
  for (void (**p)() = __preinit_array_start; p < __preinit_array_end; ++p)
    (*p)();

  for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
    (*p)();
}

void reset_handler(void)
{

  unsigned long *source;
  unsigned long *destination;

  // Copying data from Flash to RAM
  source = &_data_flash;
  for (destination = &_data_begin; destination < &_data_end;)
  {
      *(destination++) = *(source++);
  }

  // default zero to undefined variables
  for (destination = &_bss_begin; destination < &_bss_end;)
  {
      *(destination++) = 0;
  }

  static_init();

#ifndef __NO_SYSTEM_INIT
  SystemInit();
#endif

  // starting main program
  main();
}

和链接描述文件:

/* Entry Point */
ENTRY(reset_handler)

_estack = 0x20010000; /* end of 128K RAM */
/* Specify the memory areas */
/*
0x08000000 until 0x08010000 is reserved for BOOTLOADER! (64k)
*/
MEMORY
{
  EEPROM (rwx)    : ORIGIN = 0x08010000, LENGTH = 64K /*fake EEPROM!*/
  FLASH (rx)      : ORIGIN = 0x08020000, LENGTH = 896K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
  RAM2 (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
}

SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    __intvec_start__ = .;
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    _text = .;
      *(.text)           /* .text sections (code) */
    _text2 = .;
      *(.text*)          /* .text* sections (code) */
    _rodata = .;
      *(.rodata)         /* .rodata sections (constants, strings, etc.) */
      *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
      *(.glue_7)         /* glue arm to thumb code */
      *(.glue_7t)        /* glue thumb to arm code */
      *(.eh_frame)
    _init_data = .;
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
      _etext = .;        /* define a global symbols at end of code */
  } > 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 (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* used by the startup to initialize data */
  _data_flash = _sidata;

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _data_begin = .;
    *(.data)
    *(.data*)

    . = ALIGN(4);
    _data_end = .;
  } >RAM AT> FLASH


  .bss (NOLOAD) :
  {
      . = ALIGN(4);
      _bss_begin = .;
      __bss_start__ = _bss_begin;
      *(.bss)
      *(.bss*)
      *(COMMON)
      . = ALIGN(4);
      _bss_end = .;
      __bss_end__ = _bss_end;
  } > RAM

  stack_size = 1024;
  __stack_end__ = ORIGIN(RAM)+LENGTH(RAM);
  __stack_start__ = __stack_end__ - stack_size;

  heap_size = 0;
  __heap_end__ = __stack_start__;
  __heap_start__ = __heap_end__ - heap_size;

  . = __stack_start__;
  ._stack :
  {
      PROVIDE ( end = . );
      . = . + stack_size;
      . = . + heap_size;
      . = ALIGN(4);
  } > RAM

  _siccmram = LOADADDR(.ram2);
  .ram2 (NOLOAD) :
  {
    . = ALIGN(4);
    *(.ram2);
          *(.ram2*);
    . = ALIGN(4);
  } > RAM2 AT> FLASH

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

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

2 个答案:

答案 0 :(得分:1)

这应该有效,没有UB 但是,它依赖于endian。

#include <iostream>
#include <cstdint>
#include <cstring>

using namespace std;

struct elem {
    uint32_t str;
    uint32_t value;
    uint32_t value2;
};

uint32_t makeint(const char str[4])
{
    uint32_t val;
    memcpy( &val, str, 4 );
    return val;
}

const elem arr[] = {
    {makeint("CM1"), 1, 1},
    {makeint("CM2"), 2, 2},
    {makeint("CM3"), 3, 3}
};

int main()
{
    for (auto& e : arr)
        cout << e.str << endl;

    cout << "\ndone\n";
}

here

答案 1 :(得分:0)

您可以使用多字符文字:请参阅character_literal的(6.)。

注意单引号:

const struct elem array[]{
    {'CM1', 1, 1},
    {'CM2', 2, 2},
    {'CM3', 3, 3}
};

你可以看到gcc如何评估多字符文字:

https://gcc.gnu.org/onlinedocs/cpp/Implementation-defined-behavior.html#Implementation-defined-behavior

  

编译器一次评估一个字符的多字符字符常量,将前一个值左移每个目标字符的位数,然后在截断到宽度的新字符的位模式中一个目标角色。最终的位模式为int类型,因此无论单个字符是否有符号都是有符号的。如果常量中的字符数多于目标int中的符号,则编译器会发出警告,并忽略多余的前导字符。