系统移植
- 给开发板搭建linux系统
- 从官方获取源码,进行配置和编译,生成开发板所需的镜像文件
- 是驱动开发的基础
安装tftp服务器
tftp
基于udp的文件传输协议,用于将程序下载到开发板中
sudo apt-get install tftpd-hpa tftp-hpa
tftpd
服务器端
tftp
客户端
创建tftp目录
配置tftp服务器
tftp配置文件:etc/default/tftpd-hpa
TFTP_USERNAME="tftp" # tftp服务器名字
TFTP_DIRECTORY="/home/ubuntu/tftpboot/" # tftp服务器下载文件地址
TFTP_ADDRESS="0.0.0.0:69" # ip地址和端口号
TFTP_OPTIONS="-c -l -s" # 保持默认的参数
重启tftp服务sudo service tftpd-hpa restart
tftp本地测试
$ tftp 127.0.0.1 # 连接127.0.0.1(本地回环地址)的tftp服务
tftp>put test1 # 上传test1到tftp文件夹
tftp>get test2 # 下载test2
tftp>quit # 退出tftp服务
tftp传入程序流程
- 在EMMC/TF设备中固化uboot启动文件
- 在tftp服务器文件夹内准备好基于tftp服务器下载的文件
- 通过硬件(拨码开关)设置选择启动方式
- 开发板上电,uboot镜像文件加载到开发板内存中
- 在串口工具打印uboot信息,选择进入交互模式
- 使用tftp指令将程序下载到开发板内存中
安装nfs服务器
网络文件系统,ubuntu通过网络的方式过载文件到开发板中
sudo apt-get install nfs-kernel-server
家目录下创建nfs文件夹
nfs内解压 rootfs-ok.tar.xz
配置nfs
sudo vim /etc/exports
末尾添加/home/ubuntu/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
rw 可读可写
sync 同步信息
no_subtree_check 不检查子目录信息
no_root_squash 在开发板中默认位管理员权限
重启nfs :sudo service nfs-kernel-server restart
nfs本地测试
sudo mount -t nfs 192.168.250.100:/home/ubuntu/nfs/rootfs /mnt
sudo umount /mnt # 取消挂载
nfs挂载流程
- tftp传入设备树文件和uImage镜像文件启动linux后,将ubuntu准备好的根文件系统挂载到开发板中
- 挂载成功之后在串口工具,可以查看到~/nfs/rootfs目录下内容
gnu
gcc命令
编译工具,将 .s 文件生成 .o 文件
arm-linux-gnueabihf-gcc -c asm-led.S -o asm-led.o
ld连接器
将 .o 文件连接生成 .elf 文件,需要指定连接的入口地址
arm-linux-gnueabihf-ld -Ttext=c0008000 asm-led.o -o asm-led.elf
objdump生成反汇编
生成反汇编命令,将 .elf 文件生成反汇编文件
arm-linux-gnueabihf-objdump -D asm-led.elf > asm-led.dis
objcopy生成二进制文件
将 .elf 文件生成二进制文件
.elf文件:包含符号表信息,调试信息
arm-linux-gnueabihf-objcopy -O binary asm-led.elf asm-led.bin
nm查看符号表信息
arm-linux-gnueabihf-nm asm-led.elf
size查看段的大小
arm-linux-gnueabihf-size asm-led.elf
readelf查看文件头部信息
arm-linux-gnueabihf-readelf -h asm-led.elf
strip压缩文件体积
对可执行文件使用
arm-linux-gnueabihf-strip asm-led.elf
addr2line 调试段错误信息
用于内核中断错误信息的调试
arm-linux-gnueabihf-addr2line 报错地址 -e asm-led.elf -f
-e # 指定 .elf 文件
-f # 显示报错的函数和行号
gcc编译流程
预处理
展开头文件,替换宏定义,去除注释
gcc -E *.c -o *.i
编译
生成汇编文件,检查语法错误
gcc -S *.i -o *.s
汇编
生成二进制文件,检查语法错误
gcc -c *.s -o *.o
链接
链接对应的库,生成.elf可执行文件
gcc *.o -o 可执行文件
四种赋值方式
= # 直接赋值
+= # 追加赋值
:= # 立即赋值,不在随右值变量后续改变而改变
?= # 询问赋值,左值为空时赋值
wildcard
makefile 内置函数,将某个文件夹下所有内容以字符串形式进行展开,并用空格隔开
后跟需要展开的目录文件
OBJSss = $(wildcard start/*.S)
函数返回展开后的字符串结果
patsubst
makefile 内置函数,替换字符
后跟被替换字符,替换后字符,原字符串
OBJSs = $(patsubst %.s,%.o,(OBJSss))
返回修改完成后的字符串
特殊字符
$@ : 目标
$< : 第一个依赖
$^ : 所有依赖
$* : 所有去掉后缀的依赖
Makefile文件
CFLAGS += -g -marm -Wall -O0 -mabi=apcs-gnu -mfpu=neon -mfloat-abi=softfp -fno-builtin -nostbinc -I./common/include -I./include
# -g:调试信息 -marm:编译生成arm架构 -Wall:显示警告 -O0:优化高级信息 -fno-builtin:不适用linux操作系统提供的库函数 -nostdinc:不适用系统提供的头文件 -I:指定头文件路径
%.o:%.S
$(CC) $(CFLAGS) -c -o $@ $<
# 将所有以 .S 结尾的文件根据指定参数编译生成 .o 结尾的文件
uboot和bootloader
bootloader
引导加载程序
bootloader | Monitor(开源) | 描述 | x86 | ARM | PowerPC |
---|---|---|---|---|---|
LILO | 否 | Linux磁盘引导程序 | 是 | 否 | 否 |
GRUB | 否 | GNU的LILO替代程序 | 是 | 否 | 否 |
Loadlin | 否 | 从DOS引导Linux | 是 | 否 | 否 |
ROLO | 否 | 从ROM引导Linux而不需要BIOS | 是 | 否 | 否 |
Etherboot | 否 | 通过以太网卡启动Linux系统的固件 | 是 | 否 | 否 |
LinuxBIOS | 否 | 完全替代BUIS的Linux引导程序 | 是 | 否 | 否 |
BLOB | 否 | LAT等硬件平台的写道程序 | 否 | 是 | 是 |
U-boot | 是 | 通用引导程序 | 是 | 是 | 是 |
RedBoot | 是 | 基于eCos的引导程序 | 是 | 是 | 是 |
uboot
bootloader的一种
uboot特点
由德国 DNEX小组维护,开源分布式系统,支持多种硬件架构平台(ARM/X86/POWERPC),体量小,是一个裸机程序,引导内核启动完成后生命周期结束,uboot启动完成后向内核传递两个参数(bootcmd,bootargs)
uboot环境变量
help 查看uboot帮助信息
help
help
查看uboot中所有环境变量
help ubootcmd
查看对应的ubootcmd指令
loadb
串口工具输入指令
go
从地址启动程序指令
pri
打印环境变量信息
pri [-a]# 显示说有环境信息
pri gpio # 显示单个环境变量信息,以gpio为例
arch
# 指定架构
baudrate
# 波特率
board
# 开发板名称
bootartgs
# 自启动参数,进入自启动模式时传入内核的参数,设置ubuntu挂载根文件系统到开发板上的路径和ip地址
bootcmd
# 自启动命令,进入自启动模式时执行
bootdelay
# 自启动倒计时
ethaddr
# mac地址
getewayip
# 网关ip
ipaddr
# 开发板的ip地址
netmask
# 开发板子网掩码
serverip
# 服务器ip地址
run
运行指定指令
run bootcmd # 运行自启动命令
交互模式:和uboot命令交互
自启动模式:根据自启动命令运行
setenv
设置环境变量
setenv bootcm uboot命令1\;uboot命令2\;...\;
saveenv
保存所有环境变量,掉电不丢失
ping
测试开发板与ubuntu组网是否成功
tftp
使用tftp命令将文件下载到开发板内存中