您的位置:首页 > 其它

uboot源码分析——stage 1

2014-10-31 14:45 435 查看
我们人为的把uboot的启动分为stage1和stage2,区分的标准是以编程语言和代码的作用。stage1主要用arm汇编及一部分C的混合编程,完成底层硬件的初始化设置;stage2则完全用C实现,在进行一些硬件(外设)初始化的同时,为linux启动提供参数和软硬件环境。

Stage1源码分析

通过分析Makefile和u-boot.lds发现,cpu/arm920t/start.S文件经编译后最先执行。下面来分析一下这个文件。因为之前写过不少的裸机编程,所以还是比较好理解的,所以硬件操作的部分不会深入再去说明。
#include <common.h>
#include <config.h>
包含两个头文件,include/config.h文件是自动生成的include/config.h:
#include <configs/mini2440.h>
#include <asm/config.h>
configs/mini2440.h,这文件是规定了针对mini2440开发板的一些配置信息。asm/config.h,你可能会觉得奇怪,为什么在/inclued/下找不到asm目录?还记得之前说过的软链接不,这里应该是asm-arm/config.h。它的内容:
#ifndef _ASM_CONFIG_H_
#define _ASM_CONFIG_H_
 
/* Relocation to SDRAM works on all ARM boards */
#define CONFIG_RELOC_FIXUP_WORKS
 
#endif
接下来进入<span style="font-family: Verdana; font-size: 15.555556297302246px; line-height: 25.98958396911621px;">cpu/arm920t/start.S文件分析代码~~</span> .globl _start_start:	b	start_codeldr	pc, _undefined_instructionldr	pc, _software_interruptldr	pc, _prefetch_abortldr	pc, _data_abortldr	pc, _not_usedldr	pc, _irqldr	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 .balignl 16,0xdeadbeef
定义异常向量表
_TEXT_BASE:.word	TEXT_BASE
指定代码的基地址TEXT_BASE,/board/tekkamanninjia/mini2440/config.mk中:
## SMDK2410 has 1 bank of 64 MB DRAM## 3000'0000 to 3400'0000## Linux-Kernel is expected to be at 3000'8000, entry 3000'8000# optionally with a ramdisk at 3080'0000## we load ourself to 33F8'0000## download area is 3300'0000 TEXT_BASE = 0x33F80000
SMDK2410与mni2440同样是64M的SDRAM,这里应该是直接把SMDK2410的拿来用了。Linux-Kernel的入口地址在uboot中规定为3000'8000, 如果使用ramdisk则把ramdisk放在3080'0000。Uboot的入口地址为33F8'0000
.globl _armboot_start_armboot_start:.word _start
_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
__bss_start 在根目录的u-boot.lds文件中定义(按Makefile的意思是”These are defined in the board-specific linker script”.,但是我用的这个版本/board/tekkamanninja/mini2440目录下没有u-boot.lds,tekkamanninja把它放到了根目录下)__bss_start = .
#ifdef CONFIG_USE_IRQ/* IRQ stack memory (calculated at run-time) */.globl IRQ_STACK_STARTIRQ_STACK_START:.word	0x0badc0de /* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_STARTFIQ_STACK_START:.word 0x0badc0de#endif
如果定义了CONFIG_USE_IRQ那么标号IRQ_STACK_START所指向的地址作为IRQ的栈起始地址。起始地址为0x0badc0de你可能会觉得对这个值很奇怪,没关系,在后面会被修改,到时再说,现在先随意设置一个。CONFIG_USE_IRQ显然是一个宏,在某个.h文件中被定义。前面讲过start.S包含了几个个头文件,在configs/mini2440.h中:
//#undef CONFIG_USE_IRQ	 /* we don't need IRQ/FIQ stuff */#define CONFIG_USB_DEVICE 1#ifdef CONFIG_USB_DEVICE#define CONFIG_USE_IRQ 1#endif
可以看到最终#define CONFIG_USE_IRQ 1,所以这一版的uboot是使用IRQ的,并且在此分配栈。FIQ同理。
/* * the actual start code */ start_code:
重启以后跳到这里执行。
/* * set the cpu to SVC32 mode */mrs	r0, cpsrbic	r0, r0, #0x1forr	r0, r0, #0xd3msr	cpsr, r0
没什么好说的,设置处理器工作在32位系统模式。
#if	defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)/* * relocate exception table */ldr	r0, =_startldr	r1, =0x0mov	r2, #16copyex:subs	r2, r2, #1ldr	r3, [r0], #4str	r3, [r1], #4bne	copyex#endif
这段代码的本意是copy异常向量表到_start的绝对地址,但是在include/configs/mini2440.h文件中并没有定义这两个宏,所以这段代码不执行。
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)|| defined(CONFIG_S3C2440)/* turn off the watchdog */ # if defined(CONFIG_S3C2400)#  define pWTCON	0x15300000#  define INTMSK	0x14400008	/* Interupt-Controller base addresses */#  define CLKDIVN	0x14800014	/* clock divisor register */#else#  define pWTCON	0x53000000#  define INTMSK	0x4A000008	/* Interupt-Controller base addresses */#  define INTSUBMSK	0x4A00001C#  define CLKDIVN	0x4C000014	/* clock divisor register */# endif#define CLK_CTL_BASE	0x4C000000	/* tekkaman */#define MDIV_405	0x7f << 12	/* tekkaman */#define PSDIV_405	0x21	 /* tekkaman */#define MDIV_200	0xa1 << 12	/* tekkaman */#define PSDIV_200	0x31	 /* tekkaman */  ldr	r0, =pWTCONmov	r1, #0x0str	r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */mov	r1, #0xffffffffldr	r0, =INTMSKstr	r1, [r0]# if defined(CONFIG_S3C2410)ldr	r1, =0x7ffldr	r0, =INTSUBMSKstr	r1, [r0]# endif #if defined(CONFIG_S3C2440)ldr	r1, =0x7fffldr	r0, =INTSUBMSKstr	r1, [r0]#endif #if defined(CONFIG_S3C2440)/* FCLK:HCLK:PCLK = 1:4:8 */ldr	r0, =CLKDIVNmov	r1, #5str	r1, [r0]mrc	p15, 0, r1, c1, c0, 0orr	r1, r1, #0xc0000000mcr	p15, 0, r1, c1, c0, 0mov	r1, #CLK_CTL_BASEmov	r2, #MDIV_405add	r2, r2, #PSDIV_405str	r2, [r1, #0x04]	 /* MPLLCON tekkaman */ #else/* FCLK:HCLK:PCLK = 1:2:4 *//* default FCLK is 120 MHz ! */ldr	r0, =CLKDIVNmov	r1, #3str	r1, [r0] mrc	p15, 0, r1, c1, c0, 0orr	r1, r1, #0xc0000000mcr	p15, 0, r1, c1, c0, 0	/*write ctrl register tekkaman*/mov	r1, #CLK_CTL_BASE	/* tekkaman*/mov	r2, #MDIV_200add	r2, r2, #PSDIV_200str	r2, [r1, #0x04]#endif#endif	/* CONFIG_S3C2400 || CONFIG_S3C2410  || CONFIG_S3C2440*/
观看门狗,屏蔽中断。在/include/configs/mini2440.h文件中定义:#defineCONFIG_S3C24401/* in a SAMSUNG S3C2440 SoC */设置时钟405M左右,FCLK:HCLK:PCLK = 1:4:8 。
/* * we do sys-critical inits only at reboot, * not when booting from ram! */#ifndef CONFIG_SKIP_LOWLEVEL_INITbl	cpu_init_crit#endif
在看根目录下的README:- CONFIG_SKIP_LOWLEVEL_INIT[ARM only] If these variables are defined, then certain low level initializations (like setting up the memory controller) are omitted and/or U-Boot does not relocate itself into RAM.Normally these variables MUST NOT be defined. The only exception is when U-Boot is loaded (to RAM) by some other boot loader or by a debugger which performs these initializations itself.在包含的头文件中也没有找到CONFIG_SKIP_LOWLEVEL_INIT的宏定义,所以这里是要执行blcpu_init_crit的。跳转到cpu_init_crit看一下。
#ifndef CONFIG_SKIP_LOWLEVEL_INITcpu_init_crit:/* * flush v4 I/D caches */mov	r0, #0mcr	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, 0bic	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) Alignorr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cachemcr	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, ipmov	pc, lr#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
首先是对指令Cache、数据Cache的操作,全部关闭。“Caches是CPU内部的一个2级缓存,它的作用是将常用的数据和指令放在CPU内部。Caches是通过CP15管理的,刚上电的时候,CPU还不能管理Caches。上电的时候指令Cache可关闭,也可不关闭,但数据Cache一定要关闭,否则可能导致刚开始的代码里面,去取数据的时候,从Cache里面取,而这时候RAM中数据还没有Cache过来,导致数据预取异常 。”Disable MMU跳转到lowlevel_init 接下来分析/board/tekkamanninja/mini2440/lowlevel_init.S
_TEXT_BASE:.word	TEXT_BASE .globl lowlevel_initlowlevel_init:/* memory control configuration *//* make r0 relative the current location so that it *//* reads SMRDATA out of FLASH rather than memory ! */ldr     r0, =SMRDATAldr	 r1, =lowlevel_initsub	r0, r0, r1adr	 r3, lowlevel_init	 /* r3 <- current position of code   */add     r0, r0, r3ldr	r1, =BWSCON	/* Bus Width Status Controller */add     r2, r0, #13*40:ldr     r3, [r0], #4str     r3, [r1], #4cmp     r2, r0bne     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 0xb2    .word 0x30.word 0x30
贴一下之前写裸板程序时初始化SDRAM的代码:
;Set memory control registers 	;ldr	r0,=SMRDATA 	adrl	r0, SMRDATA	;be careful!ldr	r1,=BWSCON	;BWSCON Addressadd	r2, r0, #52	;End address of SMRDATA 0ldr	r3, [r0], #4str	r3, [r1], #4cmp	r2, r0bne	%B0
明确一点,我们的目标是将SMRDATA的值写进以BWSCON为首的连续的13个寄存器,已经知道了BWSCON的地址,所以只要知道SMRDATA的地址即可。下面的讨论是为了得到SMRDATA的加载地址:先看uboot源码中的:
ldr     r0, =SMRDATAldr	 r1, =lowlevel_initsub	r0, r0, r1
SMRDATA的绝对地址减去lowlevel_init的绝对地址,得到SMRDATA到lowlevel_init的偏移量,查看System.map文件:
33f804e4 T  lowlevel_init33f8051c t  SMRDATA
计算二者差存放在r0中,我们假设这个值是x。启动上电时,代码在nor中执行或从nand被拷入4k的stepstone这两种情况下,不管在norflash还是在stepstone中,SMRDATA到lowlevel_init的偏移量必定也是等于x,理解这一点很重要。
adr	r3, lowlevel_init	 /* r3 <- current position of code   */add     r0, r0, r3
通过adr位置无关指令指令得到lowlevel_init,注意是位置无关指令,得到的是pc+offset,所以r3保存的是lowlevel_init的当前运行地址,这时还没有进行代码的拷贝,所以必然是在4k之内。我们已经知道SMRDATA到lowlevel_init的偏移量x,那么lowlevel_init的当前地址+x就得到了SMRDATA的当前地址(加载地址)。剩下就是控制循环进行拷贝,没什么好说的。再看一下裸板程序中的代码,很简单,直接用adrlr0, SMRDATA得到了SMRDATA的加载地址。这里有两个疑问:既然可以adr r3, lowlevel_init,为什么不直接用adrr3, SMRDATA来获取SMRDATA的加载地址?个人理解:ADR伪指令格式 :ADR{cond} register, expr地址表达式expr的取值范围:当地址值是字节对齐时,其取指范围为: +255 ~ 255B;当地址值是字对齐时,其取指范围为: -1020 ~ 1020B;对于某些比较大的文件来说不能确保偏移量x的值小于1020B,而adrr3, lowlevel_init这条语句离lowlevel_init标号后很近,expr的值肯定是OK的。B.为什么不直接用adrl?这个没想明白。 执行完lowlevel_init以后跳转回cpu_init_crit,再从cpu_init_crit跳转回之前bl cpu_init_crit的地方。这里要注意lr寄存器的使用和保护。
/***************** CHECK_CODE_POSITION ******************************************/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/***************** CHECK_CODE_POSITION ******************************************/
Check 代码是否运行在SDRAM中。为什么要确定当前代码的运行位置呢?这与copy code to sdram 有关,我们在把代码copy到sdram中的时候,代码从sdram中运行,同样会运行到这里,这时候经过判断就不需要再次copy代码了(个人理解=。=)。在SDRAM中运行: beqstack_setup直接跳到stack_setup。在nor或者stepstone中运行: 继续向下执行,其中就包括copy code to sdram。我们要模拟的是上电启动时代码的运行方式,所以,刚开始是从nor或者nand启动的,这里不进行beqstack_setup的跳转。沿着这个线索往下看代码。
/***************** CHECK_BOOT_FLASH ******************************************/ldr	r1, =( (4<<28)|(3<<4)|(3<<2) )	 /* address of Internal SRAM  0x4000003C*/mov	r0, #0	 /* r0 = 0 */str	r0, [r1]  mov	r1, #0x3c	 /* address of men  0x0000003C*/ldr	r0, [r1]cmp	r0, #0bne	relocate /* recovery  */ldr	r0, =(0xdeadbeef)ldr	r1, =( (4<<28)|(3<<4)|(3<<2) )str	r0, [r1]/***************** CHECK_BOOT_FLASH ******************************************/
经过CHECK_CODE_POSITION 的判断,若程序能走到这一步,则说明是运行在在nor或者stepstone中。这段代码的作用:判断代码运行在norflash还是stepstone,即启动方式时norflash还是nandflash。看代码之前先了解s3c2440的Memory Map,0x0到0x4000 0000刚好是1G。0x4000 0000到0x4000 1000之间的4KB就是stepstone——Boot Internal SRAM。stepstone的物理地址为0x4000 0000到0x4000 1000,但是当从nandflash启动时,stepstone将被映射到0地址,并且nandflash的前4k会被Copy到stepstone中运行。下面来看代码:
ldr	r1, =( (4<<28)|(3<<4)|(3<<2) )	 /* address of Internal SRAM  0x4000003C*/mov	r0, #0	 /* r0 = 0 */str	r0, [r1]
这段代码的作用是将0x4000003C指向的4个Byte清零。
mov	r1, #0x3c	 /* address of men  0x0000003C*/ldr	 r0, [r1]cmp	r0, #0bne	relocate
这段代码是读0x3c地址处的值放在r0中,然后将该值与立即数0作比较。当nandflash启动时,0x4000003C和0x3c这两个地址指向的是stepstone中的同一个内存单元。当norfalsh启动时,0x4000003C指向的是stepstone,0x3c指向的是norflash中的对应存储单元。此时如果读出0x3c 的值是0,那么是nandflash启动,如果是非零,那么是norflash启动。你也许会有疑问:若果0x3c处的值本来就是0,那么这个判断不就不准确了吗?第一步在0x4000003C处清零,如果是nandflash启动,会不会破坏了0x3c处的代码?先看如下代码:
_start:	b	start_codeldr	pc, _undefined_instructionldr	pc, _software_interruptldr	pc, _prefetch_abortldr	pc, _data_abortldr	pc, _not_usedldr	pc, _irqldr	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 .balignl 16,0xdeadbeef
这是定义异常向量表及异常向量的跳转地址,一共有15条指令,每条指令4字节,共有60字节。.balignl 16,0xdeadbeef表示前面的代码所占内存必须以16个字节对齐,不够的字节用0xdeadbeef来填充。我们希望得到的是64个字节,所以缺少的4字节刚好用一个0xdeadbeef来填充,且0xdeadbeef的地址为0x3c。所以0x3c地址处的值必不为零,且该值对程序没有影响。(说到判断启动方式,韦东山的视频里面还有一种方法,利用norflash和nandflash的硬件差异性,norflash是readonly的,stepstone是ReadAndWrite,向某个内存中写入一个值,再读出,如果等于写入的值,则是nand启动,反之则是nor启动) 这时面临两个选择,nandflash启动或者是norflash启动,由OM[1:0]来控制,当然,你只要选择开发板的跳线即可。从norflash启动:执行
bne	relocate
跳转到
/***************** NOR_BOOT *************************************************/relocate:	 /* relocate U-Boot to RAM	    */      /*********** CHECK_FOR_MAGIC_NUMBER***************/ldr	r1, =(0xdeadbeef)cmp	r0, r1bne	loop3      /*********** CHECK_FOR_MAGIC_NUMBER***************/adr	r0, _start	 /* r0 <- current position of code   */ldr	r1, _TEXT_BASE	/* test if we run from flash or RAM */ldr	r2, _armboot_startldr	r3, _bss_startsub	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/***************** NOR_BOOT *************************************************/
首先是检验Magic number,0xdeadbeef如果不相等的话,进入死循环。相等的话copy code from nor to sdram。_start和_armboot_start都是0x0Source end address就是_bss_start 从nandflash启动CHECK_BOOT_FLASH的时候如果cmp r0, #0相等,则说明是nand启动。
/***************** NAND_BOOT *************************************************/ #define LENGTH_UBOOT 0x60000#define NAND_CTL_BASE 0x4E000000 #ifdef CONFIG_S3C2440/* Offset */#define oNFCONF 0x00#define oNFCONT 0x04#define oNFCMD 0x08#define oNFSTAT 0x20 @ reset NANDmov	r1, #NAND_CTL_BASEldr	r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )str	r2, [r1, #oNFCONF]ldr	r2, [r1, #oNFCONF]ldr	r2, =( (1<<4)|(0<<1)|(1<<0) )	@ Active low CE Control str	r2, [r1, #oNFCONT]ldr	r2, [r1, #oNFCONT]ldr	r2, =(0x6)	@ RnB Clearstr	r2, [r1, #oNFSTAT]ldr	r2, [r1, #oNFSTAT]mov	r2, #0xff	@ RESET commandstrb	r2, [r1, #oNFCMD]mov	r3, #0	@ waitnand1: add	r3, r3, #0x1cmp	r3, #0xablt	nand1 nand2:ldr	r2, [r1, #oNFSTAT]	@ wait readytst	r2, #0x4beq	nand2ldr	r2, [r1, #oNFCONT]orr	r2, r2, #0x2	@ Flash Memory Chip Disablestr	r2, [r1, #oNFCONT]@ get read to call C functions (for nand_read())ldr	sp, DW_STACK_START	@ setup stack pointermov	fp, #0	@ no previous frame, so fp=0 @ copy U-Boot to RAMldr	r0, =TEXT_BASEmov	r1, #0x0mov	r2, #LENGTH_UBOOTbl	nand_read_lltst	r0, #0x0beq	ok_nand_read bad_nand_read:loop2:b	loop2	@ infinite loopok_nand_read:@ verifymov	r0, #0ldr	r1, =TEXT_BASEmov	r2, #0x400	@ 4 bytes * 1024 = 4K-bytesgo_next:ldr	r3, [r0], #4ldr	r4, [r1], #4teq	r3, r4bne	notmatchsubs	r2, r2, #4beq	stack_setupbne	go_next notmatch:loop3:b	loop3	@ infinite loop#endif/***************** NAND_BOOT *************************************************/
可能用到的寄存器:完成了代码的拷贝,接下来是设置栈:
stack_setup:ldr	r0, _TEXT_BASE	 /* upper 128 KiB: relocated uboot   */sub	r0, r0, #CONFIG_SYS_MALLOC_LEN	/* malloc area              */sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */#ifdef CONFIG_USE_IRQsub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)#endifsub	sp, r0, #12Mini2440.h中:#define CONFIG_USB_DEVICE 1#ifdef CONFIG_USB_DEVICE#define CONFIG_USE_IRQ 1#endif #define CONFIG_STACKSIZE	(128*1024)	/* regular stack */#ifdef CONFIG_USE_IRQ#define CONFIG_STACKSIZE_IRQ	(4*1024)	/* IRQ stack */#define CONFIG_STACKSIZE_FIQ	(4*1024)	/* FIQ stack */#endif #define CONFIG_ENV_SIZE	 0x20000	/* Total Size of Environment Sector */#define CONFIG_SYS_MALLOC_LEN	 (CONFIG_ENV_SIZE + 128*1024)#define CONFIG_SYS_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */
所以CONFIG_SYS_MALLOC_LEN为256k,CONFIG_ENV_SIZE为128KB,nandflash一个block的大小,等于64*2k,一个page大小为2K。
README中:NOTE: the bzip2 algorithm requires a lot of RAM, sothe malloc area (as defined by CONFIG_SYS_MALLOC_LEN) shouldbe at least 4MB.- CONFIG_SYS_MALLOC_LEN:Size of DRAM reserved for malloc() use.
可见这里并没有把malloc area设置不小于4M,栈在内存中的分布如下图所示:根据“満栈减”的规则,之后栈的生长方向应该是向低地址。 接下来要清BSS段:
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, #4cmp r0, r1ble	clbss_l
这段代码也很简单,不用多说。
ldr	pc, _start_armboot
到_start_armboot标号所指向的内存中读取数据给pc,又有:
_start_armboot:	.word start_armboot
所以这里是把start_armboot的地址传给pc,pc跳到start_armboot函数处执行,接下来就是stage2的部分了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: