第一章:RK3568平台概述与调试环境搭建

各位同学,咱们直接开始。做嵌入式Linux驱动,说白了就是跟芯片寄存器、中断、DMA这些东西打交道。RK3568这颗芯片,我这两年项目里用得最多,性价比确实不错。今天先带你把平台摸清楚,再把调试环境搭起来——环境顺了,后面写代码才不闹心。

1.1 RK3568芯片架构速览

RK3568是瑞芯微推出的一款中高端ARM SoC,主打AIoT、边缘计算、工业控制。我最早接触它是在一个智能网关项目上,当时被它的异构计算能力惊到了——四核Cortex-A55加上独立的NPU,跑轻量级AI推理完全够用。

先看核心参数:

模块 规格 我的备注
CPU 4×Cortex-A55 @ 2.0GHz 支持DVFS,注意散热
GPU Mali-G52 EE 驱动坑不少,后面专门讲
NPU 0.8 TOPS RKNN工具链,挺成熟
内存 LPDDR4/LPDDR4X 最大8GB,注意PCB走线
存储 eMMC 5.1 / SPI NOR/NAND 启动顺序可配置
显示 HDMI 2.0 / eDP / MIPI-DSI 支持4K@60fps
网络 GMAC ×2 / PCIe 3.0 双千兆,适合网关

架构特点:RK3568采用大小核设计?不对,它是四核同构的A55,没有大核小核之分。但内部有独立的RISC-V协处理器,专门做低功耗管理——这个在TRM里叫"MCU子系统",我刚开始差点忽略它。

芯片内部总线架构用的是AMBA 4.0,核心互联是NIC-400。外设挂载在多个APB/AHB总线上,每个总线有自己的时钟域。嗯,这里要注意:不同总线上的外设,访问延迟差别很大。我踩过坑——把GPIO挂在低速APB总线上,结果中断响应慢了200us,查了两天才找到原因。

1.2 TRM手册导读——别从头读到尾

RK3568的TRM(Technical Reference Manual)有3000多页,你不可能全看完。我个人的习惯是:先看Chapter 2(System Overview),把芯片整体框图印在脑子里。然后直接跳到你要用的外设章节。

举个例子,你要写I2C驱动:

  1. 翻到Chapter 2,找到I2C挂在哪条总线上
  2. 翻到I2C章节,看寄存器描述——重点是控制寄存器、状态寄存器、数据寄存器
  3. 看时序图,理解START/STOP/ACK的硬件行为
  4. 看中断描述,确认哪些事件能触发中断

我的小技巧:TRM里每个外设章节末尾都有"Register Summary"表格,我一般先打印这个表格贴墙上。写代码时扫一眼就知道偏移地址,不用来回翻页。

TRM里容易忽略的几个地方:

  • Clock and Reset:每个外设的时钟门控和复位控制,不配好驱动根本跑不起来
  • Power Domain:RK3568有多个电源域,跨域访问要小心
  • Pin Mux:GPIO复用功能配置,我见过有人把UART的TX/RX接反了
  • Security:OTP、efuse、TRNG,安全相关功能一般藏在最后

避坑指南:我曾经照着TRM的寄存器描述写SPI驱动,结果死活调不通。后来发现TRM里有一个寄存器地址写错了——偏移量多了0x10。所以,TRM也有bug,关键寄存器一定要用示波器或逻辑分析仪验证。

1.3 交叉编译工具链配置

RK3568是ARMv8架构,你肯定不能在x86的电脑上直接编译ARM的代码。交叉编译工具链就是干这个的。

瑞芯微官方推荐的是gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu。我个人习惯用Linaro的版本,更新更活跃。下载后解压到 /opt/toolchains/ 目录:

# 解压
tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz \
  -C /opt/toolchains/

# 配置环境变量(加到 ~/.bashrc 里)
export PATH=/opt/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=arm64

# 验证
aarch64-none-linux-gnu-gcc --version

验证输出应该类似:

aarch64-none-linux-gnu-gcc (GCC) 10.3.1 20210621
Copyright (C) 2020 Free Software Foundation, Inc.

注意:如果你用Buildroot或Yocto,它们自带工具链,不需要手动装。但如果你写裸机驱动或U-Boot,还是得自己配。我一般备两套:一套Linaro的,一套瑞芯微官方的,防止兼容性问题。

编译一个简单的Hello World测试:

# test.c
#include <stdio.h>
int main() {
    printf("Hello RK3568!\n");
    return 0;
}

# 编译
aarch64-none-linux-gnu-gcc -o test test.c

# 查看文件类型
file test
# 输出: test: ELF 64-bit LSB executable, ARM aarch64, ...

1.4 NFS/TFTP网络调试环境搭建

做驱动开发,最烦的就是每次修改都要重新烧写固件。用网络调试,省时省力。我一般用NFS挂载根文件系统,TFTP下载内核。

1.4.1 服务器端配置(Ubuntu 22.04)

先装服务:

# NFS
sudo apt install nfs-kernel-server
sudo mkdir -p /srv/nfs/rootfs
sudo chown nobody:nogroup /srv/nfs/rootfs

# 编辑 /etc/exports
echo "/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports

sudo exportfs -a
sudo systemctl restart nfs-kernel-server

# TFTP
sudo apt install tftpd-hpa
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

防火墙:别忘了开端口。NFS用2049端口,TFTP用69端口。我有一回折腾了半天连不上,最后发现是ufw没关。调试阶段建议直接 sudo ufw disable,省心。

1.4.2 开发板端配置(U-Boot)

在U-Boot命令行设置:

# 设置网络
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.10
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0

# TFTP下载内核
setenv bootcmd 'tftp 0x02000000 Image; tftp 0x06000000 rk3568-evb.dtb; booti 0x02000000 - 0x06000000'

# NFS挂载根文件系统
setenv bootargs 'console=ttyS2,1500000 root=/dev/nfs nfsroot=192.168.1.10:/srv/nfs/rootfs rw ip=192.168.1.100'

saveenv
boot

这里有几个关键点:

  • 0x02000000 是RK3568的内存地址,Image内核镜像加载到这里
  • 0x06000000 是设备树地址,不能和内核重叠
  • 串口参数 console=ttyS2,1500000,波特率1.5Mbps,别设错了

1.4.3 验证网络调试

启动后,开发板会通过TFTP下载内核,然后挂载NFS根文件系统。如果一切正常,你会看到:

## Flattened Device Tree blob at 06000000
   Booting using the fdt blob at 0x6000000
   Loading Device Tree to 00000000f3f00000, end 00000000f3f0bfff ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.10.160 ...
[    2.345678] VFS: Mounted root (nfs filesystem) on device 0:13
[    2.456789] Freeing unused kernel memory: 1024K
[    2.567890] Run /sbin/init as init process

调试效率:用网络调试,修改驱动后只需要重新编译内核模块,scp到开发板,然后insmod。整个过程不到30秒。相比烧写固件的5分钟,效率提升10倍。我现在的项目,没有网络调试环境根本没法干活。

1.5 本章知识体系

下面这张图把本章的核心内容串起来了,你保存下来,后面写代码时对照着看:

RK3568驱动开发环境知识体系 RK3568驱动开发环境知识体系 RK3568 驱动开发 芯片架构 4×Cortex-A55 + NPU AMBA 4.0 总线架构 多电源域 / 时钟门控 TRM手册导读 先看Chapter 2 系统概览 外设章节:寄存器+时序 注意:TRM也有bug 交叉编译工具链 gcc-arm-10.3 aarch64 CROSS_COMPILE 环境变量 Buildroot自带工具链 网络调试环境 NFS挂载根文件系统 TFTP下载内核/设备树

这张图把四个核心模块串起来了:芯片架构是基础,TRM手册是地图,工具链是武器,网络调试是效率保障。缺一个,你的驱动开发都会很痛苦。