Linux驱动开发 / fbtft源码速读

哈喽,老吴又来分享学习心得啦~

一、目标与体系

  • 目标是关于你想要达到的结果,而体系是涉及导致这些结果的过程;

  • 目标的意义在于确定大方向,但体系才能促进进步。完全忽略目标,只关注体系,仍然会成功。

  • 结果并不是导致问题产生的根源。真正需要改变的是导致这些结果的体系。为了取得一劳永逸的成效,需要解决体系层面上的问题,修正输入端,输出端就会自行修正。

二、Linux驱动开发 / fbtft源码速读

1. fbtft 简介

fbtft 的作用:

  • 驱动各种 spi 接口的 TFT-LCD。

fbtft 的框架:

点击查看大图

驱动一款 spi lcd 的大致步骤:

  • 检查硬件连接;

  • 配置 spi 控制器,包括引脚配置、时钟输出、cs 脚、相位和极性等;

  • 配置 led/reset/dc gpio;

  • 添加 spi lcd 初始化代码;

  • 异常调试:

    • 示波器;

    • sysfs 读写 TFT-LCD 驱动 IC的寄存器;

    • 打开 fbtft 调试信息;

2. 快速阅读 fbtft 源码

环境:

  • Linux-5.4。

dts 大致如下:

&spi0 {
	pitft: pitft@0{
		compatible = "sitronix,st7735r";
		reg = <0>;
		pinctrl-names = "default";
		pinctrl-0 = <&tft13_gpio>;
		status = "okay";

		spi-max-frequency = <25000000>;
		fps = <30>;
		buswidth = <8>;
		dc-gpios = <&gpio1 PA5 GPIO_ACTIVE_HIGH>;
		reset-gpios = <&gpio1 PA7 GPIO_ACTIVE_LOW>;
		led-gpios = <&gpio1 PC7 GPIO_ACTIVE_LOW>;
		debug = <0x0>;
	};
};
  • compatible = "sitronix,st7735r" 指定了 TFT-LCD 驱动 IC 的驱动名称;

  • spi-max-frequency 指定 spi clock 的频率;

  • fps 指定你想用的帧数,最大值和 spi clock 挂钩;

  • dc-gpios / reset-gpios/ lcd-gpios 这些引脚的功能请自行查看 TFT-LCD 芯片手册;

  • debug 用于指定输出哪些调试信息;

几个重点源码文件:

  • fbtft-core.c,核心层,实现了一个 frambuffer 设备驱动;

  • fbtft-bus.c,提供读写寄存器 / 显存的功能;

  • fbtft-io.c,提供最底层的 spi 读写功能;

  • fbtft-sysfs.c,导出一些调试接口;

  • 具体的 TFT-LCD 芯片驱动,下面以 fb_st7735r.c 为例;

分析 fb_st7735r.c

1) 构造 struct fbtft_display:

static struct fbtft_display display = {
 .regwidth = 8,
 .width = 128,
 .height = 160,
 .init_sequence = default_init_sequence,
 .gamma_num = 2,
 .gamma_len = 16,
 .gamma = DEFAULT_GAMMA,
 .fbtftops = {
  //.init_display = init_display,
  .set_addr_win = set_addr_win,
  .set_var = set_var,
  .set_gamma = set_gamma,
 },
};

struct fbtft_display 用于描述一款 TFT-LCD,包括硬件参数+硬件访问操作函数,需要根据 LCD 驱动 IC 的手册进行填写:

  • regwidth: LCD 驱动 IC 寄存器的位宽;

  • width / height: LCD 的分辨率;

  • init_sequence:初始化序列;

  • fbtftops: LCD 操作函数集,init_display 和 init_sequence 一般只需要设置其中一项就行了;

2) 定义 platform_driver:

FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7735r", &display);

这是一个宏,它的关键内容是定义了一个 platform_driver。

  • platform_driver 会和设备树里的带有 "sitronix,st7735r" 属性的节点匹配上,触发 fbtft-core.c / fbtft_probe_common()。

分析 fbtft-core.c 里的几个重点函数

1) fbtft_probe_common(): 分配/设置/注册 framebuffer

  • fbtft_framebuffer_alloc(),定义并初始化 fb_info

  • 解析设备树里的 "sitronix,st7735r" 节点:fbtft_probe_dt(dev);

  • 使用 struct fbtft_display 来 填充 struct fbtft_par,fbtft_par 是 Main FBTFT data structure,负责保存 fbtft 所有的软硬件信息;

  • fbtft_register_framebuffer(info),注册 fb_info;

2) fbtft_register_framebuffer(): 注册 tft 设备的 framebuffer

  • par->fbtftops.init_display(par),执行 tft-lcd 的初始化操作

  • register_framebuffer(fb_info);

  • fbtft_sysfs_init(par),注册一些 sysfs 调试节点;

初始化流程图:

点击查看大图

3) fbtft_update_display(), 刷新屏幕

  • par->fbtftops.set_addr_win(),设置绘制窗口的坐标;

  • par->fbtftops.write_vmem(par, offset, len),将显存中的数据刷到屏幕上;

刷屏流程图:

点击查看大图

简单看下 fbtft-bus.c 和 fbtft-io.c

fbtft-bus.c:

// 写显存
int fbtft_write_vmem16_bus8(...) 
int fbtft_write_vmem16_bus9(...) 
int fbtft_write_vmem8_bus8(...) 
int fbtft_write_vmem16_bus16(...)

// 写 tft-lcd 的寄存器
void fbtft_write_reg8_bus8(...)
void fbtft_write_reg16_bus8(...)
void fbtft_write_reg16_bus16(...)

fbtft-io.c:

int fbtft_write_spi(...) 
int fbtft_read_spi(...) 

// 支持用 gpio 来模拟 spio 通讯
int fbtft_write_spi_emulate_9(...) 
int fbtft_write_gpio8_wr(...) 
int fbtft_write_gpio16_wr(...) 
int fbtft_write_gpio16_wr_latched(...)

3. 测试方法

功能测试:

$ git clone https://github.com/ponty/fb-test-app
$ make
$ ./fb-test

效果如下:

点击查看大图

性能测试:

在 dts 中设置 debug = 0x20,会打开 DEBUG_TIME_EACH_UPDATE 以打印 fps 的值:

spi0.0: Display update: 34100 kB/s, fps=40

三、思考技术,也思考人生

要学习技术,更要学习如何生活

你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。

嵌入式系统 (Linux、RTOS、OpenWrt、Android) 和 开源软件 感兴趣,关注公众号:嵌入式Hacker

觉得文章对你有价值,不妨点个 在看和赞

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Linux fbtft是一个用于驱动液晶显示屏的开源框架。它通过在Linux内核中添加相应的驱动程序和设备树节点来实现对液晶显示屏的控制。fbtft的核心功能是将显示屏作为一个Frame Buffer设备来操作,并提供了一些函数来进行初始化、刷新、绘制等操作。 一个重要的概念是platform_driver,它会与设备树中带有 "sitronix,st7735r" 属性的节点进行匹配,并触发fbtft-core.c / fbtft_probe_common()函数。这个函数是fbtft的核心逻辑,它会执行液晶显示屏的初始化操作。 在初始化操作中,通过执行par->fbtftops.init_display(par)函数来进行tft-lcd的初始化。这个函数会根据具体的液晶显示屏型号和配置,设置相关的参数并进行初始化操作。 总的来说,Linux fbtft是一个用于驱动液晶显示屏的开源框架,通过在Linux内核中添加驱动程序和设备树节点来实现对液晶显示屏的控制。它提供了一些函数来进行初始化、刷新、绘制等操作,通过platform_driver与设备树中的节点进行匹配来触发相关操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Linux驱动开发 / fbtft源码速读](https://blog.csdn.net/wuweidonggmail/article/details/110914325)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值