Template Information

Trang

How to write U-Boot (Bootloader)

Thứ Ba, 19 tháng 7, 2011 / 23:54

1.1 U-Boot working process

U-Boot to boot the kernel of the process can be divided into two stages, two stages of the following functions:

(1) The first stage from
Hardware initialization
Load U-Boot code to RAM space for the second stage
Set stack
Jump to the entrance of the second phase of the code

(2) The second phase of the function
Initialize the hardware devices used at this stage
Testing the system memory map
Read the kernel from Flash to RAM,
Set boot parameters for the kernel
Call kernel
1.1.1 U-Boot start the first stage of code analysis

The first phase of the corresponding file is cpu/arm920t/start.S and board/samsung/mini2440/lowlevel_init.S.

U-Boot start the first stage of the process is as follows:

Figure 2.1 U-Boot start the first stage of the process

According cpu/arm920t/u-boot.lds connection specified:

ENTRY (_start)

SECTIONS

{

. = 0×00000000;

. = ALIGN (4);

. Text:

{

cpu/arm920t/start.o (. text)

board/samsung/mini2440/lowlevel_init.o (. text)

board/samsung/mini2440/nand_read.o (. text)

* (. Text)

}

… …

}

The first link is cpu/arm920t/start.o, so u-boot.bin code cpu/arm920t/start.o entry, its source code in the cpu/arm920t/start.S. Here we analyze the cpu/arm920t/start.S implementation.
1. Hardware device initialization

(1) set an exception vector

cpu/arm920t/start.S at the beginning of the following code:

. Globl _start

_start: b start_code / * reset * /

ldr pc, _undefined_instruction / * undefined instruction vector * /

ldr pc, _software_interrupt / * software interrupt vector * /

ldr pc, _prefetch_abort / * Prefetch instruction exception vector * /

ldr pc, _data_abort / * exception vector data manipulation * /

ldr pc, _not_used / * not used * /

ldr pc, _irq / * irq interrupt vector * /

ldr pc, _fiq / * fiq interrupt vector * /

/ * Interrupt vector table entry address * /

_undefined_instruction:. word undefined_instruction

_software_interrupt:. word software_interrupt

_prefetch_abort:. word prefetch_abort

_data_abort:. word data_abort

_not_used:. word not_used

_irq:. word irq

_fiq:. word fiq

. Balignl 16,0 xdeadbeef

The above code sets the ARM exception vector table, each exception vector described below:

Table 2.1 ARM exception vector table
Address
Abnormal
Entry mode
Description

0×00000000
Reset
Management
Valid reset level, reset exception, the program jumps to the reset process at the implementation

0×00000004
Undefined instruction
Undefined mode
Instruction could not have handled, resulting in an undefined instruction exception

0×00000008
Software interrupt
Management
SWI instruction execution generated for user mode operation instruction program calls the privileged

0x0000000c
Stored instructions
Abort mode
Address of the instruction prefetch the processor does not exist, or the address is not allowed to access the current instruction to generate instruction prefetch abort exception

0×00000010
Data Manipulation
Abort mode
Address of the instruction processor data access does not exist or access the address is not allowed when the current instruction to generate the data abort exception

0×00000014
Unused
Unused
Unused

0×00000018
IRQ
IRQ
External interrupt request is valid, and I bit in the CPSR is 0, a IRQ exception

0x0000001c
FIQ
FIQ
Fast interrupt request pin is active, and the F bit in the CPSR is 0, generate FIQ exception


There are these exceptions in the cpu/arm920t/start.S corresponding exception handler. When an exception is generated, CPU exception number according to the scale anomaly found in the corresponding exception vector, and then run at the jump instruction exception vector, CPU to jump to the corresponding exception handler execution.
 Reset exception vector in which the instruction "b start_code" determine the U-Boot boot will automatically jump to the label "start_code" at the execution.

(2) CPU into the SVC mode

start_code:

/ *

* Set the cpu to SVC32 mode

* /

mrs r0, cpsr

bic r0, r0, # 0x1f / * mode bits cleared * /

orr r0, r0, # 0xd3 / * mode bit is set to "10011" (management), and interrupt and fast interrupt prohibition against bit position 1 * /

msr cpsr, r0

The above code will set the CPU mode bit of work to management, and interrupt and fast interrupt prohibition against bit position one, thus shielding the IRQ and FIQ interrupts.
(3) Set the control register address

# If defined (CONFIG_S3C2400)

# Define pWTCON 0×15300000

# Define INTMSK 0×14400008

# Define CLKDIVN 0×14800014

# Else / * s3c2410 s3c2440 the following four registers with the same address * /

# Define pWTCON 0×53000000 / * WATCHDOG control register address * /

# Define INTMSK 0x4A000008 / * INTMSK register address * /

# Define INTSUBMSK 0x4A00001C / * INTSUBMSK register address * /

# Define CLKDIVN 0x4C000014 / * CLKDIVN register address * /

# Endif

S3c2440 on the development board with the above code to complete the WATCHDOG, INTMSK, INTSUBMSK, CLKDIVN four register address setting. Each register address see references [4].
(4) Close Watchdog

ldr r0, = pWTCON

mov r1, # 0×0

str r1, [r0] / * watchdog controller, the lowest level is 0, the watchdog reset signal is not output * /

The above code is written to the Watchdog control register 0, the watchdog off. Otherwise, the U-Boot startup, CPU will continue to reboot.

(5) maskable interrupt

/ *

* Mask all IRQs by setting all bits in the INTMR – default

* /

mov r1, # 0xffffffff / * someone is set to a corresponding interrupt mask * /

ldr r0, = INTMSK

str r1, [r0]

INTMSK is the main interrupt mask register, each corresponding to SRCPND (interrupt pin register) in the one, that SRCPND the appropriate representatives of the CPU interrupt request is being processed.

According to Reference 4, INTMSK register is a 32-bit registers, each corresponding to an interrupt, write to them all the location 0xffffffff will INTMSK a register to mask the corresponding interrupt.

# If defined (CONFIG_S3C2440)

ldr r1, = 0x7fff

ldr r0, = INTSUBMSK

str r1, [r0]

# Endif

INTSUBMSK SUBSRCPND in each one corresponding to that SUBSRCPND the appropriate representatives of the CPU interrupt request is being processed.

According to Reference 4, INTSUBMSK register is a 32 bit register, but only a low 15. To write to 0x7fff is to INTSUBMSK register all valid bit (low 15) set a to mask the corresponding interrupt.
(6) set MPLLCON, UPLLCON, CLKDIVN

# If defined (CONFIG_S3C2440)

# Define MPLLCON 0x4C000004

# Define UPLLCON 0x4C000008

ldr r0, = CLKDIVN

mov r1, # 5

str r1, [r0]

ldr r0, = MPLLCON

ldr r1, = 0x7F021

str r1, [r0]

ldr r0, = UPLLCON

ldr r1, = 0×38022

str r1, [r0]

# Else

/ * FCLK: HCLK: PCLK = 1:2:4 * /

/ * Default FCLK is 120 MHz! * /

ldr r0, = CLKDIVN

mov r1, # 3

str r1, [r0]

# Endif

CPU power on a few milliseconds, the crystal output stability, FCLK = Fin (crystal frequency), CPU to execute instructions. But in fact, FCLK can be higher than Fin, to improve the system clock, the software needed to enable the PLL. This requires setting CLKDIVN, MPLLCON, UPLLCON the three registers.

CLKDIVN register sets FCLK, HCLK, PCLK ratio among the three can be set according to Table 2.2.

Table 2.2 S3C2440's CLKDIVN Register format
CLKDIVN
Bit
Help
Initial value

HDIVN
[2:1]
00: HCLK = FCLK / 1.

01: HCLK = FCLK / 2.

10: HCLK = FCLK / 4 (when CAMDIVN [9] = 0 pm)

HCLK = FCLK / 8 (when CAMDIVN [9] = 1 pm)

11: HCLK = FCLK / 3 (when CAMDIVN [8] = 0 pm)

HCLK = FCLK / 6 (when CAMDIVN [8] = 1 pm)
00

PDIVN
[0]
0: PCLK = HCLK / 1 1: PCLK = HCLK / 2
0


Set CLKDIVN to 5, will HDIVN set to binary 10, the CAMDIVN [9] has not been changed, the default is 0, so HCLK = FCLK / 4. PDIVN is set to 1, so PCLK = HCLK / 2. So divider FCLK: HCLK: PCLK = 1:4:8.

MPLLCON register used to set multiple FCLK and Fin. MPLLCON bits [19:12] called MDIV, bits [9:4] is called PDIV, bits [1:0] is called SDIV.

For S3C2440, FCLK relationship with Fin as the following formula:

MPLL (FCLK) = (2 � m � Fin) / (p � 14 2 s'>)

Where: m = MDIC +8, p = PDIV +2, s = SDIV

MPLLCON and UPLLCON can reference the value of 4 "PLL VALUE SELECTION TABLE" setting. Part of the table are summarized as follows:

Table 2.3 PLL value recommendation
Input Frequency
Output frequency
MDIV
PDIV
SDIV

12.0000MHz
48.00 MHz
56 (0×38)
2
2

12.0000MHz
405.00 MHz
127 (0x7f)
2
1


When mini2440 system frequency is set to 405MHZ, USB clock frequency is set to 48MHZ, the system can be stabilized to run, so set MPLLCON and UPLLCON as:

MPLLCON = (0x7f <<12) | (0×02 <<4) | (0×01) = 0x7f021

UPLLCON = (0×38 <<12) | (0×02 <<4) | (0×02) = 0×38022

 (7) Close the MMU, cache

Read on:

# Ifndef CONFIG_SKIP_LOWLEVEL_INIT

bl cpu_init_crit

# Endif

cpu_init_crit this code in the U-Boot starts normally only need to do that if U-Boot from RAM to start, you should comment out the code.

The following analysis of what to do about cpu_init_crit in the end:

320 # ifndef CONFIG_SKIP_LOWLEVEL_INIT

321 cpu_init_crit:

322 / *

323 * the data cache and instruction cache is invalid * /

324 * /

325 mov r0, # 0

326 mcr p15, 0, r0, c7, c7, 0 / * write 0 to the c7 will ICache and DCache void * /

327 mcr p15, 0, r0, c8, c7, 0 / * write 0 to c8 TLB will fail * /

328

329 / *

330 * disable MMU stuff and caches

331 * /

332 mrc p15, 0, r0, c1, c0, 0 / * read control register to r0 in the * /

333 bic r0, r0, # 0×00002300 @ clear bits 13, 9:8 (- V– RS)

334 bic r0, r0, # 0×00000087 @ clear bits 7, 2:0 (B —-CAM)

335 orr r0, r0, # 0×00000002 @ set bit 2 (A) Align

336 orr r0, r0, # 0×00001000 @ set bit 12 (I) I-Cache

337 mcr p15, 0, r0, c1, c0, 0 / * Save r0 to the control register * /

338

339 / *

340 * before relocating, we have to setup RAM timing

341 * because memory timing is board-dependend, you will

342 * find a lowlevel_init.S in your board directory.

343 * /

344 mov ip, lr

345

346 bl lowlevel_init

347

348 mov lr, ip

349 mov pc, lr

350 # endif / * CONFIG_SKIP_LOWLEVEL_INIT * /

Code c0, c1, c7, c8 are the ARM920T coprocessor CP15 registers. Where c7 is the cache control register, c8 is the TLB control register. 325 ~ 327 lines of code to 0 written c7, c8, the Cache, TLB void.

332 ~ 337 lines of code to turn off the MMU. This is by modifying the c1 CP15 registers to achieve, look at the c1 CP15 register format (only the bits used in the code listed):
Table 2.3 CP15 of c1 register format (Part I)
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

.
.
V
I
.
.
R
S
B
.
.
.
.
C
A
M


The significance of each bit is as follows:

V: express exception to the location scale, 0: exception vector at 0×00000000; 1: exception vector in 0xFFFF0000
I: 0: off ICaches; 1: Open ICaches
R, S: used in conjunction with page table descriptors to identify memory access with
B: 0: CPU is little endian; 1: CPU is big endian
C: 0: off DCaches; 1: Open DCaches
A: 0: data access alignment checking when no address; 1: data access address when alignment checking
M: 0: off MMU; 1: Open the MMU

332 ~ 337 lines of code to the M c1 position zero, closed the MMU.

(8) RAM control register initialization

Which lowlevel_init memory initialization is complete the work, because the memory initialization is dependent on the development board, so lowlevel_init generic code on the board following the appropriate directory. For mini2440, lowlevel_init defined in board/samsung/mini2440/lowlevel_init.S as follows:

45 # define BWSCON 0×48000000 / * 13 more storage start address * /

… …

129 _TEXT_BASE:

130. Word TEXT_BASE

131

132. Globl lowlevel_init

133 lowlevel_init:

134 / * memory control configuration * /

135 / * make r0 relative the current location so that it * /

136 / * reads SMRDATA out of FLASH rather than memory! * /

137 ldr r0, = SMRDATA

138 ldr r1, _TEXT_BASE

139 sub r0, r0, r1 / * SMRDATA by _TEXT_BASE is offset register 13 * /

140 ldr r1, = BWSCON / * Bus Width Status Controller * /

141 add r2, r0, # 13 * 4

1420:

143 ldr r3, [r0], # 4 / * register values ​​to each of the 13 assigned to the corresponding register * /

144 str r3, [r1], # 4

145 cmp r2, r0

146 bne 0b

147

148 / * everything is fine now * /

149 mov pc, lr

150

151. Ltorg

152 / * the literal pools origin * /

153

154 SMRDATA: / * The following are the 13 register values ​​* /

155. Word … …

156. Word … …

… …
 lowlevel_init initialization register 13 to achieve the RAM clock initialization. lowlevel_init function for U-Boot from NAND Flash or NOR Flash boot situation are valid.

U-Boot.lds link script with the following code:

. Text:

{

cpu/arm920t/start.o (. text)

board/samsung/mini2440/lowlevel_init.o (. text)

board/samsung/mini2440/nand_read.o (. text)

… …

}

board/samsung/mini2440/lowlevel_init.o will be linked to cpu/arm920t/start.o back, so board / samsung/mini2440/lowlevel_init.o U-Boot is also the first 4KB of code.

U-Boot in the NAND Flash start, lowlevel_init.o will automatically be read to the CPU internal 4KB of internal RAM. So the first 137 to 146 lines of code copied from the CPU registers internal RAM to the appropriate register values.

For the U-Boot boot in the case of NOR Flash, as determined when U-Boot connected U-Boot address is the address in memory, at which point U-Boot NOR Flash is still, so still need to read in the NOR Flash get data to the RAM.

NOR Flash as the start address is 0, and U-Boot to load into memory the starting address is TEXT_BASE, SMRDATA the address label is in the Flash SMRDATA-TEXT_BASE.

In summary, lowlevel_init role is to start the 13 SMRDATA copies the value of start address [BWSCON] 13 registers, thus completing the storage controller settings.

(9) Copy the second phase of U-Boot code to RAM

cpu/arm920t/start.S the original code is only support boot from NOR Flash, and a modified U-Boot is now in the NOR Flash and NAND Flash started on both realize the idea is this:

bl bBootFrmNORFlash / * determine the U-Boot in NAND Flash or NOR Flash boot * /

cmp r0, # 0 / * r0 storage bBootFrmNORFlash function return value, return 0 if the NAND Flash start, or that start in the NOR Flash * /

beq nand_boot / * Jump to NAND Flash boot code * /

/ * NOR Flash boot code * /

b stack_setup / * skip start code * NAND Flash /

nand_boot:

/ * NAND Flash boot code * /

stack_setup:

/ * Other code * /
Role is to determine the function of which bBootFrmNORFlash U-Boot in NAND Flash or NOR Flash boot boot boot NOR Flash if it returns 1, otherwise it returns 0. According to ATPCS rules, the function return value will be stored in r0 register, so after the function call bBootFrmNORFlash according able to judge the value of r0 U-Boot in the NAND Flash or NOR Flash boot start. bBootFrmNORFlash function is defined in the board/samsung/mini2440/nand_read.c as follows:

int bBootFrmNORFlash (void)

{

volatile unsigned int * pdw = (volatile unsigned int *) 0;

unsigned int dwVal;

dwVal = * pdw; / * first record the original data * /

* Pdw = 0×12345678;

if (* pdw! = 0×12345678) / * write fails, start in the NOR Flash * /

{

return 1;

}

else / * write success that started in the NAND Flash * /

{

* Pdw = dwVal; / * restore original data * /

return 0;

}

}

Either from the NAND Flash NOR Flash or from the start, the address 0 for the U-Boot for the first instruction "b start_code".

For the situation from the NAND Flash start, it starts 4KB of code will be automatically copied to the internal 4K memory, CPU, so you can modify the direct assignment method.

For the situation from the start NOR Flash, NOR Flash is the beginning of the address 0, must pass a certain sequence of commands to write data to NOR Flash, so can this difference to distinguish from the NAND Flash or NOR Flash boot: to address 0 to write a data, and then read out, if we find that the failure to write NOR Flash, otherwise NAND Flash.

NOR Flash started to analyze the following part of the code:

208 adr r0, _start / * r0 <- current position of code * /

209 ldr r1, _TEXT_BASE / * test if we run from flash or RAM * /

/ * U-Boot to determine whether it is downloaded to the RAM to run, and if so, no longer copied to the RAM in, and this usually happens only when debugging U-Boot * /

210 cmp r0, r1 / * _start equal _TEXT_BASE that is downloaded to the RAM to run * /

211 beq stack_setup

212 / * The following front label until nand_boot are NOR Flash boot code * /

213 ldr r2, _armboot_start

214 ldr r3, _bss_start

215 sub r2, r3, r2 / * r2 <- size of armboot * /

216 add r2, r0, r2 / * r2 <- source end address * /

217 / * move to the U-Boot itself in RAM * /

218 copy_loop:
 219 ldmia r0!, {R3-r10} / * from the address [r0] the NOR Flash 8 characters read into the data * /

220 stmia r1!, {R3-r10} / * r3 to r10 registers the data replication to address [r1] memory * /

221 cmp r0, r2 / * until source end addreee [r2] * /

222 ble copy_loop

223 b stack_setup / * skip start code * NAND Flash /

NAND Flash start again following analysis of part of the code:

nand_boot:

mov r1, # NAND_CTL_BASE

ldr r2, = ((7 <<12) | (7 <<8) | (7 <<4) | (0 <<0))

str r2, [r1, # oNFCONF] / * set NFCONF register * /

/ * Set NFCONT, initialize the ECC encoder / decoder, prohibiting NAND Flash Chip Select * /

ldr r2, = ((1 <<4) | (0 <<1) | (1 <<0))

str r2, [r1, # oNFCONT]

ldr r2, = (0×6) / * set NFSTAT * /

str r2, [r1, # oNFSTAT]

/ * Reset command before the first use of NAND Flash Reset * /

mov r2, # 0xff

strb r2, [r1, # oNFCMD]

mov r3, # 0

/ * Call the C function nand_read_ll ready for the stack * /

ldr sp, DW_STACK_START

mov fp, # 0

/ * The following first set r0 to r2, and then call the function U-Boot nand_read_ll read RAM * /

ldr r0, = TEXT_BASE / * destination address: U-Boot start address in RAM * /

mov r1, # 0×0 / * Source Address: U-Boot in the NAND Flash in the beginning of the address * /

mov r2, # 0×30000 / * copy the size of the file must be large compared with u-boot.bin, and the NAND Flash block size must be an integer multiple of, where is set to 0×30000 (192KB) * /

bl nand_read_ll / * jump to nand_read_ll function, U-Boot to start copying RAM * /

tst r0, # 0×0 / * check the return value is correct * /

beq stack_setup

bad_nand_read:

loop2: b loop2 / / infinite loop

. Align 2

DW_STACK_START:. Word STACK_BASE + STACK_SIZE-4

One NAND_CTL_BASE, oNFCONF other in include/configs/mini2440.h defined as follows:

# Define NAND_CTL_BASE 0x4E000000 / / NAND Flash control register base address

# Define STACK_BASE 0x33F00000 / / base address of stack

# Define STACK_SIZE 0×8000 / / size of stack

# Define oNFCONF 0×00 / * NFCONF NAND_CTL_BASE offset relative to the address * /

# Define oNFCONT 0×04 / * NFCONT NAND_CTL_BASE offset relative to the address * /

# Define oNFADDR 0x0c / * NFADDR NAND_CTL_BASE offset relative to the address * /

# Define oNFDATA 0×10 / * NFDATA NAND_CTL_BASE offset relative to the address * /

# Define oNFCMD 0×08 / * NFCMD NAND_CTL_BASE offset relative to the address * /

# Define oNFSTAT 0×20 / * NFSTAT NAND_CTL_BASE offset relative to the address * /

# Define oNFECC 0x2c / * NFECC NAND_CTL_BASE offset relative to the address * /

NAND Flash control register set of each data sheet in the S3C2440 is described in detail here not introduced.

Code nand_read_ll function in the NAND Flash in handling U-Boot to RAM, the function is defined in the board/samsung/mini2440/nand_read.c.

According to the size of NAND Flash page can be divided into two kinds: 512B/page and 2048B/page's. The two NAND Flash read operation is different. Hence the need for U-Boot to identify the type of NAND Flash, and then use the appropriate read, that can automatically adapt to nand_read_ll function of two NAND Flash.

Reference data sheet S3C2440 can know: According to the NFCONF register Bit3 (AdvFlash (Read only)) and Bit2 (PageSize (Read only)) can determine the type of NAND Flash. Bit2, Bit3 and NAND Flash's block type of relationship as follows:
Table 2.4 NFCONF the Bit3, Bit2 relationship with NAND Flash
Bit2 Bit3
0
1

0
256 B / page
512 B / page

1
1024 B / page
2048 B / page


As the NAND Flash only 512B/page and 2048 B / page two, so register under NFCONF Bit3 NAND Flash can be a distinction between the two.

See the complete code in nand_read_ll board/samsung/mini2440/nand_read.c function, here are a pseudo-code:

int nand_read_ll (unsigned char * buf, unsigned long start_addr, int size)

{

/ / Register under NFCONF Bit3 to distinguish two kinds of NAND Flash

if (NFCONF & 0×8) / * Bit is 1, that is 2KB/page the NAND Flash * /

{

////////////////////////////////////

2K block of the NAND Flash Read

////////////////////////////////////

}

else / * Bit is 0, that is 512B/page the NAND Flash * /

{

/////////////////////////////////////

Read 512B block of the NAND Flash

/////////////////////////////////////

}

return 0;

}

(10) set the stack

/ * Set the stack * /

stack_setup:

ldr r0, _TEXT_BASE / * upper 128 KiB: relocated uboot * /

sub r0, r0, # CONFIG_SYS_MALLOC_LEN / * malloc area * /

sub r0, r0, # CONFIG_SYS_GBL_DATA_SIZE / * Skip the global data area * /

# Ifdef CONFIG_USE_IRQ

sub r0, r0, # (CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)

# Endif

sub sp, r0, # 12 / * leave 3 words for abort-stack * /

As long as the sp has not been used a pointer to the memory set to complete the stack. According to the above code to know U-Boot memory usage, and as shown below:


Figure 2.2 U-Boot memory usage

(11) Clear BSS section

clear_bss:

ldr r0, _bss_start / * BSS segment start address specified in the u-boot.lds * /

ldr r1, _bss_end / * BSS segment end address, specified in the u-boot.lds * /

mov r2, # 0×00000000

clbss_l: str r2, [r0] / * clear the bss segment * /

add r0, r0, # 4

cmp r0, r1

ble clbss_l
 The initial value is 0, no initial value of global variables, static variables will be automatically placed in BSS segment. These variables should be assigned the initial value is 0, otherwise the initial value of these variables will be a random value, if some programs do not directly use the uninitialized variable will cause unknown consequences.

(12) jump to the entrance of the second phase of the code

ldr pc, _start_armboot

_start_armboot:. word start_armboot

Jump to the second phase of the code at the entrance start_armboot.
1.1.2 U-Boot start the second stage of code analysis

start_armboot function lib_arm / board.c defined, is the U-Boot code for the second phase of the entrance. U-Boot start the second phase of the process is as follows:

Figure 2.3 U-Boot the second phase of the implementation process

Start_armboot function before the analysis to look at some important data structures:

(1) gd_t structure

U-Boot uses a structure gd_t global data area to store the data, the structure in include / asm-arm / global_data.h defined as follows:

typedef struct global_data {

bd_t * bd;

unsigned long flags;

unsigned long baudrate;

unsigned long have_console; / * serial_init () was called * /

unsigned long env_addr; / * Address of Environment struct * /

unsigned long env_valid; / * Checksum of Environment valid? * /

unsigned long fb_base; / * base address of frame buffer * /

void ** jt; / * jump table * /

} Gd_t;

U-Boot uses a pointer stored in the register to record the global data area gd address:

# Define DECLARE_GLOBAL_DATA_PTR register volatile gd_t * gd asm ("r8")

DECLARE_GLOBAL_DATA_PTR gd_t global data structure to define a pointer, the pointer stored in the specified register r8. The statement also avoid compiler r8 assigned to other variables. Anyone who wants to access the global data area code, as long as the code at the beginning of accession "DECLARE_GLOBAL_DATA_PTR" line of code, and then you can use to access the global data pointer gd zone.

According to U-Boot memory map can be calculated using the gd value:

gd = TEXT_BASE-CONFIG_SYS_MALLOC_LEN – sizeof (gd_t)

(2) bd_t structure

bd_t in include / asm-arm.u / u-boot.h defined as follows:

typedef struct bd_info {

int bi_baudrate; / * Serial communication baud rate * /

unsigned long bi_ip_addr; / * IP address * /

struct environment_s * bi_env; / * start address of environment variables * /

ulong bi_arch_number; / * native code development board * /

ulong bi_boot_params; / * start address of kernel parameters * /

struct / * RAM configuration information * /

{
ulong start;

ulong size;

} Bi_dram [CONFIG_NR_DRAM_BANKS];

} Bd_t;

When U-Boot to boot the kernel to pass parameters to give the kernel, then we should use gd_t, bd_t structure the information to set the mark list.

(3) init_sequence array

U-Boot to use an array to store init_sequence development board for most every function of the implementation of the initialization function pointer. init_sequence array has more compiler options, remove the compiler option init_sequence array as follows:

typedef int (init_fnc_t) (void);

init_fnc_t * init_sequence [] = {

board_init, / * development board specific configuration –board/samsung/mini2440/mini2440.c * /

timer_init, / * clock initialization – cpu/arm920t/s3c24x0/timer.c * /

env_init, / * initialize the environment variable –common/env_flash.c or common / env_nand.c * /

init_baudrate, / * initialize the baud rate – lib_arm / board.c * /

serial_init, / * Serial initialization – drivers/serial/serial_s3c24x0.c * /

console_init_f, / * control communications platform initialization phase 1 – common / console.c * /

display_banner, / * print the U-Boot version, compile time – gedit lib_arm / board.c * /

dram_init, / * allocation of available RAM – board/samsung/mini2440/mini2440.c * /

display_dram_config, / * display RAM size – lib_arm / board.c * /

NULL,

};

Board/samsung/mini2440/mini2440.c which board_init defined function, the function sets the MPLLCOM, UPLLCON, and some GPIO register values, also set the U-Boot and kernel boot parameters of the machine code address:

/ * MINI2440 development board of the machine code * /

gd-> bd-> bi_arch_number = MACH_TYPE_MINI2440;

/ * The kernel boot parameter address * /

gd-> bd-> bi_boot_params = 0×30000100;

Which dram_init function board/samsung/mini2440/mini2440.c defined as follows:

int dram_init (void)

{

/ * The mini2440 only * /

gd-> bd-> bi_dram [0]. start = PHYS_SDRAM_1;

gd-> bd-> bi_dram [0]. size = PHYS_SDRAM_1_SIZE;

return 0;

}

mini2440 32MB of SDRAM using two components of the 64MB of memory, connected to the memory controller BANK6, address space is 0×30000000 ~ 0×34000000.

In include/configs/mini2440.h in PHYS_SDRAM_1 and PHYS_SDRAM_1_SIZE were defined as a 0×30000000 and 0×04000000 (64M).

After analyzing the above data structure, to analyze the start_armboot following functions:

void start_armboot (void)

{

init_fnc_t ** init_fnc_ptr;

char * s;

… …

/ * Calculate the address of global data structures gd * /

gd = (gd_t *) (_armboot_start – CONFIG_SYS_MALLOC_LEN – sizeof (gd_t));

… …
 memset ((void *) gd, 0, sizeof (gd_t));

gd-> bd = (bd_t *) ((char *) gd – sizeof (bd_t));

memset (gd-> bd, 0, sizeof (bd_t));

gd-> flags | = GD_FLG_RELOC;

monitor_flash_len = _bss_start – _armboot_start;

/ * One by one call init_sequence array initialization function * /

for (init_fnc_ptr = init_sequence; * init_fnc_ptr; + + init_fnc_ptr) {

if ((* init_fnc_ptr) ()! = 0) {

hang ();

}

}

/ * Armboot_start in cpu/arm920t/start.S be initialized to u-boot.lds connection script _start * /

mem_malloc_init (_armboot_start – CONFIG_SYS_MALLOC_LEN,

CONFIG_SYS_MALLOC_LEN);

/ * NOR Flash initialization * /

# Ifndef CONFIG_SYS_NO_FLASH

/ * Configure available FLASH banks * /

display_flash_config (flash_init ());

# Endif / * CONFIG_SYS_NO_FLASH * /

… …

/ * NAND Flash initialization * /

# If defined (CONFIG_CMD_NAND)

puts ("NAND:");

nand_init (); / * go init the NAND * /

# Endif

… …

/ * Configure the environment variables and re-position * /

env_relocate ();

… …

/ * Get from the IP address of environment variables * /

gd-> bd-> bi_ip_addr = getenv_IPaddr ("ipaddr");

stdio_init (); / * get the devices list going. * /

jumptable_init ();

… …

console_init_r (); / * fully init console as a device * /

… …

/ * Enable exceptions * /

enable_interrupts ();

# Ifdef CONFIG_USB_DEVICE

usb_init_slave ();

# Endif

/ * Initialize from environment * /

if ((s = getenv ("loadaddr"))! = NULL) {

load_addr = simple_strtoul (s, NULL, 16);

}
# If defined (CONFIG_CMD_NET)

if ((s = getenv ("bootfile"))! = NULL) {

copy_filename (BootFile, s, sizeof (BootFile));

}

# Endif

… …

/ * Initialize adapter * /

# If defined (CONFIG_CMD_NET)

# If defined (CONFIG_NET_MULTI)

puts ("Net:");

# Endif

eth_initialize (gd-> bd);

… …

# Endif

/ * Main_loop () can return to retry autoboot, if so just run it again. * /

for (;;) {

main_loop ();

}

/ * NOTREACHED – no way out of command loop except booting * /

}

main_loop function in common / main.c defined. Under normal circumstances, a number of seconds into the main_loop not function

















0 nhận xét:

Đăng nhận xét