韦东山嵌入式Liunx驱动大全二

文章目录

      • 一、LCD
      • 1-1 不同接口的LCD硬件操作原理
      • 1-2 LCD驱动程序框架
      • 1-3 结合APP分析LCD驱动程序框架
      • 1-4 LCD硬件时序图
      • 1-5 分析内核自带的LCD驱动程序
      • 1-6 编程LCD驱动程序框架_使用设备树
      • 1-7 LCD驱动程序框架_引脚配置
      • 1-8 LCD驱动程序框架_时钟配置
      • 1-9 LCD驱动程序框架_LCD控制器配置
      • 1-10 LCD驱动程序框架_寄存器操作

本人学习完韦老师的视频,因此来复习巩固,写以笔记记之。
韦老师的课比较难,第一遍不知道在说什么,但是坚持看完一遍,再来复习,基本上就水到渠成了。
看完视频复习的同学观看最佳!
基于 IMX6ULL-PRO

一、LCD

1-1 不同接口的LCD硬件操作原理

bpp:bits per pixel,每个像素用多少位来表示
在这里插入图片描述
假设每个像素的颜色用16位来表示,那么一个LCD的所有像素点假设有xresy res个,需要的内存为:xresyres*16 / 8,也就是要设置所有像素的颜色,需要这么大小的内存。这块内存就被称为framebuffer:

  • Framebuffer中每块数据对应一个像素
  • 每块数据的大小可能是16位、32位,这跟LCD上像素的颜色格式有关
  • 设置好LCD硬件后,只需要把颜色数据写入Framebuffer即可

统一的LCD硬件模型
在这里插入图片描述
MIPI表示Mobile Industry Processor Interface,即移动产业处理器接口。是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。
MIPI接口可以分为3类:MIPI-DBI (Display Bus Interface) ,既能发送数据,也能发送命令,常用的8080接口就属于DBI接口;MIPI-DPI (Display Pixel Interface) ,Pixel(像素),强调的是操作单个像素,在MPU上的LCD控制器就是这种接口

1-2 LCD驱动程序框架

字符设备驱动程序框架
在这里插入图片描述
① 驱动主设备号 ② 构造file_operations结构体,填充open/read/write等成员函数
③ 注册驱动:register_chrdev(major, name, &fops) ④ 入口函数 ⑤出口函数

Framebuffer驱动程序框架
分为上下两层:
(1) fbmem.c:承上启下
实现、注册file_operations结构体;把APP的调用向下转发到具体的硬件驱动程序
(2) xxx_fb.c:硬件相关的驱动程序
实现、注册fb_info结构体;实现硬件操作
编写硬件程序如下
分配fb_info:framebuffer_alloc
设置fb_info:var、fbops、硬件相关操作
注册fb_info:register_framebuffer

在这里插入图片描述

1-3 结合APP分析LCD驱动程序框架

参考:04_fb_test文件夹

open函数分析:Linux根据主设备号找到驱动程序,根据次设备号来确定驱动程序中的那一个设备。此时会调用fbmen.c文件中fb_open函数,从registered_fb[i]数组中去获取fb_info。底层驱动在此前已经注册设备驱动,并registered_fb[i] = 定义的fb_info结构体。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/*设备驱动程序的注册信息*/
static struct fb_info *myfb_info;
register_framebuffer(myfb_info);
registered_fb[i] = fb_info;

ioctl函数分析:ioctl对应于底层fb_ioctl函数再调用到do_fb_ioctl
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1-4 LCD硬件时序图

在这里插入图片描述
HSD:水平方向同步信号
VSD:垂直方向同步信号
thd:每行像素个数
LCD控制器时序图
在这里插入图片描述

1-5 分析内核自带的LCD驱动程序

(1) 打开mxsfb.c文件,首先,platform_driver结构体中的属性与内核中设备树进行匹配。
在这里插入图片描述
ubuntu系统中,通过grep查找(第一个属性的值没找到),第二个属性找到内核的imx6ull.dtsi文件的第1017行,并打开。
Dtsi:可以理解为dts的公共部分,添加、变更非常灵活。Dtsi包含在dts中。

grep "fsl,imx28-lcdif" * -nr

设备树通过compatible属性来匹配驱动程序

vi imx6ull.dtsi +1017

在这里插入图片描述
而单板的设备树需要访问100ask_imx6ull-14x14.dts设备树文件,里面有硬件的配置。
在这里插入图片描述
(2) 匹配成功,则调用probe函数。并在里面分配、设置、注册fb_info
分配
在这里插入图片描述
在这里插入图片描述
设置
在这里插入图片描述
注册
在这里插入图片描述

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

GPIO设置

  • LCD引脚
  • 背光引脚
  • GPIO设置使用设备树,在设备树中设置pinctrl。

时钟设置

  • 确定LCD控制器的时钟
  • 根据LCD的DCLK计算相关时钟

LCD控制器本身的设置

  • 比如设置Framebuffer的地址
  • 设置Framebuffer中数据格式、LCD数据格式
  • 设置时序

1-6 编程LCD驱动程序框架_使用设备树

将03文件的驱动程序进行改进
使用platform_driver注册,在probe函数里分配fb_info、设置fb_info、注册fb_info、硬件相关的设置。设备树中需要有对应的节点
驱动框架

static int mylcd_probe(struct platform_device *pdev)
{
	/*简要代码*/
	/* 1.1 分配fb_info */
	myfb_info = framebuffer_alloc(0, NULL);

	/* 1.2 设置fb_info */
	/* a. var : LCD分辨率、颜色格式 */
	myfb_info->var.xres_virtual = myfb_info->var.xres = 500;
	myfb_info->var.yres_virtual = myfb_info->var.yres = 300

	/* 1.3 注册fb_info */
	register_framebuffer(myfb_info);

	/* 1.4 硬件操作 */
	mylcd_regs = ioremap(0x021C8000, sizeof(struct lcd_regs));
	mylcd_regs->fb_base_phys = phy_addr;
	mylcd_regs->fb_xres = 500;
	mylcd_regs->fb_yres = 300;
	mylcd_regs->fb_bpp  = 16;

	return 0;
}

static int mylcd_remove(struct platform_device *pdev)
{
	/* 反过来操作 */
	/* 2.1 反注册fb_info */
	unregister_framebuffer(myfb_info);
	/* 2.2 释放fb_info */
	framebuffer_release(myfb_info);
	iounmap(mylcd_regs);
	return 0;
}

static const struct of_device_id mylcd_of_match[] = {
	{ .compatible = "100ask,lcd_drv", },
	{ },
};
MODULE_DEVICE_TABLE(of, simplefb_of_match);

static struct platform_driver mylcd_driver = {
	.driver = {
		.name = "mylcd",
		.of_match_table = mylcd_of_match,
	},
	.probe = mylcd_probe,
	.remove = mylcd_remove,
};

static int __init lcd_drv_init(void)
{
	int ret;
	struct device_node *np;

	ret = platform_driver_register(&mylcd_driver);
	if (ret)
		return ret;

	return 0;
}

/* 2. 出口 */
static void __exit lcd_drv_exit(void)
{
	platform_driver_unregister(&mylcd_driver);
}

设备树信息

framebuffer-mylcd {
	compatible = "100ask,lcd_drv"; /*未待完续*/
};

1-7 LCD驱动程序框架_引脚配置

GPIO设置:配置LCD引脚和背光引脚GPIO,在设备树中设置pinctrl。
根据原理图确定需要配置那些引脚,打开引脚配置工具/设备树生成工具,把引脚配置成LCD引脚和背光引脚。
在这里插入图片描述
在这里插入图片描述
设备树节点信息和pinctrl信息(省略,如上图所示)

framebuffer-mylcd {
	compatible = "100ask,lcd_drv";
	pinctrl-names = "default";
    pinctrl-0 = <&mylcd_pinctrl>;
	backlight-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
/*probe函数获取GPIO*/
	/* get gpio from device tree */
	bl_gpio = gpiod_get(&pdev->dev, "backlight", 0);

	/* config bl_gpio as output */
	gpiod_direction_output(bl_gpio, 1);

	/* set val: gpiod_set_value(bl_gpio, status); */

1-8 LCD驱动程序框架_时钟配置

时钟设置:确定LCD控制器的时钟和根据LCD的DCLK计算相关时钟
翻阅芯片手册Chapter 34 Enhanced LCD Interface (eLCDIF),查看LCD时钟
在这里插入图片描述

设备树添加时钟属性

framebuffer-mylcd {
	compatible = "100ask,lcd_drv";
	pinctrl-names = "default";
    pinctrl-0 = <&mylcd_pinctrl>;
	backlight-gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
	
	clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
			<&clks IMX6UL_CLK_LCDIF_APB>,
       clock-names = "pix", "axi";

};

驱动代码添加设置时钟

/*probe函数中设置CLK*/
	/*get clk form device tree*/
	clk_pix = devm_clk_get(&pdev->dev,"pix");
	clk_axi = devm_clk_get(&pdev->dev,"axi");

	/*set clk rate*/
	/*clk_axi系统启动后自动设置
	*50Mhz以后会由设备树来设置
	*/
	clk_set_rate(clk_pix, 50000000);

	/*enable clk*/
	clk_prepare_enable(clk_pix);
	clk_prepare_enable(clk_axi);

1-9 LCD驱动程序框架_LCD控制器配置

LCD控制器本身的设置:设置Framebuffer的地址、设置Framebuffer中数据格式、LCD数据格式、设置时序
设备树

display = <&display0>;

display0: display {
	bits-per-pixel = <24>;
	bus-width = <24>;

	display-timings {
		native-mode = <&timing0>;

		 timing0: timing0_1024x600 {
		 clock-frequency = <50000000>;
		 hactive = <1024>;
		 vactive = <600>;
		 hfront-porch = <160>;
		 hback-porch = <140>;
		 hsync-len = <20>;
		 vback-porch = <20>;
		 vfront-porch = <12>;
		 vsync-len = <3>;

		 hsync-active = <0>;
		 vsync-active = <0>;
		 de-active = <1>;
		 pixelclk-active = <0>;
		 };

	};
};

驱动程序

	struct device_node *display_np;
	int ret;
	int bits_per_pixel;
	struct display_timings *timings = NULL;
	
	display_np = of_parse_phandle(pdev->dev.of_node, "display", 0);

	/*get common info*/
	ret = of_property_read_u32(display_np, "bus-width", &width);
	ret = of_property_read_u32(display_np, "bits-per-pixel",
				   &bits_per_pixel);
	
	/*get timming*/
	timings = of_get_display_timings(display_np);

时序参数、引脚极性等信息,都被保存在一个display_timing结构体里:
在这里插入图片描述

1-10 LCD驱动程序框架_寄存器操作

设备树添加lcd物理地址

reg = <0x021c8000 0x4000>;

驱动程序在设备树中获取地址信息

	/* 1.4 硬件操作 */
	//lcdif = ioremap(0x021C8000, sizeof(*lcdif));
	
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	lcdif = devm_ioremap_resource(&pdev->dev, res);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/603184.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1069 微博转发抽奖

solution #include<iostream> #include<string> #include<map> using namespace std; int main(){int n, m, s, loop 0, have 0;string id;map<string, int> mp;cin >> m >> n >> s;for(int i 1; i < m; i){//编号从1开始cin…

专题五_位运算(3)

目录 137. 只出现一次的数字 II 解析 题解 面试题 17.19. 消失的两个数字 解析 题解 137. 只出现一次的数字 II 137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 解析 注意这里指的是比特位上的01来进行统计的 题解 class Solution { public:int sin…

Unity与C#的关系

第一&#xff0c;我们首先需要知道Unity与C#的关系是什么&#xff1f; 第二&#xff0c;我们要明白为什么Unity会使用C#&#xff0c;而不是C&#xff1f; 第三&#xff0c;我们需要知道Unity是怎么使用C#的&#xff1f; 第一点&#xff1a; 先说结论&#xff1a;C#是Unity用…

windows如何安装python框架

windows如何安装Python框架&#xff1f;以安装Django框架为例&#xff0c;具体如下&#xff1a; 在idea上运行Python项目时&#xff0c;出现了如下错误&#xff0c;这是因为系统中只安装了Python&#xff0c;没有安装Django。 既然报错的原因就是缺少Django&#xff0c;那我们…

深度解析 Spring 源码:揭秘 AbstractAutowireCapableBeanFactory 的 Bean 生命周期处理

文章目录 一、AbstractAutowireCapableBeanFactory 概述1.1 详细分析1.2 设计思想 二、深入解析AbstractAutowireCapableBeanFactory 的实现细节2.1 Bean 实例化过程分析2.1.1 createBean()2.1.2 createBeanInstance() 2.2 Bean 属性注入的实现机制2.2.1 populateBean()2.2.2 a…

560. 和为 K 的子数组 974. 和可被 K 整除的子数组 【前缀和】

题目链接 ​​​​​​​974. 和可被 K 整除的子数组 560. 和为 K 的子数组 今天刷题的时候&#xff0c;刷了这两题&#xff0c;感觉挺有意思的。代码写起来挺简单的&#xff0c;但是思路和其中的细节以及涉及到的知识点确实让我挺意外的。这里写个博客解析一波&#xff0c;也是…

Charles抓包工具

Charles是一个HTTP代理工具&#xff0c;使开发人员能够查看客服端和服务器之间的所有HTTP/ HTTPS/SSL网络请求。 Charles是在PC环境下常用的网络抓包截取工具&#xff0c;在做移动开发时&#xff0c;我们为了调试客户端与服务端的网络通讯协议&#xff0c;常常需要截取网络请求…

MCP3008-I/SL 模数转换器ADC SPI接口 模拟信号采集

MCP3008-I/SL 模数转换器ADC 贴片SOIC16 MCP3008-I/SL 是一款模数转换器&#xff08;ADC&#xff09;&#xff0c;属于 SAR&#xff08;逐次逼近寄存器&#xff09;架构的 ADC。它具有以下特点&#xff1a; 8 通道单 ADC 最大采样率&#xff1a;200ksps&#xff08;千样点每秒…

鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉坑指南

几点说明 kernel_liteos_a_note | 中文注解鸿蒙内核 是在 OpenHarmony 的 kernel_liteos_a 基础上给内核源码加上中文注解的版本.与官方源码按月保持同步,同步历史如下: 2021/10/09 – 增加性能优化模块perf,优化了文件映射模块2021/09/14 – common,extended等几个目录结构和M…

文献速递:深度学习医学影像心脏疾病检测与诊断--基于深度学习的低剂量SPECT心肌灌注图像去噪:定量评估与临床表现

Title 题目 Deep learning–based denoising of low‑dose SPECT myocardialperfusion images: quantitative assessment and clinical performance 基于深度学习的低剂量SPECT心肌灌注图像去噪&#xff1a;定量评估与临床表现 01 文献速递介绍 单光子发射计算机断层扫描&a…

uniapp + vue3 设置 axios proxy 代理,并重写路径

uniapp vue2 设置代理如下&#xff1a; 已生成的项目架构里面找到manifest.json文件&#xff0c;通过源码视图的方式打开文件&#xff0c;在文件中添加一下代码即可完成代理&#xff1a; "h5": {"devServer": {"disableHostCheck": true, //禁…

基于StatefulSet控制器在Kubernetes上部署MySQL一主多从

一、前提--StatefuSet特性 1.1 有状态的节点控制器 -- StatefulSet 及其网络状态 容器的解决方案是针对无状态应用场景的最佳实践&#xff0c;但对于有状态应用来说&#xff0c;就并非如此了。Kubernetes 用 StatefulSet 解决了有状态应用编排的问题&#xff0c;本文我们就来…

GitHub介绍,GitHub如何订阅充值?

一、GitHub介绍 GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持git 作为唯一的版本库格式进行托管&#xff0c;故名Github。 GitHub于2008年4月10日正式上线&#xff0c;除了git代码仓库托管及基本的Web管理界面以外&#xff0c;还提供了订阅、讨论组、…

爬取深圳2024年链家二手房数据,共3000条数据(其他城市也可)

文章目录 专栏导读1.目标2.导入相关库3.获取每个二手房的链接4.获取每个链接中的相关数据5.保存数据6.数据展示 专栏导读 ✍ 作者简介&#xff1a;i阿极&#xff0c;CSDN 数据分析领域优质创作者&#xff0c;专注于分享python数据分析领域知识。 ✍ 本文录入于《python网络爬虫…

探索数据结构

什么是数据结构 数据结构是由&#xff1a;“数据”与“结构”两部分组成 数据与结构 数据&#xff1a;如我们所看见的广告、图片、视频等&#xff0c;常见的数值&#xff0c;教务系统里的&#xff08;姓名、性别、学号、学历等等&#xff09;&#xff1b; 结构&#xff1a;当…

Pandas进阶

文章目录 第1关&#xff1a;Pandas 分组聚合第2关&#xff1a;Pandas 创建透视表和交叉表 第1关&#xff1a;Pandas 分组聚合 编程要求 使用 Pandas 中的 read_csv() 函数读取 step1/drinks.csv 中的数据&#xff0c;数据的列名如下表所示&#xff0c;请根据 continent 分组并…

VMware 虚拟机自定义规范 - 更优雅的虚拟机开局

介绍 虚拟机自定义规范可以在你克隆虚拟机的时候在vCenter 的Web界面设定虚拟机的主机名、单/多网卡IP的IP和网关、DNS服务器、唯一标识符重置&#xff08;SID等&#xff09;、硬盘分区自动扩容、设定密码、密钥、时区等信息。 让管理员不需要进入虚拟机系统内部进行配置&…

10000字讲解IoC 思想以及五大注解

文章目录 IoC 思想通过案例讲解 IoC1.传统的开发方式 SpringIoC 和 DI五大注解ControllerServiceComponentRepositoryConfiguration 为什么要有这么多的类注解类注解之间的关系方法注解 Bean重命名 bean扫描路径 IoC 思想 什么是 Spring 呢&#xff1f; 我们经常听到的都是说…

Android 13 aosp 默认关闭SELinux

通过adb修改 adb root adb shell setenforce 0 // 开SELinux&#xff0c;设置成模式permissive adb shell setenforce 1 // 关SELinux&#xff0c;设置成模式enforce adb shell getenforce // 获取当前SELinux状态源码修改 Android_source/system/core/init/selinu…

JS-导入导出

export和export default是ES6中导出模块中变量的语法 导入导出变量 //导出方法&#xff08;js文件中&#xff09; export const 变量名值//导入方法 对应导入的变量&#xff0c;一定要加花括号 import {变量名} from js文件路径 导入导出函数 //导出方法&#xff08;js文件中…