如何新增一个屏幕驱动#
本文档介绍当前显示驱动框架下新增屏幕的推荐流程。新框架已经移除了旧版的 DSI Debugger 调试路径,新增屏幕时应先在 make menuconfig 中完成显示驱动、引脚和面板选择,再按当前 connector/panel 框架补齐代码。
本文档仍以一个 368(H) x 552(V) 的 MIPI DSI 屏幕为例,说明从 menuconfig 到代码集成的完整过程。
总体流程#
新增屏幕建议按下面顺序进行:
在
make menuconfig中打开对应显示驱动,并配置引脚。在
Display Panel Drivers Configuration中选择已有面板,或为新面板添加一个新的 panel driver。编译并运行显示 sample,使用
list_connector和现有 sample 验证配置是否生效。如果面板还不在 SDK 中,再按当前框架补充
connector_type、panel_desc、初始化序列和 CanMV 映射。
验证当前配置是否生效#
建议先验证 menuconfig 配置没有问题,再开始新增代码。
使能并编译显示相关 sample#
在 RT-Smart UserSpace Examples Configuration 中,至少使能:
Enable MPP examples一个或多个 VO/显示相关 sample,例如
sample_vo_video、sample_vo_osd
重新编译镜像后,在板端查找 sample:
查看当前固件支持的 connector#
进入板端 shell 后,可以先执行:
list_connector
这个命令可以列出当前固件已经编进镜像的 connector 类型和枚举值。它能帮助你确认:
menuconfig 里选择的 panel driver 是否已经生效
新增的 panel driver 是否已经进入最终镜像
sample 运行时应传入哪个
connector_type
运行显示 sample#
例如:
./mpp/sample_vo_video.elf <connector_type>
如果 sample 可以点亮已经使能的面板,说明当前显示链路、引脚和基础时序已经通了;这时再开始新增面板代码,定位会更清晰。
准备新增面板前需要拿到的信息#
新增一个 panel driver 之前,通常需要准备两类信息:
屏幕时序参数
屏幕厂家提供的初始化序列
这两类信息最终会进入 panel driver 源码,而不是像旧版流程那样写到 SDCard 配置文件里。
屏幕时序#
以本文档示例屏幕为例,时序信息通常包括:
pclk_hz=27000000
fps=60
lane_num=2
hactive=368
hsync=8
hbp=16
hfp=16
vactive=552
vsync=48
vbp=250
vfp=250
这些值会对应到 panel_desc 里的 timing 字段,例如:
pclk_hz/pclk_khzhactivehsync_lenhback_porchhfront_porchvactivevsync_lenvback_porchvfront_porch
工程里仍然可以使用时序计算工具辅助计算:
K230 MIPI DSI Connector Info Generator
仅可以验证时序是否能够生成
初始化序列#
厂家往往会提供一组寄存器初始化表,例如:
{0xFF,5,{0x77,0x01,0x00,0x00,0x13}},
{0xEF,1,{0x08}},
{0xFF,5,{0x77,0x01,0x00,0x00,0x10}},
{0xC0,2,{0x44,0x00}},
{0xC1,2,{0x0B,0x02}},
{0xC2,2,{0x07,0x1F}},
在当前框架里,这些数据一般会被转换成 panel 源文件中的命令序列数组,例如 mipi_st7701.c 中的:
const k_u8 init_sequence[] = {
0x39, 0, 6, 0xFF, 0x77, 0x01, 0x00, 0x00, 0x13,
0x15, 0, 2, 0xEF, 0x08,
0x39, 0, 3, 0xC0, 0x44, 0x00,
};
命令格式仍然是:
cmd_type, delay_ms, cmd_data_length, cmd_data0 ... cmd_dataN
当前常用的 cmd_type 有:
0x05:单字节命令,无参数0x15:单字节命令,带一个参数0x39:长命令,带多个参数
我们仍然举两个转换例子:
{0xB0,16,{0x0F,0x1E,0x25,0x0D,0x11,0x06,0x12,0x08,0x08,0x2A,0x05,0x12,0x10,0x2B,0x32,0x1F}},
# 去掉外层 {}
# 0xB0 是命令,后面 16 个字节是参数,因此使用 0x39
# 长度 = 1 个命令字节 + 16 个参数字节 = 17
0x39,0,17,0xB0,0x0F,0x1E,0x25,0x0D,0x11,0x06,0x12,0x08,0x08,0x2A,0x05,0x12,0x10,0x2B,0x32,0x1F
{0x11,0,{0x00}},
{REGFLAG_DELAY,120,{}},
# 这一组也可以转换到 init_sequence 数组中
# 如果按“1 个命令 + 1 个参数”处理,可以写成:
0x15,120,2,0x11,0x00
在工程代码中添加屏幕#
当前框架不是简单复制一份旧面板文件再改名字,而是围绕 connector_type、panel_desc、panel_ops 和 panel_drv 组织。
1. 先定义或确认 connector_type#
屏幕类型定义位于:
src/rtsmart/mpp/include/comm/k_connector_comm.h
当前工程使用 K_CONN_TYPE(chip, bus, w, h, ver) 生成 k_connector_type。新增面板时,先为新型号补一个新的类型常量,命名风格参考现有定义:
ST7701_480_800_DSI_V1ST7701_480_854_DSI_V1ST7701_480_640_DSI_V1ST7701_368_544_DSI_V1
如果只是为现有芯片增加一个新分辨率变体,也应优先沿用现有芯片命名方式,而不是单独发明一套类型编码。
2. 在 panel 源文件中补齐初始化和描述符#
DSI 面板的实现通常位于:
src/rtsmart/mpp/kernel/connector/src/panels/
例如 ST7701 的实现文件:
src/rtsmart/mpp/kernel/connector/src/panels/mipi_st7701.c
一个新 panel 通常至少需要这些内容:
一个
init_sequence对应的初始化函数一个
panel_ops一个
panel_desc一个
panel_drv或一个新的 variant 挂到现有panel_drv下
panel_desc 的关键字段包括:
nameconnector_typebus_typetiminggpiobusbus_opsops
以 DSI 面板为例,gpio 中通常会引用 menuconfig 配置出来的引脚:
.gpio = {
.reset_pin = CONFIG_MPP_DSI_LCD_RESET_PIN,
.backlight_pin = CONFIG_MPP_DSI_LCD_BACKLIGHT_PIN,
.reset_delay_ms = 10,
.backlight_delay_ms = 0,
.reset_active_low = K_TRUE,
.backlight_active_low = K_FALSE,
},
这也是为什么新增屏幕之前,应该先在 Display Configuration 中把引脚配置清楚。
3. 把新 panel 挂到当前驱动框架中#
connector 核心会从 connector_drv_list[] 里查找可用 panel。相关逻辑位于:
src/rtsmart/mpp/kernel/connector/src/connector_dev.c
当前查找流程是:
遍历
connector_drv_list[]遍历每个驱动中的
panel_variants通过
connector_type匹配目标 panel
因此新增面板时,需要确保新 panel 最终能进入某个 panel_drv 的 panel_variants,并且该驱动本身会被编译进镜像。
4. 在 Kconfig 和 Makefile 中接入新 panel#
完成 panel 源码后,还需要把它接进构建系统。
相关文件:
src/rtsmart/mpp/Kconfigsrc/rtsmart/mpp/kernel/connector/Makefile
Kconfig 负责把新 panel 暴露到:
MPP Configuration -> Display Configuration -> Display Panel Drivers Configuration
Makefile 负责根据 Kconfig 选项决定是否编译对应源文件。例如当前 DSI 面板的接入方式是:
src-$(CONFIG_MPP_DSI_ENABLE_LCD_ST7701) += src/panels/mipi_st7701.c
新增面板时,应按同样方式补一项,并在 Kconfig 中增加一个对应的 config 条目。
5. 如需 CanMV Python 接口支持,再补充映射#
如果该面板不仅在 C sample 中使用,也希望在 CanMV Python 接口中可选,还需要同步修改:
src/canmv/port/modules/modmedia.display.c
这里主要有两部分:
PY_PANEL_TYPE_*枚举py_display_panel_map[]映射表
只有当新的 connector_type 被映射到 py_display_panel_map[] 后,CanMV Python 层才能按面板类型和分辨率选择它。
新增屏幕的最小检查清单#
提交代码前,建议至少检查下面几项:
make menuconfig中能看到新的 panel 选项。Display Configuration里的 reset/backlight/bus 引脚与实际硬件一致。Makefile已经根据新的 Kconfig 选项编译对应面板源文件。connector_type在k_connector_comm.h中已经定义。panel_desc的时序、lane 数、GPIO 和初始化序列都已填写。connector_drv_list[]查找路径可以命中新 panel。板端
list_connector可以看到新 panel。sample_vo_video或其他显示 sample 可以点亮屏幕。如果需要 Python 支持,
py_display_panel_map[]已同步更新。
常见问题#
2. 已经编译通过,但 list_connector 看不到新 panel#
优先检查:
Makefile是否已经编译对应 panel 源文件connector_dev.c中的驱动列表是否能包含该 panel 对应的panel_drvpanel_variants里是否真正挂入了新的panel_desc
list_connector仅在 RTOS SDK 中被编译
3. 屏幕上电但不显示图像#
优先检查:
reset/backlight GPIO 是否正确
DSI lane、pixel clock、porch、sync 参数是否正确
厂家初始化序列是否完整,延时是否保留
sample 使用的
connector_type是否与新增 panel 一致检查串口日志,如果依然不能解决,可以去论坛发帖请教
参考#
当前显示驱动开关与面板列表:
../userguide/display_list.md显示 sample 使用说明:
../app_develop_guide/media/display.mdVO/显示 API 说明:
../api_reference/mpp/display.md
