02.uboot分析之源码第一阶段

举报
嵌入式与Linux那些事 发表于 2022/03/28 22:50:05 2022/03/28
【摘要】   之前写的硬件相关的裸机源码的流程和uboot差不多。之前的实验主要完成以下操作:   (1)初始化:关看门狗,初始化时钟,初始化sdram。   (2)程序很大时,把程序从nandflash拷贝到sd...

  之前写的硬件相关的裸机源码的流程和uboot差不多。之前的实验主要完成以下操作:
  (1)初始化:关看门狗,初始化时钟,初始化sdram。
  (2)程序很大时,把程序从nandflash拷贝到sdaram。
  (3)调用C函数必须设置栈sp

一、cpu/arm920t/start.s启动文件分析
.globl _start
/*跳转到reset*/
_start:	b       reset
	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

	.balignl 16,0xdeadbeef

reset:
	/*
	 * set the cpu to SVC32 mode 管理模式
	 */
	mrs	r0,cpsr
	bic	r0,r0,#0x1f
	orr	r0,r0,#0xd3
	msr	cpsr,r0
/* 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 INTMOD     0X4A000004
# define INTMSK		0x4A000008	/* Interupt-Controller base addresses */
# define INTSUBMSK	0x4A00001C
# define CLKDIVN	0x4C000014	/* clock divisor register */
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
	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, =INTMSK
	str	r1, [r0]
# if defined(CONFIG_S3C2410)
	ldr	r1, =0x3ff
	ldr	r0, =INTSUBMSK
	str	r1, [r0]
# endif

	/*
	 * we do sys-critical inits only at reboot,
	 * not when booting from ram!
	 * CPU初始化
	 */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*读地址指令 如果是上电后运行,代码是从nandflash自动拷贝到sdram,则r0为0.如果是通过下载器下载到sdram,则r0为他的链接地址0x33f8000*/
	adr	r0, _start		/* r0 <- current position of code  */
	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */
	/*不相等则证明sdram还没有被初始化。*/
	cmp     r0, r1                  /* don't reloc during debug         */
	blne	cpu_init_crit
#endif

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
	/*
	 * flush v4 I/D caches 关flash
	 */
	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 清mmu
	 */
	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 */

	/* Set up the stack				设置栈		    */
	/*栈会一直减下去,指向不同的位置*/
stack_setup:
	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot r0=0x33f80000  */
	sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area    r0 =r0-CFG_MALLOC_LEN	 */
	sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo     r0 =r0-CFG_GBL_DATA_SIZE */
#ifdef CONFIG_USE_IRQ
/*r0=r0-(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)*/
	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
	sub	sp, r0, #12		/* leave 3 words for abort-stack r0=r0-12  */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*调用初始化时钟的C函数*/
    bl clock_init
#endif    

/*把代码从flash读到sdram链接地址*/
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     clear_bss
	
	ldr	r2, _armboot_start
	ldr	r3, _bss_start
	sub	r2, r3, r2		/* r2 <- size of armboot            */

/*清楚BSS段,初始化为0的静态变量或者全局变量*/
clear_bss:
	ldr	r0, _bss_start		/* find start of bss segment        */
	ldr	r1, _bss_end		/* stop here                        */
	mov 	r2, #0x00000000		/* clear                            */


	ldr	pc, _start_armboot
/*调用c函数start_armboot*/
_start_armboot:	.word start_armboot

  
 
  • 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

 小结:设置管理模式,关看门狗,屏蔽中断,sdram的初始化,设置栈,设置时钟,代码重定位,清除bss段(之前的都称为uboot的第一阶段),调用C函数start_armboot(第二阶段开始)。

二、清除BSS段原因

  BSS段清零的原因是因为这个段是BSS

  要说为什么要有BSS的话,历史就比较久远了。 BSS段我所知道的起源是Unix最初的时候(当然,不排除可能有更早的情况)。变量分两种:局部变量、全局变量。

  根据C语法的规定,局部变量不设置初始值的时候,其初始值是不确定的,局部变量(不含静态局部变量)的存储位置位于栈上,具体位置不固定。

  全局变量(和静态局部变量)有专门数据段存储,初始值是0,具体位置是固定的。

  其实说到底,就两种,一种是位置固定(数据段里),一种是位置不固定的(栈上)。

  要知道,早期的计算机存储设备是很贵的,而很多时候,数据段里的全局变量都是0(或者没有初始值),那么存储这么多的0到目标文件里其实是没有必要的。所以为了节约空间,在生成目标文件的时候,就把没有初始值(实际就是0)的数据段里的变量都放到BSS段里,这样目标文件就不需要那么大的体积里(节约磁盘空间)。只有当目标文件被载入的时候,加载器负责把BSS段清零(一个循环就可以搞定)。 之后,这个规则慢慢的成为一个标准配置,大多数编译器也就都支持了BSS段。

   然后解释几个问题: Q:为什么局部变量初始值不是0? A:局部变量初始值也可以是零(在某些语言中就是),但这实际上需要消耗硬件指令去完成,有些时候这种清零的动作意义不大,对于编译器来说也是一种负担,每次调用函数都要消耗指令去清零,负担太大。要知道全局变量在内存中只有一份,局部变量(非静态)可以是多份的,前者一次清零就可以了,后者多次清零,负担太大。

  Q:如果BSS不清零可不可以? A:可以,如果编译器规定BSS段不清零,也是可以的,但这样的话C语言语法就要改了:未初始化的全局变量和静态局部变量,其值是未知的。甚至其它语言也要跟着改语法。

  所以,BSS段清零的原因是因为这个段是BSS 现在存储介质这么便宜了,是不是BSS已经没有必要了?当然不是了,介质便宜仅限于PC和数码产品这一块,嵌入式行业永远都不存在存储介质没有限制的情况。

文章来源: blog.csdn.net,作者:嵌入式与Linux那些事,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_16933601/article/details/102826232

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。