启动脚本不初始化全局对象
startup script does not initialize global object
我有一个用于 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);
那 return:
preinit 080506E9 080506E9<\r><\n>
init 080506E9 00000000<\r><\n>
preinit2 BB4FF8E9 BB4FF8E9<\r><\n>
init2 BB4FF8E9 20000418<\r><\n>
这很有趣,似乎“__init_array_end”不知何故不正确
在发现 __init_array_end__
地址错误后,我尝试深入查看链接器脚本,并决定尝试使用 Atollic Studio for C++ 的变体。 (请注意之前的链接描述文件取自 st 标准外设示例)
与工作链接描述文件的区别主要是 .bss
没有 NOLOAD
属性和不同的初始化堆的方法,.data
设置为 >RAM AT> FLASH
只有 >RAM
我有一个用于 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);
那 return:
preinit 080506E9 080506E9<\r><\n>
init 080506E9 00000000<\r><\n>
preinit2 BB4FF8E9 BB4FF8E9<\r><\n>
init2 BB4FF8E9 20000418<\r><\n>
这很有趣,似乎“__init_array_end”不知何故不正确
在发现 __init_array_end__
地址错误后,我尝试深入查看链接器脚本,并决定尝试使用 Atollic Studio for C++ 的变体。 (请注意之前的链接描述文件取自 st 标准外设示例)
与工作链接描述文件的区别主要是 .bss
没有 NOLOAD
属性和不同的初始化堆的方法,.data
设置为 >RAM AT> FLASH
只有 >RAM