2015.10uboot移植笔记 (一、移植前编译和烧录)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/C1033177205/article/details/89791035

在学习朱有鹏老师的uboot移植的时候,只有移植了比较久的uboot,现在想移植一下可以用menuconfig配置的uboot,本来之前是想移植2017版的uboot,好像s5pv210的编译工具链比较老,不是很兼容,就选了一个比较旧的uboot的版本,而且还带了menuconfig的选项的uboot的,那就选uboot的2015年10月份的。
uboot的下载链接:
https://blog.csdn.net/qq_16777851/article/details/81782669

移植过程中只要是参考了:https://blog.csdn.net/qq_16777851/article/details/81543373 这个博主的《从零开始之uboot、移植uboot2017.01》这个专题

一、移植前编译和烧录

1,交叉编译工具和环境的搭建

这里就不描述Ubuntu环境搭建和交叉编译工具链的环境搭建了。(编译工具链就用朱老师的arm-2009q3)

uboot下载地址在上面链接已经有了,只要下载下来,解压即可。

2,编译

进入uboot根目录,也就是顶层Makefile目录

(1)首先清除整个工程,防止上次编译遗留的文件,影响我们编译

make menuconfig

(2)添加编译工具链路径

顶层Makefile的244行

#########################################################################

# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=		#uboot默认的交叉编译工具链路径
endif
#这里是我指定的编译工具链的路径,个人不喜欢添加环境变量,就用了全路径,添加了环境变量的可以直接写arm-none-linux-gnueabi-
CROSS_COMPILE := /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

KCONFIG_CONFIG	?= .config
export KCONFIG_CONFIG

添加完编译工具链之后就可以开始移植了

(3)移植开始

在configs目录下,是存放着之前已经移植过的板子的配置项,要找到了一个和s5pv210比较相近的配置项。
s5p_goni_defconfig 这个配置项跟s5pv210比较相近。那就用它了。。。

退出到根目录,接下来进行配置

make s5p_goni_defconfig

其实这个命令,实际是把configs/s5p_goni_defconfig 这个文件覆盖原来的 ./.config 文件(如果没有.config文件就创建一个)

简单讲解一下这个make s5p_goni_defconfig执行过程
这其实是一条Makefile的命令,执行这条命令就想当于去Makefile找到一个跟这个s5p_goni_defconfig匹配的目标
在顶层Makefile的473行找到了这个匹配的目录

KBUILD_DEFCONFIG := sandbox_defconfig
export KBUILD_DEFCONFIG KBUILD_KCONFIG

config: scripts_basic outputmakefile FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@

# %是通配符  echo  是我加的一个打印  可以追踪Makefile命令的执行  $@  表示目标文件 这是是指s5p_goni_defconfig
# 其实我们输入make menuconfig也是匹配这个目标
%config: scripts_basic outputmakefile FORCE	
	echo "%config $@"
	# 这条语句就是去执行scripts/kconfig 目录下的Makefile文件 目标是s5p_goni_defconfig
	$(Q)$(MAKE) $(build)=scripts/kconfig $@	 

其实还有一种追踪Makefile的打印

$(info $(u-boot-main) )		#这个函数可以打印出变量的值

然后进入scripts/kconfig目录,打开Makefile,果然又找到了我们的目标(在111行)

# $<  表示第一个依赖文件 也就是 conf
%_defconfig: $(obj)/conf
	echo "%_defconfig $(obj) $(SRCARCH) $@ $(Q) $(Kconfig)"
	# 下面这句 可以转化成 @ conf --defconfig=arch/../configs/s5p_goni_defconfig Kconfig
	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)

# Added for U-Boot (backward compatibility)
%_config: %_defconfig
	@:  
# @:关闭回显

%_defconfig是目标,$(obj)/conf是依赖,这个依赖是一个c语言编译的一个程序(主函数在conf.c里)具体Makefile怎么编译出阿里我也不清楚,之后研究清楚了,可以再补充。
conf --defconfig=arch/…/configs/s5p_goni_defconfig Kconfig
这个就是执行c程序,这个程序名字是conf 带的参数是–defconfig=arch/…/configs/s5p_goni_defconfig Kconfig
就是看conf.c的源码就会发现 带了–defconfig参数的就是拷贝这个参数下的文件覆盖./config。具体的有兴趣可以去看看源码,这里不详细介绍了。

接下来就行编译

make			#单核编译
make -j4		#多核编译 44

直接编译之后,既可看到根目录下的u-boot.bin,所以第一步编译就成功。
(注意:这个u-boot.bin是s5p_goni这块板子的uboot程序,我们还没开始正式的移植)

(4)烧录

前面一节。我们讲到编译成功了,生产了u-boot.bin
然后这一节就把u-boot.bin 烧录到sd卡中,运行,然后看看还有哪里需要修改。(一般是哪里出错,就修改哪里)

由于官网的uboot,没有sd烧录的软件,所以需要从原理的三星那边的uboot,拷贝sd_fusing目录过来。
这里
上面是sd_fusing目录的文件,这里面也是一个小程序,专门做烧录镜像的小程序。拷贝过来的时候,记得make clean后在make
这是防止上次编译的工具链跟现在的不兼容。
make 之后会生成两个可执行文件,mkbl1 这个可执行文件,是制作镜像的,另一个sd_fdisk好像是擦除sd卡和分区的吧(具体不清楚)
这个文件也是写好的脚本了,直接调用就可以烧录:

# /dev/sdb 带的这个参数,就是指SD卡的分区,可以用ls /dev/sd* 查看  里面的sda是我们电脑的磁盘分区
./sd_fusing.sh /dev/sdb

可以简单看看脚本:

#
# Copyright (C) 2010 Samsung Electronics Co., Ltd.
#              http://www.samsung.com/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
####################################
reader_type1="/dev/sdb"
reader_type2="/dev/mmcblk0"

if [ -z $1 ]
then
    echo "usage: ./sd_fusing.sh <SD Reader's device file>"
    exit 0
fi

if [ $1 = $reader_type1 ]
then 
    partition1="$11"
    partition2="$12"
    partition3="$13"
    partition4="$14"

elif [ $1 = $reader_type2 ]
then 
    partition1="$1p1"
    partition2="$1p2"
    partition3="$1p3"
    partition4="$1p4"

else
    echo "Unsupported SD reader"
    exit 0
fi

if [ -b $1 ]
then
    echo "$1 reader is identified."
else
    echo "$1 is NOT identified."
    exit 0
fi

####################################
# make partition
echo "make sd card partition"
echo "./sd_fdisk $1" 
./sd_fdisk $1 
dd iflag=dsync oflag=dsync if=sd_mbr.dat of=$1 
rm sd_mbr.dat
 
####################################
# format
umount $partition1 2> /dev/null
umount $partition2 2> /dev/null
umount $partition3 2> /dev/null
umount $partition4 2> /dev/null

echo "mkfs.vfat -F 32 $partition1"
mkfs.vfat -F 32 $partition1

#echo "mkfs.ext2 $partition2"
#mkfs.ext2 $partition2  

#echo "mkfs.ext2 $partition3"
#mkfs.ext2 $partition3  

#echo "mkfs.ext2 $partition4"
#mkfs.ext2 $partition4  

####################################
# mount 
#umount /media/sd 2> /dev/null
#mkdir -p /media/sd
#echo "mount -t vfat $partition1 /media/sd"
#mount -t vfat $partition1 /media/sd

####################################
#<BL1 fusing>
bl1_position=1		# 烧录到sd卡的bl1阶段的起始块
uboot_position=49	# 烧录到sd卡中的整个uboot的起始块

echo "BL1 fusing"
./mkbl1 ../u-boot.bin SD-bl1-8k.bin 8192	# 就是制作第一阶段8k的指令
dd iflag=dsync oflag=dsync if=SD-bl1-8k.bin of=$1 seek=$bl1_position	# 用dd命令烧录 BL1进sd卡
rm SD-bl1-8k.bin

####################################
#<u-boot fusing>
echo "u-boot fusing"
dd iflag=dsync oflag=dsync if=../u-boot.bin of=$1 seek=$uboot_position	# 用dd命令烧录 整个uboot进sd卡(也就是第二阶段)

####################################
#<Message Display>
echo "U-boot image is fused successfully."
echo "Eject SD card and insert it again."

插好sd卡,然后执行上面指令,程序就会自动烧录到sd卡中,然后拔下来,插到板子上。
如果板子上的SD0(默认会接mmc)还有程序的话,是不会执行到SD2的,这是芯片启动的时候顺序问题,所以要把SD0的程序破坏掉,
Linux下破坏的命令:

busybox dd if=/dev/zero of=/dev/mmcblk0 bs=512 seek=1 count=1 conv=sync
sync

按下电源键,启动程序,会在串口上看到:
在这里插入图片描述
第一个 SD checksum Error 是我们破坏掉的SD0的程序的检验和不通过
第二个SD checksum Error 是我们插入的SD的程序检验和不通过
第三个 Uart negotiation Error 是前面两个SD检验不通过之后,会尝试从串口启动
第四个 Insert an OYG cable into the connector 最后会尝试通过otg启动

上面就是s5pv210的启动顺序

回归正题:
为什么我们的SD卡程序检验和不通过,这个就跟三星的芯片有关了
在这里插入图片描述
从图中可以看出,s5pv210的SD卡程序是需要检验的
检验的数据分别在 0x00地址上写下BL1 的长度
和 0x08的位置上写下Check sum

这时候,可以借鉴下之前uboot的实现:
在这里插入图片描述
三星之前实现的uboot是在_start之前,申请了16个字节占位变量,然后在制作BL1的时候,再把检验和填下进入。

因为我们现在的uboot已经更新了,不能直接在_start前面添加占位变量了,所以需要查看一下链接文件:

#include <config.h>

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
	. = 0x00000000;

	. = ALIGN(4);
	.text :
	{
		*(.__image_copy_start)
		*(.vectors)
		CPUDIR/start.o (.text*)
		*(.text*)
	}

在链接文件中,我们可以看到*(.vectors) 是中断向量表的位置,CPUDIR/start.o 这个才是start.S的程序,然后在这两个之前有一个__image_copy_start这个字段,这个就是可以申请16字节占位的变量

__image_copy_start这个字段定义在arch/arm/lib/sections.c 这个文件中

char __bss_start[0] __attribute__((section(".__bss_start")));
char __bss_end[0] __attribute__((section(".__bss_end")));
char __image_copy_start[16] __attribute__((section(".__image_copy_start")));
char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
char __secure_start[0] __attribute__((section(".__secure_start")));
char __secure_end[0] __attribute__((section(".__secure_end")));
char _end[0] __attribute__((section(".__end")));

这里面都是各个字段定义的变量,如果数组大小定义为0,就不占用空间。
这里我们需要把__image_copy_start字段的数组大小修改为16.

然后回到我们只做BL1程序那里(sd_fusing/C110-EVT1-mkbl1.c)
我们现在要修改C110-EVT1-mkbl1.c文件,因为三星移植的uboot是把BL1的长度已经写好了,但是我们现在移植的uboot的BL1长度还没写好,所以需要添加一个长度的赋值语句即可:

//////////////////////////////////////////////////////////////
	a = Buf + 16;
	for(i = 0, checksum = 0; i < BufLen - 16; i++)
		checksum += (0x000000FF) & *a++;
	//就增加了这一句代码
	*( (unsigned int *)Buf ) = BufLen;
	a = Buf + 8;	
	*( (unsigned int *)a ) = checksum;

//////////////////////////////////////////////////////////////

现在我们把检验和添加上了,可以再次执行make 并且烧录到sd卡,启动看看串口信息
在这里插入图片描述
然后只看到了一个SD checksum Error 打印,上面已经说过,这个是SD0检验不通过的打印,到现在为止就已经可以把编译的程序烧录到板子上运行了,虽然还是会卡死,但是我们已经迈出第一步了,加油,离成功不远了。。。。

第一次从官网移植uboot,难免会有讲述错误的地方,如果有什么地方不对,可以通过留言告诉我,我会将其改正。

附录:
我在to_run_away的博客上看到https://blog.csdn.net/qq_16777851/article/details/81570476这一篇文章,写的计算机检验和的方式跟我这篇的不一样,因为第一次计算检验和就参考了他那篇文章,所以在这里就简单的记录一下:
实现的思想是:不需要占位的变量,uboot正常编译,在制作BL1的时候,会把整个BL1的程序拷贝到往后偏移16字节的位置上,然后在计算长度和检验和,填写到前16字节对应的位置上,代码如下:(也是修改sd_fusing/C110-EVT1-mkbl1.c文件)

#define BL_HEADER_INFO			"1234567891234567"
#define BL_HEADER_SIZE			16
	/* get write BL1 size */
	count = (fileLen < (BufLen - BL_HEADER_SIZE)) ? fileLen : (BufLen - BL_HEADER_SIZE);
	/* write BL1 header info */
	memcpy(Buf, BL_HEADER_INFO, BL_HEADER_SIZE);

	//拷贝剩下的
	nbytes = fread(Buf+BL_HEADER_SIZE, 1, count, fp);

	if ( nbytes != count )
	{
		printf("source file read error\n");
		free(Buf);
		fclose(fp);
		return -1;
	}

	fclose(fp);

//////////////////////////////////////////////////////////////
	a = Buf + 16;
	for(i = 0, checksum = 0; i < count; i++)
		checksum += (0x000000FF) & *a++;

	*(volatile unsigned int *)Buf = BufLen;
	a = Buf + 8;	
	*( (unsigned int *)a ) = checksum;

猜你喜欢

转载自blog.csdn.net/C1033177205/article/details/89791035