启动脚本不初始化全局对象

时间:2018-05-22 14:43:59

标签: stm32 cortex-m startupscript

我有一个stm32f4芯片的自定义链接描述文件,主要是工作;应用程序启动和运行,全局数组和变量被正确初始化但是全局对象不是。

我发现了一些对ctor用法的引用,而不是__init_array,但这些似乎是较老的方法。

在LD中,我添加了以下部分:

. = ALIGN(4);
.preinit_array     :
{
  PROVIDE_HIDDEN (__preinit_array_start = .);
  KEEP (*(.preinit_array*))
  PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
. = ALIGN(4);
.init_array :
{
  PROVIDE_HIDDEN (__init_array_start = .);
  KEEP (*(SORT(.init_array.*)))
  KEEP (*(.init_array*))
  PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
. = ALIGN(4);
.fini_array :
{
  PROVIDE_HIDDEN (__fini_array_start = .);
  KEEP (*(SORT(.fini_array.*)))
  KEEP (*(.fini_array*))
  PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH

和完整的启动脚本:

extern unsigned long _data_flash;
extern unsigned long _data_begin;
extern unsigned long _data_end;
extern unsigned long _bss_begin;
extern unsigned long _bss_end;
extern void (**__preinit_array_start)();
extern void (**__preinit_array_end)();
extern void (**__init_array_start)();
extern void (**__init_array_end)();


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;

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

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


  SystemInit();

  static_init();

  // starting main program
  main();

  while(1)
  {
    ; //loop forever, but we should never be there
  }
}
可能是ST的官方启动脚本正在做一些黑色(也许是专有的)魔法才能让它正常工作吗?

在使用其他编译器时,我使相同的代码正常工作,因此我在代码中排除了一个问题。

编辑: 经过一些调试我试过:

printf("preinit %32x %32x\r\n", __preinit_array_start, __preinit_array_end);
printf("init %32x %32x\r\n", __init_array_start, __init_array_end);
printf("preinit2 %32x %32x\r\n", *__preinit_array_start, *__preinit_array_end);
printf("init2 %32x %32x\r\n", *__init_array_start, *__init_array_end);

返回:

preinit 080506E9 080506E9<\r><\n>
init 080506E9 00000000<\r><\n>
preinit2 BB4FF8E9 BB4FF8E9<\r><\n>
init2 BB4FF8E9 20000418<\r><\n>

这很有意思,似乎&#34; __ init_array_end&#34;不知何故不保持

1 个答案:

答案 0 :(得分:0)

在发现__init_array_end__地址错误后,我尝试深入研究链接器脚本,并决定尝试Atollic Studio for C ++使用的变体。 (请注意,之前的链接描述文件来自st标准外设示例)

与工作链接器脚本的差异主要是.bss没有NOLOAD属性和初始化堆的不同方式,而.data设置为>RAM AT> FLASH而不是仅>RAM