系统移植
【1】什么是系统移植?
为什么学习系统移植?
学习系统移植的目的?
如何学习系统移植?
-
什么是系统移植?
就是将操作系统移植到对应的硬件平台
linux系统移植到开发板
-
为什么学习系统移植?
软硬件可裁剪
公司新的硬件平台—》移植linux系统
到硬件平台
-
学习系统移植的目的?
1》工作的需要
2》为后边的驱动开发搭建一个系统环境
3》嵌入式应用层的开发离不开操作系统
-
如何学习系统移植?
1》跟上我上课的思路,
2》掌握系统移植的流程,不要关心代码
【2】概念:本地开发和交叉开发
本地开发:PC端编写代码,编译代码,运行代码
交叉开发:PC端编写代码,编译代码,Target运行代码
PC Target
X86架构 arm架构
使用交叉编译工具链将源码编译成支持ARM架构的可执行程序,
再讲可执行程序拷贝到目标板上运行。
PC:gcc
交叉编译工具链:arm-none-linux-gnueabi-gcc
arm-none-linux-gnueabi-:交叉编译工具链的名字,
名字就是一个代码
【3】安装交叉编译工具链
1. 获取交叉编译工具链
一般交叉编译工具链和uboot和linux内核源码,
都具有配套的关系。
1》自己去gnu官网获取交叉编译工具链的源码,
自己进行编译生成对应的交叉编译工具链。
不推荐:编译过程很繁琐
2》直接从芯片厂家获取交叉编译工具链
3》直接跟开发板的生成厂家获取交叉编译工具链
4》直接找主管获取交叉编译工具链
安装交叉编译工具链:
将代码编译成ARM架构的可执行程序
安装步骤:
1. 在ubuntu的家目录(~)下,创建toolchain
mkdir toolchain
2. 拷贝gcc-4.5.1.tar.bz2到toolchain目录下
cp 目录/gcc-4.5.1.tar.bz2 ~/toolchain
3. 解压缩交叉编译工具链
tar -vxf gcc-4.5.1.tar.bz2
4. 配置环境变量
打开 sudo vi /etc/bash.bashrc
在最后一行添加以下内容:
5. 使环境变量立即生效
source /etc/bash.bashrc
export PATH=$PATH:/home/hqyj/toolchain/gcc-4.5.1/bin/
修改为自己的路径
6. 测试交叉编译工具链是否安装成功
arm-none-linux-gnueabi-gcc -v
打印以下内容,表示成功
gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50)
【4】gnu命令
1. nm
格式:nm 可执行文件
列出可执行文件中的符号
$ arm-none-linux-gnueabi-nm interface.elf
符号的地址 类型 符号名字
43c016e4 T delay_ms
43c01754 T do_irq
43c00200 T fiq
43c01a24 T hal_irq_gicc_init
43c01988 T hal_irq_gicd_init
43c01844 T hal_irq_gpio_init
43c01a6c T hal_led_init
43c000c4 t init_stack
43c001e0 T irq
43c01b44 T main
2. strip
删除可执行文件中符号表,对可执行文件进行压缩
符号表不影响程序的运行。
切记,不可以对中间文件进行压缩
格式:strip 可执行文件
使用ls -al可以查看文件的大小
3. size
查看文件中各个段的大小
格式:size 可执行文件
$ arm-none-linux-gnueabi-size interface.elf
text data bss dec hex filename
7140 2304 0 9444 24e4 interface.elf
4. objcopy
将可执行文件(elf)生成纯粹的二进制文件(.bin)
格式:arm-none-linux-gnueabi-objcopy
-O binary ***.elf ***.bin
-O:输出
binary:二进制文件
5. objdump
将可执行文件(elf)生成反汇编文件(.dis)
格式:格式:arm-none-linux-gnueabi-objdump
-D ***.elf > ***.dis
可以看反汇编代码,查看代码具体的实现,
通过可执行文件生成的汇编代码叫做反汇编(汇编指令集)代码
7 43c00000 <_start>:
指令存放的地址 机器码 通过机器码生成反汇编代码
8 43c00000: ea00000d b 43c0003c <reset>
9 43c00004: e59ff014 ldr pc, [pc, #20] ; 43c00020 <_undefined
10 43c00008: e59ff014 ldr pc, [pc, #20] ; 43c00024 <_software_
11 43c0000c: e59ff014 ldr pc, [pc, #20] ; 43c00028 <_prefetch_
12 43c00010: e59ff014 ldr pc, [pc, #20] ; 43c0002c <_data_abor
13 43c00014: e59ff014 ldr pc, [pc, #20] ; 43c00030 <_not_used>
14 43c00018: e59ff014 ldr pc, [pc, #20] ; 43c00034 <_irq>
15 43c0001c: e59ff014 ldr pc, [pc, #20] ; 43c00038 <_fiq>
6. readelf
获取可执行文件的头部信息
格式:readelf -h 可执行文件
ELF Header:
Magic: 7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: ARM
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x43c00000
Start of program headers: 52 (bytes into file)
Start of section headers: 53124 (bytes into file)
Flags: 0x602, has entry point, GNU EABI, software FP, VFP
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 18
Section header string table index: 15
7. addr2line
跟地址可以定位到地址对应的函数
格式:addr2line -e ****.elf 地址 -a -f
作用:可以用于追踪代码的错误,追踪段错误或者空指针
-e:后边跟可执行文几番
-a -f:显示函数名和行号
$ arm-none-linux-gnueabi-addr2line -e interface.elf 0x43c01a74 -a -f
0x43c01a74
hal_led_init
/home/thf/1997/arm/key_irq/main.c:92
gun命令前边什么都不加,表示X86架构下的GUN指令
gcc g++ nm addr2line readelf strip objdump objcopy
gnu命令前边添加arm-none-linux-gnueabi-的前缀
表示支持arm架构的gnu命令
对于交叉编译工具的的前缀到底是什么?
/home/thf/toolchain/gcc-4.5.1/bin
在交叉编译工具链的bin目录下查看交叉编译工具链的前缀。
arm-none-linux-gnueabi-gcc --help 查看命令的帮助手册
ubuntu中gnu命令存在的路径在:
/usr/bin
thf@thf:bin$ pwd
/usr/bin
thf@thf:bin$ ls -al gcc
lrwxrwxrwx 1 root root 7 10月 28 12:21 gcc -> gcc-4.8
thf@thf:bin$ ls -al objcopy
-rwxr-xr-x 1 root root 217000 4月 26 2017 objcopy
thf@thf:bin$ ls -al gdb
-rwxr-xr-x 1 root root 5094584 6月 10 2017 gdb
thf@thf:bin$ ls -al g++
lrwxrwxrwx 1 root root 7 4月 8 2014 g++ -> g++-4.8
【5】PC和Target如何进行硬件连接
pc Target
---------------- -----------------
| | 串口线 | |
| |-----------| |
| | | |
| | 网线 | |
| |-----------| |
| | | |
| | | |
| | | 电源 |
---------------- -----------------
串口线:打印各种调试信息得到串口工具上
网线:用于下载uboot和内核的镜像
通过网络去挂载根文件系统
需要在ubuntu中安装对应的服务器
通过网线下载文件---》tftp服务
通过网线挂载根文件系统---》nfs服务
tftp服务和nfs服务的客户端uboot和内核源码默认已经安装
【6】安装tftp服务
一个简单的文本文件传输协议,基于udp协议
1. 检查ubuntu是否安装了tftp服务
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 更新依赖
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/tftpboot"
tftp服务下载文件的存放的路径,需要修改
改成自己的对应的tftpboot的路径
5 TFTP_ADDRESS="0.0.0.0:69"
tftp服务默认使用的69端口号
6 TFTP_OPTIONS="-c -s -l"
tftp服务的参数,这个需要修改
4. 重启tftp服务
1. sudo service tftpd-hpa start 启动TFTP服务
2. sudo service tftpd-hpa restart 重启TFTP服务
5. 本地测试tftp服务是否安装成功
$ tftp 127.0.0.1
tftp> get 1.txt # 从tftpboot目录下下载
# 1.txt文件到当前目录
tftp> put 2.txt # 把当前目录中的2.txt文件
# 上传到tftpboot文件夹中
tftp> q <回车> 退出
6. 可能出现的问题
下载或上传是,一直卡,
原因:tftp服务安装成功,需要重启tftp服务
tftp服务安装不成功
关闭windows和ubuntu的防火墙
【6】nfs服务的安装
Network File System
1. 检查nfs服务是否安装
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目录下
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/thf/nfs/rootfs/ *(rw,sync,no_subtree_check,no_root_squash)
****************************
解析:
/home/thf/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/thf/nfs/rootfs/ /mnt
nfs:使用nfs服务,将本机IP地址:/home/thf/nfs/rootfs/
文件挂载到/mnt目录下
3》检查/mnt目录下是否挂载成功
cd /mnt
ls
4》卸载挂载的文件
sudo umount /mnt
注意:不可以在/mnt目录下执行卸载的命令
#####################################################
【8】uboot中的命令
1.help命令
FS6818# help 查看当前uboot支持的所有的命令
命令就是一个字符串,uboot收到字符串之后,
会解析字符串,完成对应的功能。
FS6818# help
0 - do nothing, unsuccessfully
1 - do nothing, successfully
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
cmd - cmd [command] options...
cmp - memory compare
cp - memory copy
crc32 - checksum calculation
dhcp - boot image via network using DHCP/TFTP protocol
drawbmp - darw bmpfile on address 'addr' to framebuffer
env - environment handling commands
exit - exit script
ext4load- load binary file from a Ext4 filesystem
ext4ls - list files in a directory (default /)
ext4write- create a file in the root directory
fastboot- fastboot- use USB Fastboot protocol
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
fatwrite- write file into a dos filesystem
fdisk - mmc list or create ms-dos partition tables (MAX TABLE 7)
go - start application at address 'addr'
goimage - start Image at address 'addr'
help - print command description/usage
i2c - I2C sub-system
i2cmod - set I2C mode
iminfo - print header information for application image
loadb - load binary file over serial line (kermit mode)
loadbmp - load bmpfile with command or 'bootlog' environment
loads - load S-Record file over serial line
loadx - load binary file over serial line (xmodem mode)
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
md - memory display
mdio - MDIO utility commands
mii - MII utility commands
mm - memory modify (auto-incrementing address)
mmc - MMC sub system
mmcinfo - display MMC info
mtest - simple RAM read/write test
mw - memory write (fill)
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
pmic - PMIC
printenv- print environment variables
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv - save environment variables to persistent storage
saves - save S-Record file over serial line
sdfuse - sdfuse - read images from FAT partition of SD card and write them to booting device.
setenv - set environment variables
showvar - print local hushshell variables
source - run script from memory
test - minimal test like /bin/sh
tftpboot- boot image via network using TFTP protocol
udown - Download USB
update_mmc- update mmc data
version - print monitor, compiler and linker version
2. help 命令
查看命令的帮助手册
3. loadb
loadb 下载到内存的那个地址
下载二进制文件到内存的某个地址,使用kermit协议
flash memery
掉电不丢失 掉电丢失
速度慢 速度快
价格便宜 价格贵
flash访问通过 内存以字节为单位进行访问
块去访问,
每块大小位512字节
4. go
go 内存地址
跳转到内存地址处,运行程序
5. printenv 打印uboot的环境变量
FS6818# printenv
baudrate=115200
bootargs=root=/dev/nfs nfsroot=192.168.0.222:/home/hqyj/nfs/rootfs,v4,tcp rw console=/dev/ttySAC0,115200 init=/linuxrc ip=192.168.0.250
bootcmd=loadb 43c00000;go 43c00000
bootdelay=3
bootfile=uImage
ethact=dwmac.c0060000
ethaddr=00:e2:1c:ba:e8:60
ethprime=RTL8211
fastboot=flash=mmc,2:ubootpak:2nd:0x200,0x78000;flash=mmc,2:2ndboot:2nd:0x200,0x4000;flash=mmc,2:bootloader:boot:0x8000,0x70000;flash=mmc,2:boot:ext4:0x00100000,0x04000000;flash=mmc,2:system:ext4:0x04100000,0x2F200000;flash=mmc,2:cache:ext4:0x33300000,0x1AC00000;flash=mmc,2:misc:emmc:0x4E000000,0x00800000;flash=mmc,2:recovery:emmc:0x4E900000,0x01600000;flash=mmc,2:userdata:ext4:0x50000000,0x0;
gatewayip=192.168.0.1
ipaddr=192.168.0.250
loadb=0x43c00000;go 0x43c00000
netmask=255.255.255.0
serverip=192.168.0.222
stderr=serial
stdin=serial
stdout=serial
Environment size: 872/32764 bytes
注意:uboot对命令进行匹配是,是部分匹配
pri/print/printenv 常用
5. bootm (启动内核是在用)
bootm 内核的运行地址 根文件系统的运行地址 设备树的运行地址
引导linux内核启动的
6. ping命令
ping ip地址
用于开发板和电脑是否可以ping通
7. setenv 设置环境变量
1》给uboot添加环境变量
setenv 环境变量名 环境变量对应的值
eg:setenv xiaoming nozuonodie
注:等号会自动添加
2》删除环境变量
setenv 要删除的环境变量名
eg:setenv xiaoming
3》修改环境变量
setenv 旧的环境变量名 新的环境变量值
eg:setenv xiaoming qusiba
设置完环境变量之后,环境变量存在于内存中,
重新上电数据会丢失
8. saveenv 保存环境变量到flash中
9. tftpboot
使用tftp服务,将可执行程序通过网线下载到内存中
tftpboot/tftp 内存地址 要下载的可执行文件
要求:可执行文件必须存放在tftp服务配置是指定的目录下
我的目录:/home/hqyj/tftpboot
【8】uboot中环境变量的作用
baudrate=115200 波特率
bootdelay=3 uboot启动后倒计时时间
gatewayip=192.168.1.1 网关
ipaddr=192.168.1.250 开发板的ip地址(FS6818)
netmask=255.255.255.0 子网掩码
serverip=192.168.1.222 服务器的ip地址(PC:Ubuntu)
【9】测试ping命令和tftp命令的使用
0》开发板和PC电脑如何连接
查看:开发板和PC网线进行连接.png
1》设置ubuntu的IP地址
1>修改电脑的网卡由自动切换到百兆全双工
查看:网卡百兆全双工设置.png
2>修改ubuntu的ip地址
(1) 设置ubuntu系统使用有线网卡
查看:ubuntu网络配置1.png
(2) 设置ubuntu系统为固定的IP地址
查看:Ubuntu网络配置2.png
(3)查看IP地址是否设置成功
ifconfig
2》设置开发板的IP地址
setenv serverip 192.168.1.222
setenv ipaddr 192.168.1.250
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
saveenv
3》测试开发板能够平通Ubuntu
在超级终端上执行以下命令
FS6818# ping 192.168.1.222
如果ping失败打印一下信息:
dwmac.c0060000 Waiting for PHY auto negotiation to complete… TIMEOUT !
Waiting for PHY realtime link… TIMEOUT !
done
dwmac.c0060000: No link.
ping failed; host 192.168.1.222 is not alive
如果ping成功打印一下信息:
Speed: 100, full duplex
Using dwmac.c0060000 device
host 192.168.1.222 is alive
总结:
ping 失败的原因
1》windows的防火墙可能没关
2》检查开发板和电脑之间的网线
3》重启tftp服务
4》检查tftp服务的环境配置是否正确
4》测试tftp命令的使用
拷贝ARM课程中的interface.bin文件到tftpboot目录下
在超级终端上执行以下命令:
FS6818# tftp 0x43c00000 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: #
708 KiB/s
done
Bytes transferred = 8700 (21fc hex)
FS6818# go 0x43c00000 # 运行代码
总结:tftp失败的原因
1》包含上边ping失败的原因
2》检查uboot的环境变量设置是否正确
serverip ipaddr gatewayip netmask
3》检查ubuntu的网络设置
切记,开发板和ubuntu的ip地址在同一个网段
【10】给开发板部署操作系统
-
部署uboot
1》新的开发板,一切都是空白,制作一个SD卡启动盘
1> 将sd卡启动盘的制作工具拷贝到ubuntu的toolchain目录下
cp /mnt/hgfs/share/sdtool ~/toolchain -raf
2> 进入到sdtool目录下
cd ~/toolchain/sdtool
3> 将sd卡插到电脑上,让你的ubuntu识别sd卡
注意:必须使用读卡器,不可以使用电脑自带的SD卡卡槽
将SD卡插到读卡器上,读卡器插到电脑上,
在windows下讲SD卡进行格式化。
虚拟机--》可移动设备--》realtek USB3.0-CRW
---》连接
sdtool文件中的文件是什么?
s5p6818-sdmmc.sh :烧写uboot到sd卡的脚本
ubootpak.bin:uboot的可执行文件
4> 烧写ubootpak.bin到sd卡中
在ubuntu中执行命令
sudo ./s5p6818-sdmmc.sh /dev/sdb ubootpak.bin
/dev/sdb: sd卡的设备文件
如果打印一下信息表示,部署成功:
688+1 records in
689+0 records out
352768 bytes (353 kB) copied, 0.00914641 s, 38.6 MB/s
^_^ The image is fused successfully
总结: 报SD卡只读的错误,
将sd卡中开关拨到lock的位置,
lock靠近sd卡的触点位置
5> 测试sd卡是否制作成功
将sd卡插到开发板板上,
设置开发板上的拨码开关,为sd卡启动,
拨码开关用于设置开发板上uboot的启动方式的
OM1 OM2 OM3 Device
ON ON X nand flash
OFF ON X USB
ON OFF ON EMMC 本开发板flash为EMMC
OFF OFF OFF SD/TF
6> 开发板重新上电,启动成功。
- 部署Linux内核
- 部署根文件系统