Можно ли создать базовую программу загрузки/запуска сборки на чистом железе, используя только параметры командной строки GNU LD

Можно ли создать базовую программу загрузки/запуска сборки на чистом железе, используя только параметры командной строки GNU LD вместо обычного файла сценария -T для цели Cortex-M4?

Я просмотрел документацию по GNU LD и провел поиск в различных местах, включая этот сайт; однако я не нашел никакой информации, предполагающей, что исключительное использование параметров командной строки для компоновщика GNU возможно или невозможно.

Моя попытка управлять макетом объектного файла без стандартного поставщика, предоставленного *.ld scriptfile, носит чисто академический характер. Это не домашнее задание. Я не прошу никакой помощи для написания стартового ассемблерного кода. Я просто ищу окончательный ответ или дальнейшее направление ресурсов.

$ arm-none-eabi-ld bootup.o -o bootup @bootup.ld.cli.file

Образец содержимого файла bootup.ld.cli.file

--entry 0x0
--Ttext=0x0
--section-start .isr_vector=0x0
--section-start _start=0x4
--section-start .MyCode=0x8c
--Tdata=0x20000000
--Tbss=0x20000000
-M=bootup.map
--print-gc-sections

person InfinitelyManic    schedule 02.02.2017    source источник
comment
Вы можете сделать это с помощью файла компоновщика (определить данные раздела, используя данные выходного раздела с BYTE, SHORT, LONG и QUAD. Вы также можете прочитать свой файл из стандартного ввода, чтобы использовать echo или другие методы для указания всего в командной строке. Эти операторы (BYTE, SHORT, LONG, QUAD) в основном полезны для предоставления заголовка информация для какого-то другого системного загрузчика (может быть код SOC rom). Так что это возможно, это не лучший путь и разумнее использовать ассемблер. Вы также можете импортировать необработанные двоичные файлы.   -  person artless noise    schedule 02.02.2017
comment
@artlessnoise - Да, спасибо. Но в данном случае я пытаюсь избежать файла компоновщика; по крайней мере напрямую.   -  person InfinitelyManic    schedule 02.02.2017
comment
Я вижу, ваш 'bootup.ld.cli' очень похож на файл компоновщика, но технически это не так. Я думал, вы не хотите компилировать/собирать какой-либо код для создания загрузочного/исполняемого файла. Ваш заголовок ввел меня в заблуждение.   -  person artless noise    schedule 03.02.2017
comment
@artlessnoise Да, *.ld.cli содержит параметры командной строки, однако это не обычный формат файла компоновщика. Я хочу избежать использования обычного формата файла компоновщика. Я пишу код загрузки/запуска сборки ARMv7, включающий векторные таблицы, обработчики и перемещение векторных таблиц. Извините за неясный заголовок.   -  person InfinitelyManic    schedule 03.02.2017


Ответы (1)


у вас есть ответ прямо здесь -Ttext=number -Tdata=number и так далее не являются элементами сценария компоновщика gnu, они являются элементами командной строки gnu. обратите внимание на знак at в вашей командной строке.

Сценарий компоновщика gnu выглядит примерно так (хотя большинство из них значительно сложнее, даже если в этом нет необходимости).

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

Обратите внимание, что компоновщик gnu немного забавен, когда вы используете подход -Ttext=address, иногда он будет вставлять пробелы, у вас может быть несколько килобайт программы, и вместо того, чтобы просто линейно размещать его по адресу, как это должно быть, он помещает некоторые, затем заполните некоторое мертвое пространство, затем добавьте еще немного, никогда не понимал, почему, но для чрезвычайно ограниченных целей сценарий компоновщика (по сравнению с командной строкой), все остальные факторы остаются постоянными, не создает пробел в выводе.

РЕДАКТИРОВАТЬ:

so.s

.cpu cortex-m0
.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    b hang
.thumb_func
hang:   b .

flash.s

.cpu cortex-m0
.thumb

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    bl notmain
    b hang

.thumb_func
hang:   b .

.thumb_func
.globl dummy
dummy:
    bx lr

flash.ld

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

мигалка02.c

void dummy ( unsigned int );

int notmain ( void )
{
    unsigned int ra;
    for(ra=0;ra<100;ra++) dummy(ra);
    return(0);
}

Makefile

ARMGNU = arm-none-eabi

AOPS = --warn -mcpu=cortex-m0
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding  -mcpu=cortex-m0

all : blinker02.bin sols.bin socl.bin

clean:
    rm -f *.bin
    rm -f *.o
    rm -f *.elf
    rm -f *.list

so.o : so.s
    $(ARMGNU)-as $(AOPS) so.s -o so.o

flash.o : flash.s
    $(ARMGNU)-as $(AOPS) flash.s -o flash.o

blinker02.o : blinker02.c
    $(ARMGNU)-gcc $(COPS) -mthumb -c blinker02.c -o blinker02.o

blinker02.bin : flash.ld flash.o blinker02.o
    $(ARMGNU)-ld -o blinker02.elf -T flash.ld flash.o blinker02.o
    $(ARMGNU)-objdump -D blinker02.elf > blinker02.list
    $(ARMGNU)-objcopy blinker02.elf blinker02.bin -O binary

sols.bin : so.o
    $(ARMGNU)-ld -o sols.elf -T flash.ld so.o
    $(ARMGNU)-objdump -D sols.elf > sols.list
    $(ARMGNU)-objcopy sols.elf sols.bin -O binary

socl.bin : so.o
    $(ARMGNU)-ld -o socl.elf -Ttext=0x08000000 -Tbss=0x20000000 so.o
    $(ARMGNU)-objdump -D socl.elf > socl.list
    $(ARMGNU)-objcopy socl.elf socl.bin -O binary

Разница между командной строкой и файлами списка socl и sols сценария компоновщика заключается в именах

diff sols.list socl.list
2c2
< sols.elf:     file format elf32-littlearm
---
> socl.elf:     file format elf32-littlearm

Не буду утруждать себя демонстрацией разницы, которую вы можете увидеть в будущем.

Только для сборки вам не нужно беспокоиться о файлах без запуска и других параметрах командной строки (в gcc). С объектами C вы делаете. не позволяя компоновщику использовать встроенный/настроенный инструментарий (или, скажем, библиотеку C) загрузочного кода, вы должны предоставить его, если вы не усложняете скрипт компоновщика до такой степени, что вызываются определенные объектные файлы, а затем порядок объектов в командной строке имеет значение, если вы поменяете местами flash.o и blinker02.o в командной строке ld в make-файле, двоичный файл не будет работать. вы можете установить все точки входа, которые вы хотите, но они строго для загрузчика, если это голое железо, которое кажется, то точка входа бесполезна, оборудование загружается так, как оно загружается, в этом случае с нулевым адресом cortex-m - это значение для загрузки в указатель стека, адрес четыре - это адрес вектора сброса (с установленным lsbit, поскольку это машина только для большого пальца, пусть инструменты сделают это за вас, используя специальный thumb_func ассемблера gnu, чтобы указать следующую метку адрес назначения филиала).

Я разбросал cortex-m0 об одной, потому что именно из нее я взял этот код, и двух оригинальных armv4t и armv5t или, как указано в более новых документах по рукам, «все варианты большого пальца», это самый портативный набор инструкций руки для всех ядер руки. с вашим cortex-m4 вы можете избавиться от этого или, возможно, сделать его -m3 или -m4, чтобы вытащить расширения armv7-m thumb2.

так что краткий ответ

arm-none-eabi-ld -o so.elf -Ttext=0x08000000 -Tbss=0x20000000 so.o

Более чем достаточно для создания рабочих двоичных файлов, ПРЕДПОЛАГАЯ, что вам не нужен .data.

.data требует гораздо больше материала, скрипт компоновщика, более сложный бутстрап и т. д. Это или вы делаете вещь с копированием, скомпилируйте НАСТОЯЩУЮ программу для запуска только в sram (другая точка входа в стиле полноразмерной руки, но в баране базовый адрес), затем напишите специальный инструмент, чтобы взять этот двоичный файл и превратить его, скажем, в записи .word 0xabcdef в программе, которая копирует из флэш-памяти в оперативную память всю НАСТОЯЩУЮ программу, а затем разветвляется, эта программа копирования и перехода теперь является флэш-памятью только без . ни данные, ни .bss действительно не нужны и могут использовать командную строку, поэтому НАСТОЯЩАЯ оперативная память может только программироваться. И я, наверное, уже потерял тебя на этом.

Точно так же, используя командную строку, вы не можете или не должны предполагать, что .bss обнулен, ваш бутстрап тоже должен это делать. Теперь, если у вас есть .bss и нет .data, то, конечно, вы можете вслепую обнулить всю оперативную память при загрузке, прежде чем переходить к точке входа вашей программы C (я использую notmain() в обоих случаях, потому что по крайней мере один старый компилятор добавил ненужный мусор в двоичный, если он увидел функцию main(), и чтобы подчеркнуть, что обычно в функции с именем main() нет ничего волшебного.).

Сценарии компоновщика зависят от набора инструментов, поэтому нет причин ожидать, что скрипты компоновщика gnu будут перенесены на Kiel для переноса на ARM (да, я знаю, что ARM владеет Kiel, теперь имелся в виду RVCT или что-то еще) и т. д. Итак, это первый .data /.bss проблема. В идеале вы хотите, чтобы ваши инструменты выполняли работу, чтобы они знали, насколько битны .data и .bss, поэтому просто позвольте им сказать вам, как вы позволяете им сказать вам, правильно ли вы создаете скрипт компоновщика (по крайней мере, с ld), и это сложно , но он создает переменные, если хотите, которые могут определять такие вещи, как начальный адрес для .bss, конечный адрес для .bss, возможно, даже некоторую математику, чтобы вычесть их и получить длину, аналогично для .data, затем на языке ассемблера начальной загрузки вы можете обнулить памяти .bss, используя начальный адрес и длину и/или начальный адрес и конечный адрес. Для .data вам нужны два адреса, куда вы помещаете их во флэш-память (подробнее скрипт компоновщика foo) и куда они хотят попасть в оперативной памяти, а также длину, которую затем копирует загрузчик.

так что в основном, если вы напишете этот код

unsigned int x=5;
unsigned int y;

и вы используете сценарий компоновщика командной строки, нет никаких причин ожидать, что x будет равен 5 или y будет равен 0, когда вводится первая функция C, которая использует эти переменные. Если вы предполагаете, что x будет равно 5, ваша программа завершится ошибкой.

если вы сделаете это вместо

unsigned int x;
unsigned int y;
void myfun ( void )
{
   x=5;
   y=0;
}

теперь эти назначения представляют собой инструкции в .text, а не значения в .data, поэтому всегда будет работать командная строка, а не простой скрипт компоновщика или сложный и т. д.

person old_timer    schedule 02.02.2017
comment
Макет выглядит нормально при просмотре через файл карты, objdump и readelf; однако я не могу пройти мимо ResetHandler. ПК не продвигается вперед; вот почему я спрашиваю, достаточно ли подхода только из командной строки для полного и правильного макета. Я отмечу ваш ответ соответствующим образом, так как думаю, что он должен работать. - person InfinitelyManic; 02.02.2017
comment
да, я много лет строил со скриптами компоновщика и без них, основное отличие заключается в этой странности gnu ld ... - person old_timer; 02.02.2017
comment
у вас есть один объект - это язык ассемблера или вы пытаетесь полагаться на загрузку наборов инструментов? (который не будет работать без соответствующего скрипта компоновщика, который идет с ним). - person old_timer; 02.02.2017
comment
Я написал очень простой код запуска сборки, частично полученный из файлов, предоставленных поставщиком. Итак, я использую один объектный файл; который хорошо работает при использовании Code Composer Studio с обычным скриптом компоновщика поставщика (.cmd). Так что теперь я пытаюсь сделать это с LD без обычного скрипта компоновщика. - person InfinitelyManic; 02.02.2017
comment
редактирование показывает, что вам больше не понадобится ide, если вы не хотите, хотя, если это ваш единственный путь к загрузке, вам нужно что-то придумать. если это бывшая микро часть luminary (stellaris, теперь называется tiva c) то вы можете использовать lmflash вместо CCS для загрузки программы. Подождите, вы сказали cortex-m4, так это было после того, как они купили luminary micro. Так это MSP432 наверное? Мое решение немного обманчиво, я использую openocd (swd) для загрузки программ в оперативную память, а затем написал программы, которые затем могут записывать данные во флэш-память. но я не использую CCS вообще. - person old_timer; 02.02.2017
comment
Спасибо. Я внимательно изучу это. - person InfinitelyManic; 02.02.2017
comment
конечно, нет проблем. - person old_timer; 02.02.2017
comment
Целевым устройством является TI TM4C1294 Connected LaunchPad. Соединение с OpenOCD. Возможность использовать LM4Flash. Отладка с помощью GDB с использованием команды target-extended-remote:3333 и (gdb) load ‹bootfile› для прошивки программ. - person InfinitelyManic; 02.02.2017
comment
Хорошо, хорошо, просто хотел отметить, что вам не нужно использовать CCS, если вы этого не хотите, особенно если вы хотите получить больше контроля. Но вы можете потерять некоторые из их библиотек или, по крайней мере, найти и связать их и т. д. Теперь у вас больше возможностей, поскольку вы можете напрямую управлять набором инструментов. - person old_timer; 02.02.2017