第二章 开发环境搭建:交叉编译工具链安装、Yocto/BSP源码获取、内核源码树配置、TFTP/NFS调试环境搭建
做嵌入式Linux开发,环境搭建是绕不开的第一道坎。很多新手上来就急着写驱动,结果编译都过不了,白白浪费时间。我刚开始接触R-Car平台时也踩过不少坑,今天就把这些经验整理出来,帮你把环境一次搭好。
2.1 交叉编译工具链安装
说白了,交叉编译就是在PC上编译出能在ARM架构上跑的程序。R-Car平台用的是ARM Cortex-A系列核心,所以我们需要一套针对ARM的交叉工具链。
2.1.1 工具链选择
瑞萨官方推荐使用Linaro GCC工具链。我个人习惯用gcc-arm-9.2-2019.12版本,这个版本在R-Car H3/M3/N3E上我都验证过,稳定性不错。
| 工具链版本 | 适用平台 | 下载方式 |
|---|---|---|
| gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu | R-Car H3/M3/N3E (64位) | Linaro官网 |
| gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf | R-Car E3/D3 (32位) | Linaro官网 |
| R-Car BSP自带工具链 | 全系列 | Yocto SDK |
2.1.2 安装步骤
安装其实很简单,解压后配置环境变量就行。但这里有个坑——路径不能有中文和空格。
# 下载工具链
wget https://releases.linaro.org/components/toolchain/binaries/9.2-2019.12/aarch64-linux-gnu/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz
# 解压到指定目录
sudo tar -xvf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt/
# 配置环境变量(建议写入~/.bashrc)
export PATH=/opt/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin:$PATH
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=arm64
# 验证安装
aarch64-none-linux-gnu-gcc --version
2.2 Yocto/BSP源码获取
瑞萨的BSP是基于Yocto构建的。你想想看,Yocto的好处是什么?它能把整个Linux系统——内核、文件系统、应用层——全部自动化构建出来。但坏处也很明显:第一次构建要下载好几个G的源码,耗时几个小时。
2.2.1 获取BSP源码
瑞萨官方通过GitHub发布BSP,你需要先注册一个瑞萨的账号才能访问。我记得第一次搞的时候,光权限申请就等了两天。
# 以R-Car H3为例,获取BSP 4.x版本
mkdir rcar-bsp
cd rcar-bsp
# 初始化repo
repo init -u https://github.com/renesas-rcar/rcar-bsp.git -b v4.0.0
# 同步源码(这一步很慢,建议用代理)
repo sync -j4
2.2.2 构建最小系统
源码同步完成后,就可以开始构建了。这里我建议先构建一个最小系统,验证环境没问题再搞全功能版本。
# 设置构建环境
source poky/oe-init-build-env build
# 修改local.conf,添加R-Car H3的MACHINE配置
echo 'MACHINE = "h3ulcb"' >> conf/local.conf
echo 'DL_DIR = "/path/to/downloads"' >> conf/local.conf
# 开始构建(第一次大概需要4-6小时)
bitbake core-image-minimal
repo sync时如果网络不稳定,可以加--no-clone-bundle参数。
2.3 内核源码树配置
Yocto构建完成后,内核源码会在build/tmp/work/h3ulcb-poky-linux/linux-renesas/目录下。但说实话,直接在Yocto工作目录里改内核代码很不方便。我习惯单独拉一份内核源码出来。
2.3.1 独立内核源码树
# 从Yocto构建目录复制内核源码
cp -r build/tmp/work/h3ulcb-poky-linux/linux-renesas/4.19.0+gitAUTOINC+.../git/ ~/rcar-kernel
# 进入内核目录
cd ~/rcar-kernel
# 使用R-Car H3的默认配置
make ARCH=arm64 defconfig
# 生成.config文件
make ARCH=arm64 menuconfig
2.3.2 关键配置项
在menuconfig里,有几个配置项是R-Car平台必须开启的。我列个表,你对照着检查一下:
| 配置项 | 路径 | 说明 |
|---|---|---|
| CONFIG_ARCH_RENESAS | System Type → ARM system type | 瑞萨SoC支持 |
| CONFIG_ARCH_R8A7795 | System Type → Renesas SoC | R-Car H3支持 |
| CONFIG_PINCTRL_RZA2 | Pin controllers | 引脚控制 |
| CONFIG_GPIO_RCAR | GPIO support | GPIO驱动 |
| CONFIG_I2C_RCAR | I2C support | I2C控制器 |
2.4 TFTP/NFS调试环境搭建
驱动开发过程中,最烦的就是每次修改都要重新烧写镜像。用TFTP+NFS组合,可以省掉这个步骤。TFTP负责加载内核和设备树,NFS负责挂载根文件系统。这样你改完驱动,只需要重新编译内核模块,然后重启目标板就行了。
2.4.1 搭建TFTP服务器
# 安装TFTP服务
sudo apt-get install tftpd-hpa
# 配置TFTP目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 修改配置文件 /etc/default/tftpd-hpa
# TFTP_DIRECTORY="/srv/tftp"
# TFTP_OPTIONS="--secure --create"
# 重启服务
sudo systemctl restart tftpd-hpa
2.4.2 搭建NFS服务器
# 安装NFS服务
sudo apt-get install nfs-kernel-server
# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
# 解压Yocto构建的根文件系统
sudo tar -xvf build/tmp/deploy/images/h3ulcb/core-image-minimal-h3ulcb.tar.bz2 -C /srv/nfs/rootfs
# 配置/etc/exports
echo "/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
2.4.3 U-Boot启动参数设置
目标板启动时,需要在U-Boot里设置启动参数。这里我以R-Car H3的ULCB开发板为例:
# 设置IP地址(根据你的网络环境修改)
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.10
# 设置TFTP加载内核和设备树
setenv bootcmd 'tftp 0x48080000 Image; tftp 0x48000000 r8a7795-h3ulcb.dtb; booti 0x48080000 - 0x48000000'
# 设置NFS根文件系统
setenv bootargs 'console=ttySC0,115200 root=/dev/nfs nfsroot=192.168.1.10:/srv/nfs/rootfs rw ip=192.168.1.100'
# 保存并启动
saveenv
boot
/srv/nfs/rootfs目录的owner是root,而NFS配置里没有加no_root_squash。
2.5 环境验证
环境搭好后,最好做个快速验证。我一般会写一个简单的Hello World驱动,编译后通过NFS传到目标板,加载测试。
// hello.c
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_init(void)
{
printk(KERN_INFO "Hello, R-Car H3!\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye, R-Car H3!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
# 编译(使用交叉工具链)
make -C ~/rcar-kernel M=$(pwd) modules
# 拷贝到NFS目录
cp hello.ko /srv/nfs/rootfs/home/root/
# 在目标板上加载
insmod hello.ko
# 查看输出
dmesg | tail
如果能看到"Hello, R-Car H3!"的输出,说明整个开发环境就通了。嗯,到这里,你的开发环境就算正式搭建完成了。