uboot移植-从uboot官方源码开始移植过程总结

1 选取源码 下载源码 解压源码

自行登录uboot官网,下载uboot源码,我选取的是2013.10的,因为之后的源码采用类似新的配置模式

(能用即可)。我的源码是uboot-2013.10,解压缩一份在windows(用来查看分析和修改),一份在

Linux(用来交叉编译)。

2 寻找目标板子

uboot工程里面有很多开发板,我们要找到一个和我们类似SOC的开发板,很显然最起码要匹配两个东

西才可以,一个是SOC产商,一个是SOC(Samsung和s5pv210)。寻找完毕,过程略(产商是三星,

开发板选择三星的goni)。

3 建立工程

在windows下利用sourceInsight角建立过程。这份代码只是用来分析和修改,不参与编译,所以为了分

析索引的方便,我们删除一些不需要的文件。比如我们的SOC是三星公司的s5pv210,所以其他类型的

板子完全可以删掉,在比如我们的架构是ARM,像PPC,MIPS,X86等架构的文件夹完全可以删除掉。还有

一些其他的,不知道要不要删的就不删(就是分析的时候多了些)。好了,现在建立完毕。

3 编译源码

在Linux下先编译源码,那么问题来了,就是编译工具,我们打开主makefile索引到CROSS_COMPILE

修改其为自己的交叉编译工具即可。开始编译,看看原版的运行效果(肯定不能运行的拉拉,不过我们

要从现象开始分析修改),好了,执行

make distclean

make s5p_goni_config

make

不出意外,已经生成了uboot.bin。

4 烧录

怎么烧录了?我们可以使用之前三星做好的脚本烧之,那家伙就是sd_fusing。复制到现在的uboot工程

目录下即可。呐,插卡,运行脚本./sd_fusing.sh /dev/sdx 完成烧录。

5 运行看效果

运行,这时你会看到CRT终端上打印了两个SD CHENKSUM ERROR,和UART 什么什么鬼,然后打印

insert USB啥的。

6 分析原因

打印的第一个SD CHECKSUM ERROR可以理解,因为那是SD0通道的iNAND校验失败,第二个是什么

情况勒,我们发现这时SD2通道也校验失败,并从UART启动也失败,再从USB启动,没有插USB。那

为什么校验失败了呢,sd_fusing脚本给BL1添加16字节的头部啊,程序是对的啊。这是因为我们的

uboot.bin的前16字节被覆盖了,我们start.S的头16字节是在设置中断向量表,所以在脚本给uboot.bin

添加头的时候给覆盖掉了,所以我们应该在start.S的开始处添加16字节占个位置,来存放头信息。

// uboot头部16字节的用于填充校验和 不加会check sum error
.word 0x2000
.word 0x0
.word 0x0
.word 0x0

再次编译烧录,我们可以看到这是算是运行了,现在只打印了一个SD CHECKSUM ERROR。下面运行到

哪里失败了呢,我们再分析,不过算是一件可以运行了!

接下来,基本的温饱问题解决了,我们要做的就是,分析源码,修改源码,编译源码,分析运行效果···

阻碍1:

好了,现在只能从start.S开始分析了,我们可以写个点亮某个LED的代码段来调试程序死在哪了。我们

发现,uboot第一阶段运行都正常,就是说在调用lowlevel_init之前都可以工作,但是在跳转到lowlevel_init

的第一句就不行了,这是为嘛呢?经过分析发现,在uboot的第一阶段(只有8KB,在SRAM运行),我们

没有把lowlevel_init链接到前8K,所以跳转不过去。

解决1:

既然不能链接到前8KB,那么就去修改链接脚本把lowlevel_init.o链接到前面来,在arch/arm/cpu/打开

u-boot.lds,修改如下

.text :
{
*(.__image_copy_start)
CPUDIR/start.o (.text*)
/* 把lowlevel_init.o链接到前8KB */
board/samsung/goni/lowlevel_init.o (.text*)

*(.text*)
}

重新编译,发现lowlevel_init函数重定义了,分析可知lowlevel_init.o链接了2次,我们只要删了一次就好,

打开board/samsung/goni/Makefile,修改如下

# 新添加的
#SOBJS := lowlevel_init.o
LOW := lowlevel_init.o

SRCS    := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
SOBJS := $(addprefix $(obj),$(SOBJS))
# 新添加的
all: $(obj).depend $(LOW) $(LIB)

$(LIB): $(obj).depend $(SOBJS) $(OBJS)
$(call cmd_link_o_target, $(SOBJS) $(OBJS))

OK,编译烧录,这时我们就可以运行到lowlevel_init这边了,我们在这里添加开发板供电置锁功能和点亮

一个LED,和让串口打印字符'O',修改如下

<span style="white-space:pre">	</span>/* Disable Watchdog */
	ldreq	r0, =S5PC100_WATCHDOG_BASE		@ 0xEA200000
	ldrne	r0, =S5PC110_WATCHDOG_BASE		@ 0xE2700000
	str	r5, [r0]

<span style="color:#3333ff;">		/* 给开发板供电锁存 */
		ldr r0, =0xE010E81C
		ldr r1, =0x301
		str r1, [r0]

		/* 亮一个灯 */
		ldr r0, =0x11111111			
		ldr r1, =0xE0200240			
		str r0, [r1]				
		ldr r0, =((1<<3) | (0<<4) | (1<<5))	
		ldr r1, =0xE0200244
		str r0, [r1]	<span style="white-space:pre">			</span>//我们添加的</span>
在uart_asm_init函数 末尾添加

	<span style="color:#3333ff;">// 这里我们直接向uart2的发送缓冲区写数据就会发送 因为在IROM中已经初始化了UART
	ldr	r1, =0x4f4f4f4f
	ldr r0, =0xE2900820 // UTXH2
	str	r1, [r0]		// 'O'</span>
好了,到这里编译烧录,你会发现 开发板置锁了,LED亮了,串口打印了字符'O'


阻碍2与解决2:

串口初始化完了,接下来的任务就是DDR的初始化,然后完成重定位,长跳转到DDR去运行,那么问题来

了,怎么初始化DDR。说难也难,说简单也简单,我们只要把我们之前裸机的DDR初始化代码COPY过来

即可,我们把他copy到board/samsung/goni目录下,然后进行把这个文件链接到前8KB即可,方法同上面

接着,我们在lowlevel_init.S的串口初始化后面添加DDR的初始化,如下所示:

	/* for UART */
	bl	uart_asm_init

	/* 初始化DDR 自行添加移植 */
	bl mem_ctrl_asm_init

	/* DDR初始化成功打印字符'K' */
	ldr	r1, =0x4b4b4b4b
	ldr r0, =0xE2900820 // UTXH2
	str	r1, [r0]		// 'K'

	mov	lr, r11			// 我们自己让他强制返回
	mov	pc, lr
初始化完成后打印'K'。并且返回。

阻碍3与解决3:

DDR初始化完了,接着就要进行代码重定位,并长跳转到DDR中运行,辣么,这么重定位勒,我们是从SD

卡启动的,并且分析sd_fusing目录下的烧录脚本可知,我们把uboot加16字节的头信息烧到了SD卡的第一

个扇区开始处,并且把整个uboot镜像烧录到49扇区开始的位置。所以我们重定位的方向是从SD卡的第49

扇区开始拷贝uboot.bin大小到DDR的约定位置。我们之前在裸机代码中已经写过了代码的重定位,所以跟

上面的方法类似,拷贝文件过来修改即可,我们一样拷贝到了/board/samsung/goni目录下,并且修改

Makefile和u-boot.lds链接到前8KB即可,修改如下(/board/samsung/goni/myRelocate.c):

#define SD_START_BLOCK	49
#define SD_BLOCK_CNT	(512*2)  // 512KB
#define DDR_START_ADDR	CONFIG_SYS_TEXT_BASE //0x34800000
// 通道号:0,或者2
// 开始扇区号:49
// 读取扇区个数:512*2
// 读取后放入内存地址:0x34800000
typedef unsigned int bool;
typedef bool(*pCopySDMMC2Mem)(int, unsigned int, unsigned short, unsigned int*, bool);

// 从SD卡第45扇区开始,复制32个扇区内容到DDR的0x23E00000,然后跳转到23E00000去执行
void relocate_2_ddr(void)
{
	// 读取SD卡扇区到DDR中
	pCopySDMMC2Mem p1 = (pCopySDMMC2Mem)(*(unsigned int *)0xD0037F98);	
	p1(2, SD_START_BLOCK, SD_BLOCK_CNT, (unsigned int *)DDR_START_ADDR, 0);		
}
这里我们从49扇区拷贝512KB到DDR的0x34800000。接下来就是清BSS段,并且长跳转,如下:

	// 重定位
	bl relocate_2_ddr	
	// 清BSS
	clear_bss:
	ldr	r0, _bss_start		/* find start of bss segment        */
	ldr	r1, _bss_end		/* stop here                        */
	mov 	r2, #0x00000000	<span style="white-space:pre">	</span>/* clear                            */
clbss_l:
	str	r2, [r0]		/* clear loop...                    */
	add	r0, r0, #4
	cmp	r0, r1
	ble	clbss_l
	ldr pc, __main		// 长跳转	
__main:
	.word	_main	
接下来我们就运行到了DDR中。在DDR中首先设置栈,然后运行board_init_f函数

阻碍4与解决4:

接下来就是进行一系列的初始化了,哪里不对改哪里,首先,我们可以修改板子的名字,这个简单

不赘述,重头戏是时钟,我们看到可串口上打印的是400MHz,那是因为我们之前没有设置过时钟

,使用的是IROM中初始化的,默认的初始化的ARMCLK是400MHz,我们要把它初始化为1GHz,

怎么做勒,一样的,我们在裸机代码中写过时钟的初始化,SO,在/board/samsung/goni目录下添

加时钟的初始化文件myClockInit.S把时钟初始化为1GHz即可,并且把它放到lowlevel_init.S中去,

时钟初始化代码较长,这里就不贴了,在下面的地方调用初始化之~

	/* Disable Watchdog */
	ldreq	r0, =S5PC100_WATCHDOG_BASE		@ 0xEA200000
	ldrne	r0, =S5PC110_WATCHDOG_BASE		@ 0xE2700000
	str	r5, [r0]

	/* 时钟初始化 */
	bl my_clock_init
在关看门狗后,初始化时钟。这时我们会看到时钟变成了1000MHz。接下来就是配置DDR的信息

DDR几个bank,每个bank有多大这些···,因为我们的板子DDR总共512MB,bank0@256MB,

bank1@256MB,其实地址分别为0x30000000和0x40000000所以其配置,如下所示:

/* Goni has 3 banks of DRAM, but swap the bank */
#define CONFIG_NR_DRAM_BANKS	2
#define PHYS_SDRAM_1		CONFIG_SYS_SDRAM_BASE	/* OneDRAM Bank #0   */
#define PHYS_SDRAM_1_SIZE	0x10000000		/* 256 MB in Bank #0 */
#define PHYS_SDRAM_2		0x40000000		/* mDDR DMC1 Bank #1 */
#define PHYS_SDRAM_2_SIZE	0x10000000		/* 256 MB in Bank #1 */
//#define PHYS_SDRAM_3		0x50000000		/* mDDR DMC2 Bank #2 */
//#define PHYS_SDRAM_3_SIZE	0x0			/* 128 MB in Bank #2 */
接下来配置gd->bd->bi_arch_number要与内核移植,所以我们配置为MACH_TYPE_SMDKV210

具体值为2456。




  • 2
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
正点原子uboot移植流程一般可以按照以下步骤进行: 1. 找到参考的开发平台,一般是正点原子提供的开发板。 2. 下载正点原子提供的uboot源码。 3. 配置uboot源码,根据目标硬件的具体情况进行相应的配置,包括处理器架构、存储器布局、外设等。 4. 编译uboot源码,生成可执行的uboot镜像文件。 5. 将生成的uboot镜像文件烧录到目标硬件的存储介质中,如闪存、SD卡等。 6. 配置目标硬件的启动方式,使其能够从烧录了uboot的存储介质中启动。 7. 连接目标硬件与开发主机,通过串口或网络等方式与uboot进行通信。 8. 在uboot中设置环境变量bootcmd和bootargs,以便启动Linux内核。 9. 启动目标硬件,通过观察启动过程中的输出信息,判断uboot移植是否成功。 10. 如果uboot移植成功,可以继续进行Linux内核的移植和启动。 需要注意的是,正点原子uboot移植流程可能会因具体的硬件平台和uboot版本而有所差异,建议参考正点原子提供的相关文档和资料进行具体操作。 #### 引用[.reference_title] - *1* *2* *3* [【正点原子I.MX6U-MINI移植篇】u-boot移植过程详解(一)](https://blog.csdn.net/qq_39400113/article/details/127121945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值