uboot 2013.01 代码简析(2)第一阶段初始化
uboot执行"make smdk2410_config"之后就可以进行编译了,可以执行make命令进行编译,
因为整个输出太长,我仅仅列出部分最关键的输出(部分我不关心的内容直接用......代替):
arm-linux-gcc ....... < u-boot-2013.01.01/arch/arm/cpu/u-boot.lds >u-boot.lds
arm-linux-ld -pie -T u-boot.lds -Bstatic -Ttext 0x0 $UNDEF_LST arch/arm/cpu/arm920t/start.o --start-group api/libapi.o arch/arm/cpu/arm920t/libarm920t.o arch/arm/cpu/arm920t/s3c24x0/libs3c24x0.o arch/arm/lib/libarm.o board/samsung/common/libsamsung.o common/libcommon.o disk/libdisk.o drivers/bios_emulator/libatibiosemu.o drivers/block/libblock.o drivers/dfu/libdfu.o drivers/dma/libdma.o drivers/fpga/libfpga.o drivers/gpio/libgpio.o drivers/hwmon/libhwmon.o drivers/i2c/libi2c.o drivers/input/libinput.o drivers/misc/libmisc.o drivers/mmc/libmmc.o drivers/mtd/libmtd.o drivers/mtd/nand/libnand.o drivers/mtd/onenand/libonenand.o drivers/mtd/spi/libspi_flash.o drivers/mtd/ubi/libubi.o drivers/net/libnet.o drivers/net/phy/libphy.o drivers/pci/libpci.o drivers/pcmcia/libpcmcia.o drivers/power/battery/libbattery.o drivers/power/fuel_gauge/libfuel_gauge.o drivers/power/libpower.o drivers/power/pmic/libpmic.o drivers/rtc/librtc.o drivers/serial/libserial.o drivers/sound/libsound.o drivers/spi/libspi.o drivers/twserial/libtws.o drivers/usb/eth/libusb_eth.o drivers/usb/gadget/libusb_gadget.o drivers/usb/host/libusb_host.o drivers/usb/musb-new/libusb_musb-new.o drivers/usb/musb/libusb_musb.o drivers/usb/phy/libusb_phy.o drivers/usb/ulpi/libusb_ulpi.o drivers/video/libvideo.o drivers/watchdog/libwatchdog.o fs/cbfs/libcbfs.o fs/cramfs/libcramfs.o fs/ext4/libext4fs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o fs/libfs.o fs/reiserfs/libreiserfs.o fs/ubifs/libubifs.o fs/yaffs2/libyaffs2.o fs/zfs/libzfs.o lib/libfdt/libfdt.o lib/libgeneric.o lib/lzma/liblzma.o lib/lzo/liblzo.o lib/zlib/libz.o net/libnet.o post/libpost.o test/libtest.o board/samsung/smdk2410/libsmdk2410.o --end-group /home/host/prac/u-boot-2013.01.01/arch/arm/lib/eabi_compat.o -L /home/host/soft/FriendlyARM/toolschain/4.4.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.4.3 -lgcc -Map u-boot.map -o u-boot
从这两行输出可以知道,先由arch/arm/cpu/u-boot.lds在当前文件夹下生成u-boot.lds,然后在用生成的u-boot.lds对前面编译过程中生成的目标文件和静态库进行链接。
另外还需要注意的是arm-linux-ld的一些选项的含义:
-pie 用于生成“位置无关代码” -T u-boot.lds 使用u-boot.lds来作为链接脚本 -Bsharable 生成共享库 -Ttext 0x0 指定代码段的初始地址为0
--start-group和--end-group 用于标志一个组的开始和结束(用于多个目标文件和库文件中都存在相互依赖关系,可以多次执行依赖查找)
-Map u-boot.map 生成Map文件,其名称为u-boot.map
生成的u-boot.lds内容如下:
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 2 OUTPUT_ARCH(arm) 3 ENTRY(_start) 4 SECTIONS 5 { 6 . = 0x00000000; 7 . = ALIGN(4); 8 .text : 9 { 10 __image_copy_start = .; 11 arch/arm/cpu/arm920t/start.o (.text*) 12 *(.text*) 13 } 14 . = ALIGN(4); 15 .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } 16 . = ALIGN(4); 17 .data : { 18 *(.data*) 19 } 20 . = ALIGN(4); 21 . = .; 22 . = ALIGN(4); 23 .u_boot_list : { 24 _u_boot_list__start = .; 25 _u_boot_list_cmd__start = .; 26 *(SORT(.u_boot_list.cmd.*)); 27 _u_boot_list_cmd__end = .; 28 _u_boot_list_env_clbk__start = .; 29 *(SORT(.u_boot_list.env_clbk.*)); 30 _u_boot_list_env_clbk__end = .; 31 *(SORT(.u_boot_list.*)); 32 _u_boot_list__end = .; 33 } 34 . = ALIGN(4); 35 __image_copy_end = .; 36 .rel.dyn : { 37 __rel_dyn_start = .; 38 *(.rel*) 39 __rel_dyn_end = .; 40 } 41 .dynsym : { 42 __dynsym_start = .; 43 *(.dynsym) 44 } 45 _end = .; 46 . = ALIGN(4096); 47 .mmutable : { 48 *(.mmutable) 49 } 50 .bss __rel_dyn_start (OVERLAY) : { 51 __bss_start = .; 52 *(.bss*) 53 . = ALIGN(4); 54 __bss_end__ = .; 55 } 56 /DISCARD/ : { *(.dynstr*) } 57 /DISCARD/ : { *(.dynamic*) } 58 /DISCARD/ : { *(.plt*) } 59 /DISCARD/ : { *(.interp*) } 60 /DISCARD/ : { *(.gnu*) } 61 }
从这个链接脚本可以知道,代码段中最开始是arch/arm/cpu/arm920t/start.o(由arch/arm/cpu/arm920t/start.S编译而成),
start.o之后才是其他的目标文件对应的代码。
arch/arm/cpu/arm920t/start.S内容如下:
1 /* 2 * armboot - Startup Code for ARM920 CPU-core 3 * 4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> 5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> 6 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 7 * 8 * See file CREDITS for list of people who contributed to this 9 * project. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License as 13 * published by the Free Software Foundation; either version 2 of 14 * the License, or (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 24 * MA 02111-1307 USA 25 */ 26 27 #include <asm-offsets.h> 28 #include <common.h> 29 #include <config.h> 30 31 /* 32 ************************************************************************* 33 * 34 * Jump vector table as in table 3.1 in [1] 35 * 36 ************************************************************************* 37 */ 38 39 40 .globl _start 41 _start: b start_code 42 ldr pc, _undefined_instruction 43 ldr pc, _software_interrupt 44 ldr pc, _prefetch_abort 45 ldr pc, _data_abort 46 ldr pc, _not_used 47 ldr pc, _irq 48 ldr pc, _fiq 49 50 _undefined_instruction: .word undefined_instruction 51 _software_interrupt: .word software_interrupt 52 _prefetch_abort: .word prefetch_abort 53 _data_abort: .word data_abort 54 _not_used: .word not_used 55 _irq: .word irq 56 _fiq: .word fiq 57 58 .balignl 16,0xdeadbeef 59 60 61 /* 62 ************************************************************************* 63 * 64 * Startup Code (called from the ARM reset exception vector) 65 * 66 * do important init only if we don't start from memory! 67 * relocate armboot to ram 68 * setup stack 69 * jump to second stage 70 * 71 ************************************************************************* 72 */ 73 74 .globl _TEXT_BASE 75 _TEXT_BASE: 76 .word CONFIG_SYS_TEXT_BASE 77 78 /* 79 * These are defined in the board-specific linker script. 80 * Subtracting _start from them lets the linker put their 81 * relative position in the executable instead of leaving 82 * them null. 83 */ 84 .globl _bss_start_ofs 85 _bss_start_ofs: 86 .word __bss_start - _start 87 88 .globl _bss_end_ofs 89 _bss_end_ofs: 90 .word __bss_end__ - _start 91 92 .globl _end_ofs 93 _end_ofs: 94 .word _end - _start 95 96 #ifdef CONFIG_USE_IRQ 97 /* IRQ stack memory (calculated at run-time) */ 98 .globl IRQ_STACK_START 99 IRQ_STACK_START: 100 .word 0x0badc0de 101 102 /* IRQ stack memory (calculated at run-time) */ 103 .globl FIQ_STACK_START 104 FIQ_STACK_START: 105 .word 0x0badc0de 106 #endif 107 108 /* IRQ stack memory (calculated at run-time) + 8 bytes */ 109 .globl IRQ_STACK_START_IN 110 IRQ_STACK_START_IN: 111 .word 0x0badc0de 112 113 /* 114 * the actual start code 115 */ 116 117 start_code: 118 /* 119 * set the cpu to SVC32 mode 120 */ 121 mrs r0, cpsr 122 bic r0, r0, #0x1f 123 orr r0, r0, #0xd3 124 msr cpsr, r0 125 126 #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) 127 /* 128 * relocate exception table 129 */ 130 ldr r0, =_start 131 ldr r1, =0x0 132 mov r2, #16 133 copyex: 134 subs r2, r2, #1 135 ldr r3, [r0], #4 136 str r3, [r1], #4 137 bne copyex 138 #endif 139 140 #ifdef CONFIG_S3C24X0 141 /* turn off the watchdog */ 142 143 # if defined(CONFIG_S3C2400) 144 # define pWTCON 0x15300000 145 # define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ 146 # define CLKDIVN 0x14800014 /* clock divisor register */ 147 #else 148 # define pWTCON 0x53000000 149 # define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ 150 # define INTSUBMSK 0x4A00001C 151 # define CLKDIVN 0x4C000014 /* clock divisor register */ 152 # endif 153 154 ldr r0, =pWTCON 155 mov r1, #0x0 156 str r1, [r0] 157 158 /* 159 * mask all IRQs by setting all bits in the INTMR - default 160 */ 161 mov r1, #0xffffffff 162 ldr r0, =INTMSK 163 str r1, [r0] 164 # if defined(CONFIG_S3C2410) 165 ldr r1, =0x3ff 166 ldr r0, =INTSUBMSK 167 str r1, [r0] 168 # endif 169 170 /* FCLK:HCLK:PCLK = 1:2:4 */ 171 /* default FCLK is 120 MHz ! */ 172 ldr r0, =CLKDIVN 173 mov r1, #3 174 str r1, [r0] 175 #endif /* CONFIG_S3C24X0 */ 176 177 /* 178 * we do sys-critical inits only at reboot, 179 * not when booting from ram! 180 */ 181 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 182 bl cpu_init_crit 183 #endif 184 185 bl _main 186 187 /*------------------------------------------------------------------------------*/ 188 189 /* 190 * void relocate_code (addr_sp, gd, addr_moni) 191 * 192 * This "function" does not return, instead it continues in RAM 193 * after relocating the monitor code. 194 * 195 */ 196 .globl relocate_code 197 relocate_code: 198 mov r4, r0 /* save addr_sp */ 199 mov r5, r1 /* save addr of gd */ 200 mov r6, r2 /* save addr of destination */ 201 202 adr r0, _start 203 cmp r0, r6 204 moveq r9, #0 /* no relocation. relocation offset(r9) = 0 */ 205 beq relocate_done /* skip relocation */ 206 mov r1, r6 /* r1 <- scratch for copy_loop */ 207 ldr r3, _bss_start_ofs 208 add r2, r0, r3 /* r2 <- source end address */ 209 210 copy_loop: 211 ldmia r0!, {r9-r10} /* copy from source address [r0] */ 212 stmia r1!, {r9-r10} /* copy to target address [r1] */ 213 cmp r0, r2 /* until source end address [r2] */ 214 blo copy_loop 215 216 #ifndef CONFIG_SPL_BUILD 217 /* 218 * fix .rel.dyn relocations 219 */ 220 ldr r0, _TEXT_BASE /* r0 <- Text base */ 221 sub r9, r6, r0 /* r9 <- relocation offset */ 222 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ 223 add r10, r10, r0 /* r10 <- sym table in FLASH */ 224 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ 225 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ 226 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ 227 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ 228 fixloop: 229 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ 230 add r0, r0, r9 /* r0 <- location to fix up in RAM */ 231 ldr r1, [r2, #4] 232 and r7, r1, #0xff 233 cmp r7, #23 /* relative fixup? */ 234 beq fixrel 235 cmp r7, #2 /* absolute fixup? */ 236 beq fixabs 237 /* ignore unknown type of fixup */ 238 b fixnext 239 fixabs: 240 /* absolute fix: set location to (offset) symbol value */ 241 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ 242 add r1, r10, r1 /* r1 <- address of symbol in table */ 243 ldr r1, [r1, #4] /* r1 <- symbol value */ 244 add r1, r1, r9 /* r1 <- relocated sym addr */ 245 b fixnext 246 fixrel: 247 /* relative fix: increase location by offset */ 248 ldr r1, [r0] 249 add r1, r1, r9 250 fixnext: 251 str r1, [r0] 252 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ 253 cmp r2, r3 254 blo fixloop 255 #endif 256 257 relocate_done: 258 259 mov pc, lr 260 261 _rel_dyn_start_ofs: 262 .word __rel_dyn_start - _start 263 _rel_dyn_end_ofs: 264 .word __rel_dyn_end - _start 265 _dynsym_start_ofs: 266 .word __dynsym_start - _start 267 268 .globl c_runtime_cpu_setup 269 c_runtime_cpu_setup: 270 271 mov pc, lr 272 273 /* 274 ************************************************************************* 275 * 276 * CPU_init_critical registers 277 * 278 * setup important registers 279 * setup memory timing 280 * 281 ************************************************************************* 282 */ 283 284 285 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 286 cpu_init_crit: 287 /* 288 * flush v4 I/D caches 289 */ 290 mov r0, #0 291 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 292 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 293 294 /* 295 * disable MMU stuff and caches 296 */ 297 mrc p15, 0, r0, c1, c0, 0 298 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 299 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 300 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 301 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 302 mcr p15, 0, r0, c1, c0, 0 303 304 /* 305 * before relocating, we have to setup RAM timing 306 * because memory timing is board-dependend, you will 307 * find a lowlevel_init.S in your board directory. 308 */ 309 mov ip, lr 310 311 bl lowlevel_init 312 313 mov lr, ip 314 mov pc, lr 315 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 316 317 /* 318 ************************************************************************* 319 * 320 * Interrupt handling 321 * 322 ************************************************************************* 323 */ 324 325 @ 326 @ IRQ stack frame. 327 @ 328 #define S_FRAME_SIZE 72 329 330 #define S_OLD_R0 68 331 #define S_PSR 64 332 #define S_PC 60 333 #define S_LR 56 334 #define S_SP 52 335 336 #define S_IP 48 337 #define S_FP 44 338 #define S_R10 40 339 #define S_R9 36 340 #define S_R8 32 341 #define S_R7 28 342 #define S_R6 24 343 #define S_R5 20 344 #define S_R4 16 345 #define S_R3 12 346 #define S_R2 8 347 #define S_R1 4 348 #define S_R0 0 349 350 #define MODE_SVC 0x13 351 #define I_BIT 0x80 352 353 /* 354 * use bad_save_user_regs for abort/prefetch/undef/swi ... 355 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 356 */ 357 358 .macro bad_save_user_regs 359 sub sp, sp, #S_FRAME_SIZE 360 stmia sp, {r0 - r12} @ Calling r0-r12 361 ldr r2, IRQ_STACK_START_IN 362 ldmia r2, {r2 - r3} @ get pc, cpsr 363 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 364 365 add r5, sp, #S_SP 366 mov r1, lr 367 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 368 mov r0, sp 369 .endm 370 371 .macro irq_save_user_regs 372 sub sp, sp, #S_FRAME_SIZE 373 stmia sp, {r0 - r12} @ Calling r0-r12 374 add r7, sp, #S_PC 375 stmdb r7, {sp, lr}^ @ Calling SP, LR 376 str lr, [r7, #0] @ Save calling PC 377 mrs r6, spsr 378 str r6, [r7, #4] @ Save CPSR 379 str r0, [r7, #8] @ Save OLD_R0 380 mov r0, sp 381 .endm 382 383 .macro irq_restore_user_regs 384 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 385 mov r0, r0 386 ldr lr, [sp, #S_PC] @ Get PC 387 add sp, sp, #S_FRAME_SIZE 388 /* return & move spsr_svc into cpsr */ 389 subs pc, lr, #4 390 .endm 391 392 .macro get_bad_stack 393 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 394 395 str lr, [r13] @ save caller lr / spsr 396 mrs lr, spsr 397 str lr, [r13, #4] 398 399 mov r13, #MODE_SVC @ prepare SVC-Mode 400 @ msr spsr_c, r13 401 msr spsr, r13 402 mov lr, pc 403 movs pc, lr 404 .endm 405 406 .macro get_irq_stack @ setup IRQ stack 407 ldr sp, IRQ_STACK_START 408 .endm 409 410 .macro get_fiq_stack @ setup FIQ stack 411 ldr sp, FIQ_STACK_START 412 .endm 413 414 /* 415 * exception handlers 416 */ 417 .align 5 418 undefined_instruction: 419 get_bad_stack 420 bad_save_user_regs 421 bl do_undefined_instruction 422 423 .align 5 424 software_interrupt: 425 get_bad_stack 426 bad_save_user_regs 427 bl do_software_interrupt 428 429 .align 5 430 prefetch_abort: 431 get_bad_stack 432 bad_save_user_regs 433 bl do_prefetch_abort 434 435 .align 5 436 data_abort: 437 get_bad_stack 438 bad_save_user_regs 439 bl do_data_abort 440 441 .align 5 442 not_used: 443 get_bad_stack 444 bad_save_user_regs 445 bl do_not_used 446 447 #ifdef CONFIG_USE_IRQ 448 449 .align 5 450 irq: 451 get_irq_stack 452 irq_save_user_regs 453 bl do_irq 454 irq_restore_user_regs 455 456 .align 5 457 fiq: 458 get_fiq_stack 459 /* someone ought to write a more effiction fiq_save_user_regs */ 460 irq_save_user_regs 461 bl do_fiq 462 irq_restore_user_regs 463 464 #else 465 466 .align 5 467 irq: 468 get_bad_stack 469 bad_save_user_regs 470 bl do_irq 471 472 .align 5 473 fiq: 474 get_bad_stack 475 bad_save_user_regs 476 bl do_fiq 477 478 #endif
40行是代码的入口:
.globl _start _start: b start_code
然后跳转到start_code处:
start_code: /* * set the cpu to SVC32 mode */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr cpsr, r0 #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) /* * relocate exception table */ ldr r0, =_start ldr r1, =0x0 mov r2, #16 copyex: subs r2, r2, #1 ldr r3, [r0], #4 str r3, [r1], #4 bne copyex #endif #ifdef CONFIG_S3C24X0 /* turn off the watchdog */ # if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ # define CLKDIVN 0x14800014 /* clock divisor register */ #else # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ # endif ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #endif /* CONFIG_S3C24X0 */ /* * we do sys-critical inits only at reboot, * not when booting from ram! */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit #endif bl _main
前面几行代码将切换到svc32模式。
之后会判断是否配置了CONFIG_AT91RM9200DK或者CONFIG_AT91RM9200EK,
而从include/configs/smdk2410.h文件中没有这样的配置,所以这几行代码不被执行。
然后会判断是否定义了CONFIG_S3C24X0(smdk2410确实配置了这个选项),
然后根据是否定义了CONFIG_S3C2400(smdk2410没有配置这个选项)来确定pWTCON、INTMSK、CLKDIVN等寄存器的地址。
接下来关闭看门狗:
ldr r0, =pWTCON mov r1, #0x0 str r1, [r0]
接着设置中断屏蔽寄存器的值为0xffffffff:
mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0]
接着配置副中断屏蔽寄存器的值为0x3ff(总共有11个有效位,所以0x3ff表示第11位未屏蔽)
# if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif
然后对分频进行设置:
而CLKDIVN最低位为0(CLKDIVN[0])时表示PCLK与HCLK相同,为1表示PCLK等于HCLK的1/2。
而CLKDIVN次低两位(CLKDIVN[2:1])为0时表示HCLK等于FCLK,为1时表示HCLK等于FCLK的1/2.
/* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0]
因为没有定义CONFIG_SKIP_LOWLEVEL_INIT,所以接下来会跳转到cpu_init_crit:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
cpu_init_crit代码如下:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT cpu_init_crit: /* * flush v4 I/D caches */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ /* * disable MMU stuff and caches */ mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) orr r0, r0, #0x00000002 @ set bit 2 (A) Align orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0 /* * before relocating, we have to setup RAM timing * because memory timing is board-dependend, you will * find a lowlevel_init.S in your board directory. */ mov ip, lr bl lowlevel_init mov lr, ip mov pc, lr #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
cpu_init_crit功能先flush Cache和TLB,然后禁止MMU和Cache,然后会跳转到lowlevel_init执行。
lowlevel_init位于board/samsung/smdk2410/lowlevel_init.S文件,代码如下:
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init lowlevel_init: /* memory control configuration */ /* make r0 relative the current location so that it */ /* reads SMRDATA out of FLASH rather than memory ! */ ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 ldr r1, =BWSCON /* Bus Width Status Controller */ add r2, r0, #13*4 0: ldr r3, [r0], #4 str r3, [r1], #4 cmp r2, r0 bne 0b /* everything is fine now */ mov pc, lr
.ltorg
/* the literal pools origin */
SMRDATA:
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0x32
.word 0x30
.word 0x30
lowlevel_init用于初始化SDRAM,对2410的bank0-bank7都进行初始化。寄存器含义可以查看http://www.embedu.org/Column/Column169.htm
接下来就是执行“bl _main”跳转到_main函数,这属于第二阶段初始化的内容,在下一篇博文中再进行讲述。
总之,第一阶段初始化内容如下:
(1)进入SVC32模式
(2)关闭看门狗,屏蔽中断
(3)设置分频(FCLK:HCLK:PCLK = 1:2:4)
(4)Flush Cache和TLB, 禁止MMU和Cache
(5)初始化SDRAM(即配置Bank0-Bank7)
posted on 2014-05-14 13:52 qiaoqiao2003 阅读(1087) 评论(0) 编辑 收藏 举报