JZ2440 развитие голой платы практика # 6 компоновщик сценария и перемещение

На полный контроль SDRAM, SDRAM и теперь мы можем читать и писать, поэтому содержание кода , чтобы сделать что - то с SDRAM перебазирования. Некоторое содержание было https://blog.csdn.net/G_METHOD/article/details/104508545 упомянуто в переезде , что, почему следует различать переезды, а также компоновщик скрипт , используемый для адреса, так здесь будет проще описанием.

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

Как правило , включают в себя репликацию перемещаемых сегментов и очистить секцию ПБСА, ПБС секция не глобальное переменное начальное значение 0 или начальное значение сбора переменных, а не как присутствие ПБСА секции сегмента данных сохраняют бункер размера файла. И делать ссылки навигации для перемещения является сценарием, такими как адрес источника, адрес назначения и поэтому может быть задан сценарием компоновщика, сценарий может сделать в то время как расположение отображения ссылки памяти, положение и взаимное расположение произвольного сегмента соглашений распределения памяти, в результате чего Я надеюсь , что их собственный пустой, компоновщик скрипт специфичны и подробное содержание можно прочитать http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#IDX237 , может быть более четкое понимание и использовать скрипт компоновщика, чтобы поговорить об оптимизации основной части.

SECTIONS {
...
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
  { contents } >region :phdr =fill
...
}

Это ядро, где мы используем для ссылки на сценарий, РАЗДЕЛЫ фиксированного формата, ссылка скрипт должен иметь не более одного, и только мы можем организовать в SECTION сегмент отображения памяти. secname это имя сегмента, как правило, .data, .text, .rodata, .bss и т.д., имя сегмента должен быть признан линкера. Заполните начальный адрес нашей желаемой программы работает, и если не указано иное, порядок и продолжительность прессовой части, непосредственно предшествовавшие дано. BLOCK (выравнивание) мы можем установить только абсолютно нормальную работу на начальный адрес сегмента адреса выравнивается, таким образом, чтобы обеспечить программу, после того, как выравнивание текста не является единственным способом это будет сказано по-другому. NOLOAD указывает, что сегмент в исполняемый файл, прочитать эльф может просмотреть сегмент, но не загружается в память, когда программа работает, потому что мы голые процедуры на борту судна, который загружается по адресу места хранения, и, следовательно, не сказать, что это нагрузка концепция, лично думаю, что загружается только для эльфа прикладного уровня. Обратите внимание, что: AT, перед AT: обе стороны должны иметь место. адрес нагрузки при (ldadr) инструкции программы, в файле бен, эта функция может быть использована для управления размером бункера, например, текста и данных и ПБС расположены следующее место, но каждый раз, когда перемещение адрес соответствующего выполнения, Если же начальный адрес не указан AT (ldadr) адрес, адрес загрузки по умолчанию и запустить. содержание нашей свободы организации местного содержания в рамках того же пункта заказа. А за область из-за PHDR и заполнить неиспользуемый здесь не вдаваться в подробности, там подробно описано в вышеописанном втором месте связанного документа.

Пример JZ2440 вывод ссылка на следующий сценарий, начальный адрес в SDRAM 0x30000000, который был использован в качестве исходного адреса, используемого здесь. Символ, символ, указывающий текущего адрес позиции, доступна только в секции, будет использоваться в качестве правильного значения текущее назначение адреса переменной, как в следующей ссылке скрипт __copy_start = .. При использовании в качестве левого значения используется для указания текущего адреса, назначение следует отметить, что операции, связанные с необходимостью добавления, конечный символ. Algin (4) представляет собой 4-байтный адрес выровненный с, так как рычаг 4 байта опорного значения декодирования шаг выполнения, если адрес не выровнен 4 байта, принудительное выравнивание, если мы не выравнивают, может произойти 0x3002 сегмент данных в это время необходимости писать область данных выравнивается непосредственно выполнить назначение адресов 0x3000, 0x3000 случай, если адрес действительный код будет перезаписывать, программа вызывает неполадки в работе, поэтому страхование причины, должны быть приведены в соответствие с каждым сегментом.

linker.lds
-------------------------
SECTIONS{
	. = 0x30000000;
	. = ALIGN(4);
	
	_copy_start = .;
	.text : { *(.text) }
	
	. = ALIGN(4);
	.rodata :{ *(.rodata) }
	
	. = ALIGN(4);
	.data : { *(.data) }
	
	. = ALIGN(4);
	_copy_end = .; 
	
	_bss_start = . ;
	.bss : {
		*(.bss)
		*(.COMMON)
	}
	_bss_end = .;
}

Содержание часть линкера сценарий, описывающий то, что мы будем размещать в сегменте, шаблон * для всех файлов, здесь реализация Л.Д. -T linker.lds xxx.o yyy.o указания целевого файла, каждый из целевого файла в памяти порядок указанного объекта выполняется в порядке положения и Л.Д., и, если это оговорено способом, описанным выше, то порядок xxx.o yyy.o, конечно, для того, чтобы указать целевой содержимое файла, например, мы должны начать. S файл запуска помещается перед другими файлами, так что вы можете

.text : { Start.o(.text) *(.text) }

Разделенные промежуточных пространств.

Здесь переезды относятся к примерной репликации сегмента программы и ПБС сегменты очищены, соответствующие переменным, определенные в положении, соответствующий сегмент для переориентации программы. Нужно сказать, что переменные, определенные в УЧАСТКАХ, нет никаких признаков ценности присутствует в эльфе в таблице символов, расширить его, глобальные переменные и функции сохраняются в таблице символов, таблица символов, соответствующий символу есть соответствующий адрес, адрес адрес указывает на область начальное значение переменной, ситуация является функцией более сложного здесь не расширяется, а переменная ссылка скрипты, хранящиеся здесь, но и соответствующий адрес, но нет никакого значения, то соответствующий адрес значение переменных компоновщик сценариев, Поэтому мы должны использовать в качестве символа для внешнего использования, но его только взять адрес, как показано ниже, с использованием 32-битный типом указателя адреса, указывающего на соответствующие операции может быть завершен быстро на этом этапе (для программного обеспечения и аппаратные возможности уровней, определенных ).

extern uint32_t _bss_start;
uint32_t *target_start_address = &_bss_start;

Детальное знание таблицы символов и линкер сценарий переменных и , как использовать C переменном языка сценариев ссылки можно просматривать https://sourceware.org/ml/binutils/2007-07/msg00154.html , на основании вышеизложенного, выходной код следующим образом :

Start.S
----------------
.text
.global _start

_start:
	MOV R0,#0
	LDR R1,[R0]
	
	STR R0,[R0]
	LDR R2,[R0]
	
	CMP R2,R0
	LDR SP,=0x40000000+4096
	MOVEQ SP,#4096
	STREQ R1,[R0]
	
	bl HardwareInitAll          //相对跳转
	ldr pc,=main                //绝对跳转,到SDRAM上运行
halt:
    b halt
s3c2440.c
------------------------
#include "s3c2440.h"

....

static void CopySegmentForReloacte(void)
{
	extern uint32_t _copy_start,_copy_end;
	uint32_t *source_start = 0;
	uint32_t *target_start = &_copy_start;
	uint32_t *target_end = &_copy_end;

	while(target_start <= target_end)
	{
		*target_start++ = *source_start++;
	}
}

static void CleanBssSegment(void)
{
	extern uint32_t _bss_start,_bss_end;
	uint32_t *target_start_address = &_bss_start;
	uint32_t *target_end = &_bss_end;

	while(target_start_address <= target_end)
	{
		*target_start_address++ = 0;
	}
}


void HardwareInitAll(void)
{
	WatchDogDisable();
	ClockDevideConfig();
	ChangeModeToAsynchronous();
	MPLLConfig();
	MemoryControllerInit();
	CopySegmentForReloacte();
	CleanBssSegment();
}

main.c
------
#include <stdint.h>

#include "s3c2440.h"
#include "led.h"
#include "uart.h"

char test_char = 'A';

int main()
{
	UartInit();

	while(1)
	{
		putc(test_char);
		if(++test_char > 'Z') { test_char = 'A'; }
		Delay(1000);
	}
	return 0;
}

Makefile, используйте опцию -t, чтобы указать скрипт линкера следующим образом

al:
        arm-linux-gcc -o Start.o -c Start.S
        arm-linux-gcc -o main.o -c main.c
        arm-linux-gcc -o s3c2440.o -c s3c2440.c
        arm-linux-gcc -o uart.o -c uart.c
        arm-linux-gcc -o led.o -c led.c
        arm-linux-gcc -o key.o -c key.c
        arm-linux-ld -T linker.lds -o led.elf Start.o s3c2440.o led.o key.o uart.o main.o
        arm-linux-objcopy -O binary -S led.elf led.bin
        arm-linux-objdump -D led.elf > led.dis

clean:
        rm *.dis *.o *.bin *.elf

Запись в Norflash скомпилированного, если нормальный последовательный вывод последовательно АЗ т.е. успешное перемещение.

Бл Start.S относительного переход к функции инициализации инициализирует и репозиционирование, поскольку эффективные данные инструкции перед операцией перемещения не являются исполняемыми, если адрес не завершен, выполнение программы прыжков относительно интеллигентного на Norflash, когда программа переселения то есть, после того, как во время выполнения адреса по данным SDRAM будут готовы, используя LDR абсолютного скачка официального скачка к операции SDRAM. Можно сделать вывод о том, что запрет на использование перемещения позиционно-зависимый код до того, как код может быть использован только независимо от положения исполнения программного кода.

Оставьте это поле пустым, а затем определить, дополненной позиционно-независимый код.

Опубликовано 19 оригинальных статей · вона похвала 7 · просмотров 6921

рекомендация

отblog.csdn.net/G_METHOD/article/details/104527632