c++ - 如何用C++编写简单的启动代码?

标签 c++ arm startup

我在互联网上找到了 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() 函数在程序中做什么?提前致谢。

最佳答案

链接器脚本指示链接器将数据放置在闪存中,但链接代码就像数据位于 RAM 中一样。在启动代码中,数据从加载数据的地址(闪存)复制到数据应该位于的地址(RAM)。

关于c++ - 如何用C++编写简单的启动代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50586050/

相关文章:

c++ - GCC __attribute__((constructor)) 在对象构造函数之前被调用

linux - cups arm交叉编译错误: unknown type name ‘gss_OID’

assembly - MIPS 和 ARM 数据路径之间的区别

raspberry-pi - ARM 处理器如何使用超过 4GB 的内存?

mysql - Centos启动时不自动启动MySql

performance - Entity Framework 启动时间

python - C-contiguous fashion在caffe blob存储中意味着什么?

带链表的 C++ 泛型容器

c++ - 在 cv::Mat 和 Eigen::Matrix 之间转换矩阵

linux - MongoDB 服务无法在 Linux 上的不同用户下启动