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

2024-05-08 21:36

本文主要是介绍韦东山嵌入式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);

这篇关于韦东山嵌入式Liunx驱动大全二的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971498

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

嵌入式方向的毕业生,找工作很迷茫

一个应届硕士生的问题: 虽然我明白想成为技术大牛需要日积月累的磨练,但我总感觉自己学习方法或者哪些方面有问题,时间一天天过去,自己也每天不停学习,但总感觉自己没有想象中那样进步,总感觉找不到一个很清晰的学习规划……眼看 9 月份就要参加秋招了,我想毕业了去大城市磨练几年,涨涨见识,拓开眼界多学点东西。但是感觉自己的实力还是很不够,内心慌得不行,总怕浪费了这人生唯一的校招机会,当然我也明白,毕业

秒变高手:玩转CentOS 7软件更换的方法大全

在 CentOS 7 中更换软件源可以通过以下步骤完成。更换源可以加快软件包的下载速度,特别是当默认源速度较慢时。以下是详细步骤: 前言 为了帮助您解决在使用CentOS 7安装不了软件速度慢的问题,我们推出了这份由浪浪云赞助的教程——“CentOS7如何更换软件源加快下载速度”。 浪浪云,以他们卓越的弹性计算、云存储和网络服务受到广泛好评,他们的支持和帮助使得我们可以将最前沿的技术知识分

深入探索嵌入式 Linux

摘要:本文深入探究嵌入式 Linux。首先回顾其发展历程,从早期尝试到克服诸多困难逐渐成熟。接着阐述其体系结构,涵盖硬件、内核、文件系统和应用层。开发环境方面包括交叉编译工具链、调试工具和集成开发环境。在应用领域,广泛应用于消费电子、工业控制、汽车电子和智能家居等领域。关键技术有内核裁剪与优化、设备驱动程序开发、实时性增强和电源管理等。最后展望其未来发展趋势,如与物联网融合、人工智能应用、安全性与

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

嵌入式技术的核心技术有哪些?请详细列举并解释每项技术的主要功能和应用场景。

嵌入式技术的核心技术包括处理器技术、IC技术和设计/验证技术。 1. 处理器技术    通用处理器:这类处理器适用于不同类型的应用,其主要特征是存储程序和通用的数据路径,使其能够处理各种计算任务。例如,在智能家居中,通用处理器可以用于控制和管理家庭设备,如灯光、空调和安全系统。    单用途处理器:这些处理器执行特定程序,如JPEG编解码器,专门用于视频信息的压缩或解压。在数字相机中,单用途

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键