首页
商城
  • English
  • 简体中文
首页
商城
  • English
  • 简体中文
  • 产品系列

    • FPGA+ARM

      • GM-3568JHF

        • 一、简介

          • GM-3568JHF 简介
        • 二、快速开始

          • 00 前言
          • 01 环境搭建
          • 02 编译说明
          • 03 烧录指南
          • 04 调试工具
          • 05 软件更新
          • 06 查看信息
          • 07 测试命令
          • 08 应用编译
          • 09 源码获取
        • 三、外设与接口

          • 01 USB
          • 02 显示与触摸
          • 03 以太网
          • 04 WIFI
          • 05 蓝牙
          • 06 TF-Card
          • 07 音频
          • 08 串口
          • 09 CAN
          • 10 RTC
        • 四、应用开发

          • 01 UART读写案例
          • 02 按键检测案例
          • 03 LED灯闪烁案例
          • 04 MIPI屏幕检测案例
          • 05 读取 USB 设备信息案例
          • 06 FAN 检测案例
          • 07 FPGA FSPI 通信案例
          • 08 FPGA DMA 读写案例
          • 09 GPS调试案例
          • 10 以太网测试案例
          • 11 RS485读写案例
          • 12 FPGA IIC 读写案例
          • 13 PN532 NFC读卡案例
          • 14 TF卡读写案例
        • 五、QT开发

          • 01 ARM64交叉编译器环境搭建
          • 02 QT 程序加入开机自启服务
        • 六、RKNN_NPU开发

          • 01 RK3568 NPU 概述
          • 02 开发环境搭建
          • 运行官方 YOLOv5 示例
        • 七、FPGA开发

          • ARM与FPGA通讯
          • FPGA开发手册
        • 八、其他

          • 01 根目录文件系统的修改
          • 02 系统自启服务
        • 九、资料下载

          • 资料下载
    • ShimetaPi

      • M4-R1

        • 一、简介

          • M4-R1简介
        • 二、快速上手

          • 01 OpenHarmony概述
          • 02 镜像烧录
          • 03 应用开发快速上手
          • 04 设备开发快速上手
        • 三、应用开发

          • 01 ArkUI

            • 1 ArkTS语言简介
            • 2 UI 组件-Row 容器介绍
            • 3 UI 组件-Column 容器介绍
            • 4 UI 组件-Text 组件
            • 5 UI 组件-Toggle 组件
            • 6 UI 组件-Slider 组件
            • 7 UI 组件-Animation 组件&Transition 组件
          • 02 资料获取

            • 1 OpenHarmony 官方资料
          • 03 开发须知

            • 1 Full-SDK替换教程
            • 2 引入和使用三方库
            • 3 HDC调试
            • 4 命令行恢复出厂模式
            • 5 升级App为system权限
          • 04 构建第一个应用

            • 1 构建第一个ArkTs应用-HelloWorld
          • 05 案例

            • 01 串口调试助手应用案例
            • 02 手写板应用案例
            • 03 数字时钟应用案例
            • 04 WIFI 信息获取应用案例
        • 四、设备开发

          • 1 Ubuntu环境开发

            • 01 环境搭建
            • 02 下载源码
            • 03 编译源码
          • 2 使用DevEco Device Tool 工具

            • 01 工具简介
            • 02 开发环境的搭建
            • 03 导入SDK
            • 04 HUAWEI DevEco Tool 功能介绍
        • 五、内核外设与接口

          • 01 指南
          • 02 设备树介绍
          • 03 NAPI 入门
          • 04 ArkTS入门
          • 05 NAPI开发实战演示
          • 06 GPIO介绍
          • 07 I2C通讯
          • 08 SPI通信
          • 09 PWM 控制
          • 10 串口通讯
          • 11 TF卡
          • 12 屏幕
          • 13 触摸
          • 14 Ethernet(以太网)
          • 15 M.2 硬盘
          • 16 音频
          • 17 WIFI & BT
          • 18 摄像头
        • 六、资料下载

          • 资料下载
      • M4-R2

        • 一、产品简介

          • M4-R2 产品简介
        • 二、快速上手

          • 快速上手
        • 三、Android 系统

          • 1 快速上手

            • Android系统烧录与启动
            • 开发环境搭建
            • ADB调试与日志分析
            • SDK下载与编译环境搭建
            • Android系统基础操作
          • 2 SDK 编译

            • Android_SDK编译
            • Android构建系统与增量编译
          • 3 系统开发

            • Android系统定制
          • 4 应用开发

            • Android应用开发入门
            • Android JNI开发
          • 5 驱动与 HAL

            • Android HAL开发
          • 6 AI 与 NPU

            • Android NPU使用指南
        • 四、硬件参考

          • 核心板参数
          • 底板接口定义
          • 40PIN引脚定义
          • 电源管理
        • 五、常见问题与故障排除

          • 系统启动问题
          • 外设驱动问题
          • 网络连接问题
          • 显示问题
          • 常见编译错误
        • 六、应用方案参考

          • 智能显示终端方案
          • 边缘AI计算方案
          • 工业控制方案
          • NVR安防监控方案
          • 智能家居网关方案
        • 七、资料下载

          • 资料下载
      • M5-R2A

        • 一、产品简介

          • M5-R2A 产品简介
        • 二、快速上手

          • 系统烧录指南
          • 开发环境搭建
          • 快速上手
          • SDK下载与编译环境搭建
        • 四、Debian/Ubuntu 系统

          • 1 快速上手

            • 系统启动与基础操作
            • 网络配置与SSH
            • 软件包管理与更新
            • Debian 与 Ubuntu 镜像差异
          • 2 系统开发

            • Linux SDK编译
            • 内核配置与裁剪
            • 设备树详解与实践
            • 根文件系统构建
          • 3 外设驱动开发

            • GPIO驱动与控制
            • I2C驱动开发
            • SPI驱动开发
            • UART串口驱动
            • PWM驱动
            • ADC驱动
            • CAN/CAN-FD驱动
            • USB主机与设备驱动
            • SDMMC/eMMC驱动
            • 以太网GMAC驱动
            • 音频驱动
            • 摄像头Camera驱动
            • 触摸屏驱动
            • 显示DRM驱动
            • HDMI显示驱动
            • PCIe驱动
            • WiFi/蓝牙驱动
            • 看门狗WDT驱动
            • 热敏传感器THERMAL驱动
          • 4 应用开发

            • C/C++应用开发入门
            • Python应用开发
            • Qt嵌入式开发实战
            • GStreamer多媒体开发
            • 网络编程与应用
            • 文件系统与存储
          • 5 AI 与 NPU

            • NPU架构与性能概览
            • RKNN Toolkit2安装与使用
            • 模型转换与量化
            • 分类模型部署(LeNet/ResNet)
            • 目标检测部署(YOLOv5/v7/v8)
            • 语义分割部署
            • 人脸检测与识别
            • OCR文字识别
            • NPU性能调优与调试
          • 6 多媒体

            • 显示框架
            • 摄像头应用
            • 视频编解码(MPP)
            • 音频开发与ALSA
            • RGA图像处理
          • 7 性能优化与调试

            • 系统启动时间优化
            • CPU/GPU/NPU调优
            • 内存与存储优化
            • 功耗分析与优化
            • 调试工具使用指南
          • 8 高级主题

            • 安全启动与加密
            • OTA远程升级
            • Docker容器部署
            • ROS/ROS2机器人开发
            • RTOS与Linux协同
        • 五、Android 系统

          • 1 快速上手

            • Android系统烧录与启动
            • Android系统基础操作
            • ADB调试与日志分析
          • 2 SDK 编译

            • Android SDK编译
            • Android构建系统与增量编译
          • 3 系统开发

            • Android系统定制
          • 4 应用开发

            • Android应用开发入门
            • Android JNI开发
          • 5 驱动与 HAL

            • Android HAL开发
          • 6 AI 与 NPU

            • Android NPU使用指南
        • 六、硬件参考

          • 核心板参数
          • 底板接口定义
          • 40PIN引脚定义
          • 电源管理
        • 七、资料下载

          • 资料下载
      • Pico-G1

        • 一、产品概述

          • 01 产品介绍
          • 02 SDK版本基本信息
        • 二、快速入门

          • 01 开发环境搭建
          • 02 镜像编译
          • 03 镜像烧录
          • 04 系统登录
          • 05 网络配置
          • 06 文件传输
          • 07 SDK目录结构
          • 08 部署第一个应用程序
          • 09 部署第一个驱动程序
          • 10 SD卡挂载
        • 三、外设与接口

          • 01 GPIO控制
          • 02 UART串口通信
          • 03 I2C 通信
          • 04 SPI 通信
        • 四、MPP媒体开发

          • 01 MPP媒体处理软件
          • 02 图像处理链路
          • 03 视频输入
          • 04 图像编码
        • 五、NPU与AI

          • 01 NPU驱动与运行库架构
          • 02 .xmm 模型加载
          • 03 SVP视频处理
          • 04 AI降噪 (AI_NR)
        • 六、应用程序示例

          • 01 加解密接口应用
          • 02 ADC 采集应用
          • 03 低功耗应用
          • 04 音频处理应用
          • 05 视频编码应用
          • 06 视频输入应用
          • 07 视频图形子系统应用
          • 08 区域叠加应用
          • 09 智能视频引擎应用
          • 10 UVC 网络摄像头应用
          • 11 综合快速演示应用
          • 12 FPN 校正应用
          • 13 区域运动检测应用
          • 14 MTCNN 人脸检测应用
        • 七、扩展板外设功能例程

          • 00 - Pico 扩展板外设功能例程总览
          • 01 - OLED 显示应用
          • 02 - TFT 显示应用
          • 03 - MPU6050 陀螺仪应用
          • 04 - ADC 采集应用
          • 05 - 无源蜂鸣器应用
          • 06 - MQ 气体传感器应用
          • 07 - GPS 定位应用
          • 08 - SHT20 温湿度应用
          • 09 - 超声波测距应用
          • 10 - SPO2 血氧传感器应用
          • 11 - 电机控制应用
          • 12 - 舵机控制应用
    • 开源鸿蒙

      • SC-3568HA

        • 一、简介

          • SC-3568HA简介
        • 二、快速上手

          • OpenHarmony概述
          • 镜像烧录
          • 开发环境准备
          • Hello World应用以及部署
        • 三、应用开发

          • ArkUI

            • 第一章 ArkTS语言简介
            • 第二章 UI组件介绍和实际应用(上)
            • 第三章 UI组件介绍和实际应用(中)
            • 第四章 UI组件介绍和实际应用(下)
          • 拓展

            • 第一章 入门指引
            • 第二章 三方库的引用和使用
            • 第三章 应用编译以及部署
            • 第四章 命令行恢复出厂设置
            • 第五章 系统调试--HDC调试
            • 第六章 APP 稳定性测试
            • 第七章 应用测试
        • 四、设备开发

          • 第一章 环境搭建
          • 第二章 下载源码
          • 第三章 编译源码
        • 五、内核的外设与接口

          • 树莓派接口
          • GPIO 接口
          • I2C 接口
          • SPI通信
          • PWM控制
          • 串口通讯
          • TF Card
          • 屏幕
          • 触摸
          • 音频
          • RTC
          • Ethernet
          • M.2
          • MINI-PCIE
          • Camera
          • WIFI&BT
          • 树莓派拓展板
        • 六、资料下载

          • 资料下载
      • M-K1HSE

        • 一、简介

          • M-K1HSE 简介
        • 二、快速开始

          • 开发环境搭建
          • 源码获取
          • 编译说明
          • 烧录指南
        • 三、应用开发

          • 00 应用开发环境搭建
          • 01 第一个应用-Hello World
        • 四、外设与接口

          • 01 Audio
          • 02 RS485
          • 03 Display
        • 五、系统定制开发

          • 系统移植
          • 系统定制
          • 驱动开发
          • 系统调试
          • OTA升级
        • 六、资料下载

          • 资料下载
    • HVS视觉融合相机

      • 快速开始

        • 01 SDK 介绍
        • 02 资料下载
        • 03 设备固件烧录
        • 04 第一个 C++ 程序
        • 05 第一个 Python 程序
        • 06 Python 数据分析
        • 07 MultiVision Studio
        • 08 版本介绍
      • 二次开发

        • 01 编程指引

          • 01 打开相机
          • 02 读取事件
          • 03 录制与回放
          • 04 事件处理
          • 05 显示与可视化
          • 06 调参
          • 07 采集 APS 图像
          • 08 帧率切换
          • 09 时间戳同步
        • 02 Toolkit SDK

          • 01 Hybrid Vision Toolkit
          • 02 快速上手
          • 03 C++ API
          • 04 Python API
        • 03 Algo SDK

          • 01 Hybrid Vision Algo
          • 02 Algo API
          • 03 Windows Algo SDK
        • 04 USB数据协议
        • 05 示例程序总览
        • 06 应用场景
      • 基础知识

        • 01 事件相机基础原理
        • 02 HVS 融合视觉
        • 03 事件可视化
        • 04 数据格式参考
        • 05 术语表
        • 06 偏置与调参
        • 07 视频教程
      • HVS 相机

        • 01 HVS 相机快速上手
        • 02 网络化能力

          • 01 HVS 相机系统架构
          • 2 EVS Network Server
          • 3 EVS Time Sync
          • 4 Web Window
        • 03 HVS 相机兼容性矩阵
        • 04 常见问题解决指南
        • 05 产品

          • CF-NRS1(灵光一号视觉融合相机)
      • HVS 模块

        • 01 MIPI 模块快速上手
        • 02 载板适配

          • RDK X5 载板适配
          • RDK S100 载板适配
          • 树莓派载板适配
          • shimetapi 板载板适配
        • 03 MIPI 模块兼容性矩阵
        • 04 产品

          • EVS_003 传感器模块
    • AI硬件

      • 1684XB-32T

        • 一、简介

          • AIBOX-1684XB-32简介
        • 二、快速上手

          • 初次使用
          • 网络配置
          • 磁盘使用
          • 内存分配
          • 风扇策略
          • 固件升级
          • 交叉编译
          • 模型量化
        • 三、应用开发

          • 开发简介

            • Sophgo SDK开发
            • SOPHON-DEMO简介
          • 大语言模型

            • 部署Llama3示例
            • Sophon LLM_api_server开发
            • 部署MiniCPM-V-2_6
            • Qwen-2-5-VL图片视频识别DEMO
            • Qwen3-chat-DEMO
            • Qwen3-Qwen Agent-MCP开发
            • Qwen3-langchain-AI Agent
          • 深度学习

            • ResNet(图像分类)
            • LPRNet(车牌识别)
            • SAM(通用图像分割基础模型)
            • YOLOv5(目标检测)
            • OpenPose(人体关键点检测)
            • PP-OCR(光学字符识别)
        • 四、资料下载

          • 资料下载
      • 1684X-416T

        • 简介

          • AIBOX-1684X-416简介
        • Demo简单操作指引

          • shimeta智慧监控demo的简单使用说明
      • RDK-X5

        • 简介

          • RDK-X5 硬件简介
        • 快速开始

          • RDK-X5 快速开始
        • 应用开发

          • AI在线模型开发

            • 实验01-接入火山引擎豆包 AI
            • 实验02-图片分析
            • 实验03-多模态视觉分析定位
            • 实验04-多模态图文比较分析
            • 实验05-多模态文档表格分析
            • 实验06-摄像头运用-AI视觉分析
          • 大语言模型

            • 实验01-语音识别
            • 实验02-语音对话
            • 实验03-多模态图片分析-语音对话
            • 实验04-多模态图片比较-语音对话
            • 实验05-多模态文档分析-语音对话
            • 实验06-多模态视觉运用-语音对话
          • ROS2基础开发

            • 实验01-搭建环境
            • 实验02-工作包的创建及编译
            • 实验03-运行 ROS2 话题通信节点
            • 实验04-ROS2 相机应用
          • 40pin-IO开发

            • 实验01-GPIO 输出(LED闪烁)
            • 实验02-GPIO 输入
            • 实验03-按键控制 LED
            • 实验04-PWM 输出
            • 实验05-串口输出
            • 实验06-IIC 实验
            • 实验07-SPI 实验
          • USB模块开发使用

            • 实验01-USB 语音模块使用
            • 实验02-声源定位模块使用
          • 机器视觉技术实战

            • 实验01-打开 USB 摄像头
            • 实验02-颜色识别检测
            • 实验03-手势识别体验
            • 实验04-YOLOv5物体检测
      • RDK-S100

        • 简介

          • RDK-S100 硬件简介
        • 快速开始

          • RDK-S100 硬件简介
        • 应用开发

          • AI在线模型开发

            • 实验01-接入火山引擎豆包 AI
            • 实验02-图片分析
            • 实验03-多模态视觉分析定位
            • 实验04-多模态图文比较分析
            • 实验05-多模态文档表格分析
            • 实验06-摄像头运用-AI视觉分析
          • 大语言模型

            • 实验01-语音识别
            • 实验02-语音对话
            • 实验03-多模态图片分析-语音对话
            • 实验04-多模态图片比较-语音对话
            • 实验05-多模态文档分析-语音对话
            • 实验06-多模态视觉运用-语音对话
          • ROS2基础开发

            • 实验01-搭建环境
            • 实验02-工作包的创建及编译
            • 实验03-运行 ROS2 话题通信节点
            • 实验04-ROS2 相机应用
          • 40pin-IO开发

            • 实验01-GPIO 输出(LED闪烁)
            • 实验02-GPIO 输入
            • 实验03-按键控制 LED
            • 实验04-PWM 输出
            • 实验05-串口输出
            • 实验06-IIC 实验
            • 实验07-SPI 实验
          • USB模块开发使用

            • 实验01-USB 语音模块使用
            • 实验02-声源定位模块使用
          • 机器视觉技术实战

            • 实验01-打开 USB 摄像头
            • 实验02-图像处理基础
            • 实验03-目标检测
            • 实验04-图像分割
      • AIBOX-M88(RK1828)

        • 一、简介

          • AIBOX-M88(RK1828) - 产品介绍
          • AIBOX-M88(RK1828) 硬件规格
          • AIBOX-M88(RK1828) 使用与安全
        • 二、快速开始

          • AIBOX-M88(RK1828) 镜像烧录
          • RK182X 硬件安装与验证
          • RK182X 开发环境快速搭建
          • RK182X SDK 总览
          • RK182X 环境搭建详解
          • RK182X 快速开始
          • 原厂 SDK 资料抽取记录
        • 三、开发指南

          • ClawChips 架构与原理
          • SKILL 使用手册
          • RK182X系列LLM推理(RK1828型号)
          • RK182X系列CNN推理(RK1828型号)
          • 模型转换
          • RK182X AI Agent 应用开发指南
          • RK182X 工业异常检测应用
        • 四、SDK 参考

          • RKNN3-SDK 概述

            • RKNN3 SDK 概述
          • RKNN3-Toolkit

            • RKNN3 Toolkit 安装与使用
          • RKLLM

            • RKLLM 设备端 LLM 推理
          • RK182X系列 NPU 概述与架构(RK1828型号)
          • RK182X INT8 量化推理部署
          • RK182X MPP 多媒体处理框架
          • MPP 详解

            • RK182X 视频解码
            • RK182X 视频编码
          • NPU 详解

            • RKNN 模型转换
            • RK182X NPU INT8 量化推理
            • RK182X 多模型并行推理
          • RGA 详解

            • RK182X RGA 2D 图形加速
          • VPU 详解

            • RK182X VPU 编解码
        • 五、硬件参考

          • RK182X系列 硬件架构概述(RK1828型号)
          • RK182X 引脚定义与复用配置
          • RK182X 引脚定义
          • RK182X 电源管理
          • RK182X 时钟与 PLL 配置
          • RK182X 时钟与频率配置
        • 六、实战教程

          • Hello World
          • Hello RK1828 - 第一个程序
          • RTSP 推流
          • RTSP 推流 + AI 分析
          • 视美泰AI龙虾一键部署
          • PaddleOCR-VL 文字识别
          • Qwen3-1.7B LLM 文本对话
          • AI 巡检多视角(Qwen3-VL 包装)
          • YOLOv5 目标检测
        • 七、资料下载

          • 资料下载
        • 八、常见问题

          • 常见问题
    • 核心板

      • C-3568BQ

        • 简介

          • C-3568BQ 简介
      • C-3588LQ

        • 简介

          • C-3588LQ 简介
      • GC-3568JBAF

        • 简介

          • GC-3568JBAF 简介
      • C-K1BA

        • 简介

          • C-K1BA 简介
    • 软件平台

      • ShiMetaPi Workbench

        • 一、产品简介

          • 产品概述
          • 核心架构
          • 功能入口
          • 支持的硬件
          • 版本说明
        • 二、快速入门

          • 安装与登录
          • 连接设备
          • 配置环境
          • 接入 AIHub
          • 首次调用模型
        • 三、用户指南

          • 工作区总览
          • 设备管理
          • 模型广场
          • 一键部署
          • 视觉 - SVP
          • 视觉 - 自定义模型
          • shimeta-py IDE
          • 终端
          • Agent 调试助手
          • 设置与资源
        • 四、常见问题

          • 安装与登录
          • 设备连接
          • 模型与部署
          • 视觉与运行时
          • 设置与其他
      • ShimetaPi软件源

        • 简介

          • ShimetaPi 软件源
        • Pico G1 (GK7206)

          • 快速开始

            • 安装与首次推理
            • shimeta_infer — 图片推理
            • shimeta_camera — 摄像头实时推理
            • SVP 场景检测
            • 文件传输与内置模型参考
            • 常见问题
          • HTTP API & Python SDK

            • HTTP API 参考
      • 模型微调训练平台

        • 一、平台介绍

          • 模型训练平台
        • 二、快速上手

          • 注册与登录
          • 创建第一个模型(30 分钟快速体验)
        • 三、训练指南

          • 数据准备与标注
          • 训练参数配置
          • 启动与监控训练
          • 模型评估与测试
        • 四、模型部署

          • 导出模型
          • 部署到边缘设备

显示框架(DRM/KMS)

目标平台: RK3576 | NPU 算力: 6 TOPS | 文档版本: V1.0
适用板型: C-3576BQ 核心板 + M4-R2 底板
最后更新: 2026-10-23

1. 概述

1.1 功能简介

RK3576 的显示框架基于 Linux DRM/KMS(Direct Rendering Manager / Kernel Mode Setting)子系统构建。DRM/KMS 是 Linux 内核中统一管理 GPU 和显示控制器的标准框架,负责帧缓冲分配、显示时序控制、图层合成和多屏管理。RK3576 采用 Rockchip VOP(Video Output Processor)系列显示控制器,配合 Mali-G52 MC3 GPU 实现图形渲染与多屏输出。

与传统 Framebuffer 设备(/dev/fb*)相比,DRM/KMS 提供更强大的硬件抽象能力,包括 Atomic Mode Setting(原子模式设置)、硬件 Plane 合成、DMA-BUF 缓冲区共享和 DRM GEM(Graphics Execution Manager)内存管理。现代 Linux 发行版已全面转向 DRM/KMS,Framebuffer 仅作为兼容层保留。

核心组件:

组件说明
VOP 显示控制器Rockchip VOP 系列,具体寄存器基地址以实际发布的 RK3576 SDK 设备树为准
HDMI 控制器1 路,Type-A 母座,最高 4K×2K(规格书标注 4Kx2K@120Hz)
MIPI DSI 控制器1 路,40pin/0.5mm FPC,4-Lane,实测支持 720×1280
Mali-G52 MC3GPU,支持 OpenGL ES 1.1/2.0/3.2、OpenCL 2.0、Vulkan 1.1,内嵌高性能 2D 加速
DRM/KMS 内核框架管理 CRTC、Plane、Encoder、Connector 等抽象对象

说明: RK3576 内核镜像中显示控制器节点、寄存器基地址、中断号与时钟标识以实际发布的 RK3576 SDK 设备树为准(待板上确认),本文档以通用结构 vop@<base_addr> 等占位符表示。

显示接口能力(依据 M4-R2 规格书):

接口最大分辨率协议版本物理接口备注
HDMI4096×2160(标注 4Kx2K@120Hz)HDMI 1.4 / 2.0Type-A 母座支持 1920x1080、1280x720、720x576、720x480 等
MIPI DSI2560×1600(标注最大值)MIPI DSI 2.0FPC 连接器(4-Lane)实测已支持 720×1280,可直接驱动多种分辨率 MIPI 液晶屏

实际可用的最大刷新率与分辨率受显示器 EDID、线缆质量和系统驱动配置影响,需在板端实测确认(待板上验证)。

1.2 应用场景

应用场景显示接口说明
双屏异显HDMI + MIPI DSI同时输出不同内容
桌面系统HDMI + WestonLinux 桌面图形界面
数字标牌HDMI广告机、信息发布系统
工业 HMIMIPI DSI工业控制触摸屏界面
视频播放HDMI + DRM Direct Show硬件解码 + DRM 直接显示
嵌入式 GUIMIPI DSI / HDMI嵌入式设备人机交互

1.3 工作原理

RK3576 DRM/KMS 显示系统硬件架构:

+--------------------------------------------------------------+
|                      Application Layer                        |
|       libdrm / GBM / EGL / Mali GPU / Weston / X11           |
+--------------------------------------------------------------+
|                  Kernel DRM/KMS Driver Layer                   |
|    +----------------------------------------------------+     |
|    |             VOP Display Controller (RK3576)         |     |
|    |       (Video Port 数量、基地址以 SDK 设备树为准)    |     |
|    +-----|--------|-------------------------------------+     |
|          |        |                                            |
|    +-----|--------|----------------------------+               |
|    |        Encoder / Connector Layer          |               |
|    |       HDMI      MIPI DSI                  |               |
|    +---------------------|---------------------+               |
+--------------------------|-----------------------------+
             +-------------+-----------+
             |       Display Device    |
             +-------------------------+

DRM/KMS 核心对象关系:

+--------------------------------------------------------------+
|                      DRM Device Node                          |
|                    /dev/dri/card0                             |
+--------------------------------------------------------------+
|                                                              |
|  Connector ------> Encoder ------> CRTC                     |
|  (Physical I/F)    (Protocol)      (Display Controller)      |
|  HDMI-A-1          dw_hdmi         VP <n>                   |
|  DSIA              dw_mipi_dsi2    VP <n>                   |
|                                                              |
|  CRTC <--------- Plane (Layer)                                |
|  (VP<n>)          Cluster / Esmart (具体以 SDK 内核为准)    |
|                                                              |
|  Plane <--------- Framebuffer (Framebuffer Object)            |
|                  GEM / DMA-BUF                                |
+--------------------------------------------------------------+

DRM 子系统核心概念:

概念说明RK3576 对应
CRTC显示控制器抽象,管理显示时序和 Plane 合成VOP 中的 Video Port
Plane硬件图层,支持多种像素格式和缩放Cluster / Esmart / Smart 等
Encoder将像素数据编码为特定接口协议信号dw_hdmi、dw_mipi_dsi2 等
Connector物理显示接口,支持热插拔检测HDMI-A、DSI 等
BridgeEncoder 与 Panel 之间的桥接设备HDMI bridge、DSI bridge
Framebuffer帧缓冲对象,存储像素数据GEM 对象,支持 DMA-BUF 共享
GEMDRM 缓冲区管理与分配类似 ION / DMA-BUF heap

Framebuffer 设备 vs DRM 设备:

对比项Framebuffer (/dev/fb*)DRM (/dev/dri/card0)
硬件抽象简单的像素缓冲区CRTC + Plane + Encoder + Connector
模式设置内核固定分辨率Atomic Mode Setting(用户态控制)
多图层不支持(单层)支持多硬件 Plane 合成
缓冲区管理mmap 直接访问GEM / DMA-BUF / GBM
热插拔不支持原生支持
GPU 合成不支持支持 EGL/Vulkan 渲染输出
用途嵌入式简单显示现代图形系统

RK3576 同其它 Rockchip 平台一样,同时支持两种模式:DRM 设备节点 /dev/dri/card0 用于 DRM/KMS 框架,Framebuffer 设备节点 /dev/fb0 用于传统兼容模式(需启用 CONFIG_DRM_FBDEV_EMULATION)。


2. 硬件准备

2.1 硬件清单

序号组件型号/规格数量备注
1核心板C-3576BQ(RK3576)1含 RK3576 SoC、LPDDR5 4GB、eMMC 32GB
2底板ShimetaPi M4-R2 V101含 HDMI、MIPI DSI、MIPI Camera 接口
3电源适配器5V/2A(Type-C 或 6pin)1空载最小 1000mA
4HDMI 显示器支持 HDMI 1.4+1用于 HDMI 输出测试
5HDMI 线缆HDMI 1.4 / 2.01建议使用认证线缆
6MIPI DSI 屏(可选)支持 MIPI DSI,4-Lane1用于 DSI 输出测试(实测支持 720×1280)
7调试串口线USB 转 TTL(3.3V)1波特率 1500000
8TF 卡32GB+,Class101系统存储

2.2 显示接口引出

M4-R2 底板引出以下显示接口(参考 S-04 底板资料):

接口说明
HDMI TX1 路,标准 HDMI Type-A 母座(S-01 规格书/S-04 底板标注)
MIPI DSI1 路,40pin/0.5mm 立式 FPC 插座,4-Lane
MIPI Camera1 路,30pin/0.5mm FPC 插座,最高支持 1600W 摄像头(用于摄像头应用,见 ch02)

注意:M4-R2 板卡只引出 1 路 HDMI 和 1 路 MIPI DSI 输出,无 DP / eDP 接口。具体连接器编号请查阅 S-04 底板资料。

2.3 硬件确认

# 查看 DRM 设备节点
ls /sys/class/drm/
# 输出示例:card0  card0-HDMI-A-1  card0-DSIA  version

# 查看 HDMI 连接状态
cat /sys/class/drm/card0-HDMI-A-1/status
# 输出:connected 或 disconnected

# 查看所有显示接口状态
for f in /sys/class/drm/card0-*/status; do
    echo "$(basename $(dirname $f)): $(cat $f)"
done

# 查看 VOP 显示控制器设备树状态(节点名以实际 RK3576 SDK 设备树为准)
cat /proc/device-tree/soc/vop@<base_addr>/status
# 预期输出:okay

# 查看 HDMI 控制器设备树状态
cat /proc/device-tree/soc/hdmi@<base_addr>/status
# 预期输出:okay

# 查看 DSI 控制器设备树状态
cat /proc/device-tree/soc/dsi@<base_addr>/status

# 查看 framebuffer 信息
ls /dev/fb*
cat /sys/class/graphics/fb0/virtual_size

# 查看 DRM 设备版本
cat /sys/class/drm/version

# 检查 Mali-G52 GPU 设备
ls /dev/dri/renderD128
cat /sys/class/misc/mali0/device/uevent

vop@<base_addr>、hdmi@<base_addr>、dsi@<base_addr> 为通用结构占位符,具体节点名与寄存器基地址以实际发布的 RK3576 SDK 设备树为准(待板上确认)。


3. 软件准备

3.1 依赖安装

# 安装 DRM 测试工具
apt-get update
apt-get install -y libdrm-tests libdrm-dev

# 安装显示相关库
apt-get install -y \
    libegl-dev libgles-dev \
    libgbm-dev \
    libwayland-dev libwayland-bin \
    weston wayland-protocols \
    xwayland

# 安装 Mesa(用户态 GPU 驱动)
apt-get install -y \
    mesa-utils libgl1-mesa-dev \
    mesa-vulkan-drivers

# 安装 edid-decode(EDID 解析工具)
apt-get install -y edid-decode

# 安装 Weston 配置工具
apt-get install -y weston-init

# 确认 Mali-G52 GPU 驱动
# RK3576 使用 panfrost(开源)或 mali(闭源)驱动,具体以实际发布 SDK 为准
# apt-get install -y libmali   # 闭源驱动(如有提供)

3.2 内核配置

在内核配置中启用 DRM/KMS 相关驱动(具体配置项名称以实际发布的 RK3576 SDK 内核为准):

# DRM 核心框架
CONFIG_DRM=y
CONFIG_DRM_ROCKCHIP=y

# VOP 显示控制器(RK3576 SDK 内核中的具体配置项)
CONFIG_ROCKCHIP_VOP2=y

# HDMI 输出
CONFIG_ROCKCHIP_HDMI=y
CONFIG_DRM_ROCKCHIP_ANALOGIX_HDMI=y

# MIPI DSI 输出
CONFIG_ROCKCHIP_DW_MIPI_DSI=y

# 通用 Panel 驱动
CONFIG_DRM_PANEL_SIMPLE=y

# DRM GEM / CMA 缓冲区管理
CONFIG_DRM_GEM_CMA_HELPER=y
CONFIG_DRM_CMA_HELPER=y

# Framebuffer 兼容层
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_FB=y
CONFIG_FB_ROCKCHIP=y

查看当前内核配置:

# 查看 VOP 配置
grep -i "VOP\|ROCKCHIP" /boot/config-$(uname -r)

# 查看 DRM 配置
grep -i "DRM_ROCKCHIP" /boot/config-$(uname -r)

# 查看 HDMI 配置
grep -i "HDMI\|ROCKCHIP_HDMI" /boot/config-$(uname -r)

# 检查已加载的 DRM 模块
lsmod | grep -i "drm\|rockchip"
# 预期看到:drm rockchip vop dw_hdmi 等模块

3.3 设备树配置

以下为 RK 平台显示控制器设备树结构的通用示例,寄存器基地址、中断号与时钟标识均以实际发布的 RK3576 SDK 设备树为准(待板上确认):

vop: vop@<base_addr> {
    compatible = "rockchip,rk3576-vop";   /* 具体 compatible 以 SDK 为准 */
    reg = <0x0 <base_addr> 0x0 0x2000>;
    reg-names = "regs", "gamma_luts";
    interrupts = <GIC_SPI <irq> IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>,
             <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
    clock-names = "aclk", "hclk",
                  "dclk_vp0", "dclk_vp1";
    power-domains = <&power RK3576_PD_VOP>;
    status = "disabled";
};

HDMI 控制器设备树通用结构:

hdmi0: hdmi@<base_addr> {
    compatible = "rockchip,rk3576-hdmi";  /* 具体 compatible 以 SDK 为准 */
    reg = <0x0 <base_addr> 0x0 0x20000>;
    interrupts = <GIC_SPI <irq> IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru PCLK_HDMI_TX>, <&cru CLK_HDMI_REF>,
             <&cru CLK_HDMI_TX>;
    clock-names = "pclk", "ref", "phy";
    rockchip,phy = <&hdmi_phy>;
    pinctrl-names = "default";
    pinctrl-0 = <&hdmi0_tx_cec &hdmim0_tx_hpd>;
    status = "disabled";
};

MIPI DSI 控制器设备树通用结构:

dsi0: dsi@<base_addr> {
    compatible = "rockchip,rk3576-mipi-dsi";  /* 具体 compatible 以 SDK 为准 */
    reg = <0x0 <base_addr> 0x0 0x10000>;
    interrupts = <GIC_SPI <irq> IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&cru PCLK_DSI0>, <&cru CLK_DSI0_TXCLK>,
             <&cru CLK_DSI0_RXCLK>, <&cru CLK_DSI0_24M>;
    clock-names = "pclk", "txclk", "rxclk", "clk24m";
    power-domains = <&power RK3576_PD_VOP>;
    rockchip,grf = <&sysgrf>;
    status = "disabled";
};

以上设备树节点仅为平台通用结构示例。RK3576 的实际寄存器基地址、中断号、时钟与 reset 标识、IOMMU 与电源域引用等,均需以实际发布的 RK3576 SDK 设备树源码为准(待板上确认),切勿直接套用其它平台的数值。

3.4 display_subsystem 路由配置

启用 HDMI + MIPI DSI 双屏路由配置(节点名与 connect 属性以 SDK 设备树为准):

display_subsystem: display-subsystem {
    compatible = "rockchip,display-subsystem";
    ports = <&vop_out>;

    route {
        route_hdmi: route-hdmi {
            status = "okay";
            logo,uboot = "logo.bmp";
            logo,kernel = "logo_kernel.bmp";
            logo,mode = "center";
        };

        route_dsi0: route-dsi0 {
            status = "okay";
            logo,uboot = "logo.bmp";
            logo,kernel = "logo_kernel.bmp";
            logo,mode = "center";
        };
    };
};

VP 与显示接口连接关系配置:

&hdmi0 {
    status = "okay";
};

&dsi0 {
    status = "okay";
    rockchip,lane-rate = <1500>;
};

&route_hdmi {
    status = "okay";
};

&route_dsi0 {
    status = "okay";
};

一个显示接口在同一时刻只能连接一个 VP。在板级配置中,需要把不使用的通路设置为 disabled 状态。具体 connect 通路名称以 SDK 设备树为准。

3.5 Weston 合成器配置

安装 Weston:

apt-get install -y weston libwayland-dev wayland-protocols

weston.ini 基本配置:

[core]
backend=drm-backend.so
shell=desktop-shell.so

[output]
name=HDMI-A-1
mode=1920x1080-60

3.5.1 Weston 动态配置

Weston 支持通过环境变量和配置文件动态调整显示输出:

# 环境变量
export WESTON_DRM_PRIMARY=HDMI-A-1

# 动态配置文件
echo "[output]
name=HDMI-A-1
mode=1920x1080-60" > /tmp/.weston_drm.conf

动态配置文件 /tmp/.weston_drm.conf 在运行时被 Weston 监控,修改后自动生效,无需重启 Weston 进程(需 Weston 版本支持该特性)。


4. 操作步骤

4.1 DRM 基础测试

# 查看 DRM 设备信息
modetest -M rockchip -c

# 查看所有 connector 信息(包含分辨率列表)
modetest -M rockchip -c | grep -A 30 "Connectors:"

# 测试 HDMI 1080p 输出(connector ID 需根据实际 modetest 输出确定)
modetest -M rockchip -s 32:1920x1080-60 -P 38:1920x1080

# 测试 HDMI 4K 输出(需显示器与驱动支持,待板上验证)
modetest -M rockchip -s 32:3840x2160-60 -P 38:3840x2160

# 使用 solid color 测试平面
modetest -M rockchip -r -s 32:1920x1080-60 -P 38:1920x1080 -F solid

# 查看 VOP 当前状态信息
cat /sys/kernel/debug/dri/0/state

命令中的 connector ID(示例 32)与 plane ID(示例 38)只是示例,实际 ID 需根据本机 modetest -M rockchip -c 的输出确定。

4.2 DRM 设备节点检查

# 查看 DRM 设备信息
ls -la /dev/dri/
# card0      - DRM 主设备节点
# renderD128 - GPU 渲染节点

# 查看 framebuffer 设备节点
ls -la /dev/fb*
# fb0        - 传统 framebuffer 兼容节点

# 查看 VOP 时钟频率(节点名以实际 SDK 内核为准)
cat /sys/kernel/debug/clk/clk_dclk_vp0/clk_rate

# 查看 ACLK VOP 时钟(内存带宽相关)
cat /sys/kernel/debug/clk/clk_aclk_vop/clk_rate

# 查看 DRM debug 信息
cat /sys/kernel/debug/dri/0/name
cat /sys/kernel/debug/dri/0/state

4.3 验证 HDMI 输出

# 查看 HDMI 连接状态
cat /sys/class/drm/card0-HDMI-A-1/status
# 应输出: connected

# 查看 HDMI 支持的分辨率
cat /sys/class/drm/card0-HDMI-A-1/modes

# 查看 EDID 信息
cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode

# 强制设置 HDMI 分辨率
xrandr --output HDMI-1 --mode 1920x1080 --rate 60

# 使用 modetest 设置 HDMI 输出
modetest -M rockchip -s 32:1920x1080-60 -P 38:1920x1080

M4-R2 规格书标注 HDMI 最高支持 4096×2160(4Kx2K@120Hz)。实际可用的最大分辨率与刷新率受显示器、线缆及驱动配置影响,需在板端实测(待板上验证)。

4.4 配置 MIPI DSI 输出

# 查看 DSI 连接状态
cat /sys/class/drm/card0-DSIA/status

# 查看 DSI 支持的模式
cat /sys/class/drm/card0-DSIA/modes

# DSI 屏幕需要在设备树中配置 panel-timing
# 常见方式:在 DTS 中添加 panel 节点,如 panel-simple 或厂家自定义驱动
dmesg | grep -i panel

M4-R2 规格书标注 MIPI 屏最大支持 2560×1600,实测已支持 720×1280。接入特定 LCD 模组时,需在设备树中配置对应的 panel 时序(panel-timing)并确认背光与复位引脚配置。

4.5 多屏同时显示配置

M4-R2 板卡引出 1 路 HDMI + 1 路 MIPI DSI,规格书声明支持双屏显示、双屏异显:

# 查看当前所有连接器状态
for f in /sys/class/drm/card0-*/status; do
    echo "$(dirname $f | xargs basename): $(cat $f)"
done

# 示例输出:
#   card0-HDMI-A-1: connected
#   card0-DSIA: connected

# 同时启用 HDMI 和 DSI 显示(connector/plane ID 需根据 modetest 输出确定)
modetest -M rockchip \
    -s 39:1920x1080-60 \
    -s 46:1080x1920-60 \
    -P 31:1920x1080 \
    -P 49:1080x1920

4.6 Framebuffer 设备操作

# 查看 framebuffer 信息
cat /sys/class/graphics/fb0/virtual_size
cat /sys/class/graphics/fb0/bits_per_pixel
cat /sys/class/graphics/fb0/stride

# 使用 fbset 修改 framebuffer 参数
fbset -fb /dev/fb0 -info
fbset -fb /dev/fb0 -g 1920 1080 1920 2160 32

使用 Python 写入 framebuffer 测试图案:

#!/usr/bin/env python3
"""
fb_test.py - Framebuffer 测试图案写入工具
适用平台: RK3576 (ShimetaPi M4-R2), Linux 6.1
"""

import struct
import os

FB_DEV = "/dev/fb0"

def get_fb_info():
    """获取 framebuffer 基本信息"""
    info = {}

    with open("/sys/class/graphics/fb0/virtual_size", "r") as f:
        size = f.read().strip()
        width, height = [int(x) for x in size.split(",")]
        info["width"] = width
        info["height"] = height

    with open("/sys/class/graphics/fb0/bits_per_pixel", "r") as f:
        info["bpp"] = int(f.read().strip())

    with open("/sys/class/graphics/fb0/stride", "r") as f:
        info["stride"] = int(f.read().strip())

    return info

def create_gradient(width, height, bpp=32):
    """创建 RGB 渐变测试图案"""
    stride = ((width * bpp + 255) >> 8) << 8
    line_size = stride // 8

    framebuffer = bytearray(line_size * height)
    for y in range(height):
        for x in range(width):
            offset = y * line_size + (x * bpp) // 8
            r = int(255 * x / width)    # X 轴红色渐变
            g = 0
            b = int(255 * y / height)   # Y 轴蓝色渐变
            a = 255
            # BGRA8888 格式(Rockchip 默认)
            struct.pack_into("<BBBB", framebuffer, offset, b, g, r, a)

    return framebuffer

def main():
    print("=" * 50)
    print("RK3576 Framebuffer 测试")
    print("=" * 50)

    # 获取 framebuffer 信息
    info = get_fb_info()
    print(f"  分辨率: {info['width']}x{info['height']}")
    print(f"  位深: {info['bpp']} bpp")
    print(f"  步长: {info['stride']} bytes")

    # 生成测试图案
    buffer = create_gradient(info["width"], info["height"], info["bpp"])

    # 写入 framebuffer
    fb = open(FB_DEV, "wb")
    fb.write(buffer)
    fb.close()

    print("  测试图案已写入")
    print("  显示器应显示红蓝渐变图案")

if __name__ == "__main__":
    main()

4.7 DRM Framebuffer 操作(C 语言)

/*
 * drm_fb_test.c
 * RK3576 (ShimetaPi M4-R2) DRM/KMS framebuffer 操作示例
 *
 * 编译: gcc -o drm_fb_test drm_fb_test.c -ldrm
 * 运行: sudo ./drm_fb_test
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <libdrm/drm.h>
#include <libdrm/drm_mode.h>

#define DRM_DEVICE "/dev/dri/card0"

/* DRM 设备资源结构体 */
struct drm_res {
    int fd;
    uint32_t conn_id, enc_id, crtc_id, fb_id;
    drmModeModeInfo mode;
    uint32_t width, height, pitch, handle, size;
    uint8_t *map;
};

/* 获取 DRM 设备资源 */
static int get_drm_res(struct drm_res *res)
{
    drmModeRes *resources;
    drmModeConnector *conn;
    drmModeEncoder *encoder;
    int i;

    res->fd = open(DRM_DEVICE, O_RDWR);
    if (res->fd < 0) {
        perror("open DRM device");
        return -1;
    }

    resources = drmModeGetResources(res->fd);
    if (!resources) {
        perror("get DRM resources");
        close(res->fd);
        return -1;
    }

    printf("DRM: %d connectors, %d encoders, %d CRTCs\n",
           resources->count_connectors, resources->count_encoders,
           resources->count_crtcs);

    /* 遍历 connector,找到第一个已连接的 */
    res->conn_id = 0;
    for (i = 0; i < resources->count_connectors; i++) {
        conn = drmModeGetConnector(res->fd, resources->connectors[i]);
        if (!conn)
            continue;

        if (conn->connection == DRM_MODE_CONNECTED && conn->count_modes > 0) {
            const char *type_name = "Unknown";
            if (conn->connector_type == DRM_MODE_CONNECTOR_HDMIA)
                type_name = "HDMI";
            else if (conn->connector_type == DRM_MODE_CONNECTOR_DSI)
                type_name = "DSI";

            printf("Connector %d: %s, %d modes\n",
                   conn->connector_id, type_name, conn->count_modes);
            res->conn_id = conn->connector_id;
            memcpy(&res->mode, &conn->modes[0], sizeof(drmModeModeInfo));
            res->width = conn->modes[0].hdisplay;
            res->height = conn->modes[0].vdisplay;
            printf("Mode: %dx%d@%dHz\n",
                   res->width, res->height, res->mode.vrefresh);

            if (conn->encoder_id) {
                encoder = drmModeGetEncoder(res->fd, conn->encoder_id);
                if (encoder) {
                    res->enc_id = encoder->encoder_id;
                    res->crtc_id = encoder->crtc_id;
                    drmModeFreeEncoder(encoder);
                }
            }
            drmModeFreeConnector(conn);
            break;
        }
        drmModeFreeConnector(conn);
    }

    drmModeFreeResources(resources);

    if (!res->conn_id) {
        fprintf(stderr, "No connected display found\n");
        return -1;
    }
    return 0;
}

/* 创建 DRM framebuffer 并填充纯色 */
static int create_fb(struct drm_res *res, uint32_t color)
{
    struct drm_mode_create_dumb creq = {0};
    struct drm_mode_map_dumb mreq = {0};
    uint32_t i;
    uint32_t bpp = 32;

    res->pitch = ((res->width * bpp + 255) >> 8) << 8;

    /* 创建 dumb buffer */
    creq.width = res->width;
    creq.height = res->height;
    creq.bpp = bpp;
    creq.pitch = res->pitch;
    if (drmIoctl(res->fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq)) {
        perror("create dumb buffer");
        return -1;
    }
    res->handle = creq.handle;
    res->size = creq.size;

    /* 创建 framebuffer */
    if (drmModeAddFB(res->fd, res->width, res->height, 24,
                     bpp, res->pitch, res->handle, &res->fb_id)) {
        perror("add framebuffer");
        return -1;
    }
    printf("Framebuffer created: fb_id=%u, %ux%u\n",
           res->fb_id, res->width, res->height);

    /* 映射到用户空间 */
    mreq.handle = res->handle;
    if (drmIoctl(res->fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) {
        perror("map dumb buffer");
        return -1;
    }

    res->map = mmap(0, res->size, PROT_READ | PROT_WRITE,
                    MAP_SHARED, res->fd, mreq.offset);
    if (res->map == MAP_FAILED) {
        perror("mmap");
        return -1;
    }

    /* 填充纯色 */
    uint32_t *pixels = (uint32_t *)res->map;
    uint32_t pixel_count = (res->pitch / 4) * res->height;
    for (i = 0; i < pixel_count; i++)
        pixels[i] = color;

    return 0;
}

/* 设置 CRTC 显示模式 */
static int set_crtc(struct drm_res *res)
{
    if (!res->crtc_id) {
        /* 如果 encoder 没有绑定 CRTC,获取第一个可用的 */
        drmModeRes *r = drmModeGetResources(res->fd);
        if (r && r->count_crtcs > 0)
            res->crtc_id = r->crtcs[0];
        if (r)
            drmModeFreeResources(r);
    }

    if (drmModeSetCrtc(res->fd, res->crtc_id, res->fb_id,
                        0, 0, &res->conn_id, 1, &res->mode)) {
        perror("set crtc mode");
        return -1;
    }

    printf("CRTC %u: %ux%u@%uHz\n",
           res->crtc_id, res->width, res->height, res->mode.vrefresh);
    return 0;
}

/* 清理资源 */
static void cleanup(struct drm_res *res)
{
    if (res->map && res->map != MAP_FAILED)
        munmap(res->map, res->size);

    if (res->fb_id)
        drmModeRmFB(res->fd, res->fb_id);

    if (res->handle) {
        struct drm_mode_destroy_dumb d = {0};
        d.handle = res->handle;
        drmIoctl(res->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &d);
    }

    if (res->fd >= 0)
        close(res->fd);
}

int main(void)
{
    struct drm_res res = {0};

    printf("RK3576 DRM/KMS Framebuffer Test\n");
    printf("==============================\n\n");

    /* 获取 DRM 设备资源 */
    if (get_drm_res(&res) < 0) {
        fprintf(stderr, "Failed to get DRM resources\n");
        return 1;
    }

    /* 创建红色 framebuffer */
    printf("\nCreating framebuffer with red color (0xFF0000FF)...\n");
    if (create_fb(&res, 0xFF0000FF) < 0) {
        cleanup(&res);
        return 1;
    }

    /* 设置 CRTC 显示模式 */
    if (set_crtc(&res) < 0) {
        cleanup(&res);
        return 1;
    }

    printf("\nPress Enter to exit...\n");
    getchar();

    /* 清理资源 */
    cleanup(&res);
    printf("Done.\n");
    return 0;
}

4.8 Atomic Mode Setting 示例

/*
 * drm_atomic_test.c
 * RK3576 (ShimetaPi M4-R2) DRM Atomic Mode Setting 示例
 * 展示如何使用 atomic commit 进行模式设置
 *
 * 编译: gcc -o drm_atomic_test drm_atomic_test.c -ldrm
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#define DRM_DEVICE "/dev/dri/card0"

/*
 * Atomic commit 流程:
 * 1. 获取 DRM 资源(CRTC, Plane, Connector)
 * 2. 创建 dumb buffer -> framebuffer
 * 3. 创建 atomic request
 * 4. 设置 CRTC 属性(mode, active)
 * 5. 设置 Plane 属性(fb_id, src, dest)
 * 6. 提交 atomic commit
 */

static int atomic_set_mode(int fd, uint32_t crtc_id, uint32_t conn_id,
                           drmModeModeInfo *mode, uint32_t fb_id)
{
    drmModeAtomicReq *req;
    int ret;

    req = drmModeAtomicAlloc();
    if (!req) {
        perror("atomic alloc");
        return -1;
    }

    /* 获取 connector 和 CRTC 的 property ID */
    drmModeObjectRes *obj = drmModeGetObjectProperties(fd, crtc_id,
                            DRM_MODE_OBJECT_CRTC);
    if (!obj) {
        perror("get crtc properties");
        drmModeAtomicFree(req);
        return -1;
    }

    /* 设置 CRTC active 属性 */
    for (uint32_t i = 0; i < obj->count_props; i++) {
        drmModePropertyRes *prop = drmModeGetProperty(fd, obj->props[i]);
        if (!prop) continue;

        if (strcmp(prop->name, "ACTIVE") == 0) {
            drmModeAtomicAddProperty(req, crtc_id, prop->prop_id, 1);
            printf("Set CRTC %u ACTIVE = 1\n", crtc_id);
        }

        if (strcmp(prop->name, "MODE_ID") == 0) {
            /* 创建 mode blob */
            uint32_t blob_id;
            ret = drmModeCreatePropertyBlob(fd, mode, sizeof(*mode), &blob_id);
            if (ret < 0) {
                perror("create mode blob");
                drmModeFreeProperty(prop);
                drmModeFreeObjectProperties(obj);
                drmModeAtomicFree(req);
                return -1;
            }
            drmModeAtomicAddProperty(req, crtc_id, prop->prop_id, blob_id);
            printf("Set CRTC %u MODE_ID = %u (%dx%d@%d)\n",
                   crtc_id, blob_id, mode->hdisplay,
                   mode->vdisplay, mode->vrefresh);
        }

        drmModeFreeProperty(prop);
    }
    drmModeFreeObjectProperties(obj);

    /* 提交 atomic commit */
    ret = drmModeAtomicCommit(fd, req,
                              DRM_MODE_ATOMIC_ALLOW_MODESET |
                              DRM_MODE_ATOMIC_TEST_ONLY, NULL);
    if (ret < 0) {
        fprintf(stderr, "Atomic commit test failed: %s\n", strerror(-ret));
        drmModeAtomicFree(req);
        return -1;
    }

    /* 正式提交 */
    ret = drmModeAtomicCommit(fd, req,
                              DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
    if (ret < 0) {
        fprintf(stderr, "Atomic commit failed: %s\n", strerror(-ret));
    } else {
        printf("Atomic commit succeeded\n");
    }

    drmModeAtomicFree(req);
    return ret;
}

int main(void)
{
    int fd;
    drmModeRes *resources;
    drmModeConnector *conn = NULL;
    drmModeEncoder *encoder = NULL;
    drmModeModeInfo mode;
    uint32_t crtc_id = 0;

    printf("RK3576 DRM Atomic Mode Setting Test\n\n");

    fd = open(DRM_DEVICE, O_RDWR);
    if (fd < 0) {
        perror("open DRM");
        return 1;
    }

    resources = drmModeGetResources(fd);
    if (!resources) {
        perror("get resources");
        close(fd);
        return 1;
    }

    /* 找到已连接的 connector */
    for (int i = 0; i < resources->count_connectors; i++) {
        conn = drmModeGetConnector(fd, resources->connectors[i]);
        if (conn && conn->connection == DRM_MODE_CONNECTED &&
            conn->count_modes > 0) {
            printf("Found connected display: connector %u\n", conn->connector_id);
            memcpy(&mode, &conn->modes[0], sizeof(drmModeModeInfo));
            crtc_id = resources->crtcs[0];
            break;
        }
        if (conn) drmModeFreeConnector(conn);
        conn = NULL;
    }

    if (!conn) {
        fprintf(stderr, "No connected display found\n");
        drmModeFreeResources(resources);
        close(fd);
        return 1;
    }

    printf("Using mode: %dx%d@%dHz\n",
           mode.hdisplay, mode.vdisplay, mode.vrefresh);

    /* 执行 atomic mode setting */
    atomic_set_mode(fd, crtc_id, conn->connector_id, &mode, 0);

    /* 释放资源 */
    drmModeFreeConnector(conn);
    drmModeFreeResources(resources);
    close(fd);

    printf("Done.\n");
    return 0;
}

4.9 Weston/Wayland 合成器启动

# 基础启动(DRM 后端)
weston --backend=drm-backend.so &

# 或使用 weston-init 服务
systemctl start weston

# 多屏 Weston 配置文件
cat > /etc/wayland/weston.ini << 'EOF'
[core]
backend=drm-backend.so

[output]
name=HDMI-A-1
mode=1920x1080@60

[output]
name=DSIA
mode=720x1280@60
transform=90
EOF

# 启动 Weston
weston

4.9.1 测试 Weston 显示输出

启动 Weston 后,运行以下测试程序验证显示输出:

# OpenGL ES 渲染测试
weston-simple-egl

# CPU 渲染测试
weston-simple-shm

# 花朵窗口演示
weston-flower

# 启动终端窗口(Wayland 协议客户端)
weston-terminal

4.10 屏幕旋转配置

# === 方式一:Weston transform 配置(推荐) ===
# 在 /etc/wayland/weston.ini 中添加:
#
# [output]
# name=DSIA
# mode=720x1280@60
# transform=90
#
# transform 取值:
#   0 = 正常 (0°)
#   1 = 顺时针 90°
#   2 = 180°
#   3 = 逆时针 90° (即 270° 顺时针)
#   4 = 水平翻转
#   5 = 水平翻转 + 90°
#   6 = 垂直翻转
#   7 = 垂直翻转 + 90°

# === 方式二:X11 xrandr 旋转 ===
xrandr --output DSIA --rotate left

# === 方式三:DRM Plane rotation 属性 ===
# 通过 modetest 查看 plane 的 rotation 属性
modetest -M rockchip -c | grep -A 20 "Planes:"

旋转 90/270° 后,宽高需要交换。例如:1920x1080 旋转后变为 1080x1920。

4.11 冻屏(Freeze Display)

冻结当前显示内容,防止开机 logo 到 UI 之间的黑屏过渡:

# 查看当前显示状态
cat /sys/kernel/debug/dri/0/state | grep "ACTIVE"

# 设置 Framebuffer 固定显示
echo 1 > /sys/class/graphics/fb0/blank

5. 代码详解

5.1 内核驱动结构

Rockchip DRM 显示驱动源码目录(以 RK3576 Linux SDK 内核为准):

drivers/gpu/drm/rockchip/          # Rockchip DRM 核心驱动
drivers/gpu/drm/bridge/synopsys/   # HDMI / MIPI DSI 桥接驱动
drivers/phy/rockchip/              # 物理层驱动
drivers/video/rockchip/            # Framebuffer 驱动

核心驱动文件:

模块驱动文件说明
Corerockchip_drm_drv.cDRM 驱动核心,注册 DRM 设备
Corerockchip_drm_fb.c帧缓冲管理
Corerockchip_drm_gem.cGEM 缓冲区管理
Corerockchip_drm_logo.cLogo 显示
VOProckchip_drm_vop.c / vop2*.cVOP 显示控制器驱动
HDMIdw_hdmi.cDesignWare HDMI 驱动
HDMIrockchip_dw_hdmi.cRockchip HDMI 封装
MIPI DSIdw-mipi-dsi2.cDesignWare MIPI DSI 驱动
Panelpanel-simple.c通用 Panel 驱动
FBfb_rockchip.c传统 Framebuffer 驱动

驱动文件具体名称与版本以实际发布的 RK3576 Linux SDK 为准。

5.2 驱动加载流程

Kernel boot up
    |
    +-- reserved-memory: drm_logo (保留 logo 显示缓冲区)
    |
    +-- 各显示设备 probe(顺序无关,使用 deferred probe)
    |   +-- dw_hdmi_rockchip_probe   :component_add
    |   +-- dw_mipi_dsi2_probe       :component_add
    |   +-- vop_probe                :component_add
    |
    +-- rockchip_drm_platform_probe
    |   +-- 解析 display 节点,将显示设备加入 component
    |
    +-- rockchip_drm_bind
    |   +-- component_bind_all: 执行各子设备 bind 程序
    |       +-- vop_bind
    |       +-- dw_hdmi_rockchip_bind
    |       +-- dw_mipi_dsi_bind
    |
    +-- show_loader_logo()
    |   +-- 解析 dts 中 logo 显示链路,将 logo 显示到对应设备
    |
    +-- rockchip_drm_fbdev_init
    |   +-- 加入 framebuffer 兼容支持(创建 /dev/fb0)
    |
    +-- DRM kernel 阶段加载完成

DRM 驱动利用 Linux 内核的 deferred probe 机制:当某个依赖资源未就绪时,驱动返回 -EPROBE_DEFER(-517),Linux kernel 会在稍后重新尝试加载该驱动,直到所有依赖资源就绪。

具体启动日志中的 base 地址、设备名与模块名以 RK3576 SDK 内核实际输出为准。

5.3 用户空间调用链

User Space Application (modetest / program)
  |
  +-- open("/dev/dri/card0")
  |
  +-- drmIoctl(DRM_IOCTL_GET_MAGIC)           // 获取 DRM 魔数
  |
  +-- drmIoctl(DRM_IOCTL_MODE_GETRESOURCES)   // 获取 CRTC/Connector/Encoder 资源
  |
  +-- drmIoctl(DRM_IOCTL_MODE_GETCONNECTOR)   // 获取 Connector 支持的显示模式
  |
  +-- drmIoctl(DRM_IOCTL_MODE_SETCRTC)        // 设置 CRTC 显示模式
  |   +-- vop_crtc_enable()
  |       +-- 启动 VOP 显示控制器
  |
  +-- drmIoctl(DRM_IOCTL_MODE_GETPlane)       // 获取可用 Plane
  |
  +-- drmIoctl(DRM_IOCTL_MODE_SETPLANE)       // 设置 Plane 显示内容
  |   +-- vop_plane_atomic_update()
  |       +-- 向 CRTC 写入帧缓冲数据
  |
  +-- drmIoctl(DRM_IOCTL_MODE_PAGE_FLIP)      // 页面翻转
      +-- vop_crtc_atomic_flush()
          +-- 提交显示帧

5.4 DRM/KMS 与 Framebuffer 关系

+-----------------------------------------------------------+
|                    User Space Application                   |
+-----------------+-----------------------------------------+
|  DRM Application|    Framebuffer Compatibility Layer        |
|  (modetest)     |    (/dev/fb0)                            |
+-----------------+-----------------------------------------+
|  libdrm         |    fb_rockchip.c                         |
|  GBM            |    (auto-creates fb0 device node)        |
+-----------------+-----------------------------------------+
|              DRM/KMS Kernel Framework                       |
|         /dev/dri/card0                                      |
+-----------------------------------------------------------+
|                    VOP Display Controller                   |
|         vop@<base_addr>(以 SDK 设备树为准)                |
+-----------------------------------------------------------+
|                    Display Interfaces                        |
|           HDMI            MIPI DSI                        |
+-----------------------------------------------------------+

Rockchip 的 DRM 驱动在初始化时会自动创建 Framebuffer 设备节点(/dev/fb0),该节点作为 DRM 框架的兼容层存在。传统 Framebuffer 应用可以通过 /dev/fb0 直接操作,但功能受限于单图层、无硬件合成。


6. 常见问题

6.1 显示无输出

现象: 连接显示器后无信号显示。

排查步骤:

# 1. 检查设备树中 VOP 节点状态(节点名以实际 SDK 设备树为准)
cat /proc/device-tree/soc/vop@<base_addr>/status
# 应输出:okay

# 2. 检查 HDMI 节点状态
cat /proc/device-tree/soc/hdmi@<base_addr>/status
# 应输出:okay

# 3. 检查连接状态
cat /sys/class/drm/card0-HDMI-A-1/status
# 应输出:connected

# 4. 检查 VOP 时钟
cat /sys/kernel/debug/clk/clk_dclk_vp0/clk_rate

# 5. 查看 DRM 驱动加载日志
dmesg | grep -i "rockchip-drm"

# 6. 检查设备树 route 节点
cat /proc/device-tree/soc/display-subsystem/route/route_hdmi/status
# 应输出:okay

解决方案: 确认设备树中 VOP 和对应显示接口节点 status = "okay",检查 route 节点中 connect 属性是否正确连接到对应 VP。若为 MIPI DSI 屏,还需确认 panel 节点与背光、复位引脚配置正确。

6.2 HDMI 未检测到

现象: 连接 HDMI 线缆后,status 始终显示 disconnected。

排查步骤:

# 1. 检查 HPD(Hot Plug Detect)引脚状态
cat /sys/kernel/debug/gpio | grep HDMI

# 2. 检查 HDMI PHY 状态
cat /sys/kernel/debug/clk/clk_hdmi_ref/clk_rate

# 3. 查看 HDMI 驱动日志
dmesg | grep -i "hdmi"

# 4. 检查 EDID 读取
cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode

解决方案: 检查 HPD 引脚的 pinctrl 配置是否正确,确认 HDMI PHY 时钟配置。对于不支持热插拔的显示器,可在设备树中将 HDMI connector 的 status 设置为 fixed。确认电源供电满足要求(M4-R2 采用 5V/2A 供电,空载最小 1000mA)。

6.3 分辨率不正确或显示异常

现象: 显示分辨率与预期不符,或画面拉伸/压缩。

# 查看显示器支持的分辨率
cat /sys/class/drm/card0-HDMI-A-1/modes

# 使用 modetest 设置分辨率
modetest -M rockchip -s 32:1920x1080-60

# 查看当前 EDID 信息
cat /sys/class/drm/card0-HDMI-A-1/edid | edid-decode

# 查看 VOP 当前显示时序
cat /sys/kernel/debug/dri/0/state

解决方案: 检查 EDID 读取是否正常,确认 HDMI 线缆支持所需带宽。M4-R2 规格书标注 HDMI 最高支持 4096×2160,实际最大分辨率需在板端实测(待板上验证)。对于不支持自动协商的显示器,可在设备树中手动配置显示时序(display-timings 节点)。

6.4 Framebuffer 设备节点不存在

现象: /dev/fb0 不存在,但 /dev/dri/card0 存在。

# 检查 DRM 设备
ls -la /dev/dri/
# 应看到 card0 和 renderD128

# 检查 Framebuffer 相关配置
grep "FB_ROCKCHIP\|DRM_FBDEV_EMULATION" /boot/config-$(uname -r)

# 手动创建 framebuffer 设备节点(临时方案)
mknod /dev/fb0 c 29 0

解决方案: 确认内核配置中启用了 CONFIG_DRM_FBDEV_EMULATION=y 和 CONFIG_FB_ROCKCHIP=y。DRM 驱动加载成功后会自动创建 /dev/fb0 设备节点。

6.5 DRM 设备权限不足

现象: 非 root 用户无法打开 /dev/dri/card0。

# 检查设备权限
ls -la /dev/dri/card0
# 预期输出:crw-rw---- 1 root video ...

# 检查用户组
groups
# 当前用户应在 video 组中

# 添加用户到 video 组
sudo usermod -a -G video $USER

# 重新登录后生效

解决方案: 确认当前用户在 video 组中,或修改 /dev/dri/card0 的设备权限。

6.6 VOP 驱动加载失败

现象: DRM 设备节点不存在,dmesg 中有 VOP 相关错误。

# 查看 VOP 驱动加载日志
dmesg | grep -i "vop"

# 检查设备树节点状态
cat /proc/device-tree/soc/vop@<base_addr>/status

# 检查 VOP 时钟
cat /sys/kernel/debug/clk/clk_aclk_vop/clk_rate

# 检查 power domain
cat /sys/kernel/debug/pm_genpd/pm_genpd_summary | grep vop

解决方案: 确认设备树中 vop 节点 status = "okay",检查时钟和 power domain 配置是否正确。VOP 驱动加载失败通常是设备树配置问题。

6.7 DRM Framebuffer 创建失败

现象: drmModeAddFB 或 drmModeAddFB2 返回 -ENOMEM 或 -EINVAL。

# 1. 检查像素格式是否支持
# RK3576 支持: DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888 等

# 2. 检查可用内存
cat /proc/meminfo | grep MemAvail

# 3. 检查 GEM handle 是否有效
# 确保 create_dumb 成功后再创建 FB

解决方案: 确认使用 Rockchip 支持的像素格式(优先使用 DRM_FORMAT_XRGB8888),检查 dumb buffer 创建是否成功,确认 GEM handle 有效。

6.8 Mali-G52 GPU 驱动问题

现象: GPU 渲染节点不存在或 EGL 初始化失败。

# 检查 GPU 驱动是否加载
lsmod | grep panfrost    # 开源驱动
# 或
lsmod | grep mali        # 闭源驱动

# 检查 GPU 渲染节点
ls -la /dev/dri/renderD12*
# renderD128 -> GPU 0

# 使用 eglinfo 查看 GPU 能力
eglinfo | head -30

# 检查 Mesa 版本
glxinfo | grep "OpenGL version"

解决方案: RK3576 使用 Mali-G52 MC3 GPU,具体采用 panfrost 开源驱动还是 mali 闭源驱动(libmali),以实际发布的 RK3576 SDK 为准。如需使用闭源驱动以获得更好性能,需安装 SDK 提供的 libmali 驱动包。

6.9 Weston 无法启动

现象: 执行 weston 命令后无窗口显示或报错退出。

# 检查 DRM 设备
ls -la /dev/dri/card0

# 查看 Weston 日志
WESTON_DEBUG=1 weston 2>&1 | head -50

# 检查用户权限
groups  # 确认在 video 组中

解决方案: 确认当前用户在 video 组中,DRM 设备权限正确(crw-rw---- root video)。

6.10 冻屏后画面不显示

现象: 执行 echo 1 > /sys/class/graphics/fb0/blank 后画面不恢复。

# 恢复显示
echo 0 > /sys/class/graphics/fb0/blank

# 检查 fb0 状态
cat /sys/class/graphics/fb0/blank

解决方案: 使用 echo 0 恢复显示,或重启 Weston 合成器重新初始化显示输出。


7. 相关文档

文档名称路径说明
摄像头应用摄像头应用MIPI/USB 摄像头与预览
视频编解码 (MPP)视频编解码(MPP)MPP 视频编解码框架
音频开发与 ALSA音频开发与ALSAALSA 音频框架
RGA 图像处理RGA图像处理RGA 2D 图形加速
内核配置与裁剪内核配置与裁剪内核配置方法
设备树详解与实践设备树详解与实践设备树配置方法
Linux SDK 编译Linux_SDK编译SDK 获取与编译
RKNN 模型转换与量化模型转换与量化ONNX → RKNN 模型转换

在 GitHub 上编辑此页