Миро Самек. Построение простых систем на ARM-контроллерах с использованием инструментов GNU (перевод)
- переводы |
- Miro Samek |
- GNU |
- Bare-Metal |
- arm
Часть 3
В этой части описывается управляющий файл компоновщика GNU для простого (bare-metal) проекта на процессоре ARM. Рекомендуется прочесть "Embedded System Design on a Shoestring" by Lewin Edwards [1], а именно третью главу "Ld - GNU Linker".
3.1 Управляющий файл компоновщика
Имена секций и специальные символы управляющего файла компоновщика должны соответствовать стартовому коду, описанному в части 2 "2.1 Стартовый код". Управляющий файл не может быть универсальным, так как в нём объявляется конкретная карта распределения памяти целевого кристалла с учётом требований приложения.
Управляющий файл компоновщика, упоминаемый здесь как "blinky.ld", соответствует примеру "Blinky", мигающему четырьмя светодиодами отладочной платы AT91SAM7S-EK. Версия для языка "Си" располагается в каталоге "c_blinky", а для языка C++ - в каталоге "cpp_blinky".
-
Листинг 3.1 Управляющий файл компоновщика для учебного проекта "Blinky" (AT91SAM7S64) (1) OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") (2) OUTPUT_ARCH(arm) (3) ENTRY(_vectors) (4) MEMORY { /* memory map of AT91SAM7S64 */ (5) ROM (rx) : ORIGIN = 0x00100000, LENGTH = 64k (6) RAM (rwx) : ORIGIN = 0x00200000, LENGTH = 16k } /* The sizes of the stacks used by the application. */ (7) C_STACK_SIZE = 512; IRQ_STACK_SIZE = 0; FIQ_STACK_SIZE = 0; SVC_STACK_SIZE = 0; ABT_STACK_SIZE = 0; UND_STACK_SIZE = 0; /* The size of the heap used by the application. */ HEAP_SIZE = 0; (8) SECTIONS { (9) .reset : { /* startup code (ARM vectors and reset handler) */ (10) *startup.o (.text) (11) . = ALIGN(0x4); (12) } >ROM (13) .ramvect : { /* used for vectors remapped to RAM */ __ram_start = .; (14) . = 0x40; (15) } >RAM (16) .fastcode : { (17) __fastcode_load = LOADADDR (.fastcode); (18) __fastcode_start = .; (19) *(.glue_7t) *(.glue_7) *isr.o (.text.*) (20) *(.text.fastcode) (21) *(.text.Blinky_dispatch) (22) /* add other modules here ... */ . = ALIGN (4); __fastcode_end = .; (23) } >RAM AT>ROM (24) .text : { . = ALIGN(4); *(.text) /* code) */ *(.text*) /* code) */ (27) *(.rodata) /* constants, strings, etc. */ *(.rodata*) /* constants, strings, etc. */ (25) *(.glue_7) /* NOTE: placed already in .fastcode */ *(.glue_7t) /* NOTE: placed already in .fastcode */ KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* global symbol at end of code */ (28) } >ROM (26) .preinit_array : { ... .init_array : { ... .fini_array : { ... } >ROM (30) .data : { __data_load = LOADADDR (.data); __data_start = .; *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; (31) } >RAM AT>ROM (32) .bss : { __bss_start__ = . ; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = .; (33) } >RAM (37) PROVIDE ( end = _ebss ); PROVIDE ( _end = _ebss ); PROVIDE ( __end__ = _ebss ); .heap : { __heap_start__ = . ; . = . + HEAP_SIZE; . = ALIGN(4); __heap_end__ = . ; } >RAM (34) .stack : { __stack_start__ = . ; . += IRQ_STACK_SIZE; . = ALIGN (4); __irq_stack_top__ = . ; . += FIQ_STACK_SIZE; ... ... . += C_STACK_SIZE; . = ALIGN (4); (35) __c_stack_top__ = . ; __stack_end__ = .; (36) } >RAM /* Remove information from the standard libraries */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } }
Выше представлен управляющий файл компоновщика для примера "Blinky". Небольшие отличия версий файла для "Си" и C++ будут объснены позднее. Ниже отмечаются основные особенности.
(1) Директива "OUTPUT_FORMAT" объявляет формат выходного файла (elf32, little-endian, ARM).
(2) Директива "OUTPUT_ARCH" объявляет архитектуру целевой машины.
(3) "ENTRY" указывает конкретную инструкцию [метку] с которой начинается исполняемый код программы.
(4) "MEMORY" описывает размер и расположение блоков памяти целевого контроллера.
(5) Область "ROM" соответствует флэш-памяти кристалла AT91SAM7S64. Она может включать секции "только для чтения" и исполняемые секции (rx), начинается с адреса 0x00100000 и имеет размер 64KB.
(6) Область "RAM" соответствует статической памяти кристалла AT91SAM7S64. Она может включать секции "только для чтения", секции для "чтения-записи" и исполняемые секции (rwx), начинается по адресу 0x00200000 и имеет размер 16KB.
(7) Данные идентификаторы объявляют размеры стеков, которые следует подогнать под требования конкретного приложения. "C-stack" не может иметь нулевой размер.
(8) Команда "SECTIONS" предваряет объявление секций.
(9) Секция ".reset" содержит стартовый код (включая таблицу векторов ARM) и должна быть первой в программной памяти (области ROM).
(10) Данная строка относит к секции ".reset" содержимое всех секций ".text" из файла "startup.o".
(11) Секция должна быть выровнена по границе слова (4 байта).
(12) Секция относится к области "ROM", определённой командой "MEMORY".
(13) Секция ".ramvect" содержит таблицу векторов в оперативной памяти и вторичную таблицу адресов переходов и должна быть первой в оперативной памяти (области RAM).
(14) Размер таблицы векторов и вторичнай таблицы адресов переходов известен - 0x40 байт. Данной инструкцией счётчик адресов секции увеличивается на 0x40 байт, резервируя место под таблицы.
(15) Секция ".ramvect" относится к области "RAM", определённой командой "MEMORY".
(16) Секция ".fastcode" предназначена для кода, исполняемого из оперативной памяти. Располагается он в программной памяти ("ROM"), откуда впоследствии копируется в оперативную память ("RAM"), где и исполняется.
(17) В секции ".fastcode" адрес расположения (load memory address - LMA) отличается от рабочего адреса (virtual memory address - VMA). Идентификатор "__fastcode_load" соответствует LMA в области "ROM" и требуется для стартового кода при копировании секции из программной памяти в оперативную.
(18) Идентификатор "__fastcode_start" соответствует рабочему адресу (VMA) секции ".fastcode" и нужен стартовому коду при копировании секции из программной памяти в оперативную [в данном примере секция ".fastcode" будет находиться в оперативной памяти сразу после обеих таблиц векторов].
(19) Секции ".glue_7t" и ".glue_7" автоматически создаются компилятором когда в коде объявляется переход между наборами машинных инструкций "ARM" и "THUMB". Секции содержат декоративные вызовы между кодом "THUMB" и "ARM" и вызываются при каждом переключении между наборами инструкций. В большинстве случаев выгодно располагать эти маленькие участки "горячего" кода в оперативной памяти.
(20) Код конкретных C/C++ функций явным образом располагается в секции ".text.fastcode" с помощью директивы "__attribute__ ((section (".text.fastcode")))".
(21) Компилятор GNU может располагать каждую функцию в индивидуальной кодовой секции с названием, получаемым добавлением имени функции к имени секции (требуется указать опцию компилятора "-ffunction-sections"). Это позволяет избирательно подходить к расположению кода каждой функции (расположить, например, "Blinky_dispatch()" в оперативной памяти).
Примечание. Компилятор C++ проводит декорирование имён (name-mangling) и для выяснения идентификатора, присвоенного конкретной функции, следует заглянуть в "map"-файл. (Скажем, метод "Blinky::shift()" располагается в секции ".text._ZN6Blinky5shiftEv").
(22) Возможно, в процессе настройки понадобится переместить в оперативную память и другие функции.
(23) Рабочий адрес секции ".fastcode" находится в оперативной памяти, но размещается она в области "ROM".
(24) Секция ".text" предназначена для кода и данных "только для чтения", остающихся на своём месте (в области "ROM"). [адрес размещения (LMA) и рабочий адрес (VMA) совпадают]
(25) При повторном объявлении о размещении кода, уже упомянутого в другой секции (скажем, в ".fastcode"), первое [в порядке появления] объявление имеет преимущество. Но если впоследствии будет решено убрать объявление о размещении из первой секции (здесь - ".fastcode"), заработает второе объявление.
(26) Данные секции создаются компилятором GNU C++ и используются для статических конструкторов и деструкторов.
(27) Секция ".rodata" используется для констант (данных "только для чтения") таких, как таблицы. Так же, как и для кода, для часто используемых констант можно выбирать расположение в оперативной памяти, помещая их в секцию ".fastcode".
(28) Секция ".text" находится и загружается в область "ROM".
(29) [отсутствует] Секция ".ARM.exidx" используется для обработки исключений языка C++ и показана здесь для полноты картины. Простые (Bare-metal) проекты не могут позволить себе избыточный код таких обработчиков.
(30) Секция ".data" содержит инициализированные данные.
(31) Секция ".data" должна находиться в оперативной памяти и копируется из области размещения в "ROM" по рабочему адресу на этапе начальной загрузки.
(32) Секция ".bss" содержит область неинициализированных данных. Стандарты C/C++ требуют, чтобы данная секция была обнулена перед использованием.
(33) Секция ".bss" размещается только в оперативной памяти.
(34) В секции ".stack" располагаются все стеки. На этапе начальной загрузки эта секция заполняется специальным значением.
(35) Инструменты GNU учитывают, что архитектура ARM использует модель стека, растущего к младшим адресам памяти. Поэтому файл компоновщика указывает только адреса верхушек стеков при их инициализации. "Си"-стек (он же стек SYS) располагается в конце секции ".stack".
(36) Секция ".stack" размещается в оперативной памяти.
(37) Идентификаторы "_end", "__end" и "end" используются для указания на начало динамической области памяти, если таковая используется.
(38) [отсутствует] Эта и последующие секции используются отладчиком и не загружаются в целевой контроллер.
- блог пользователя teap0t
- 158026 просмотров
Новые записи в блогах
- Устранение дребезга контактов на основе вертикальных счетчиков
- Диагностика Imprecise Bus Faults в микроконтроллерах Cortex-M3/M4/M4F
- Self-powered камера
- Фоновый модулятор: беспроводная связь из ничего (перевод)
- Texas Instruments Analog Applications Journal SLYT612 "Снижение искажений в аналоговых КМОП ключах" (перевод)
- USB MSD. Часть 6. Команды SCSI (перевод)
- USB MSD. Часть 3. USB класс накопителей данных (перевод)
- Texas Instruments Application Report SBAA042 "Кодовые схемы, используемые в аналогово-цифровых преобразователях" (перевод)
- 10 принципов правильного интерфейса
- Релиз SDK на русский микропроцессор КРОЛИК
Recent comments
12 часов 25 минут назад
1 день 13 часов назад
2 дня 7 часов назад
2 дня 13 часов назад
2 дня 19 часов назад
3 дня 20 часов назад
4 дня 15 часов назад
5 дней 10 часов назад
1 неделя 1 день назад
1 неделя 1 день назад