S3c2440 code relocation details 2---Introduction and simple test of link script

Publisher:温暖梦想Latest update time:2021-10-16 Source: eefocusKeywords:S3c2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

When the program was run, it was found that the performance was different when booting from Nand Flash and Nor Flash.


It is set to Nand Flash boot without any problem and displays ABCDE...


If it is set to NOor Flash startup, it will display AAA...


What is the reason for this?


Nor Start

insert image description here

Nor Flash is considered as address 0, and g_Char is placed after 0x700. After the CPU is powered on, it starts to execute from address 0. It can read the code on Nor Flash and print A. When g_Char++ is performed, the write operation is invalid, and the data read next time is still A.


NAND Boot

insert image description here

After power-on, the first 4K code of Nand Flash is automatically copied to SRAM, which is considered by the CPU as address 0. After power-on, the CPU starts to execute from address 0, reads the code on SRAM, and modifies the variable with g_Char++. The next read data increases in sequence.


In order to solve the problem that variables in Nor Flash cannot be written, we put the data segment where the variables are located in SDRAM to see if it works.


Modify Makefile to specify the data segment as 0x30000000 -Tdata 0x30000000:


 arm-linux-ld -Ttext 0 -Tdata 0x30000000  start.o led.o uart.o init.o main.o -o sdram.elf


In this case, the compiled bin file has a file size of more than 700MB from address 0 to address 0x30000000, and there is a gap between the code segment and the data segment, which is called a black hole.

insert image description here

There are two ways to solve black holes:

First method:

①Put the g_Char of the data segment and the code segment together

② Burn on Nor Flash

③Copy g_char (global variable) to SDRAM, i.e. 0x3000000 (relocation) during runtime;

How to implement the first method

Modify the code segment address of Makefile and specify it using the link script sdram.lds.


Note: #arm-linux-ld -Ttext 0 -Tdata 0x30000000 start.o led.o uart.o init.o main.o -o sdram.elf

Modify to: arm-linux-ld -T sdram.lds start.o led.o uart.o init.o main.o -o sdram.elf


The syntax of the linker script is:


SECTIONS {

...

secname start BLOCK(align) (NOLOAD) : AT ( ldadr )

  { contents } >region :phdr =fill

...

}


We need to arrange the code segment, read-only data segment, data segment, .bss segment, and .common in sequence.


The data segment is placed at 0x800, but at runtime it is at 0x3000000:


SECTIONS {

   .text 0 : { *(.text) } //.text of all files

   .rodata : { *(.rodata) } //Read-only data segment

   .data 0x30000000 : AT(0x800) { *(.data) } //Put at 0x700, but run at 0x3000000

   .bss : { *(.bss) *(.COMMON) } // bss segment of all files, .COMMON segment of all files

}


After recompiling and burning the bin file, it was found that garbled characters were displayed after startup. The reason is that we get g_Char from 0x30000000, but before that, there is no data prepared at 0x30000000. Therefore, it is necessary to relocate the data segment, move the data at 0x700 to 0x30000000, and add the following to start.S:


 bl sdram_init


 /* Relocate the data segment */

 mov r1, #0x700 

 ldr r0, [r1]

 move r1, #0x30000000

 str r0, [r1]


 bl main


The above method can only copy one bit of data at 0x800, which is not very general. Here is a more general copy method:

The linker script is modified as follows:


SECTIONS {

   .text   0  : { *(.text) }

   .rodata : { *(.rodata) }

   .data 0x30000000 : AT(0x700) 

   { 

      data_load_addr = LOADADDR(.data);

      data_start = . ;//equal to the current position

      *(.data) //Equal to the size of the data segment

      data_end = . ;//equal to the current position

   }

   .bss  : { *(.bss) *(.COMMON) }

}


Modify start.S


    bl sdram_init   


    /* Relocate the data segment */

    ldr r1, =data_load_addr /* data segment address in bin file, load address*/

    ldr r2, =data_start /* data segment at relocation address, address at runtime*/

    ldr r3, =data_end /* data segment end address*/


cpy:

    ldrb r4, [r1] //Read from r1 to r4

    strb r4, [r2] // store r4 in r2

    add r1, r1, #1 //r1+1

    add r2, r2, #1 //r2+1

    cmp r2, r3 //r2 r3 comparison

    bne cpy //If not, continue copying


    bl main


Second method

① Let the file start directly from 0x30000000, and the global variable is at 0x3...;

② Burn address 0 on Nor Flash;

③ The operation will copy the entire code segment and data segment (the entire program) from address 0 to 0x30000000 of SDRAM (relocation);


The difference between these two methods is that the former only relocates the data segment, while the latter relocates the data segment and the code segment.

Keywords:S3c2440 Reference address:S3c2440 code relocation details 2---Introduction and simple test of link script

Previous article:s3c2440 learning road-012-1 Undefined undefined interrupt
Next article:S3c2440 code relocation details 3---analysis of link script

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号