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、INTMSKCLKDIVN等寄存器的地址。

接下来关闭看门狗:

    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)

原文地址:https://www.cnblogs.com/qiaoqiao2003/p/3726958.html