Uboot 分析(4)

还记得上节中,u-boot.lds文件连接的内容吗??

代码段  数据段  命令段   bss段

下面来看第一部分:代码段,对应于uboot的第一阶段 start.S文件

附上代码:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<span style= "font-size: 14px;" >#include <config.h>
#include <version.h>
 
 
/*
  *************************************************************************
  *
  * Jump vector table as in table 3.1 in [1]
  *
  *************************************************************************
  */
 
 
.globl _start    /*声明一个全局变量,可以被其他文件引用*/
_start: b       reset       /* 复位 */ b是不带返回的跳转(bl是带返回的跳转),意思是无条件直接跳转到_start执行程序
     <span style= "color: #ff0000;" >ldr   pc, _undefined_instruction</span>     /* 未定义指令向量 ldr相当于mov操作*/
     ldr pc, _software_interrupt
     ldr pc, _prefetch_abort
     ldr pc, _data_abort
     ldr pc, _not_used
     ldr pc, _irq
     ldr pc, _fiq
/*  中断向量表入口地址 */
_undefined_instruction: .word undefined_instruction      /*就是在当前地址,即_undefined_instruction 处存放 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
/*  word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的expr初始化*/ <br><br>
     .balignl 16,0xdeadbeef
 
/*</span><br><br>

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<span style= "font-size: 14px;" >*/
/*
  *************************************************************************
  *
  * Startup Code (reset vector)
  *
  * do important init only if we don't start from memory!
  * relocate armboot to ram
  * setup stack
  * jump to second stage
  *
  *************************************************************************
  */
 
_TEXT_BASE:
     .word   TEXT_BASE    </span><br><br><span style= "font-size: 14px;" >/*_TEXT_BASE:   .word    TEXT_BASE  //0x33F80000,在board/smdk2410/config.mk中</span>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
<span style= "font-size: 14px;" >这段话表示,用户告诉编译器<span style= "color: #ff0000;" >编译地址</span>的起始地址*/
 
.globl _armboot_start
_armboot_start:
     .word _start
 
/*
  * These are defined in the board-specific linker script.
  */
.globl _bss_start
_bss_start:
     .word __bss_start
 
.globl _bss_end
_bss_end:
     .word _end
 
#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
     .word   0x0badc0de
 
/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
     .word 0x0badc0de
#endif
 
 
/*
  * the actual reset code
  */
 
reset:
     /*
      * set the cpu to SVC32 mode
      */
     mrs r0,cpsr
     bic r0,r0,#0x1f   /*工作模式位清零*/
     orr r0,r0,#0xd3   /*工作模式位设置为“10011”(管理模式),并将中断禁止位和快中断禁止位置1 */
     msr cpsr,r0
/*<span> 以上代码将CPU的工作模式位设置为管理模式,即设置相应的CPSR程序状态字,并将中断禁止位和快中断禁止位置一,<br>从而屏蔽了IRQ和FIQ中断。</span>*/ <br>
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON     0x15300000
# define INTMSK     0x14400008  /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014  /* clock divisor register */
#elif defined(CONFIG_S3C2410)
# define pWTCON     0x53000000
# define INTMSK     0x4A000008  /* Interupt-Controller base addresses */
# define INTSUBMSK  0x4A00001C
# define CLKDIVN    0x4C000014  /* clock divisor register */
#endif
<br> /*<span> 以上代码完成了WATCHDOG,INTMSK,INTSUBMSK,CLKDIVN四个寄存器的地址的设置</span>*/
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
     ldr     r0, =pWTCON
     mov     r1, #0x0
     str     r1, [r0]
 
     /*
     <span style="color: #ff0000;"> * mask all IRQs by setting all bits in the INTMR - default</span>
      */
     mov r1, #0xffffffff
     ldr r0, =INTMSK
     str r1, [r0]
# if defined(CONFIG_S3C2410)
     ldr r1, =0x3ff
     ldr r0, =INTSUBMSK
     str r1, [r0]
# endif
/*<span style="color: #ff0000;"><strong>设置MPLLCON,UPLLCON, CLKDIVN</strong>*</span>/
     /* FCLK:HCLK:PCLK = 1:2:4 */
     /* default FCLK is 120 MHz ! */
     ldr r0, =CLKDIVN
     mov r1, #3
     str r1, [r0]
#endif  /* CONFIG_S3C2400 || CONFIG_S3C2410 */
 
     /*
      * we do sys-critical inits only at reboot,
      * not when booting from ram!
      */ <br> /*接着往下看:*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
     bl  cpu_init_crit <span> /* </span><span>;跳转并把转移后面紧接的一条指令地址保存到链接寄存器LR(R14)中,<br>                      以此来完成子程序的调用*/ </span> 
#endif
 
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:               /* relocate U-Boot to RAM       */
     adr r0, _start      /* r0 <- current position of code   */
     ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */
     cmp     r0, r1                  /* don't reloc during debug         */
     beq     stack_setup
 
     ldr r2, _armboot_start
     ldr r3, _bss_start
     sub r2, r3, r2      /* r2 <- size of armboot            */
     add r2, r0, r2      /* r2 <- source end address         */
 
copy_loop:
     ldmia   r0!, {r3-r10}       /* copy from source address [r0]    */
     stmia   r1!, {r3-r10}       /* copy to   target address [r1]    */
     cmp r0, r2          /* until source end addreee [r2]    */
     ble copy_loop
#endif  /* CONFIG_SKIP_RELOCATE_UBOOT */
 
     /* Set up the stack                         */
stack_setup:
     ldr r0, _TEXT_BASE      /* upper 128 KiB: relocated uboot   */
     sub r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
     sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */
#ifdef CONFIG_USE_IRQ
     sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
     sub sp, r0, #12     /* leave 3 words for abort-stack    */
 
clear_bss:
     ldr r0, _bss_start      /* find start of bss segment        */
     ldr r1, _bss_end        /* stop here                        */
     mov     r2, #0x00000000     /* clear                            */
 
clbss_l:str r2, [r0]        /* clear loop...                    */
     add r0, r0, #4
     cmp r0, r1
     ble clbss_l
 
#if 0
     /* try doing this stuff after the relocation */
     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, =INTMR
     str r1, [r0]
 
     /* FCLK:HCLK:PCLK = 1:2:4 */
     /* default FCLK is 120 MHz ! */
     ldr r0, =CLKDIVN
     mov r1, #3
     str r1, [r0]
     /* END stuff after relocation */
#endif
 
     ldr pc, _start_armboot
 
_start_armboot: .word start_armboot
 
 
/*
  *************************************************************************
  *
  * CPU_init_critical registers
  *
  * setup important registers
  * setup memory timing
  *
  *************************************************************************
  */
 
 
#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 */
 
/*
  *************************************************************************
  *
  * Interrupt handling
  *
  *************************************************************************
  */
 
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72
 
#define S_OLD_R0    68
#define S_PSR       64
#define S_PC        60
#define S_LR        56
#define S_SP        52
 
#define S_IP        48
#define S_FP        44
#define S_R10       40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0
 
#define MODE_SVC 0x13
#define I_BIT    0x80
 
/*
  * use bad_save_user_regs for abort/prefetch/undef/swi ...
  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
  */
 
     .macro  bad_save_user_regs
     sub sp, sp, #S_FRAME_SIZE
     stmia   sp, {r0 - r12}          @ Calling r0-r12
     ldr r2, _armboot_start
     sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
     sub r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort  stack
     ldmia   r2, {r2 - r3}           @ get pc, cpsr
     add r0, sp, #S_FRAME_SIZE       @ restore sp_SVC
 
     add r5, sp, #S_SP
     mov r1, lr
     stmia   r5, {r0 - r3}           @ save sp_SVC, lr_SVC, pc, cpsr
     mov r0, sp
     .endm
 
     .macro  irq_save_user_regs
     sub sp, sp, #S_FRAME_SIZE
     stmia   sp, {r0 - r12}          @ Calling r0-r12
     add     r8, sp, #S_PC
     stmdb   r8, {sp, lr}^                   @ Calling SP, LR
     str     lr, [r8, #0]                    @ Save calling PC
     mrs     r6, spsr
     str     r6, [r8, #4]                    @ Save CPSR
     str     r0, [r8, #8]                    @ Save OLD_R0
     mov r0, sp
     .endm
 
     .macro  irq_restore_user_regs
     ldmia   sp, {r0 - lr}^          @ Calling r0 - lr
     mov r0, r0
     ldr lr, [sp, #S_PC]         @ Get PC
     add sp, sp, #S_FRAME_SIZE
     subs    pc, lr, #4          @ return  & move spsr_svc into cpsr
     .endm
 
     .macro get_bad_stack
     ldr r13, _armboot_start     @ setup our mode stack
     sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
     sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort  stack
 
     str lr, [r13]           @ save caller lr / spsr
     mrs lr, spsr
     str     lr, [r13, #4]
 
     mov r13, #MODE_SVC          @ prepare SVC-Mode
     @ msr   spsr_c, r13
     msr spsr, r13
     mov lr, pc
     movs    pc, lr
     .endm
 
     .macro get_irq_stack            @ setup IRQ stack
     ldr sp, IRQ_STACK_START
     .endm
 
     .macro get_fiq_stack            @ setup FIQ stack
     ldr sp, FIQ_STACK_START
     .endm
 
/*
  * exception handlers
  */
     .align  5
undefined_instruction:
     get_bad_stack
     bad_save_user_regs
     bl  do_undefined_instruction
 
     .align  5
software_interrupt:
     get_bad_stack
     bad_save_user_regs
     bl  do_software_interrupt
 
     .align  5
prefetch_abort:
     get_bad_stack
     bad_save_user_regs
     bl  do_prefetch_abort
 
     .align  5
data_abort:
     get_bad_stack
     bad_save_user_regs
     bl  do_data_abort
 
     .align  5
not_used:
     get_bad_stack
     bad_save_user_regs
     bl  do_not_used
 
#ifdef CONFIG_USE_IRQ
 
     .align  5
irq:
     get_irq_stack
     irq_save_user_regs
     bl  do_irq
     irq_restore_user_regs
 
     .align  5
fiq:
     get_fiq_stack
     /* someone ought to write a more effiction fiq_save_user_regs */
     irq_save_user_regs
     bl  do_fiq
     irq_restore_user_regs
 
#else
 
     .align  5
irq:
     get_bad_stack
     bad_save_user_regs
     bl  do_irq
 
     .align  5
fiq:
     get_bad_stack
     bad_save_user_regs
     bl  do_fiq
 
#endif
</span>

  上面给出了代码的部分相关注释,个人学习uboot的总结是,要仔细的反复熟读源码框架,然后再进行不停地分析明一条指令

  下节具体分析第一阶段的源码,以及为什么要那么做??

你可能感兴趣的:(Uboot 分析(4))