基于 Linux 6.x 内核与 Rockchip RK3588 平台,涵盖环境搭建、基础驱动到常见外设的全栈内容。
目录
- 开发环境搭建
- 硬件准备
- 软件环境与 SDK 获取
- 第一个 Hello World 内核模块
- 核心驱动开发实践
- 阶段一:基础入门 -- LED 字符设备驱动
- 阶段二:核心框架 -- Platform 驱动与设备树
- 阶段三:进阶探索 -- PCIe, NPU
- 常见外设驱动原理与应用
- USB 2.0/3.0 与 Type-C
- I2C 总线
- SDIO 与 WiFi/BT 组合模块
- I2S 音频子系统
- EEPROM (NVMEM)
- HDMI 显示与音频
- GMAC 以太网
- 红外遥控 (IR)
- NFC
- 补充外设驱动详解
- SPI 总线
- NAND Flash 与 MTD 子系统
- 时钟子系统与晶振
- UART 与 AUART
- DAC / ADC (IIO 框架)
- PMU 与电源管理
- 显示子系统 (DRM / VOP / MIPI DSI / eDP)
- 开源代码与社区资源
1. 开发环境搭建
硬件准备
- RK3588 / RK3588S 开发板(如 Firefly ROC-RK3588S-PC,Orange Pi 5,鲁班猫4)
- Ubuntu 18.04/20.04 x86 主机
- Type-C 数据线,12V 电源适配器
软件环境与 SDK 获取
安装必要软件包:
bash
sudo apt-get update
sudo apt-get install git build-essential lzop libssl-dev device-tree-compiler u-boot-tools
获取 Rockchip 官方 SDK:
bash
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
PATH=~/bin:$PATH
mkdir ~/rk3588_sdk && cd ~/rk3588_sdk
repo init -u https://github.com/rockchip-linux/manifests -b master -m rk3588_linux_release.xml
repo sync
配置交叉编译器(SDK 自带或手动设置):
bash
export PATH=/path/to/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
第一个 Hello World 内核模块
在 kernel/drivers/ 下新建 hello 目录,创建 hello.c 和 Makefile。
hello.c
c
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_init(void) {
printk(KERN_INFO "Hello, RK3588 Kernel Module!\n");
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_INFO "Goodbye, RK3588 Kernel Module!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
Makefile
makefile
obj-m += hello.o
KERNELDIR := /path/to/rk3588_sdk/kernel
CROSS_COMPILE := aarch64-linux-gnu-
ARCH := arm64
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
编译并测试:
bash
make
# 将 hello.ko 传至开发板
insmod hello.ko
rmmod hello.ko
dmesg | tail
2. 核心驱动开发实践
阶段一:基础入门 -- LED 字符设备驱动
目标:编写控制板载 LED 的字符设备驱动。
关键步骤:
- 动态分配设备号。
- 实现
file_operations结构体(.open,.release,.read,.write)。 - 通过
gpio_request,gpio_direction_output等 API 控制 GPIO。 - 编写用户态测试程序,通过
write系统调用控制 LED。
阶段二:核心框架 -- Platform 驱动与设备树
目标:将 LED 驱动改造为 Platform 驱动,使用设备树描述硬件资源。
设备树修改示例 (在 rk3588-evb.dtsi 中添加):
dts
led_demo: led-demo {
compatible = "rockchip,led-demo";
led-gpios = <&gpio4 RK_PC5 GPIO_ACTIVE_HIGH>;
status = "okay";
};
Platform 驱动骨架:
c
static int led_probe(struct platform_device *pdev) {
struct device_node *np = pdev->dev.of_node;
// 解析 GPIO 并初始化
return 0;
}
static int led_remove(struct platform_device *pdev) {
// 清理
return 0;
}
static const struct of_device_id led_of_match[] = {
{ .compatible = "rockchip,led-demo" },
{ }
};
MODULE_DEVICE_TABLE(of, led_of_match);
static struct platform_driver led_driver = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "led_demo",
.of_match_table = led_of_match,
},
};
module_platform_driver(led_driver);
阶段三:进阶探索 -- PCIe 与 NPU
PCIe 驱动要点
- 理解 SMMU/IOMMU 对 DMA 的影响。
- 设备树中配置 PCIe 控制器的电源、复位引脚和 PHY 节点。
- 参考
drivers/pci/controller/dwc/pcie-designware-plat.c。
NPU 驱动
- 上游
accel/rocket驱动正在合并,支持三个独立核心。 - 用户态驱动位于 Mesa 项目,开源趋势明显。
3. 常见外设驱动原理与应用
USB 2.0/3.0 与 Type-C
驱动框架 :dwc3 核心驱动 + phy-rockchip-usbdp + Type‑C 控制器(如 fusb302)。
设备树配置示例:
dts
&usbdp_phy {
status = "okay";
};
&usb_host0_xhci {
dr_mode = "host"; // 或 "peripheral", "otg"
status = "okay";
};
调试命令 :lsusb,配置 gadget 使用 configfs。
I2C 总线
子系统结构:
- 核心:
drivers/i2c/i2c-core.c - 适配器驱动:
drivers/i2c/busses/i2c-rk3x.c - 客户端驱动:用户实现
i2c_driver
AP3216C 传感器驱动实例:
设备树:
dts
&i2c3 {
status = "okay";
ap3216c@1e {
compatible = "dht,ap3216c";
reg = <0x1e>;
};
};
客户端驱动骨架:
c
static int ap3216c_probe(struct i2c_client *client) {
// 创建字符设备,实现读写接口
}
static const struct i2c_device_id ap3216c_id[] = {
{ "ap3216c", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ap3216c_id);
static struct i2c_driver ap3216c_driver = {
.driver = {
.name = "ap3216c",
.of_match_table = ap3216c_of_match,
},
.probe = ap3216c_probe,
.id_table = ap3216c_id,
};
module_i2c_driver(ap3216c_driver);
SDIO 与 WiFi/BT 组合模块
原理 :WiFi 通过 SDIO 连接,蓝牙通过 UART 连接。驱动基于 mmc 子系统和 cfg80211/mac80211。
设备树配置(以 AP6275S 为例):
dts
&sdio {
status = "okay";
bus-width = <4>;
cap-sdio-irq;
// 引脚配置等
};
内核配置 :CONFIG_MMC, CONFIG_BRCMFMAC 等。
用户空间 :使用 wpa_supplicant 连接网络。
I2S 音频子系统
ASoC 框架:
- Platform 驱动:
sound/soc/rockchip/rockchip_i2s_tdm.c - Codec 驱动:如
rt5640.c,es8316.c - Machine 驱动:可使用
simple-audio-card
设备树示例(ES8316):
dts
&i2s0 {
status = "okay";
};
&es8316 {
status = "okay";
// 连接 i2s0
};
&sound {
compatible = "simple-audio-card";
simple-audio-card,cpu {
sound-dai = <&i2s0>;
};
simple-audio-card,codec {
sound-dai = <&es8316>;
};
};
测试 :aplay -l, speaker-test.
EEPROM (NVMEM 子系统)
原理 :通过 NVMEM 框架统一访问,驱动位于 drivers/misc/eeprom/at24.c。
设备树:
dts
&i2c2 {
eeprom@50 {
compatible = "microchip,24c04";
reg = <0x50>;
pagesize = <16>;
};
};
访问 :/sys/bus/i2c/devices/2-0050/eeprom 或通过 NVMEM sysfs。
HDMI 显示与音频
驱动组件 :VOP2 + dw-hdmi-qp + PHY 驱动。使用 DRM/KMS 框架。
设备树配置:
dts
&hdmi {
status = "okay";
};
&hdmi_phy {
status = "okay";
};
&vop {
status = "okay";
};
测试 :连接显示器,使用 modetest 或 weston。
GMAC 以太网
驱动 :通用 stmmac + Rockchip glue 驱动 dwmac-rk.c。
设备树:
dts
&gmac0 {
status = "okay";
phy-mode = "rgmii";
phy-handle = <&phy0>;
snps,reset-gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_LOW>;
// 时钟配置等
};
验证 :ifconfig eth0 up, ethtool eth0。
红外遥控 (IR)
原理 :使用 PWM 捕获或专用 rockchip_pwm_remotectl 驱动。按键映射位于设备树。
设备树:
dts
&pwm_ir {
status = "okay";
rockchip,key_table = <
0x00ec KEY_POWER
0x00b8 KEY_MUTE
// ...
>;
};
测试 :evtest 查看按键事件。
NFC
框架 :Linux NFC 子系统(net/nfc/),控制器驱动(drivers/nfc/)。
设备树示例(PN532 通过 UART):
dts
&uart3 {
status = "okay";
pn532 {
compatible = "nxp,pn532";
// 引脚等
};
};
用户空间 :使用 neard 协议栈。
4. 补充外设驱动详解
SPI 总线
子系统 :drivers/spi/,控制器驱动 spi-rockchip.c。
设备树:
dts
&spi0 {
status = "okay";
num-cs = <2>;
spidev@0 {
compatible = "rockchip,spidev";
reg = <0>;
spi-max-frequency = <24000000>;
};
};
用户空间访问 :/dev/spidevX.X,可使用 spidev_test 工具。
NAND Flash 与 MTD 子系统
MTD 层 :drivers/mtd/nand/raw/,控制器驱动 rk-nandc.c。
设备树:
dts
&nandc0 {
status = "okay";
nand@0 {
reg = <0>;
nand-ecc-mode = "hw";
nand-bus-width = <8>;
};
};
操作 :通过 /dev/mtdX 或 mtd-utils 工具。
时钟子系统与晶振
驱动文件 :drivers/clk/rockchip/clk-rk3588.c。
关键 API :clk_prepare_enable, clk_disable_unprepare, clk_get_rate。
外部晶振 :设备树中描述 ext-clk 节点。
调试 :cat /sys/kernel/debug/clk/clk_summary。
UART 与 AUART
驱动 :8250 通用驱动 + 平台适配 8250_dw.c。
设备树:
dts
&uart7 {
status = "okay";
pinctrl-0 = <&uart7m2_xfer>;
};
**使用**:`/dev/ttyS7`,`stty` 设置参数。
### DAC / ADC
**ADC 驱动**:`rockchip_saradc.c` 基于 IIO 框架。
**设备树**:
```dts
&saradc {
status = "okay";
vref-supply = <&vcc_1v8>;
};
读取 :cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw,换算公式:电压 = raw * 1.8 / 4095。
Audio DAC/ADC:通过 Codec 驱动(如 ES8388)实现,ALSA 控制。
PMU 与电源管理
SoC 内部 PMU :drivers/soc/rockchip/pm_domains.c 管理电源域。
外部 PMIC :通过 I2C 连接,设备树中配置 rockchip,reset-mode。
调试 :/sys/kernel/debug/pm_genpd。
显示子系统 (DRM / VOP / MIPI DSI / eDP)
核心组件:
- VOP2 驱动:
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c - MIPI DSI:
rockchip-dsi2.c,PHY 驱动phy-rockchip-samsung-dcphy.c - eDP:与 HDMI 共享复合 PHY,二者不能同时工作。
设备树配置(DSI 屏幕):
dts
&dsi0 {
status = "okay";
panel@0 {
compatible = "boe,tv080wum-nl6";
reg = <0>;
enable-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
backlight = <&backlight>;
};
};
&vop_mmu {
status = "okay";
};
测试 :modetest -M rockchip,或运行 weston。
5. 开源代码与社区资源
| 资源类型 | 地址 / 说明 |
|---|---|
| Rockchip 官方内核 | https://github.com/rockchip-linux/kernel |
| 主线 Linux 内核 | https://git.kernel.org/ |
| Collabora RK3588 开发树 | https://gitlab.collabora.com/hardware-enablement/rockchip-3588/linux |
| RGA 驱动(2D 加速) | https://github.com/airockchip/librga |
| 设备树覆盖示例 | https://deepwiki.com/radxa-pkg/radxa-overlays |
| 社区论坛 | Firefly 社区、Radxa 论坛、Armbian 论坛、Linux 内核邮件列表 (LKML) |
结束语
本文档从开发环境搭建开始,系统讲解了 RK3588 平台下各类常见外设(USB, I2C, SPI, NAND, 时钟, UART, DAC/ADC, PMU, 显示等)的 Linux 驱动原理、设备树配置、典型代码实例以及测试方法。建议读者结合具体开发板(如鲁班猫4、Firefly ROC-RK3588S-PC)的实际硬件原理图和 Rockchip 官方 SDK 源码进行实践。
提示:由于内核版本迭代,部分驱动路径或 API 可能微调,请以实际内核源码为准。主线内核正在持续完善对 RK3588 的支持,推荐跟踪 upstream 进展。
祝你驱动开发顺利!
你可以将以上内容完整复制,粘贴到文本编辑器中,保存为 `RK3588_Linux_Driver_Development.md`,即可使用任何支持 Markdown 的阅读器(如 Typora、VS Code、GitHub 等)打开学习。如果需要进一步定制(如添加个人笔记、调整章节顺序),可以在此基础上继续修改。