【发布时间】:2018-05-29 13:50:06
【问题描述】:
我在互联网上找到了 arm cortex m 内核的启动代码并使用了这些来源,但我对来源中的功能有一些疑问,在这里我粘贴了代码和此处使用的相应链接器脚本。
// very simple startup code with definition of handlers for all cortex-m cores
// location of these variables is defined in linker script
extern unsigned __data_load;
extern unsigned __data_start;
extern unsigned __data_end;
extern unsigned __bss_start;
extern unsigned __bss_end;
extern unsigned __heap_start;
extern unsigned __init_array_start;
extern unsigned __init_array_end;
extern unsigned __fini_array_start;
extern unsigned __fini_array_end;
// main application
extern void main_app();
void copy_data() {
unsigned *src = &__data_load;
unsigned *dst = &__data_start;
while (dst < &__data_end) {
*dst++ = *src++;
}
}
void zero_bss() {
unsigned *dst = &__bss_start;
while (dst < &__bss_end) {
*dst++ = 0;
}
}
void fill_heap(unsigned fill=0x55555555) {
unsigned *dst = &__heap_start;
register unsigned *msp_reg;
__asm__("mrs %0, msp\n" : "=r" (msp_reg) );
while (dst < msp_reg) {
*dst++ = fill;
}
}
void call_init_array() {
unsigned *tbl = &__init_array_start;
while (tbl < &__init_array_end) {
((void (*)())*tbl++)();
}
}
void call_fini_array() {
unsigned *tbl = &__fini_array_start;
while (tbl < &__fini_array_end) {
((void (*)())*tbl++)();
}
}
// reset handler
void RESET_handler() {
copy_data();
zero_bss();
fill_heap();
call_init_array();
// run application
main_app();
// call destructors for static instances
call_fini_array();
// stop
while (true);
}
以下是正在使用的链接器描述
SECTIONS {
. = ORIGIN(FLASH);
.text : {
KEEP(*(.stack))
KEEP(*(.vectors))
KEEP(*(.vectors*))
KEEP(*(.text))
. = ALIGN(4);
*(.text*)
. = ALIGN(4);
KEEP(*(.rodata))
*(.rodata*)
. = ALIGN(4);
} >FLASH
.init_array ALIGN(4): {
__init_array_start = .;
KEEP(*(.init_array))
__init_array_end = .;
} >FLASH
.fini_array ALIGN(4): {
__fini_array_start = .;
KEEP(*(.fini_array))
__fini_array_end = .;
} >FLASH
}
SECTIONS {
__stacktop = ORIGIN(SRAM) + LENGTH(SRAM);
__data_load = LOADADDR(.data);
. = ORIGIN(SRAM);
.data ALIGN(4) : {
__data_start = .;
*(.data)
*(.data*)
. = ALIGN(4);
__data_end = .;
} >SRAM AT >FLASH
.bss ALIGN(4) (NOLOAD) : {
__bss_start = .;
*(.bss)
*(.bss*)
. = ALIGN(4);
__bss_end = .;
*(.noinit)
*(.noinit*)
} >SRAM
. = ALIGN(4);
__heap_start = .;
}
我的问题是在copy_data() 函数中,为什么我们需要将__data_load 的地址分配给指针*src?是__data_load = LOADADDR(.data); 与__data_start 相同。 copy_data() 函数在程序中做了什么?提前致谢。
【问题讨论】:
-
顺便说一句,这看起来像 C++ 而不是 C。
void fill_heap(unsigned fill=0x55555555)不是有效的 C。while (true);也不是,因为从不包含 stdbool.h。call_init_array看起来它正在为具有静态存储持续时间的 C++ 对象执行构造函数。只有糟糕的 (P)C++ 程序员才会为 MCU 编写这样的代码:main_app(); // call destructors for static instances call_fini_array(); // stop while (true);我很确定这段代码不是由专业人士编写的。 -
使用 C(++) 引导 C(++) 是个坏主意。
-
用您的链接描述文件进行实验,到目前为止,您似乎是正确的 __data_load 和 __data_start 都在闪存中。这可能不是您想要的。有很多更简单的方法可以做到这一点(无需使用相同语言引导语言,无需引导程序的引导程序)。使用工具本身来简单地查看它们产生了什么。
-
从 C 开始作为您的第一个引导程序和链接器脚本,然后有一天如果您仍然觉得需要,尝试 C++。