如何在C++编写简单的启动代码?
How to write simple start up code in C++?
我在互联网上找到了 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, mspn" : "=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()
功能在程序中做什么?提前谢谢。
链接器脚本指示链接器将数据放在闪存中,但链接代码就像数据在 RAM 中一样。在启动代码中,数据从加载数据的地址(闪存(复制到数据应该在的地址(RAM(。
copy_data()
将从起始地址__data_load
的内存读取复制到从__data_start
到__data_end
的地址范围
因此,复制的总大小为__data_end
-__data_start
。
当然,您已经在__data_load
上拥有可用的数据。该程序将其从闪存复制到SRAM,在那里可以根据需要读取和写入。
问题
我们在嵌入式代码中存在问题。 存储选项是非易失性但不可修改的(闪存/ROM等(或易失性可修改的存储。 "data"是初始化的非零任意值,可以修改(相对于const
或rodata
(。 这怎么安排呢?
数据的副本被放入闪存或ROM中。 然后将此数据复制到RAM,在那里读取和写入。
我的问题是在 copy_data(( 函数中,为什么我们需要将__data_load的地址分配给指针 *src?Is __data_load = LOADADDR(.data(;与__data_start相同。copy_data(( 函数在程序中做什么?
copy_data()
是上述问题的解决方案。 它从闪存(加载位置(中获取内存并将其复制到RAM。 虚拟寻址也可以存在类似的二分法。 在启用 MMU 之前,您需要将物理地址和虚拟地址内容安排为相同。 链接器文档通常将运行/RAM 位置称为"VADDR"。
使用操作系统或某些ROM引导加载程序,您可以从磁盘/MMC(NAND闪存(加载到RAM并能够规避copy_data()
。 仅当您的代码将直接从非易失性设备运行时,才需要它。 将整个映像从闪存复制到RAM通常更快,更简单。 当然,这取决于资源。 从 RAM 读取访问通常比闪存快。 同样,这将取决于您的系统。
- 如何使用 ctypes 停止和重新启动从 Python 运行的C++代码
- 在我的以下代码中获取 MLE(内存限制错误).尝试解决 ROUND C 2019(问题 A-摆动行走)启动问题
- 为什么我在启动任务时收到成功代码,但它什么也不做?
- 如何获取代码::块以在代码::块重新启动后保持库的配置?
- 如何在C++编写简单的启动代码?
- 在GDB中:在启动程序中以代码1退出.在GDB之外运行良好
- 如何设置cmakelists.txt文件以启动和运行Xtensor-python示例代码
- QTimer timeout()方法不再在代码重组后启动
- 此代码如何启动索引为 1 的 C 样式字符串
- 从C 启动多线程Python代码
- 我是一个大的C 菜鸟,我需要帮助我的程序启动代码块
- 可以通过代码(使用 C、C++ 或 .NET)重新启动 PCIe 卡
- 如果应用程序从安装选项启动,则加载库失败,错误代码为 126
- Windows生物识别框架样本UMDF驱动程序:此设备无法启动.(代码10)
- 需要帮助启动用于C++的分析代码生成器
- 将 GDB 或 LLDB 嵌入程序C++并从代码启动调试器
- 无法在 Visual Studio 代码中启动 c++ 的调试器
- C 从内部程序代码上将应用程序添加到Linux程序上的启动中
- C# 类库 如何添加启动代码
- 设备无法启动.(代码10)umdf驱动程序开发中的错误