Linux系统移植学习笔记【1】u-boot移植

Linux系统移植学习笔记1

一、U-boot的移植

1.准备工作

1.本地开发和交叉开发
①本地开发:本地编写代码,本地编译代码,本地运行代码
②交叉开发:本地编写代码,本地编译代码,开发板运行代码
2.ubuntu系统=linux内核+GUI+动态库+命令+文件系统
3.GNU命令(GNU’s not unix一个提倡软件*的组织)

 1. gcc/g++
 2. gdb 
 3. ld 链接  
	将所有的.o文件链接生成.elf文件 
 4. objdump  
	将elf文件生成反汇编文件(.dis)
 5. objcopy 
	将elf文件生成纯粹的二进制文件(.bin)
 6. nm  查看符号表 (了解)
	nm ***.elf
 7. size  查看文件各个段的大小 (了解)	
	size ***.elf 
 8. readelf  查看elf文件的信息 (了解)	
	readelf -h  ***.elf
 9. strip  用于缩小文件的体积 (重点)
	注意: 不可以对中间文件执行strip,
		比如***.o
	strip ***.elf  // 不影响程序的正常运行
 10. addr2line 根据地址定位错误信息 (重点)
	常用于段错误,	
	addr2line  地址  -e ***.elf -f  
	-e:指定可执行文件 
	-f:回显函数名
	定位错误的信息,函数名及函数所在的文件及行号
	gnu命令  --help  : 查看gun命令的帮助手册,借助百度。

4.安装ubuntu版本的交叉编译工具链

1. 在ubuntu的家目录下创建toolchains 
2. 拷贝交叉编译工具链到toolchains目录下,
	并进行解压缩
	FS6818(学生资料)\工具软件\ubuntu版本交叉编译器\gcc-4.5.1.tar.bz2		
	tar -xvf gcc-4.5.1.tar.bz2	
3. 配置ubuntu系统的环境变量
	/etc/envirenment
	/etc/profile
	/etc/bash.bashrc 
	~/.bashrc		
	修改/etc/bash.bashrc,在最后边添加一下内容
	export PATH=$PATH:/home/linux/toolchains/gcc-4.5.1/bin	
4. 使环境变量立即生效 
	source /etc/bash.bashrc		
	./xxx.sh 
	bash  xxx.sh    开一个子终端执行shell脚本
	source xxx.sh   当前终端执行shell脚本
5. 测试交叉编译工具链是否安装成功 
	arm-none-linux-gnueabi-gcc -v
	64位ubuntu系统 : 		
	sudo apt-get install libncurses5-dev
	sudo apt-get install lib32z1

ps.不同的硬件平台,或者不同的linux和u-boot,源码的版本不一致,用到的交叉编译工具链版本也不一样。

5.安装tftp服务
(Trivial File Transfer Protocol:基于TCP/IP协议的一个用来在客户机与服务器之间进行简单文件传输的协议)

作用: 通过TFTP服务下载文件到开发板中
	
	1. 检查ubuntu是否安装了tftp服务
		sudo dpkg -s tftpd-hpa
		打印以下内容表示安装了tftp服务:
		Architecture: i386
		Source: tftp-hpa
		Version: 5.2-7ubuntu3.1

	2. 安装tftp服务 (前提:ubuntu必须能连接外网)
		sudo apt-get update 更新源
		sudo apt-get install -f 跟新依赖
		
		安装tftp服务的命令:
		sudo apt-get install tftpd-hpa tftp-hpa 
	
	3. 配置tftp服务
		1. 在家目录下创建一个tftpboot文件夹
			mkdir tftpboot 
			目的:tftpboot目录下存放的是你要下载到
			开发板上的可执行文件
		2. 修改tftpboot的权限
			chmod 777 tftpboot
		3. 配置tftp服务的环境变量
			打开sudo vi /etc/default/tftpd-hpa 
			修改一下内容:
			  1 # /etc/default/tftpd-hpa
			  2 
			  3 TFTP_USERNAME="tftp" 
					tftp用户名,不需要修改
			  4 TFTP_DIRECTORY="/home/hqyj/ttpboot"
					tftp服务下载文件的存放的路f径,需要修改
					改成自己的对应的tftpboot的路径
			  5 TFTP_ADDRESS="0.0.0.0:69"
					tftp服务默认使用的69端口号
			  6 TFTP_OPTIONS="-c -s -l"  
					tftp服务的参数,这个需要修改
					-l:以standalone/listen模式启动TFTP服务
					-c:可创建新文件。默认情况下,
						TFTP只允许覆盖原有文件,不能创建新文件。
					-s:改变TFTP启动的根目录。
						加了-s后,客户端使用TFTP时,
						不再需要输入指定目录,填写文件的完整路径,
						而是使用配置文件中写好的目录。
						这样也可以增加安全性。
	
	4. 重启tftp服务(只需要执行一个)
		1. sudo service tftpd-hpa start  启动TFTP服务
		2. sudo service tftpd-hpa restart  重启TFTP服务(默认执行重启)
		
		注意:有时一旦重启系统或者长时间不使用tftp服务,
		都需要重启tftp服务
		
	5. 本地测试tftp服务是否安装成功
		$ tftp 127.0.0.1  # 本地回环测试IP地址
		tftp> get 1.txt   # 从tftpboot目录下下载,
						  # 需要在tftpboot目录下创建1.txt
						  # 1.txt文件到当前目录 
		tftp> put 2.txt   # 把当前目录中的2.txt文件,当前目录下需要创建2.txt
						  # 上传到tftpboot文件夹中
	
		tftp> q   <回车>  退出
	
	6. 可能出现的问题
		下载或上传是,一直卡,
		原因:
			1. tftp服务安装成功,需要重启tftp服务
			2. tftp服务安装不成功,重新安装tftp服务
			3. tftp安装成功,检查/etc/default/tftpd-hpa
				环境变量修改是否正确,如果修改环境变量,
				必须重启tftp服务
			4. 关闭windows和ubuntu的防火墙
				(ubuntu的防火墙默认都是关闭的)
				sudo ufw disable

6.安装nfs服务
(Network File System:网络文件系统,通过网络的方式远程挂载根文件系统)

	1. 检查nfs服务是否安装
		sudo dpkg -s nfs-kernel-server
	2. 安装nfs服务(前提:可以上网)
		sudo apt-get install nfs-kernel-server
	3. 配置nfs服务
		1》在家目录下创建nfs文件夹
			mkdir nfs 
		2》设置文件夹的权限最大
			chmod 777 nfs 
		3》拷贝根文件系统到nfs目录下
			根文件系统一会发给你们(rootfs-ok.tar.bz2)
			cp /mnt/hgfs/share/rootfs-ok.tar.bz2 ~/nfs
		4》对根文件系统的压缩包进行解压缩
			cd ~/nfs
			tar -vxf rootfs-ok.tar.bz2
		5》配置nfs服务的环境变量
			sudo vi /etc/exports
			在文件的最后一行添加以下内容:
			****************************************
			 /home/hqyj/nfs/rootfs/ *(rw,sync,no_subtree_check,no_root_squash) 
			****************************
			解析:
			/home/hqyj/nfs/rootfs/:自己的根文件系统的路径
			*:所有的用户,注:*和后边的左括号"("之间不可以出现空格.
			rw:可读可写的权限
			sync:同步文件
			no_subtree_check:不对子目录检查文件的权限
			no_root_squash:如果客户端位root用户,那么他对整个文件具有root的权限
			
			注意:这段话前边不要加#,#号是这个文件中的注释符号
			
	4. 重启nfs服务
		1. sudo service nfs-kernel-server start  启动nfs服务
		2. sudo service nfs-kernel-server restart  重启nfs服务
			
	5. 本地测试nfs服务是否安装成功
		1》回到家目录下
			cd ~
		2》sudo mount -t nfs 本机IP地址:/home/hqyj/nfs/rootfs/ /mnt
		nfs:使用nfs服务,将本机IP地址:/home/hqyj/nfs/rootfs/
		文件挂载到/mnt目录下
		3》检查/mnt目录下是否挂载成功
			cd /mnt 
			ls 
		4》卸载挂载的文件
			sudo umount /mnt
			注意:不可以在/mnt目录下执行卸载的命令

2.u-boot的移植

1.bootloader概念
boot : 引导
loader: 加载
bootloader:用于引导加载内核的程序的一种统称。

2.u-boot和bootloader区别 ?
bootloader:是一系列引导启动程序的统称。
u-boot:属于bootloader中的一种引导程序。
vivi redboot u-boot bios都属于bootloader
在实际开发中大多数使用的是u-boot。

3.u-boot的特点?引导内核启动

    1. u-boot是开源的软件 
	2. u-boot支持多种架构和硬件平台 
		ARM   X86  Mips  PowerPC ...
	3. u-boot源码短小精悍。
	4. u-boot就是一个裸机程序。
	5. u-boot是一个短命鬼,
		主要作用就是引导内核启动,
		内核一旦启动成功,u-boot的使命结束。
	6. u-boot启动时完成部分硬件的初始化
		内存,flash,串口,时钟系统,电源系统...
	7. u-boot用于引导linux内核启动,
		并且给内核传递参数。

4.u-boot支持的命令 <重点>

1. help 
	查看u-boot支持的所有的命令
	help  u-boot命令 : 查看某个命令的帮助手册
2. loadb   下载应用程序
3. go      运行应用程序
4. printenv/print/pri : 打印u-boot的环境变量
	baudrate=115200   # 串口波特率
	board_name=FS6818  # 板子名字
	bootargs=root=/dev/nfs nfsroot=192.168.2.200:/home/hqyj/nfs/rootfs tcp,v4 rw console=/dev/ttySAC0,115200 init=/linuxrc ip=192.168.2.100
	bootcmd=loadb 43c00000;go 43c00000
	bootdelay=50            # 引导的倒计时时间
	gatewayip=192.168.2.1   # 开发板网关
	ipaddr=192.168.2.100    # 开发板IP地址
	netmask=255.255.255.0   # 开发板的子网掩码
	serverip=192.168.2.200  # ubuntu的IP地址
	stderr=serial           # 标准出错
	stdin=serial            # 标准输入
	stdout=serial           # 标准输出

5. 设置环境变量  
	setenv  : 设置环境变量  增加/删除/修改
		设置环境变量时,默认修改的是内存中的值
	saveenv :保存环境变量
		保存环境变量从内存到flash中
	1> 增加一个新的环境变量: 
		setenv 新的环境变量名  环境变量的值
		eg:
		setenv  target fs6818
		saveenv 

		setenv target name  fs6818
		环境变量的名字之间不允许出现空格

	2> 修改环境变量的值 
		setenv  旧的环境变量名   新的环境变量值
		saveenv  
		
		eg: 
		setenv  bootdelay  10
		   注: 不可以将倒计时时间设置为0
		saveenv

	3> 删除环境变量 
		setenv  要删除的环境变量名 
		
		eg: 
		setenv  target  
		saveenv

	练习以上命令: 
	
	1. 设置开发板的环境变量:
		gatewayip ipaddr  netmask serverip
		
	网段跟自己的ubuntu系统一致,
	IP地址,每个人保证唯一性。

6. tftpboot/tftp命令   <后边练习> 
	使用tftp服务,从ubuntu的tftpboot目录下,
	下载文件到开发板中。
	
	前提: 
	1> ubuntu必须安装好tftp服务 
	2> u-boot支持tftp的客户端 
	3> u-boot阶段必须完成网卡的初始化
	
	tftpboot [loadAddress] [bootfilename] : 
	下载bootfilename文件到内存的loadAddress地址中

7. ping命令 <后边练习> 
	pingu-boot是否可以和ubuntu的服务器通信
	
	ping pingAddress

8. md 命令  
	md address 
	回显内存地址中的值。

9. nm 命令  
	nm address  
	设置内存地址中的值。 

5.ping和tftp命令的练习

[准备]
	1. ubuntu必须安装tftp服务 
	2. 关闭windows和ubuntu的防火墙 
	3. 设置windows的网卡为百兆全双工
	控制面板-》网络和Internet-》网络和共享中心-》
	更改适配器设置-》以太网(USB转网卡)-》属性-》
	配置-》高级-》Speed & Duplex -》100M full Duplex

[配置ubuntu的网络地址]:配置ubuntu为固定的IP地址
	
[配置开发板的网络地址]
	gatewayip   # 开发板网关
	ipaddr      # 开发板IP地址
	netmask     # 开发板的子网掩码
	serverip    # ubuntu的IP地址

	setenv  gatewayip 192.168.1.1
	setenv  ipaddr   192.168.1.250
	setenv  netmask  255.255.255.0
	setenv serverip  192.168.1.222
	saveenv 

[使用ping命令测试开发板是否可以ping通ubuntu]
	FS6818# ping 192.168.1.222  # 在串口工具上执行
	
	打印以下信息表示可以开发板可以ping通ubuntu
	dwmac.c0060000 Waiting for PHY auto negotiation to complete.... done
	Speed: 100, full duplex
	Using dwmac.c0060000 device
	host 192.168.1.222 is alive

	总结卡发板无法ping通ubuntu的原因。
	
	1> windows和ubuntu防火墙灭有关闭 
	2> ubuntu系统和开发板的网络的配置,是否在同一个网段
	3> 检查网线
[使用tftp命令下载interface.bin文件到内存中]

	1. 拷贝interface.bin到tftpboot 
	
	2. 使用tftp命令进行下载 
		FS6818# tftp 43c00000 interface.bin
		Speed: 100, full duplex
		Using dwmac.c0060000 device
		TFTP from server 192.168.1.222; our IP address is 192.168.1.250
		Filename 'interface.bin'.
		Load address: 0x43c00000
		Loading: #
				 1.1 MiB/s
		done
		Bytes transferred = 9076 (2374 hex)
		
		总结: tftp下载不成功的原因
		1》 ping不通的原因
		2》 tftp服务安装成功,需要重启tftp服务
		3》 tftp服务安装不成功,重新安装tftp服务
		4》 tftp安装成功,检查/etc/default/tftpd-hpa
				环境变量修改是否正确,如果修改环境变量,
				必须重启tftp服务	
		5》关闭windows和ubuntu的防火墙
				(ubuntu的防火墙默认都是关闭的)
				sudo ufw disable
		
	3. 运行应用程序

6.开发板系统的部署方式

ubootpak.bin  : u-boot的镜像文件
uImage        :linux内核的镜像文件
rootfs        :根文件系统 
ramdisk.img   : 根文件系统的镜像,通过rootfs打包压缩生成ramdisk.img 

[1. 开发阶段的系统部署]
	ubootpak.bin :   EMMC/SD 
	uImage       :   tftp服务下载程序到内存中
	rootfs       :    nfs服务挂载根文件系统

[2. 产品阶段的系统的部署]
	ubootpak.bin :   EMMC/SD 
	uImage       :   EMMC/SD
	ramdisk.img  :    EMMC/SD

Linux系统移植学习笔记【1】u-boot移植
7.开发阶段的系统部署步骤

	1> 启动开发板,进入uboot的交互模式
	2> 拷贝uImage内核镜像文件到ubuntu的tftpboot目录下
	3> 使用tftp命令下载uImage内核镜像到内存中 
		tftp 0x48000000 uImage 
	4> 设置uboot环境变量中的bootargs环境变量<重要>
		setenv bootargs root=/dev/nfs nfsroot=192.168.1.222:/home/hqyj/nfs/rootfs tcp,v4 rw console=/dev/ttySAC0,115200 init=/linuxrc ip=192.168.1.250
		saveenv
		bootargs环境变量的作用:
			自启动的参数,内核启动成功之后,需要从uboot的环境变量的分区读取bootargs
			环境变量对应的值。
		root=/dev/nfs : 使用网络文件系统
		nfsroot=192.168.1.222:/home/hqyj/nfs/rootfs :网络文件系统的服务器的地址和路径
		tcp,v4 : tcp v4版本
		rw : 可读可写的权限
		console=/dev/ttySAC0,115200 : 串口
		init=/linuxrc : 挂载跟文件系统成功之后,运行的1号进程
		ip=192.168.1.250 : 开发版的IP地址
		只需要设置1次
		
	5> 启动内核,内核启动成功之后会自动挂载根文件系统
		bootm  0x48000000   # 引导启动内核的命令 
		# 注: 不可以是用go命令
	
	6> 观察现象,并进行应用程序测试
		可以写一个hello world的应用程序在开发板上进行测试,
		注:需要使用交叉编译工具链进行编译。
	
	7> 以上启动方式属于交互的方式,
		设置系统为自启动的方式。
		
		设置uboot中的bootcmd环境变量,
		
		bootcmd的作用?
		自启动的环境变量,uboot启动之后,
		倒计时减到0之前,不按任意键,默认会自动执行
		bootcmd环境变量中的所有的命令会被依次执行。
		
		bootcmd的格式:
		setenv bootcmd uboot命令1\;uboot命令2\;.....
			
		setenv bootcmd tftp 48000000 uImage\; bootm 48000000
		saveenv 
		
		如果进入到uboot的交互模式可以执行boot命令,
		bootcmd环境变量中的命令也会被依次执行。

8.移植u-boot源码

1. 准备u-boot源码
	1) 拷贝u-boot源码到ubuntu中
		u-boot-2014.07-netok.tar.bz2
	2) 解压缩
		tar -vxf u-boot-2014.07-netok.tar.bz2
	3) 进入到u-boot源码目录
		cd u-boot-2014.07
	注:u-boot源码不要再共享目录或者windows下解压		
2. 分析u-boot源码的目录结构
	平台相关代码:跟硬件有关的代码
		平台相关代码,所有的硬件都有自己的一套代码
	arch : 架构
	board : 板子
	
	平台无关代码:跟硬件无关的代码,
		平台无关代码,所有的硬件都共用一套代码
	common : uboot命令	
	drivers : 驱动
	fs : 文件系统
	include : 头文件 
	lib : 库
	net : 网络 
	tools : 工具
	.....
		
3. 配置编译u-boot源码 
	配置:让u-boot源码支持s5p6818芯片 
	编译: 有选择性的编译uboot源码,生成ubootpak.bin
	1> 配置交叉编译工具链
	 
	 240 ifeq ($(HOSTARCH),$(ARCH))
	 241 CROSS_COMPILE ?=                                             
	 242 endif
	  修改为:
	 198 ifeq (arm,arm)
	 199 CROSS_COMPILE ?= arm-none-linux-gnueabi-       
	 200 endif

	2> make help 获取对uboot源码make编译时的信息
		清除中间文件
		make clean 
		make distclean  
		编译uboot源码生成uboot的可执行文件 
		make/make all 
		
	3> 读README
	 254 For all supported boards there are ready-to-use default
	 255 configurations available; just type "make <board_name>_config".
	 256 
	 257 Example: For a TQM823L module type:
	 258 
	 259     cd u-boot                                                
	 260     make TQM823L_config
	
	4> 配置uboot源码支持fs6818开发板  
		make fs6818_config
		
		注: 一旦执行了make distclean,需要重新执行
		make fs6818_config 命令
		
		make fs6818_config命令只需要在最开始的时候执行一次。

	5> 编译uboot源码  
		make -j4 all 
		最终就可以生成ubootpak.bin 
		
		生成windows版本的ubootpak.bin  
		dd if=/dev/zero of=512B bs=512 count=1
		chmod 777 512B 
		cat 512B ubootpak.bin > win_ubootpak.bin

	6> 测试新生成的uboot镜像是否可以使用 
		烧写ubootpak.bin到EMMC中
		
		可以使用开发阶段系统部署的方式启动一下系统。
  1. loadb命令的移植
	自己移植的uboot支持大多数的uboot命令,但不支持uboot命令 
	
	1. 使用grep命令搜索loadb
	grep "loadb" * -nR
	搜索结果如下:
	common/cmd_load.c:389: * loadb command (load binary) included
	common/cmd_load.c:1059:	loadb, 3, 0,	do_load_serial_bin,

	
	2. 打开common目录下的Makefile文件
	
	133 obj-y += cmd_load.o 
		说明cmd_load.o文件被编译到ubootpak.bin 
	
		all:${obj-y}
	
	3. CONFIG_CMD_LOADB宏没有定义

		在板子的头文件中添加宏定义
		find . -name fs6818.h

		打开:vi include/configs/fs6818.h 
		添加以下内容
		121 #define CONFIG_CMD_LOADB  

	4. 重新编译uboot源码,进行测试。
上一篇:uboot的环境变量


下一篇:uboot、Linux内核(kernel)和文件系统(System)的编译