JZ2440 bare board development practice # 6 linker script and relocation

On a complete control of SDRAM, SDRAM and now we can read and write, so the content of the code to do something with SDRAM relocation. Some content has been https://blog.csdn.net/G_METHOD/article/details/104508545 mentioned in relocating what, why should distinguish between relocations, as well as linker script used to address, so here it will be simpler description.

When our program can not be executed in the original destination address, the code will need to be relocated, and the code is to do the relocation program to move to address the purpose of the program is running from the normal operation of the address can not currently running normally.

Generally comprises relocatable segments replication and clear the bss section, a bss section no global variable initial value 0 or the initial value of variables collection, and not as a data segment presence bss section saves the file size bin. And do navigation links for relocation is the script, such as source address, destination address and so can be given by the linker script, the script can do while link memory mapping arrangement, the position and the relative position of arbitrary memory distribution arrangements segment, leaving I hope their own empty, linker script specific and detailed content can be read http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#IDX237 , can be more clear understanding and use the linker script, here to talk about streamlining the core part.

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

This is the core of where we use to link to the script, SECTIONS fixed format, a link script must have at most one and only, we can arrange inside SECTION memory mapping segment. secname is the segment name, generally .data, .text, .rodata, .bss, etc., segment name must be recognized by the linker. Fill the start address of our desired program is running, and if not specified, the order and length of the press section directly preceding given. BLOCK (align) we can set only absolutely normal operation at the start address of the segment address is aligned, so as to ensure the program, after the alignment of the text is not the only way this will be mentioned in another way. NOLOAD indicates that the segment in the executable file, read elf can view the segment, but not loaded into memory when the program is running, because we are the bare board procedures, that is loaded at the storage location address, and therefore did not say this load concept, personally think that there is only loaded for elf application layer. Note that: AT, in front of the AT: both sides must have the space. Load address AT (ldadr) instructions of the program, in the bin file, this feature can be used to control the size of the bin, such as text and data and bss arranged next place, but each time the relocation address to the respective runtime, If the same start address is not specified AT (ldadr) the address, default load address and run. contents of our freedom to organize local content within the same paragraph of the order. And behind the region due phdr and fill unused here is not to go into details, there is detailed in the above-described second site linked document.

Example JZ2440 output link to the following script, the start address in the SDRAM 0x30000000, which was used as a starting address, used here. Symbol, symbol indicating the current position address, is available only in a SECTIONS, will be used as the right value current address assignment to a variable, as in the following link script __copy_start =.. When used as a left value is used to specify the current address, the assignment should be noted that operations related to the need to add; end symbol. ALGIN (4) represents a 4-byte aligned address, since the arm 4 bytes reference value decoding execution step, when the address is not 4 byte aligned, forced alignment, if we do not align, may occur 0x3002 data segment at this time need to write the data region becomes aligned directly perform address assignment 0x3000, 0x3000 case if the address is a valid code will overwrite, the program causing abnormal operation, therefore the insurance reasons, should be aligned with each segment.

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 = .;
}

contents part of the linker script describing what we will be placed in the segment, the wildcard * for all files, here is the implementation of ld -T linker.lds xxx.o yyy.o specified target file, each target file in memory order of the specified object is executed in order of the position and ld, and if arranged in the manner described above, then the order is xxx.o yyy.o, of course, in order to specify a target file contents, such as we need to Start. S the startup file placed before the other files, so you can

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

Separated by intermediate spaces.

Here relocations relate to exemplary program segment replication and bss segments cleared, the corresponding variables defined at a position corresponding segment for repositioning program. Need to say that the variables defined in SECTIONS, there is no sign of the value is present in the elf in the symbol table, expand it, global variables and functions are stored in the symbol table, the symbol table corresponding to the symbol there is a corresponding address, the address points to the area is the initial value of the variable, the situation is a function of more complex here not expand, and the variable link scripts stored here, but also a corresponding address, but there is no value, the corresponding address is the value of the linker script variables, Therefore we should be used as a symbol for external use, but its only to take the address, as follows, using the 32-bit address pointer type pointing to the corresponding operation can be completed quickly at this stage (for software and hardware features levels determined ).

extern uint32_t _bss_start;
uint32_t *target_start_address = &_bss_start;

Detailed knowledge of the symbol table and a linker script variables and how to use C language script variable link can view https://sourceware.org/ml/binutils/2007-07/msg00154.html , based on the above, the output code is as follows:

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, use the -T option to specify the linker script, as follows

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

Writing to the NorFlash compiled, if the normal serial output sequentially AZ i.e. a successful relocation.

Bl Start.S the relative jump to the initialization function initializes and repositioning, since the effective instruction data before the relocation operation is not executable when the address is not completed, the program execution jumps by a relatively intelligent on the NorFlash, when the relocation program that is, after the run-time address on the SDRAM data are ready, using ldr absolute jump official jump to SDRAM operation. It can be concluded that prohibit the use of the relocation position-dependent code before the code can only be used irrespective of the position of execution of the program code.

Leave this blank, later supplemented determine position-independent code.

Published 19 original articles · won praise 7 · views 6921

Guess you like

Origin blog.csdn.net/G_METHOD/article/details/104527632