u-boot2010.03 第一阶段--start.S

本博客转载于:http://blog.csdn.net/yyttiao/article/details/7916495


经过前面的配置,编译分析。选择可以开始进入移植篇了。
其实我在想,是先出移植篇呢还是先出分析篇。因为这两者息息相关。整个uboot的启动流程懂了,那么移植也就不那么无从下手了。
我手上的板子是S3C6410的,如果一直对S3C6400 进行分析,那会不会影响到读者的分析。。
最终我决定,分析移植一起进行更新,,一般我会先出分析帖,然后再出教程帖。间隔应该不会特别长时间。
最近我同学说了,说我的帖子不够正式,没有转载说明,没有版权说明,,以后慢慢补上吧。


下面开始 分析篇(一)-----start.S
-----------------------------
使用环境 
PC:                  ubuntu 11.04
kernel:            2.6.32-28-generic
corss:             arm-linux-gcc 4.3.2
arm:                s3c6410
-----------------------------
作者:               LvApp
联系方式:       97164811@qq.com


一切版权均有作者所有,欢迎转载,请指明出处,如何修改请与本人联系,谢谢


今天,我们正式进入了uboot启动代码的分析,从上一次分析的makefile中,关于lds的说明,可以知道为什么要从这个文件开始,要是忘记了,可以去复习下。
u-boot2010.03 配置编译目标分析
u-boot2010.03 Makefile分析


这里就不细说了,arm上电启动执行的第一条语句就是在这个start.S中。
由于代码比较长,依旧采取边帖代码边分析的方式

[cpp]  view plain copy
  1. /* 
  2. ************************************************************************* 
  3. * 
  4. * Jump vector table as in table 3.1 in [1] 
  5. * 
  6. ************************************************************************* 
  7. */  
  8.   
  9.   
  10. .globl _start  
  11. _start: b   reset  
  12.     #ifndef CONFIG_NAND_SPL  
  13.     ldr pc, _undefined_instruction  
  14.     ldr pc, _software_interrupt  
  15.     ldr pc, _prefetch_abort  
  16.     ldr pc, _data_abort  
  17.     ldr pc, _not_used  
  18.     ldr pc, _irq  
  19.     ldr pc, _fiq  
  20.   
  21.   
  22. _undefined_instruction:  
  23.     .word undefined_instruction  
  24. _software_interrupt:  
  25.     .word software_interrupt  
  26. _prefetch_abort:  
  27.     .word prefetch_abort  
  28. _data_abort:  
  29.     .word data_abort  
  30. _not_used:  
  31.     .word not_used  
  32. _irq:  
  33.     .word irq  
  34. _fiq:  
  35.     .word fiq  
  36. _pad:  
  37.     .word 0x12345678 /* now 16*4=64 */  
  38. #else  
  39. . = _start + 64  
  40. #endif  
首先进入的就是arm的异常项量表,这对于有过裸机开发的人应该不陌生,如果不了解这个,这里我就不多说,因为这不是这次的主题,可以去查阅相关资料,其实arm的中断入口地址就是在这里指定的
_start: b reset  这就是arm执行的第一条代码,直接通过跳转,进入到了 reset 地址处
[cpp]  view plain copy
  1. /* 
  2.  * the actual reset code 
  3.  */  
  4. reset:  
  5. /* 
  6.  * set the cpu to SVC32 mode 
  7.  */  
  8.     mrs r0, cpsr            /* 把cpsr 放到r0 中 */  
  9.     bic   r0, r0, #0x3f     /* 清 0x3f 对应位 11 1111 为0 */  
  10.     orr    r0, r0, #0xd3    /* 或上 1011 0011 模式设置为SRC32 禁止中断和快速中断*/  
  11.     msr cpsr, r0  
此处就是arm执行的第二条语句,将arm设置为 src 模式,并禁止了中断以及快速中断。可以查看s3c6410数据手册,查看 cpsr 寄存器的作用


下面开始初始化cpu了,这部分是关于协处理器的,我也不是很懂,想具体了解的人,可以去看协处理器手册
[cpp]  view plain copy
  1. *************************************************************************  
  2. *  
  3. * CPU_init_critical registers  
  4. *  
  5. * setup important registers  
  6. * setup memory timing  
  7. *  
  8. *************************************************************************  
  9. */  
  10. /* 
  11. * we do sys-critical inits only at reboot, 
  12. * not when booting from ram! 
  13. */  
  14. cpu_init_crit:  
  15. /* 
  16. * When booting from NAND - it has definitely been a reset, so, no need 
  17. * to flush caches and disable the MMU 
  18. */  
  19. #ifndef CONFIG_NAND_SPL  
  20. /* 
  21. * flush v4 I/D caches 
  22. */  
  23. mov r0, #0  
  24. mcr p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */  
  25. mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */  
  26.   
  27.   
  28. /* 
  29. * disable MMU stuff and caches 
  30. */  
  31. mrc p15, 0, r0, c1, c0, 0  
  32. bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)  
  33. bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)  
  34. orr r0, r0, #0x00000002 @ set bit 2 (A) Align  
  35. orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache  
  36. /* Prepare to disable the MMU */  
  37. adr r1, mmu_disable_phys  
  38. /* We presume we're within the first 1024 bytes */  
  39. and r1, r1, #0x3fc  
  40. ldr r2, _TEXT_PHY_BASE  
  41. ldr r3, =0xfff00000  
  42. and r2, r2, r3  
  43. orr r2, r2, r1  
  44. b   mmu_disable  
  45.   
  46.   
  47. .align 5  
  48. /* Run in a single cache-line */  
  49. mmu_disable:  
  50. mcr p15, 0, r0, c1, c0, 0   /* 禁止MMU就是这一句了,没必要判断那么多,其实只要把这句话移到上面,直接禁止了就好了。反正现在就是要关掉对吧 */  
  51. nop  
  52. nop  
  53. mov pc, r2  
  54. #endif  
  55.   
  56.   
  57. /* 设置MMC映射地址,如果MMU开启,那么地址将被映射到0x70000000起始位置 0x13 为256MB 查看arm1176jzfs */  
  58. mmu_disable_phys:  
  59. /* Peri port setup */  
  60. ldr r0, =0x70000000  
  61. orr r0, r0, #0x13  
  62. mcr p15,0,r0,c15,c2,4 @ 256M (0x70000000 - 0x7fffffff)  
  63. 这里就是根据你的外部的内存大小来设置的,我这里是256MB,所以设置为0x13具体的数值根据arm1176jzfs手册可以查看到,s3c6410的核心就是arm1176  
  64.   
  65.   
  66. 下面这个就相对来说比较重要了,很比较复杂。我这里就先留个脚印,回头下一篇细细的分析  
  67. /* 
  68. * Go setup Memory and board specific bits prior to relocation. 
  69. */  
  70. bl  lowlevel_init    /* go setup pll,mux,memory */  
  71. 注释也说了,是初始化 pll mux memory 之类的,对于cpu的工作频率就是在这里设置的  
  72. 继续分析  
  73. after_copy: /* 注意这里噢。。有个after_copy,移植篇的时候,会在这里加上适当的代码 */  
  74. #ifdef CONFIG_ENABLE_MMU  
  75. enable_mmu:  
  76. /* enable domain access */  
  77. ldr r5, =0x0000ffff  
  78. mcr p15, 0, r5, c3, c0, 0   /* load domain access register */  
  79.   
  80.   
  81. /* Set the TTB register */  
  82. ldr r0, _mmu_table_base  
  83. ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE  
  84. ldr r2, =0xfff00000  
  85. bic r0, r0, r2  
  86. orr r1, r0, r1  
  87. mcr p15, 0, r1, c2, c0, 0  
  88.   
  89.   
  90. /* Enable the MMU */  
  91. mrc p15, 0, r0, c1, c0, 0  
  92. orr r0, r0, #1   /* Set CR_M to enable MMU */  
  93.   
  94.   
  95. /* Prepare to enable the MMU */  
  96. adr r1, skip_hw_init  
  97. and r1, r1, #0x3fc  
  98. ldr r2, _TEXT_BASE  
  99. ldr r3, =0xfff00000  
  100. and r2, r2, r3  
  101. orr r2, r2, r1  
  102. b   mmu_enable  
  103.   
  104.   
  105. .align 5  
  106. /* Run in a single cache-line */  
  107. mmu_enable:  
  108.   
  109.   
  110. mcr p15, 0, r0, c1, c0, 0  
  111. nop  
  112. nop  
  113. mov pc, r2  
  114. #endif  
这段代码主要是是否启动mmu的,一般都不开启,直接跳过就好了。
Ps:看到那个 after_copy 了没?之前分析的时候,没说过要copy对不对?很奇怪吧。。。其实不然,看了下面的代码,你会发现,下面就剩下设置栈,clear bss以及启动第二阶段的部分了
也就是说,uboot 如果是从nand启动的,那么选择的pc指针还在 stepping stone内,而该区域只有4K的大小,有点小了。。。而对于nor flash启动的,以及其它media都有类似的问题,
不是速度慢就是没法直接执行代码,都需要将代码拷贝到ram中去。
移植的一个问题就出来了,在这里 添加拷贝代码。。
[cpp]  view plain copy
  1. skip_hw_init:  
  2. /* Set up the stack  */  
  3. stack_setup:  
  4. ldr r0, =CONFIG_SYS_UBOOT_BASE  /* base of copy in DRAM  */  
  5. sub r0, r0, #CONFIG_SYS_MALLOC_LEN  /* malloc area */  
  6. sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */  
  7. sub sp, r0, #12  /* leave 3 words for abort-stack */  
这一部分是设置栈,而栈设置的位置在哪呢? CONFIG_SYS_UBOOT_BASE  在 include/configs/xxx.h 中定义,此处我的是 s3c6400.h  打开该文件,还是别关了,经常要看这个里面是不是定义了什么宏的
[cpp]  view plain copy
  1. /* NAND U-Boot load and start address */  
  2. #define CONFIG_SYS_SDRAM_BASE    0x50000000  
  3. #define CONFIG_SYS_MAPPED_RAM_BASE  CONFIG_SYS_SDRAM_BASE  
  4. #define CONFIG_SYS_UBOOT_BASE    (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)  
最终这个 CONFIG_SYS_UBOOT_BASE = 0x50000000 + 0x07e00000  为什么后面要加上0x07e00000(126MB) 其实uboot在将自己拷贝到内存中的时候,会放到内存最大值往下2MB的位置,这里呢,uboot
默认就以为自己是128MB了。往下就是126MB的位置了,该值可以根据实际情况而改变,一般不改也没事的
[cpp]  view plain copy
  1. #define CONFIG_ENV_SIZE  0x4000 /* Total Size of Environment Sector */  
  2. #define CONFIG_SYS_MALLOC_LEN    (CONFIG_ENV_SIZE + 1024 * 1024)  
  3. CONFIG_SYS_MALLOC_LEN = 0x4000 + 1024*1024  
  4. #define CONFIG_SYS_GBL_DATA_SIZE    128 /* size in bytes for initial data */  
最终 sp = 0x50000000 + 0x07e00000 - (0x4000 + 1024*1024) - 128 - 12
[cpp]  view plain copy
  1. clear_bss:  
  2. ldr r0, _bss_start   /* find start of bss segment */  
  3. ldr r1, _bss_end     /* stop here */  
  4. mov r2, #0   /* clear */  
  5.   
  6.   
  7. clbss_l:  
  8. str r2, [r0]     /* clear loop... */  
  9. add r0, r0, #4  
  10. cmp r0, r1  
  11. ble clbss_l  
这一段就是  clear_bss  固定清为0 由此可知bss也不是天生就是0,也是人为的原因
[cpp]  view plain copy
  1. #ifndef CONFIG_NAND_SPL  
  2. ldr pc, _start_armboot  
  3.   
  4.   
  5. _start_armboot:  
  6. .word start_armboot  
  7. #else  
  8. b   nand_boot  
  9. /*  .word nand_boot*/  
  10. #endif  
进入最后一部分,就是一个 ldr pc,_start_armboot  这个地址最终会保存 start_armboot ,启动第二阶段


finish.
thanks a lot.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值