本博客转载于: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中。
由于代码比较长,依旧采取边帖代码边分析的方式
- /*
- *************************************************************************
- *
- * Jump vector table as in table 3.1 in [1]
- *
- *************************************************************************
- */
- .globl _start
- _start: b reset
- #ifndef CONFIG_NAND_SPL
- ldr pc, _undefined_instruction
- 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
- _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
- _pad:
- .word 0x12345678 /* now 16*4=64 */
- #else
- . = _start + 64
- #endif
_start: b reset 这就是arm执行的第一条代码,直接通过跳转,进入到了 reset 地址处
- /*
- * the actual reset code
- */
- reset:
- /*
- * set the cpu to SVC32 mode
- */
- mrs r0, cpsr /* 把cpsr 放到r0 中 */
- bic r0, r0, #0x3f /* 清 0x3f 对应位 11 1111 为0 */
- orr r0, r0, #0xd3 /* 或上 1011 0011 模式设置为SRC32 禁止中断和快速中断*/
- msr cpsr, r0
下面开始初始化cpu了,这部分是关于协处理器的,我也不是很懂,想具体了解的人,可以去看协处理器手册
- *************************************************************************
- *
- * CPU_init_critical registers
- *
- * setup important registers
- * setup memory timing
- *
- *************************************************************************
- */
- /*
- * we do sys-critical inits only at reboot,
- * not when booting from ram!
- */
- cpu_init_crit:
- /*
- * When booting from NAND - it has definitely been a reset, so, no need
- * to flush caches and disable the MMU
- */
- #ifndef CONFIG_NAND_SPL
- /*
- * 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
- /* Prepare to disable the MMU */
- adr r1, mmu_disable_phys
- /* We presume we're within the first 1024 bytes */
- and r1, r1, #0x3fc
- ldr r2, _TEXT_PHY_BASE
- ldr r3, =0xfff00000
- and r2, r2, r3
- orr r2, r2, r1
- b mmu_disable
- .align 5
- /* Run in a single cache-line */
- mmu_disable:
- mcr p15, 0, r0, c1, c0, 0 /* 禁止MMU就是这一句了,没必要判断那么多,其实只要把这句话移到上面,直接禁止了就好了。反正现在就是要关掉对吧 */
- nop
- nop
- mov pc, r2
- #endif
- /* 设置MMC映射地址,如果MMU开启,那么地址将被映射到0x70000000起始位置 0x13 为256MB 查看arm1176jzfs */
- mmu_disable_phys:
- /* Peri port setup */
- ldr r0, =0x70000000
- orr r0, r0, #0x13
- mcr p15,0,r0,c15,c2,4 @ 256M (0x70000000 - 0x7fffffff)
- 这里就是根据你的外部的内存大小来设置的,我这里是256MB,所以设置为0x13具体的数值根据arm1176jzfs手册可以查看到,s3c6410的核心就是arm1176
- 下面这个就相对来说比较重要了,很比较复杂。我这里就先留个脚印,回头下一篇细细的分析
- /*
- * Go setup Memory and board specific bits prior to relocation.
- */
- bl lowlevel_init /* go setup pll,mux,memory */
- 注释也说了,是初始化 pll mux memory 之类的,对于cpu的工作频率就是在这里设置的
- 继续分析
- after_copy: /* 注意这里噢。。有个after_copy,移植篇的时候,会在这里加上适当的代码 */
- #ifdef CONFIG_ENABLE_MMU
- enable_mmu:
- /* enable domain access */
- ldr r5, =0x0000ffff
- mcr p15, 0, r5, c3, c0, 0 /* load domain access register */
- /* Set the TTB register */
- ldr r0, _mmu_table_base
- ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
- ldr r2, =0xfff00000
- bic r0, r0, r2
- orr r1, r0, r1
- mcr p15, 0, r1, c2, c0, 0
- /* Enable the MMU */
- mrc p15, 0, r0, c1, c0, 0
- orr r0, r0, #1 /* Set CR_M to enable MMU */
- /* Prepare to enable the MMU */
- adr r1, skip_hw_init
- and r1, r1, #0x3fc
- ldr r2, _TEXT_BASE
- ldr r3, =0xfff00000
- and r2, r2, r3
- orr r2, r2, r1
- b mmu_enable
- .align 5
- /* Run in a single cache-line */
- mmu_enable:
- mcr p15, 0, r0, c1, c0, 0
- nop
- nop
- mov pc, r2
- #endif
Ps:看到那个 after_copy 了没?之前分析的时候,没说过要copy对不对?很奇怪吧。。。其实不然,看了下面的代码,你会发现,下面就剩下设置栈,clear bss以及启动第二阶段的部分了
也就是说,uboot 如果是从nand启动的,那么选择的pc指针还在 stepping stone内,而该区域只有4K的大小,有点小了。。。而对于nor flash启动的,以及其它media都有类似的问题,
不是速度慢就是没法直接执行代码,都需要将代码拷贝到ram中去。
移植的一个问题就出来了,在这里 添加拷贝代码。。
- skip_hw_init:
- /* Set up the stack */
- stack_setup:
- ldr r0, =CONFIG_SYS_UBOOT_BASE /* base of copy in DRAM */
- sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
- sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
- sub sp, r0, #12 /* leave 3 words for abort-stack */
- /* NAND U-Boot load and start address */
- #define CONFIG_SYS_SDRAM_BASE 0x50000000
- #define CONFIG_SYS_MAPPED_RAM_BASE CONFIG_SYS_SDRAM_BASE
- #define CONFIG_SYS_UBOOT_BASE (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)
默认就以为自己是128MB了。往下就是126MB的位置了,该值可以根据实际情况而改变,一般不改也没事的
- #define CONFIG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */
- #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 1024 * 1024)
- CONFIG_SYS_MALLOC_LEN = 0x4000 + 1024*1024
- #define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes for initial data */
- clear_bss:
- ldr r0, _bss_start /* find start of bss segment */
- ldr r1, _bss_end /* stop here */
- mov r2, #0 /* clear */
- clbss_l:
- str r2, [r0] /* clear loop... */
- add r0, r0, #4
- cmp r0, r1
- ble clbss_l
- #ifndef CONFIG_NAND_SPL
- ldr pc, _start_armboot
- _start_armboot:
- .word start_armboot
- #else
- b nand_boot
- /* .word nand_boot*/
- #endif
finish.
thanks a lot.