у вас есть ответ прямо здесь -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
BYTE
,SHORT
,LONG
иQUAD
. Вы также можете прочитать свой файл из стандартного ввода, чтобы использоватьecho
или другие методы для указания всего в командной строке. Эти операторы (BYTE, SHORT, LONG, QUAD
) в основном полезны для предоставления заголовка информация для какого-то другого системного загрузчика (может быть код SOC rom). Так что это возможно, это не лучший путь и разумнее использовать ассемблер. Вы также можете импортировать необработанные двоичные файлы. - person artless noise   schedule 02.02.2017