uboot 分析之一 start.S

来源:互联网 发布:通过交换数据位运算 编辑:程序博客网 时间:2024/04/30 08:22

 最近给 Mini6410 添加开机启动画面和操作系统未启动时充电管理画面。使用的平台是友善的mini6410。
      由于操作系统未启动,大部分工作要在UBoot里进行完成。现在充电管理和开机动画基本实现,呵呵,中间经历了N多磨难啊 现在把做的工作记录下来。
      前面有两篇文章是介绍UBoot的makefile的。我们从makefile中看到编译生成的第一个目标文件是start.o,现在我们就从start.s进行分析。
      系统刚启动没有准备好C运行的堆栈,所以start.s实现为汇编。

[cpp] view plaincopyprint?
  1. #include <config.h>  
  2. #include <version.h>  
  3. #ifdef CONFIG_ENABLE_MMU  
  4. #include <asm/proc/domain.h>  
  5. #endif  
  6. #include <regs.h>  
  7.   
  8. #ifndef CONFIG_ENABLE_MMU  
  9. #ifndef CFG_PHY_UBOOT_BASE  
  10. #define CFG_PHY_UBOOT_BASE CFG_UBOOT_BASE //使用了MMU 此处值为 0xc7e00000  
  11. #endif  
  12. #endif  
  13.   
  14. /* 
  15.  ************************************************************************* 
  16.  * 
  17.  * Jump vector table as in table 3.1 in [1] 
  18.  * 
  19.  ************************************************************************* 
  20.  */  
  21. /*异常向量表*/  
  22. .globl _start  
  23. _start: b reset  
  24.  ldr pc, _undefined_instruction  
  25.  ldr pc, _software_interrupt  
  26.  ldr pc, _prefetch_abort  
  27.  ldr pc, _data_abort  
  28.  ldr pc, _not_used  
  29.  ldr pc, _irq  
  30.  ldr pc, _fiq  
  31. /*在当前标号_undefined_instruction所在的地址处放入四字节的数据,这个数据就是undefined_instruction标号  
  32. /* 的地址.意思就是说在当前_undefined_instruction对应的地址中放的是undefined_instruction的地址  
  33. /*word伪操作用于分配一段字内存单元(分配的单元都是字对齐的),并用伪操作中的expr初始化。.long和.int作用与之相同。 
  34. _undefined_instruction: 
  35.  .word undefined_instruction 
  36. _software_interrupt: 
  37.  .word software_interrupt 
  38. _prefetch_abort: 
  39.  .word prefetch_abort 
  40. _data_abort: 
  41.  .word data_abort 
  42. _not_used: 
  43.  .word not_used 
  44. _irq: 
  45.  .word irq 
  46. _fiq: 
  47.  .word fiq 
  48. _pad: 
  49.  .word 0x12345678 /* now 16*4=64 */  
  50. .global _end_vect  
  51. _end_vect:  
  52.   
  53.  .balignl 16,0xdeadbeef  
  54. /* 
  55.  ************************************************************************* 
  56.  * 
  57.  * Startup Code (reset vector) 
  58.  * 
  59.  * do important init only if we don't start from memory! 
  60.  * setup Memory and board specific bits prior to relocation. 
  61.  * relocate armboot to ram 
  62.  * setup stack 
  63.  * 
  64.  ************************************************************************* 
  65.  */  
  66. /*TEXT_BASE 在/board/config.mk文档中定义, 他定义了代码在运行时所在的地址, _TEXT_BASE中保存了这个地址 
  67. _TEXT_BASE: 
  68.  .word TEXT_BASE 
  69.  
  70. /* 
  71.  * Below variable is very important because we use MMU in U-Boot. 
  72.  * Without it, we cannot run code correctly before MMU is ON. 
  73.  * by scsuh. 
  74.  */  
  75. _TEXT_PHY_BASE:  
  76.  .word CFG_PHY_UBOOT_BASE /*使用了MMU 此处值为 0xc7e00000*/  
  77.   
  78.   
  79. .globl _armboot_start/*声明全局标志. 声明的该标号_armboot_start可以被外部使用*/  
  80. _armboot_start:  
  81.  .word _start  
  82.   
  83. /* 
  84.  * These are defined in the board-specific linker script. 
  85.  */  
  86. /* 
  87. BSS段 数据段 代码段 堆栈 
  88. 声明:大部分来自于维基百科,自由的百科全书。 
  89. BSS段:在采用段式内存管理的架构中,BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。 
  90. 数据段:在采用段式内存管理的架构中,数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。 
  91. 代码段:在采用段式内存管理的架构中,代码段(codesegment / text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许自修改程序。 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。 
  92. 堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减) 
  93. 栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。 
  94. */  
  95. .globl _bss_start //bss段开始  
  96. _bss_start:  
  97.  .word __bss_start  
  98.   
  99. .globl _bss_end //bss段结束  
  100. _bss_end:  
  101.  .word _end  
  102.   
  103. #ifdef CONFIG_USE_IRQ  
  104. /* IRQ stack memory (calculated at run-time) */  
  105. .globl IRQ_STACK_START/*预处理标号 目的:让IRQ_STACK_START指向地址0x0badc0de(这个需要根据硬件更改)*/  
  106. IRQ_STACK_START:  
  107.  .word 0x0badc0de  
  108.   
  109. /* IRQ stack memory (calculated at run-time) */  
  110. .globl FIQ_STACK_START  
  111. FIQ_STACK_START:  
  112.  .word 0x0badc0de  
  113. #endif  
  114.   
  115. /* 
  116.  * the actual reset code 
  117.  */  
  118. /* 开机及中断跳转到此 
  119. reset:/* * set the cpu to SVC32 mode 
  120.   */  
  121. /*EC: 模式位清零*//*bic是位清零(Bit Clear)指令,本语句是把r0的Bit[4:0]位清零(由0x1F指示),然后把结果写入r0中。*/           
  122. /*EC: 工作模式位设置为10011,为管理模式,irq fiq设置为1,屏蔽中断*/   
  123. /*orr指令是按位求或,本语句是r0的 Bit7,Bit6,Bit4,Bit1,Bit0 置为1,其它位保持不变。*/  
  124. /*执行完上述操作后,cpsr中的 I=1, F=1, T保持不变(默认为0),M[4:0]=10011,意思是禁止IRQ,禁止FIQ,/*执行完上述操作后,cpsr中的 I=1, F=1, T保持不变(默认为0),M[4:0]=10011,意思是禁止IRQ,禁止FIQ,工作在ARM状态,工作在SVC32模式。*/  
  125.  mrs r0,cpsr  
  126.  bic r0,r0,#0x1f  
  127.  orr r0,r0,#0xd3  
  128.  msr cpsr,r0  
  129.   
  130. /* 
  131.  ************************************************************************* 
  132.  * 
  133.  * CPU_init_critical registers 
  134.  * 
  135.  * setup important registers 
  136.  * setup memory timing 
  137.  * 
  138.  ************************************************************************* 
  139.  */  
  140.          /* 
  141.          * we do sys-critical inits only at reboot, 
  142.          * not when booting from ram! 
  143.          */  
  144. cpu_init_crit:  
  145.  /* 
  146.   * flush v4 I/D caches 
  147.   *//*数据处理指令对于存放在寄存器中的数据进行操作。*/   
  148.  mov r0, #0  
  149.  mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */  
  150.  mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */  
  151. /*协处理器指令用于扩展指令集P协处理器指令可用于提供附加的计算能力,有可用于控制包括cache和内存 
  152.  * 管理的存储子系统。协处理器指令包括数据处理指令,寄存器传输指令及内存传输指令。协处理器指令只用于带 
  153.  * 有协处理器的ARM内核。 
  154.  * CDP {<cond>} cp, opcode1, Cd, Cn{,opcode2}  协处理器数据处理 -- 在协处理器内部执行一个数据处理操作 
  155.  * <MRC/MCR> {<cond>} cp, opcode1, Rd, Cn, Cm{,opcode2} 协处理器寄存器传输 -- 把数据送入/取出协处理器寄存器 
  156.  * <LDC/STC> {<cod>} cp, Cd, addressing  协处理器内存比较 -- 从协处理器装载/存储一个内存数据块 
  157.  * 其中:cp域代表协处理器的编号,为p0~P15. opcode域描述要在协处理器中进行的操作。Cn, Cm及Cd描述在协处理器中的寄存器。 
  158.  * 协处理器15(CP15)是为系统控制预留的,如内存管理,写缓冲控制,cache控制及寄存器识别等。 
  159.  * MRC p15,0,r10,c0,c0,0 把协处理器15寄存器c0的内容拷贝到r10中,cp15寄存器c0中包含处理器标识,其内容拷贝到通用寄存器r10 
  160.  */   
  161.  /* 
  162.   * disable MMU stuff and caches 
  163.   */  
  164.  mrc p15, 0, r0, c1, c0, 0  
  165.  bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)  
  166.  bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)  
  167.  orr r0, r0, #0x00000002 @ set bit 2 (A) Align  
  168.  orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache  
  169.  mcr p15, 0, r0, c1, c0, 0  
  170.   
  171.  /* Peri port setup */  
  172.  ldr r0, =0x70000000  
  173.  orr r0, r0, #0x13  
  174.      mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)  
  175.   
  176.   
  177.  /* 
  178.   * Go setup Memory and board specific bits prior to relocation. 
  179.   */  
  180.  bl lowlevel_init /* go setup pll,mux,memory */  
  181.   
  182.  /* when we already run in ram, we don't need to relocate U-Boot. 
  183.   * and actually, memory controller must be configured before U-Boot 
  184.   * is running in ram. 
  185.   *//*此处如果当前地址和原始定义的起始地址相同则跳过代码复制*/  
  186.  ldr r0, =0xff000fff  
  187.  bic r1, pc, r0 /* r0 <- current base addr of code */  
  188.  ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */  
  189.  bic r2, r2, r0 /* r0 <- current base addr of code */  
  190.  cmp r1, r2 /* compare r0, r1 */  
  191.  beq after_copy /* r0 == r1 then skip flash copy */  
  192.   
  193. #ifdef CONFIG_BOOT_NAND  
  194.  mov r0, #0x1000  
  195.  bl copy_from_nand /*copy uboot to ram from nand*/  
  196. #endif  
  197.   
  198. after_copy: /*对指示灯进行操作*/  
  199.  ldr r0, =ELFIN_GPIO_BASE  
  200.  ldr r1, =0xC00  
  201.  str r1, [r0, #GPPDAT_OFFSET]  
  202.  ldr r1, [r0, #GPFPUD_OFFSET]  
  203.  bic r1, r1, #0xc0000000  
  204.  orr r1, r1, #0x80000000  
  205.  str r1, [r0, #GPFPUD_OFFSET]  
  206.  ldr r1, [r0, #GPFDAT_OFFSET]  
  207.  orr r1, r1, #0x8000  
  208.  str r1, [r0, #GPFDAT_OFFSET]  
  209.  ldr r1, [r0, #GPFCON_OFFSET]  
  210.  bic r1, r1, #0xc0000000  
  211.  orr r1, r1, #0x40000000  
  212.  str r1, [r0, #GPFCON_OFFSET]  
  213.   
  214.   
  215. #ifdef CONFIG_ENABLE_MMU  
  216. enable_mmu:  
  217.  /* enable domain access */  
  218.  ldr r5, =0x0000ffff  
  219.  mcr p15, 0, r5, c3, c0, 0 @ load domain access register  
  220.   
  221.  /* Set the TTB register */  
  222.  ldr r0, _mmu_table_base  
  223.  ldr r1, =CFG_PHY_UBOOT_BASE  
  224.  ldr r2, =0xfff00000  
  225.  bic r0, r0, r2  
  226.  orr r1, r0, r1  
  227.  mcr p15, 0, r1, c2, c0, 0  
  228.   
  229.  /* Enable the MMU */  
  230. mmu_on:  
  231.  mrc p15, 0, r0, c1, c0, 0  
  232.  orr r0, r0, #1 /* Set CR_M to enable MMU */  
  233.  mcr p15, 0, r0, c1, c0, 0  
  234.  nop  
  235.  nop  
  236.  nop  
  237.  nop  
  238. #endif  
  239.   
  240. skip_hw_init:  
  241.  /* Set up the stack */  
  242. stack_setup: //设置栈地址   
  243. #ifdef CONFIG_MEMORY_UPPER_CODE  
  244.  ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0xc)  
  245. #endif  
  246. //设置BSS段  
  247. clear_bss:  
  248.  ldr r0, _bss_start /* find start of bss segment */  
  249.  ldr r1, _bss_end /* stop here */  
  250.  mov r2, #0x00000000 /* clear */  
  251.   
  252. clbss_l:  
  253.  str r2, [r0] /* clear loop... */  
  254.  add r0, r0, #4  
  255.  cmp r0, r1  
  256.  ble clbss_l  
  257.   
  258.  ldr pc, _start_armboot /*跳转到SDRAM中运行*/  
  259.   
  260. _start_armboot:          
  261.  .word start_armboot  
  262.   
  263. #ifdef CONFIG_ENABLE_MMU  
  264. _mmu_table_base:  
  265.  .word mmu_table  
  266. #endif  
  267.   
  268. /* 
  269.  * copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND) 
  270.  * r0: size to be compared 
  271.  * Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size 
  272.  */  
  273.  .globl copy_from_nand  
  274. copy_from_nand:  
  275.  mov r10, lr /* save return address */  
  276.   
  277.  mov r9, r0  
  278.  /* get ready to call C functions */  
  279.  ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */  
  280.  sub sp, sp, #12  
  281.  mov fp, #0 /* no previous frame, so fp=0 */  
  282.  mov r9, #0x1000  
  283. // ldr r0, =ELFIN_UART_BASE  
  284. // ldr r1, =0x4b4b4b4b  
  285. // str r1, [r0, #UTXH_OFFSET]  
  286.  bl copy_uboot_to_ram  
  287.   
  288. 3: tst r0, #0x0 /*copy_uboot_to_ram返回0 复制成功*/  
  289.  bne copy_failed  
  290.  /*Stepping Stone start address 0x0c000000*/  
  291.  ldr r0, =0x0c000000  
  292.  ldr r1, _TEXT_PHY_BASE  
  293. 1: ldr r3, [r0], #4  
  294.  ldr r4, [r1], #4  
  295.  teq r3, r4  
  296.  bne compare_failed /* not matched */  
  297.  subs r9, r9, #4  
  298.  bne 1b /* 此处循环测了一段4k 相同 */  
  299.   
  300. 4: mov lr, r10 /* all is OK */  
  301.  mov pc, lr  
  302.   
  303. copy_failed:  
  304.  nop /* copy from nand failed */  
  305.  b copy_failed  
  306.   
  307. compare_failed:  
  308.  nop /* compare failed */  
  309.  b compare_failed  
  310.   
  311. /* 
  312.  * we assume that cache operation is done before. (eg. cleanup_before_linux()) 
  313.  * actually, we don't need to do anything about cache if not use d-cache in U-Boot 
  314.  * So, in this function we clean only MMU. by scsuh 
  315.  * 
  316.  * void theLastJump(void *kernel, int arch_num, uint boot_params); 
  317.  */  
  318. #ifdef CONFIG_ENABLE_MMU  
  319.  .globl theLastJump  
  320. theLastJump:  
  321.  mov r9, r0  
  322.  ldr r3, =0xfff00000  
  323.  ldr r4, _TEXT_PHY_BASE  
  324.  adr r5, phy_last_jump  
  325.  bic r5, r5, r3  
  326.  orr r5, r5, r4  
  327.  mov pc, r5  
  328. phy_last_jump:  
  329.  /* 
  330.   * disable MMU stuff 
  331.   */  
  332.  mrc p15, 0, r0, c1, c0, 0  
  333.  bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */  
  334.  bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */  
  335.  orr r0, r0, #0x00000002 /* set bit 2 (A) Align */  
  336.  orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */  
  337.  mcr p15, 0, r0, c1, c0, 0  
  338.   
  339.  mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */  
  340.   
  341.  mov r0, #0  
  342.  mov pc, r9  
  343. #endif  
  344. /* 
  345.  ************************************************************************* 
  346.  * 
  347.  * Interrupt handling 
  348.  * 
  349.  ************************************************************************* 
  350.  */  
  351. @  
  352. @ IRQ stack frame.  
  353. @  
  354. #define S_FRAME_SIZE 72  
  355.   
  356. #define S_OLD_R0 68  
  357. #define S_PSR 64  
  358. #define S_PC 60  
  359. #define S_LR 56  
  360. #define S_SP 52  
  361.   
  362. #define S_IP 48  
  363. #define S_FP 44  
  364. #define S_R10 40  
  365. #define S_R9 36  
  366. #define S_R8 32  
  367. #define S_R7 28  
  368. #define S_R6 24  
  369. #define S_R5 20  
  370. #define S_R4 16  
  371. #define S_R3 12  
  372. #define S_R2 8  
  373. #define S_R1 4  
  374. #define S_R0 0  
  375.   
  376. #define MODE_SVC 0x13  
  377. #define I_BIT 0x80  
  378.   
  379. /* 
  380.  * use bad_save_user_regs for abort/prefetch/undef/swi ... 
  381.  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 
  382.  */  
  383.   
  384.  .macro bad_save_user_regs  
  385.  sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack  
  386.  stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12  
  387.   
  388.  ldr r2, _armboot_start  
  389.  sub r2, r2, #(CFG_MALLOC_LEN)  
  390.  sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack  
  391.  ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs)  
  392.  add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack  
  393.   
  394.  add r5, sp, #S_SP  
  395.  mov r1, lr  
  396.  stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr  
  397.  mov r0, sp @ save current stack into r0 (param register)  
  398.  .endm  
  399.   
  400.  .macro irq_save_user_regs  
  401.  sub sp, sp, #S_FRAME_SIZE  
  402.  stmia sp, {r0 - r12} @ Calling r0-r12  
  403.  add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.  
  404.  stmdb r8, {sp, lr}^ @ Calling SP, LR  
  405.  str lr, [r8, #0] @ Save calling PC  
  406.  mrs r6, spsr  
  407.  str r6, [r8, #4] @ Save CPSR  
  408.  str r0, [r8, #8] @ Save OLD_R0  
  409.  mov r0, sp  
  410.  .endm  
  411.   
  412.  .macro irq_restore_user_regs  
  413.  ldmia sp, {r0 - lr}^ @ Calling r0 - lr  
  414.  mov r0, r0  
  415.  ldr lr, [sp, #S_PC] @ Get PC  
  416.  add sp, sp, #S_FRAME_SIZE  
  417.  subs pc, lr, #4 @ return & move spsr_svc into cpsr  
  418.  .endm  
  419.   
  420.  .macro get_bad_stack  
  421.  ldr r13, _armboot_start @ setup our mode stack (enter in banked mode)  
  422.  sub r13, r13, #(CFG_MALLOC_LEN) @ move past malloc pool  
  423.  sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ move to reserved a couple spots for abort stack  
  424.   
  425.  str lr, [r13] @ save caller lr in position 0 of saved stack  
  426.  mrs lr, spsr @ get the spsr  
  427.  str lr, [r13, #4] @ save spsr in position 1 of saved stack  
  428.   
  429.  mov r13, #MODE_SVC @ prepare SVC-Mode  
  430.  @ msr spsr_c, r13  
  431.  msr spsr, r13 @ switch modes, make sure moves will execute  
  432.  mov lr, pc @ capture return pc  
  433.  movs pc, lr @ jump to next instruction & switch modes.  
  434.  .endm  
  435.   
  436.  .macro get_bad_stack_swi  
  437.  sub r13, r13, #4 @ space on current stack for scratch reg.  
  438.  str r0, [r13] @ save R0's value.  
  439.  ldr r0, _armboot_start @ get data regions start  
  440.  sub r0, r0, #(CFG_MALLOC_LEN) @ move past malloc pool  
  441.  sub r0, r0, #(CFG_GBL_DATA_SIZE+8) @ move past gbl and a couple spots for abort stack  
  442.  str lr, [r0] @ save caller lr in position 0 of saved stack  
  443.  mrs r0, spsr @ get the spsr  
  444.  str lr, [r0, #4] @ save spsr in position 1 of saved stack  
  445.  ldr r0, [r13] @ restore r0  
  446.  add r13, r13, #4 @ pop stack entry  
  447.  .endm  
  448.   
  449.  .macro get_irq_stack @ setup IRQ stack  
  450.  ldr sp, IRQ_STACK_START  
  451.  .endm  
  452.   
  453.  .macro get_fiq_stack @ setup FIQ stack  
  454.  ldr sp, FIQ_STACK_START  
  455.  .endm  
  456.   
  457. /* 
  458.  * exception handlers 
  459.  */  
  460.  .align 5  
  461. undefined_instruction:  
  462.  get_bad_stack  
  463.  bad_save_user_regs  
  464.  bl do_undefined_instruction  
  465.   
  466.  .align 5  
  467. software_interrupt:  
  468.  get_bad_stack_swi  
  469.  bad_save_user_regs  
  470.  bl do_software_interrupt  
  471.   
  472.  .align 5  
  473. prefetch_abort:  
  474.  get_bad_stack  
  475.  bad_save_user_regs  
  476.  bl do_prefetch_abort  
  477.   
  478.  .align 5  
  479. data_abort:  
  480.  get_bad_stack  
  481.  bad_save_user_regs  
  482.  bl do_data_abort  
  483.   
  484.  .align 5  
  485. not_used:  
  486.  get_bad_stack  
  487.  bad_save_user_regs  
  488.  bl do_not_used  
  489.   
  490. #ifdef CONFIG_USE_IRQ  
  491.   
  492.  .align 5  
  493. irq:  
  494.  get_irq_stack  
  495.  irq_save_user_regs  
  496.  bl do_irq  
  497.  irq_restore_user_regs  
  498.   
  499.  .align 5  
  500. fiq:  
  501.  get_fiq_stack  
  502.  /* someone ought to write a more effiction fiq_save_user_regs */  
  503.  irq_save_user_regs  
  504.  bl do_fiq  
  505.  irq_restore_user_regs  
  506.   
  507. #else  
  508.   
  509.  .align 5  
  510. irq:  
  511.  get_bad_stack  
  512.  bad_save_user_regs  
  513.  bl do_irq  
  514.   
  515.  .align 5  
  516. fiq:  
  517.  get_bad_stack  
  518.  bad_save_user_regs  
  519.  bl do_fiq  
  520.   
  521. #endif  
  522.  .align 5  
  523. .global arm1136_cache_flush  
  524. arm1136_cache_flush:  
  525.   mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache  
  526.   mov pc, lr @ back to caller  
  527.   
  528. #if defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_CINTEGRATOR)  
  529. /* Use the IntegratorCP function from board/integratorcp/platform.S */  
  530. #elif defined(CONFIG_S3C64XX)  
  531. /* For future usage of S3C64XX*/  
  532. #else  
  533.  .align 5  
  534. .globl reset_cpu  
  535. reset_cpu:  
  536.  ldr r1, rstctl /* get addr for global reset reg */  
  537.  mov r3, #0x2 /* full reset pll+mpu */  
  538.  str r3, [r1] /* force reset */  
  539.  mov r0, r0  
  540. _loop_forever:  
  541.  b _loop_forever  
  542. rstctl:  
  543.  .word PM_RSTCTRL_WKUP  
  544. #endif   

可以看出 start.s主要做的工作就是ARM初始化 lowlevel_init 下节分析。把nandflah中的代码读到SDRAM,设置堆栈和初始化BSS段。通过ldrpc, _start_armboot 跳转到SDRAM中执行C代码 start_armboot 。 下一节我们主要分析 lowlevel_init、copy_uboot_to_ram及start_armboot 做了哪些工作。

原创粉丝点击