Как написать простой стартовый код на C ++? - PullRequest
0 голосов
/ 29 мая 2018

Я нашел стартовый код для ядер 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() в программе?Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

Сценарий компоновщика дает указание компоновщику поместить данные во флэш-память, но связать код, как если бы данные были в оперативной памяти.В коде запуска данные затем копируются с адреса, по которому данные загружаются (флэш-память), по адресу, который должен быть (ОЗУ) данных.

0 голосов
/ 29 мая 2018

Проблема

У нас есть проблема во встроенном коде.Варианты хранения: энергонезависимое, но неизменяемое (флэш-память, ПЗУ и т. Д.) Или энергозависимое хранилище«data» - это инициализированные ненулевые произвольные значения, которые могут быть изменены (по сравнению с const или rodata).Как это можно организовать?

Копия данных помещается во флэш-память или в ПЗУ.Эти данные затем копируются в ОЗУ, где они читаются и записываются.


Мой вопрос заключается в функции copy_data (), почему нам нужно присвоить адрес __data_load указателю *ЦСИ?Is __data_load = LOADADDR (.data);такой же, как __data_start.Что делает функция copy_data () в программе?

copy_data() является решением вышеуказанной проблемы.Он забирает память из флэш-памяти (место загрузки) и копирует ее в оперативную память.Подобная дихотомия может существовать с виртуальной адресацией.Где вы должны расположить физический адрес и содержимое виртуального адреса, чтобы они были одинаковыми перед включением MMU.Документация компоновщика часто называет расположение запуска / ОЗУ «VADDR».

С помощью загрузчиков ОС или некоторых ПЗУ вы можете загрузить диск / MMC (флэш-память NAND) в ОЗУ и иметь возможность обойти copy_data().Это необходимо только в том случае, если ваш код будет работать напрямую с энергонезависимого устройства.Часто бывает проще и быстрее просто скопировать все изображение из флэш-памяти в оперативную память.Это зависит от ресурсов, конечно.Доступ для чтения из оперативной памяти часто быстрее, чем флэш.Опять же, это будет зависеть от вашей системы.

0 голосов
/ 29 мая 2018

copy_data() копирует показания памяти с начального адреса __data_load в диапазон адресов, начиная с __data_start до __data_end

Таким образом, общий скопированный размер составляет __data_end - __data_start.

Конечно, у вас уже есть данные, доступные на __data_load.Программа копирует его из FLASH в SRAM, где его можно читать и записывать столько, сколько нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...