第二章 嵌入式Linux开发环境搭建
说实话,搭建开发环境这件事,看着琐碎,但真不能马虎。我见过太多新手,代码写得挺溜,结果卡在环境配置上,一卡就是好几天。这一章,咱们就把这些基础工作捋清楚。
2.1 交叉编译工具链安装
嵌入式设备资源有限,没法直接在板子上编译大型程序。所以我们在PC上编译,生成目标板能运行的二进制文件。这就是交叉编译。
工具链的选择
我个人习惯用Linaro提供的工具链,稳定且社区活跃。以ARM Cortex-A7为例,常用的是gcc-arm-linux-gnueabihf。
安装步骤:
- 下载工具链:
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz - 解压到指定目录:
tar -xvf gcc-linaro-*.tar.xz -C /opt/ - 添加环境变量:编辑
~/.bashrc,加入export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin - 验证安装:
arm-linux-gnueabihf-gcc --version
小技巧:我曾经在项目里遇到过工具链版本不匹配的问题,导致编译出来的程序在板子上段错误。后来我养成了一个习惯——每次拿到新板子,先确认官方推荐的工具链版本,再动手安装。省心不少。
2.2 TFTP/NFS服务器配置
开发阶段,频繁烧写文件系统太浪费时间。TFTP和NFS就是用来解决这个问题的。TFTP传内核和设备树,NFS挂载根文件系统。
TFTP服务器配置
说白了,TFTP就是一个轻量级的文件传输协议。我一般在Ubuntu上这样配:
sudo apt-get install tftpd-hpa
sudo mkdir -p /tftpboot
sudo chmod 777 /tftpboot
sudo vim /etc/default/tftpd-hpa
配置文件内容:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"
重启服务:sudo systemctl restart tftpd-hpa
NFS服务器配置
NFS允许开发板通过网络挂载PC上的目录作为根文件系统。调试时改代码、重启,立竿见影。
sudo apt-get install nfs-kernel-server
sudo mkdir -p /nfsroot
sudo chmod 777 /nfsroot
sudo vim /etc/exports
添加一行:
/nfsroot *(rw,sync,no_subtree_check,no_root_squash)
重启服务:sudo systemctl restart nfs-kernel-server
注意:我曾经因为no_root_squash没加,导致开发板上的进程无法以root权限写文件。折腾了半天才发现是权限问题。嗯,这里一定要加上。
2.3 开发板与PC的网络连接
网络连接是开发环境的基础。我建议用静态IP,避免DHCP带来的不确定性。
PC端设置:
- 有线网卡设置静态IP,比如
192.168.1.100 - 子网掩码
255.255.255.0 - 网关可以不设,或者设成
192.168.1.1
开发板端设置(U-Boot中):
setenv ipaddr 192.168.1.200
setenv serverip 192.168.1.100
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
saveenv
测试连通性:在PC上ping 192.168.1.200,在板子上ping 192.168.1.100。能通,就说明网络没问题。
避坑指南:我曾经遇到过网线直连但ping不通的情况。后来发现是PC的防火墙把ICMP包给拦了。关掉防火墙或者加一条规则,问题就解决了。
2.4 SSH与串口终端的使用
开发板跑起来后,我们得有个方式跟它交互。串口是基础,SSH是进阶。
串口终端
串口是嵌入式开发的「生命线」。我用的是minicom或者screen。
sudo apt-get install minicom
sudo minicom -s
配置串口参数:
- 波特率:115200
- 数据位:8
- 停止位:1
- 无校验
- 硬件流控:关闭
SSH连接
系统启动后,如果网络正常,就可以用SSH登录了。
ssh root@192.168.1.200
第一次连接会提示确认主机密钥,输入yes即可。默认密码一般是root或空密码。
我的习惯:我一般同时开两个终端。一个串口看内核启动日志,一个SSH做日常操作。串口用来排查启动问题,SSH用来传输文件和执行命令。分工明确,效率高。
2.5 文件系统烧录与启动
终于到了让板子跑起来的环节。文件系统烧录,说白了就是把根文件系统镜像写到存储介质上。
烧录方式
常见的有两种:通过SD卡烧录,或者通过网络烧录到NAND/MMC。
SD卡烧录:
- 将SD卡插入PC,用
lsblk确认设备名(比如/dev/sdb) - 使用
dd命令写入镜像:sudo dd if=rootfs.ext4 of=/dev/sdb bs=4M status=progress - 同步并卸载:
sync && sudo umount /dev/sdb
警告:我曾经有一次不小心把of参数写成了/dev/sda,结果把系统盘给覆盖了。嗯,血的教训。操作前一定再三确认设备名。
网络烧录(通过U-Boot):
如果板子支持网络启动,可以在U-Boot中直接烧录:
tftp 0x82000000 rootfs.ext4
mmc write 0x82000000 0x800 0x2000
这里的0x800和0x2000是MMC的起始扇区和扇区数,具体值要看你的分区表。
启动配置
烧录完成后,设置U-Boot的启动参数:
setenv bootargs 'console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootfstype=ext4'
setenv bootcmd 'mmc read 0x82000000 0x800 0x4000; bootz 0x82000000'
saveenv
boot
如果一切顺利,你会看到内核启动日志,最后出现登录提示符。那一刻,成就感满满。
个人经验:第一次启动时,我建议用串口盯着看。如果卡住了,看最后一条日志,十有八九是文件系统路径或者分区号写错了。别慌,改一下U-Boot参数再试。
好了,环境搭建这部分就到这里。这些基础工作虽然繁琐,但做扎实了,后面的开发会顺畅很多。下一章,咱们开始写第一个TBOX应用。