第一章: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驱动:
- 翻到Chapter 2,找到I2C挂在哪条总线上
- 翻到I2C章节,看寄存器描述——重点是控制寄存器、状态寄存器、数据寄存器
- 看时序图,理解START/STOP/ACK的硬件行为
- 看中断描述,确认哪些事件能触发中断
我的小技巧: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 本章知识体系
下面这张图把本章的核心内容串起来了,你保存下来,后面写代码时对照着看:
这张图把四个核心模块串起来了:芯片架构是基础,TRM手册是地图,工具链是武器,网络调试是效率保障。缺一个,你的驱动开发都会很痛苦。