2. R-Car硬件基础

说实话,R-Car 开发的第一步,往往就把不少人卡住了。不是芯片有多难,而是环境没搭对。我见过太多工程师拿着开发板,却连一个 Hello World 都跑不起来——问题全出在工具链和构建系统上。

这一章,咱们就把这三件事彻底搞定:交叉编译工具链、Yocto/Buildroot 构建系统、NFS/TFTP 网络调试环境。这三板斧抡好了,后面的驱动开发才能顺风顺水。

2.1 交叉编译工具链:GCC for ARM

R-Car 用的是 ARM Cortex-A 系列核心(比如 A57、A53、A76)。你的 PC 是 x86 架构,没法直接在 PC 上编译出 ARM 能跑的二进制。所以,我们需要交叉编译工具链。

说白了,就是在 x86 的 PC 上,用一套专门的 GCC,编译出 ARM 架构的代码。

2.1.1 工具链的选择

我个人习惯用 Linaro 提供的 GCC 工具链,稳定且社区支持好。瑞萨官方 BSP 也推荐这个。

工具链名称 适用场景 下载来源
gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf 32位用户空间 + 内核 Linaro 官方 Release
gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu 64位用户空间 + 内核 Linaro 官方 Release
R-Car BSP 自带工具链 与 BSP 严格匹配 瑞萨官网 / Yocto SDK
我的建议:如果你刚开始,直接用 Linaro 的 aarch64 版本。64位是主流,R-Car V3U、S4 这些新片子都是纯 64 位。

2.1.2 安装步骤

安装其实很简单,解压、加路径就行。但有个坑——路径里不要有中文或空格,否则编译时你会哭的。

# 下载 aarch64 工具链
wget https://releases.linaro.org/components/toolchain/binaries/8.3-2019.03/aarch64-linux-gnu/gcc-linaro-8.3.1-2019.03-x86_64_aarch64-linux-gnu.tar.xz

# 解压到 /opt
sudo tar -xvf gcc-linaro-8.3.1-2019.03-x86_64_aarch64-linux-gnu.tar.xz -C /opt/

# 添加环境变量(建议写到 ~/.bashrc 里)
export PATH=/opt/gcc-linaro-8.3.1-2019.03-x86_64_aarch64-linux-gnu/bin:$PATH
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64

# 验证
aarch64-linux-gnu-gcc --version
注意:我曾经遇到过工具链版本与内核不匹配,导致编译出来的内核无法启动。后来我养成了习惯——每次拿到 BSP,第一件事就是看它配套的工具链版本号,严格对齐。

2.2 构建系统:Yocto vs Buildroot

R-Car 的 BSP 官方推荐 Yocto。但如果你只是做驱动验证,Buildroot 更轻量。我两个都用过,说说我的感受。

2.2.1 Yocto:全功能但重

Yocto 能生成完整的 Linux 发行版,包括内核、文件系统、各种库。瑞萨的 R-Car BSP 就是基于 Yocto 的。

但 Yocto 的学习曲线……嗯,确实陡。我第一次配 Yocto 环境,光下载源码就花了大半天。

# 以 R-Car BSP 为例
mkdir rcar-yocto && cd rcar-yocto
repo init -u https://github.com/renesas-rcar/rcar-bsp.git -b v5.1.0
repo sync

# 设置构建环境
source poky/oe-init-build-env build

# 编译目标(以 H3ULCB 为例)
bitbake core-image-minimal

Yocto 的优点是可定制性强,缺点就是慢。第一次全量编译,4 核 CPU 大概要 2-3 小时。

2.2.2 Buildroot:轻量快速

如果你只是想快速验证驱动,Buildroot 是更好的选择。它配置简单,编译快,20 分钟就能出一个可用的根文件系统。

# 下载 Buildroot
git clone git://git.buildroot.net/buildroot
cd buildroot

# 配置(选择 aarch64 目标)
make qemu_aarch64_virt_defconfig
make menuconfig

# 编译
make -j4
我的经验:做驱动开发时,我通常用 Buildroot 做快速原型验证。等驱动稳定了,再移植到 Yocto 的正式 BSP 中。这样既快又稳。

2.3 网络调试环境:NFS + TFTP

驱动开发最怕什么?每次改代码都要重新烧写整个系统。太慢了。所以我们需要网络启动:内核用 TFTP 加载,根文件系统用 NFS 挂载。

这样,你在 PC 上改完驱动,重新编译,重启开发板就能看到效果。效率提升不止一个量级。

2.3.1 TFTP 服务器搭建

TFTP 用来传输内核镜像(Image)和设备树(.dtb)。

# 安装 TFTP 服务器
sudo apt-get install tftpd-hpa

# 配置
sudo vim /etc/default/tftpd-hpa
# 内容如下:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

# 创建目录并设置权限
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp

# 重启服务
sudo systemctl restart tftpd-hpa

把编译好的 Image 和 .dtb 文件复制到 /srv/tftp 目录下。

2.3.2 NFS 服务器搭建

NFS 用来挂载根文件系统。这样开发板启动后,直接使用 PC 上的文件系统。

# 安装 NFS 服务器
sudo apt-get install nfs-kernel-server

# 配置导出目录
sudo vim /etc/exports
# 添加一行(假设根文件系统在 /srv/nfs/rootfs)
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)

# 创建根文件系统目录
sudo mkdir -p /srv/nfs/rootfs

# 将 Buildroot 或 Yocto 生成的根文件系统解压到这里
sudo tar -xvf output/images/rootfs.tar -C /srv/nfs/rootfs

# 重启 NFS 服务
sudo systemctl restart nfs-kernel-server
关键点:no_root_squash 这个选项很重要。不加的话,开发板上的 root 用户会被映射成 nobody,很多操作会权限不足。我曾经因为这个排查了半天。

2.3.3 U-Boot 启动参数配置

最后一步,在 U-Boot 里设置启动参数,让开发板从网络启动。

# 在 U-Boot 命令行中设置
setenv ipaddr 192.168.1.100          # 开发板 IP
setenv serverip 192.168.1.10         # PC(服务器)IP
setenv netmask 255.255.255.0

# 设置 TFTP 加载内核和设备树
setenv bootcmd 'tftp 0x48080000 Image; tftp 0x48000000 r8a77951-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

2.4 整体环境架构图

下面这张图,把整个开发环境的流程串起来了。建议你保存下来,搭建环境时对照着看。

R-Car 开发环境网络启动架构 PC 开发主机 (x86) 交叉编译工具链 Yocto / Buildroot TFTP 服务器 (端口 69) NFS 服务器 (端口 2049) 源码 / 驱动代码 以太网 R-Car 开发板 (ARM) U-Boot 引导 TFTP 加载内核 + DTB NFS 挂载根文件系统 Linux 内核启动 驱动加载与调试 网络启动流程 ① 开发板上电 → U-Boot 启动 ② U-Boot 通过 TFTP 从 PC 加载 Image 和 .dtb 到内存 ③ U-Boot 通过 NFS 挂载 PC 上的根文件系统 ④ 内核启动,驱动加载 ⑤ 在 PC 上修改驱动 → 重新编译 → 重启开发板 → 验证

2.5 验证环境是否搭建成功

环境搭好了,怎么知道对不对?我一般用三步验证法:

  1. 编译验证:写一个简单的 Hello World,用交叉编译器编译,确认能生成 ARM 可执行文件。
  2. 网络验证:开发板通过 TFTP 加载内核,能进入内核启动日志。
  3. 文件系统验证:内核启动后,能正常挂载 NFS 根文件系统,进入 shell。
# 第一步:交叉编译 Hello World
cat > hello.c << EOF
#include <stdio.h>
int main() {
    printf("Hello R-Car!\n");
    return 0;
}
EOF

aarch64-linux-gnu-gcc -o hello hello.c
file hello
# 输出应包含:ELF 64-bit LSB executable, ARM aarch64

# 第二步:放到 NFS 根文件系统里
cp hello /srv/nfs/rootfs/home/root/

# 第三步:开发板启动后,在板子上运行
# 在开发板的 shell 中执行:
# /home/root/hello
# 输出:Hello R-Car!
小技巧:如果 NFS 挂载失败,先检查 PC 上的防火墙。我遇到过好几次,都是防火墙把 NFS 端口给拦了。临时关掉防火墙试试:sudo ufw disable。