当前位置: 首页 > news >正文

嵌入式Linux驱动开发(LCD屏幕专题)(二)

一、结合APP分析LCD驱动程序

1、open

app:  open("/dev/fb0", ...)   主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:fb_open   // fbmem.cstruct fb_info *info;info = get_fb_info(fbidx);if (info->fbops->fb_open) {res = info->fbops->fb_open(info,1);   // 硬件相关的驱动if (res)module_put(info->fbops->owner);}      

2、获得可变信息(含有分辨率等)

app:  	ioctl(fd, FBIOGET_VSCREENINFO, &fb_info->var);
-------------------------------------------------------------------------
kernel:fb_ioctl   // fbmem.cstruct fb_info *info = file_fb_info(file);do_fb_ioctl(info, cmd, arg);var = info->var;     // 硬件相关的驱动设置的ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;

3、获得固定信息(含有显存信息)

app:  	ioctl(fd, FBIOGET_FSCREENINFO, &fb_info->fix);
-------------------------------------------------------------------------
kernel:fb_ioctl   // fbmem.cstruct fb_info *info = file_fb_info(file);do_fb_ioctl(info, cmd, arg);fix = info->fix;     // 硬件相关的驱动设置的ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;

4、mmap

app:void *ptr = mmap(0,fb_info->var.yres_virtual * fb_info->fix.line_length,PROT_WRITE | PROT_READ,MAP_SHARED, fd, 0);
-------------------------------------------------------------------------
kernel:fb_mmap   // fbmem.cstruct fb_info *info = file_fb_info(file);start = info->fix.smem_start;len = info->fix.smem_len;return vm_iomap_memory(vma, start, len);

二、分析内核自带的LCD驱动程序

刚拿到手一款新的芯片进入目录 drivers/video/fbdev/ 目录下查看有哪些.o文件,就可以得知有没有LCD驱动程序。
LCD驱动程序核心就是:

  • 分配fb_info
  • 设置fb_info
  • 注册fb_info
  • 硬件相关的设置

2.1、入口函数注册

在这里插入图片描述

2.2、设备树有对应节点

在这里插入图片描述

三、编写硬件相关的代码

我们只需要针对IMX6ULL的编写硬件相关的代码,涉及3部分:

  • GPIO设置
    • LCD引脚
    • 背光引脚
  • 时钟设置
    • 确定LCD控制器的时钟
    • 根据LCD的DCLK计算相关时钟
  • LCD控制器本身的设置
    • 比如设置Framebuffer的地址
    • 设置Framebuffer中数据格式、LCD数据格式
    • 设置时序

3.1、GPIO设置

有两种方法:

  • 直接读写相关寄存器
  • 使用设备树,在设备树中设置pinctrl
    • 本课程专注于LCD,所以使用pinctrl简化程序

设备树arch/arm/boot/dts/100ask_imx6ull-14x14.dts中:
在这里插入图片描述

3.2 、时钟设置

IMX6ULL的LCD控制器涉及2个时钟:
在这里插入图片描述
代码里直接使用时钟子系统的代码。

  • 在设备树里指定频率:

    • 文件:arch/arm/boot/dts/100ask_imx6ull-14x14.dts

    • 代码:clock-frequency

       display-timings {native-mode = <&timing0>;timing0: timing0_1024x768 {clock-frequency = <50000000>;
  • 从设备树获得dot clock,存入display_timing

    • 文件:drivers\video\of_display_timing.c

    • 代码:

      ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
      
  • 使用display_timing来设置videomode

    • 文件:drivers\video\videomode.c

    • 代码:

void videomode_from_timing(const struct display_timing *dt,struct videomode *vm)
{vm->pixelclock = dt->pixelclock.typ;vm->hactive = dt->hactive.typ;vm->hfront_porch = dt->hfront_porch.typ;vm->hback_porch = dt->hback_porch.typ;vm->hsync_len = dt->hsync_len.typ;vm->vactive = dt->vactive.typ;vm->vfront_porch = dt->vfront_porch.typ;vm->vback_porch = dt->vback_porch.typ;vm->vsync_len = dt->vsync_len.typ;vm->flags = dt->flags;
}

根据videomode的值,使用时钟子系统的函数设置时钟:

  • 文件:drivers\video\fbdev\mxc\ldb.c
  • 代码
    在这里插入图片描述

3.3、LCD控制器的配置

以设置分辨率为例。

  • 在设备树里指定频率:

    • 文件:arch/arm/boot/dts/100ask_imx6ull-14x14.dts

    • 代码:clock-frequency

             display-timings {native-mode = <&timing0>;timing0: timing0_1024x768 {hactive = <1024>;vactive = <600>;
  • 从设备树获得分辨率,存入display_timing

    • 文件:drivers\video\of_display_timing.c

    • 代码:

      	ret |= parse_timing_property(np, "hactive", &dt->hactive);ret |= parse_timing_property(np, "vactive", &dt->vactive);
      
  • 使用display_timing来设置videomode

    • 文件:drivers\video\videomode.c

    • 代码:

      void videomode_from_timing(const struct display_timing *dt,struct videomode *vm)
      {vm->hactive = dt->hactive.typ;vm->vactive = dt->vactive.typ;
      
  • 根据videomode的值,设置fb_videomode

    • 文件:drivers\video\fbdev\core\fbmon.c

    • 代码:

      int fb_videomode_from_videomode(const struct videomode *vm,struct fb_videomode *fbmode)
      {unsigned int htotal, vtotal;fbmode->xres = vm->hactive;fbmode->yres = vm->vactive;
  • 根据fb_videomode的值,设置fb_info中的var:

    • 文件:drivers\video\fbdev\core\modedb.c

    • 代码:

      void fb_videomode_to_var(struct fb_var_screeninfo *var,const struct fb_videomode *mode)
      {var->xres = mode->xres;var->yres = mode->yres;
  • 根据var的分辨率,设置寄存器

    • 文件:drivers\video\fbdev\mxsfb.c

    • 代码:

writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),host->base + host->devdata->transfer_count);

相关文章:

嵌入式Linux驱动开发(LCD屏幕专题)(二)

一、结合APP分析LCD驱动程序 1、open app: open("/dev/fb0", ...) 主设备号: 29, 次设备号: 0 -------------------------------------------------------------- kernel:fb_open // fbmem.cstruct fb_info *info;info get_fb_info(fbidx);if (info->fbop…...

React的jsx的用法

React是一个流行的JavaScript库&#xff0c;用于构建用户界面。它使用一种名为JSX的语法扩展来描述组件的结构和样式。JSX是React的核心语言之一&#xff0c;它允许开发人员在JavaScript中编写HTML&#xff0c;从而使代码更加简洁和易于阅读。 JSX是一种语法扩展&#xff0c;它…...

Ei Scopus检索 | 2024年第四届能源与环境工程国际会议(CoEEE 2024)

会议简介 Brief Introduction 2024年第四届能源与环境工程国际会议(CoEEE 2024) 会议时间&#xff1a;2023年5月22日-24日 召开地点&#xff1a;意大利米兰 大会官网&#xff1a;www.coeee.org CoEEE 2024将围绕“能源与环境工程”的最新研究领域而展开&#xff0c;为研究人员、…...

习题练习 C语言(暑期第四弹)

自我小提升&#xff01; 前言一、数组二、指针运算三、统计每个月兔子的总数四、双指针的应用五、判断指针六、珠玑妙算七、两数之和八、数组下标九、指针十、寻找峰值十一、二级指针十二、大端小端十三、无符号参数十四、数对十五、截取字符串总结 前言 重要的事说三遍&#…...

【docker快速部署微服务若依管理系统(RuoYi-Cloud)】

工作原因&#xff0c;需要一个比较完整的开源项目测试本公司产品。偶然发现RuoYi-Cloud非常适合&#xff0c;它有足够多的中间件&#xff0c;而且官方提供docker安装&#xff0c;但我本人在安装过程中遇到了很多坑&#xff0c;在这里记录一下防止下次会再次遇到。 项目地址 ht…...

面试求职-简历编写技巧

没有高水平简历 只有高匹配的简历 试问一下&#xff1a;如果一个非常牛逼的软件工程的硕士&#xff0c;投递市场营销岗位&#xff0c;结果会是什么样呢&#xff1f; 这位同学大概率没办法通过简历。 不是因为他不够优秀&#xff0c;而是因为简历和岗位不够匹配。 在公司的招…...

云原生安全性:构建可信任的云应用的最佳实践

文章目录 云原生安全性的重要性1. 数据隐私2. 恶意攻击3. 合规性要求4. 业务连续性 构建可信任的云应用的最佳实践1. 安全开发2. 身份验证与授权3. 容器安全性4. 监控与审计5. 持续集成与持续交付&#xff08;CI/CD&#xff09;6. 安全培训和教育 未来趋势&#xff1a;服务网格…...

第一章 数据库SQL-Server(及安装管理详细)

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 21 世纪&#xff0c;人类迈入了“信息爆炸时代”&#xff0c…...

chrome extension无法获取window对象

背景见上一篇博客修改网页内容的方法 上一篇博客之后&#xff0c;我要修改的网页有一个新改版&#xff0c;然后有个数据存在了window中&#xff0c;我直接在js中使用window.xxx发现无法获取。所以有本文。 https://juejin.cn/post/7145749643316428830 https://onelinerhub.com…...

在linux虚拟机上安装docker(我的实践)

参考文章&#xff1a; https://blog.csdn.net/qq_29479041/article/details/82659218 步骤&#xff1a; 1.安装docker 参考文章&#xff1a; https://blog.csdn.net/qq_29479041/article/details/82659218 https://blog.csdn.net/qq_38345468/article/details/110128659 2.…...

Spring之事务开发

什么是事务&#xff1f; 事务是指数据库管理系统中的一个执行单位或一个逻辑工作单元&#xff0c;它由一个或多个数据库操作序列组成。事务具有以下四个特性&#xff0c;通常被称为ACID特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务是一个不可分…...

干了三年的功能测试,让我女朋友跑了,太难受了...

简单概括一下 先说一下自己的情况&#xff0c;普通本科&#xff0c;19年通过校招进入深圳某软件公司&#xff0c;干了3年多的功能测试&#xff0c;21年的那会&#xff0c;因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不…...

JavaScript函数的使用

前言 程序中的foo、bar、baz 在学习编程的过程中&#xff0c;你可能会经常看到foo、bar、baz这些名词&#xff1a; 它们通常被用来作为函数、变量、文件的名词&#xff1b;目前已经编程了计算机编程的术语一部分&#xff1b;但是它们本身并没有特别的用途和意义&#xff1b;…...

【算法】Java-使用数组模拟单向链表,双向链表

目录 试题1&#xff1a;实现一个单链表&#xff0c;并实现以下功能&#xff1a; 试题2&#xff1a;实现一个双链表&#xff0c;并实现以下功能 思路总结&#xff1a; 什么情况下可能涉及到用数组实现链表呢&#xff1f; 在学习时了解到了可以用数组模拟链表&#xff0c;使其…...

Nessus简单介绍与安装

Nessus简单介绍与安装 1.Nessus简介 Nessus号称是世界上最流行的漏洞扫描程序&#xff0c;全世界有超过75000个组织在使用它。该工具提供完整的电脑漏洞扫描服务&#xff0c;并随时更新其漏洞数据库。Nessus不同于传统的漏洞扫描软件&#xff0c;Nessus可同时在本机或远端上遥…...

【每天一道算法题】day2-认识时间复杂度

认识时间复杂度&#xff1a; O&#xff1a;读作big O&#xff0c;在数学上指的是上限的意思 常数时间的操作 一个操作如果和样本的数据量没有关系&#xff0c;每次都是固定时间内完成的操作&#xff0c;叫做常数操作。时间复杂度为一个算法流程中&#xff0c;常数操作数量的一…...

前端报错合集

error Component name “index“ should always be multi-word vue/multi-word-component-names 的解决办法 原因组件命名是 没有采用驼峰 error Component name “index“ should always be multi-word vue/multi-word-component-names 的解决办法_error component name &qu…...

Milvus以及Web UI 安装

向量数据库懂的都懂 版本数据 [rootiZ7xv7q4im4c48qen2do2bZ project]# cat /etc/redhat-release CentOS Stream release 9 [rootiZ7xv7q4im4c48qen2do2bZ project]# docker version Client: Docker Engine - CommunityVersion: 24.0.5API version: 1.43Go v…...

Go for循环中的defer

背景 写个后台程序&#xff0c;定时抓取服务器指标&#xff0c;代码逻辑如下&#xff0c;使用一段时间后内存不断增加 func CollectInfo() {for {// 获取服务器信息代码// ...............resp, err : http.Post("http://server", "application/json", str…...

创建开机自启的脚本

在启动许多ros节点时有多种方式&#xff0c;我推荐使用launch来启动所有的节点&#xff0c;这也是一种规范的方式。以后会慢慢向这个方向靠。 除此之外还可以通过创建的脚本来启动&#xff1a; 脚本位置不限&#xff0c;只需要&#xff1a; sudo gedit xxx.sh在里面添加相应的…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...