Boot——移植u-boot

bootloader启动过程:
1.初始化硬件,关闭看门狗,设置时钟,设置SDRAM,初始化NAND FLASH
2.如果bootloader比较大,要将其重定位到SDRAM中
3.把内核从NAND FLASH读到SDRAM
4.设置要传给内核的参数
5.跳转执行内核

start.s文件
1.设置为管理模式;set the cpu to SVC32 mode
在这里插入图片描述

2.关看门狗turn off the watchdog
在这里插入图片描述

3.屏蔽所有中断;mask all IRQs by setting all bits in the INTMR - default
在这里插入图片描述

4.设置时钟比例;
在这里插入图片描述

5.设置内存控制器;Set stackpointer in internal RAM to call board_init_f
在这里插入图片描述

6.设置栈,调用c函数board_init_f
在这里插入图片描述

7.调用函数数组init_sequence的各个初始化函数
7.1
8.在7中的init_sequence调用函数之后会有重定位代码relocate_code
在u-boot中重定位代码,在FLASH中的代码会被复制到SDRAM中的链接地址(代码应该所处的位置),cpu在刚开始运行的时候是运行位置无关码(这段代码不管位于那个位置都可以执行)。

重定位代码:
将NOR FLASH中的代码复制到SDRAM中,复制的目标地址可以任选;由于程序的链接地址是0,访问全局变量,静态变量,调用函数时是使用基于0地址编译的到的地址,然而把程序复制到SDRAM中后,需要修改代码,把原来基于0地址编译得到的地址,改为新地址,需要在链接的时候使用PIE;
简单来说为什么需要重定位代码,就是因为链接地址和运行地址不同时CPU运行会产生错误,cpu在运行的时候是依靠芯片内部的SRAM,但是芯片内部的SRAM很小,不足以存储所有的代码。当芯片启动出现链接地址和运行地址不同时,就需要进行重定位,执行一段位置无关码,这段位置无关码的作用就是将原先的那一份代码复制到链接地址去,然后再跳转到新的那一份代码中进行运行;
relocated_code (addr_sp,id,addr)
addr_sp:设置栈的位置
id:变量gd_t的地址
addr:代码从FLASH中拷贝到的目标地址
在这里插入图片描述

9.清除bss
10.调用c函数board_init_r

汇编代码中使用到了ldr = 伪汇编指令,需要将代码进行反汇编获取u-boot.dis反汇编文件,在反汇编文件中获取地址信息
在这里插入图片描述

分析重定位,修改代码为新地址

/*
	 * fix .rel.dyn relocations
	 */
	ldr	r0, _TEXT_BASE		/* r0 <- Text base */                   //ldr 没有等于号就是读内存指令  r0 = _TEXT_BASE = 0,代码中的基地址
	sub	r9, r6, r0		/* r9 <- relocation offset */               //r9 = r6-r0 = 0x33f41000 - 0 = 0x33f41000
	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */          //r10 = _dynsym_start_ofs	=__dynsym_start - _start =00073608  动态变在反汇编代码中查看
	add	r10, r10, r0		/* r10 <- sym table in FLASH */         //r10 = r10+r0 = 00073608
	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */       //r2 = _rel_dyn_start_ofs= __rel_dyn_start - _start = 0006b568	
	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */          //r2 = r2+r0 = 0006b568
	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */         //r3= _rel_dyn_end_ofs = __rel_dyn_end - _start = 00073608
	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */           //r3 = r3+r0 = 00073608
fixloop:                                                            //循环修改地址将原来地址改为新地址
	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */   
	//第1次循环  r0 = [0006b568] = 00000020 
	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
	//第一次循环 r0 = r0+r9 = 00000020+0x33f41000 = 0x33f41020
	ldr	r1, [r2, #4]
	//第一次循环:r1 = [0006b568+4] = 00000017根据反汇编得到
	and	r7, r1, #0xff
	//第一次循环: r7= r1&0xff = 00000017
	cmp	r7, #23			/* relative fixup? */
	//第一次循环:比较r7是否等同于23(0x17)
	beq	fixrel
	//如果上一个比较命令相等跳到fixrel执行
	cmp	r7, #2			/* absolute fixup? */
	beq	fixabs
	/* ignore unknown type of fixup */
	b	fixnext
fixabs:
	/* absolute fix: set location to (offset) symbol value */
	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
	add	r1, r10, r1		/* r1 <- address of symbol in table */
	ldr	r1, [r1, #4]		/* r1 <- symbol value */
	add	r1, r1, r9		/* r1 <- relocated sym addr */
	b	fixnext
fixrel:
	/* relative fix: increase location by offset */
	ldr	r1, [r0]
	//第一次循r1 = [r0] = 000001e0
	add	r1, r1, r9
	//第一次循环r1 = r1+r9 = 000001e0 +0x33f41000 = 33F411E0
fixnext:
	str	r1, [r0]
	//第一次循环: [r0]=r1     [0x33f41020] = 33F411E0
	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
	//第一次循环  r2 = r2+8 = 0006b568 + 8 = 6B570
	cmp	r2, r3
	//第一次循环:比较r2 r4  如果相等则全部结束,如果不等则跳转fixloop
	blo	fixloop
#endif

程序中有些地址在链接时不能确定,要到运行前才能确定;fixabs

修改u-boot
建立一个单板:
1.进入单板目录将smdk2410复制一份为smdk2440
在这里插入图片描述
2.进入include/config中将smdk2410.h 复制一份为smdk2440.h
在这里插入图片描述
3.在u-boot源码目录下搜索smdk2410,按照smdk2410的配置同步smdk2440
在这里插入图片描述

修改boards.cfg
仿照65行命令添加66行命令
在这里插入图片描述

4.make smdk2440_config生成.config文件
5.make 编译生成单板
6.烧写看结果(如果板内的u-boot不能用,先烧写可以使用的u-boot,然后再将编译的u-boot烧录进去)
7.调试

观察时钟和内存设置
阅读代码发现问题:
(1).u-boot中先以60MHz的时钟计算参数来设置内存控制器,但是现在MPLL(系统时钟)还未设置

处理方法:把MPLL的设置放到start.s里面,取消board_early_init_f里对MPLL的设置
在这里插入图片描述

在start.s中设置时钟
在这里插入图片描述

#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))

	/* 2. 设置时钟 */
	ldr r0, =0x4c000014
	mov r1, #0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
	str r1, [r0]

	/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
	mrc	p15, 0, r1, c1, c0, 0		/* 读出控制寄存器 */ 
	orr	r1, r1, #0xc0000000			/* 设置为“asynchronous bus mode” */
	mcr	p15, 0, r1, c1, c0, 0		/* 写入控制寄存器 */

	/* MPLLCON = S3C2440_MPLL_200MHZ */
	ldr r0, =0x4c000004
	ldr r1, =S3C2440_MPLL_200MHZ
	str r1, [r0]

在lowlevel_init.s中修改内存

SMRDATA:
    .long 0x22011110	 //BWSCON
	.long 0x00000700	 //BANKCON0
	.long 0x00000700	 //BANKCON1
	.long 0x00000700	 //BANKCON2
	.long 0x00000700	 //BANKCON3  
	.long 0x00000700	 //BANKCON4
	.long 0x00000700	 //BANKCON5
	.long 0x00018005	 //BANKCON6
	.long 0x00018005	 //BANKCON7
	.long 0x008C04F4	 // REFRESH
	.long 0x000000B1	 //BANKSIZE
	.long 0x00000030	 //MRSRB6
	.long 0x00000030	 //MRSRB7

(2).将修改后的文件放入服务器中进行编译再烧入开发板观察现象,发现乱码,查看是串口波特率设置出现问题,找到串口波特率设置函数_serial_setbrg里面的get_HCLK没有定义CONFIG_S3C2440这个宏;
处理方法:include/configs/smdk2440.h: 去掉#define CONFIG_s3c2410,加上#define CONFIG_S3C2440,
编译之后还是会报错s3c2410_nand,根据报错信息查看对应文件中,通过Makefile看错误依赖于宏CONFIG_CMD_NAND
去掉#define CONFIG_CMD_NAND再编译;

修改u-boot支持NAND启动:
原来的代码在链接的时候添加了-pie选项,使得u-boot.bin里多了"(.rel)",".dynsym)"等信息使得程序很大,不利于从NAND启动(重定位之前的代码应该小于4K);所以需要去掉-pie
参考之前编写的bootloader中start.s和init.c来修改代码
添加编写bootlaoder时的init.c函数放入单板目录board/samsung/smdk2440中
根据bootloader中start.s设置u-boot中的nand_init_ll的汇编代码
1.bootloader中start.s重定位代码:
在这里插入图片描述
根据u-boot的start.s文件的起始位置修改汇编代码
在这里插入图片描述
修改后的代码:
在这里插入图片描述
设置起始位置为0x33f00000
在这里插入图片描述

2.根据链接地址文件将bootloader赋值过来的init.c清除bss段修改为和u-boot的函数名一样
在这里插入图片描述
修改后的代码
在这里插入图片描述

3.修改start,s文件,设置跳转清除bss和board_inti函数,
在这里插入图片描述

由于重定位已经完成过,所以将board_init_f中的relocate_code去掉
在这里插入图片描述

实现了自己的重定位代码和清除bss段之后,就可以将start.s文件中的relocate和清除bss代码段删掉;
第一阶段完成;

第二阶段
在start.s中代码运行到board_init_f之后就进入到第二阶段board_init_r
第二阶段的board_init_r函数
在这里插入图片描述
根据函数可知该函数需要两个参数,第一个参数是第一阶段中的id,所以设置board_init_f函数返回值为unsigned int ,函数末尾return id
将之前的void改为unsigned int
在这里插入图片描述
还要修改所在头文件common.h
在这里插入图片描述

返回id
在这里插入图片描述
board_init_r函数的第一个参数就是程序的连接地址;因此可以在start.s中添加汇编代码:
在这里插入图片描述
第二阶段完成;

修改board/samsung/smdk2440目录下的Makefile,将init.c放入Makefile
在这里插入图片描述
查找u-boot源码目录下-pie,去掉-pie
在这里插入图片描述
去掉arch/arm/config.mk 的75行
在这里插入图片描述

修改链接脚本:把start.s,init.c, lowlevel.s等文件放在前面
删除u-boot.lds再进行编译会自动生成链接脚本
在这里插入图片描述
使用make编译之后,find -name “u-boot.lds”
在这里插入图片描述
在找到的arch/arm/cpu/u-boot.lds中进行修改
在这里插入图片描述
根据lowlevel_init.s和init.c所在文件夹可以看出,lowlevel_init.s和init.c文件应该是在库smdk2440.o中

在这里插入图片描述
根据内存分布图需要将board.文件中的addr
addr = 0x33f00000(所以u-boot一定不能超过512k)
也可以利用之前修改过的宏对其进行赋值
在这里插入图片描述
修改u-boot支持Nor Flash
deviers/mts/jedec_flash.c加上新的型号

修改u-boot支持Nand Flash
修改smdk2440.h #define CONFIG_CMD_NAND

修改u-boot支持网卡支持DM9000
Dm9000在drivers/net中打开drivers/net中的Makefile,将Dm9000编译到u-boot中去
在这里插入图片描述
根据Makefile知道需要配置宏CONFIG_DRIVER_DM9000才能支持Dm9000;
在smdk2440.h中需要去掉cs8900加上宏CONFIG_DRIVER_DM9000
先进行编译,然后根据报错,观察其他的文件中如何给Dm9000进行设置,仿照其进行改写;
设置访问地址
根据电路原理图片选引脚nGCS4和芯片手册的内存控制器对应的片选引脚,设置基地址0x20000000;
CMD引脚为LADDR2,所以bit2为高电平(100也就是4)时可以读数据
在这里插入图片描述
按照芯片手册设置内存控制器
包括设置时序和位宽;
设置lowlevel_init 中的BANKCON4寄存器;
在这里插入图片描述
编译之后仍然有问题,找到问题所在地
board.c 中eth初始化
在这里插入图片描述
etn_initialize中的单板初始化board_eth_init
在这里插入图片描述

在board_eth_init中设置
在这里插入图片描述
仿照cs8900添加dm9000初始化函数
在这里插入图片描述
再对其进行编译,编译通过烧到开发板,设置IP地址和MAC地址,使用网线与电脑ping看是否ping通;

u-boot易用性修改裁剪以及制作补丁
裁剪u-boot,在smdk2440.h中去掉不需要使用的宏,让u-boot变小;
如usb等等
在这里插入图片描述

系统默认环境参数在env_common.c中;根据这些信息在smdk2440.h中设置宏
默认环境参数
在这里插入图片描述
在smdk2440.h中设置相关环境变量
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值