如何写分层驱动(复杂的字符驱动)----以lcd驱动为例

*********如何写分层驱动(复杂的字符驱动)----以lcd驱动为例**************

思路:复杂的驱动都是建立在简单的驱动的基础上,所以首先要知道内核简单字符设备驱动如何写

1.如何简单驱动程序

1.1 构造file_operations

.open = drv_open

.read = drv_read

1.2 告诉内核有1.1这个结构,register_chrdev(主设备号,fop,name)

上面可以被下面三句话代替

分配cdev

设置cdev

cdev_add

1.3 入口函数:调用1.2的注册函数

1.4 出口函数:unregister_chrdev

2.复杂设备驱动程序:1.简单驱动程序框架+分层

第一层:和简单驱动程序框架类似,这里以fbmem.c为例

2.1. 构造file_operations

open/read/write

2.2.register_chrdev

2.3.入口/出口

第二层:驱动层:硬件相关(具体驱动具体不同):三把斧

3.1. 分配一个fb_info结构体: framebuffer_alloc

3.2. 设置

3.3. 注册: register_framebuffer: 实质:register_framebuffer做的事:设置registered_fb数组的值

3.4. 硬件相关的操作

****************************************************************************************

总体架构:

分析fbmem.c

static const struct file_operations fb_fops = { // -------2.1

.owner =
THIS_MODULE,

.read =
fb_read,

.write =
fb_write,

.ioctl =
fb_ioctl,

.mmap =
fb_mmap,

.open =
fb_open,

.release =
fb_release,

};

static int __init

fbmem_init(void)// ------2.3

{

create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);

if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) // ----------2.2

printk("unable to get major %d for fb devs\n", FB_MAJOR);

fb_class = class_create(THIS_MODULE, "graphics"); // 注册设备类

if (IS_ERR(fb_class)) {

printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));

fb_class = NULL;

}

return 0;

}

例子:具体分析:LCD驱动程序   // 要具体由app到内核到驱动分析才知道整个架构如何形成

假设:

app:  open("/dev/fb0", ...)   主设备号: 29, 次设备号: 0

--------------------------------------------------------------

kernel:

fb_open
// 第一层的通用代码作用:1.中转作用:判断参数和设置参数,成为子类的多态函数参数  2.提供通用的操作:如果子类没有覆盖调用该方法,则使用通用代码,实现多态

int fbidx = iminor(inode);    // 这个是register_framebuffer时候设置的,次设备号就是数组的下标

struct fb_info *info = = registered_fb[0];  // 获取3.3驱动注册的结构体

file->private_data = info;// 方法1:重新设置file的fop,设置成info里面提供的fop

// 方法2:不重新设置file的fop,根据次设备号获取驱动设置的fop,调用驱动提供的函数

if (info->fbops->fb_open) {

res = info->fbops->fb_open(info,1);

if (res)

module_put(info->fbops->owner);

}

app:  read()

---------------------------------------------------------------

kernel:

fb_read

int fbidx = iminor(inode);

struct fb_info *info = registered_fb[fbidx];// 同fb_open

if (!info || ! info->screen_base)// 中转作用:参数合法性判断

return -ENODEV;

if (info->state != FBINFO_STATE_RUNNING)

return -EPERM;

if (info->fbops->fb_read)// 多态:子类有自己实现,那么用子类函数

return info->fbops->fb_read(info, buf, count, ppos);

// 如果子类没有覆盖掉该方法则用基类提供通用方法

src = (u32 __iomem *) (info->screen_base + p);

dst = buffer;

*dst++ = fb_readl(src++);

copy_to_user(buf, buffer, c)

附录:register_framebuffer分析

int

register_framebuffer(struct fb_info *fb_info)

{

int i;

struct fb_event event;

struct fb_videomode mode;

if (num_registered_fb == FB_MAX)

return -ENXIO;

num_registered_fb++;

// 1.算法:找到次设备号

for (i = 0 ; i < FB_MAX; i++)

if (!registered_fb[i])

break;

fb_info->node = i;

// 2.建立设备节点

fb_info->dev = device_create(fb_class, fb_info->device,//以该次设备号建立设备节点

MKDEV(FB_MAJOR, i), "fb%d", i);//
在app open的时候fb%d,就有次设备号就传递进来了

// 驱动可以利用该次设备号

if (IS_ERR(fb_info->dev)) {

/* Not fatal */

printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));

fb_info->dev = NULL;

} else

fb_init_device(fb_info);

return 0;

}

忠于梦想 勇于实践

时间: 2024-12-07 04:40:30

如何写分层驱动(复杂的字符驱动)----以lcd驱动为例的相关文章

LCD驱动应该怎么写?–基于stm32F407 [复制链接]

够用的硬件能用的代码使用的教程 (拷贝过来的代码有点乱,请下载附件查看文档) 资料下载地址:https://pan.baidu.com/s/1bHUVe6X6tymktUHk_z91cA 网络上配套STM32开发板有很多LCD例程,主要是TFT LCD跟OLED的.从这些例程,大家都能学会如何点亮一个LCD.但是不知道有多少人会直接使用这些代码,至少我不用,不是不用,而是用不了.这代码都有下面这些问题: 1 分层不清晰,通俗讲就是模块化太差.2 接口乱.其实只要接口不乱,分层就会好很多了.3 可

如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)

六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上) 八.LCD1602点阵字符型液晶显示模块驱动封装(中) 已经有好一阵子没写了,一方面是因为最近闲杂的事特多,另一方面(主要方面)是因为我卡在了LCD1602驱动的权衡上面——总共3个控制线和一个8位并行的数据线,放在51

从Linux内核LED驱动来理解字符设备驱动开发流程

目录 博客说明 开发环境 1. Linux字符设备驱动的组成 1.1 字符设备驱动模块加载与卸载函数 1.2 字符设备驱动的file_operations 结构体中的成员函数 2. 字符设备驱动--设备号注册卸载 2.1 设备号注册 2.2 设备号注销 3. 字符设备驱动--文件操作 参考资料 示例代码 @(从Linux内核LED驱动来理解字符设备驱动开发流程) 博客说明 撰写日期 2018.12.08 完稿日期 2019.10.06 最近维护 暂无 本文作者 multimicro 联系方式 [

linux驱动学习(1)——字符设备驱动开发

(一)驱动程序介绍 (a)Linux驱动程序学习 知识结构: 1. Linux驱动程序设计模式(40%) 2. 内核相关知识(30%) 3. 硬件相关知识(30%) (b)驱动分类: ①字符设备: 字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现 open, close,read和 write 系统调用. ②块设备: 在大部分的 Unix 系统, 块设备不能按字节处理数据,只能一次传送一个或多个长度是512字节( 或一个更大的 2 次幂的数 )的整块数据,而Lin

驱动学习之字符设备驱动的原理

1:嵌入式系统的整体工作原理 应用层->API->设备驱动->硬件 比如,在应用层,现在使用read函数去读取一个设备文件,这个read函数是属于应用层的,它不能直接读取设备文件,而是通过内核层的函数(其实就是和file_operations结构体中read这个函数指针相绑定的函数,这个函数才是真正操作硬件的函数)来实现读取文件, 2:file_operations结构体 (1)这个结构体里面存放的是一个驱动里面操作文件的各种函数指针,比如,现有一个驱动,它可以打开一个文件,那么这个驱动

LCD驱动分析(一)字符设备驱动框架分析

LCD驱动也是字符设备驱动,也遵循字符设备驱动的流程: a. 分配主设备号 b. 构建file_operations结构体中的open,write,read...等函数 c. 调用register_chrdev()函数注册字符设备 d. 调用class_register()注册类 e. 调用device_create()创建设备,linux会在sysfs目录下自动创建字符设备. 以上的步骤同样适用于分析输入子系统,只不过上面的各个步骤可能分散在不同的文件与函数中完成. 1.linux/drive

解构领域驱动设计(二):领域驱动设计的核心之分层架构

反映业务规则的代码是整个软件的核心,但是它一般只占很小的一部分,在传统的基于贫血模型的分层软件架构中,业务规则可能分散到各个层.各个代码段,从而使得通过代码来还原业务规则或者保证代码与业务规则一致将变得非常困难.DDD分层架构的核心思想就是将所有业务规则的代码抽取到领域层,保证领域层的编码与领域模型是完全一致的. 下图是DDD的分层架构.?我将通过代码来演示这个新的分层架构. 1 应用层 应用层在这里非常的简单清晰,它仅仅是将基础设施层.领域层提供的功能装配起来完成任务,这一层的代码逻辑非常简单

S3C2440 LCD驱动(FrameBuffer)实例开发&lt;二&gt;(转)

开发板自带的LCD驱动是基于platform总线写的,所以如果要使其它的LCD能够在自己的开发板上跑起来,那么就先了解platform驱动的架构,下面简单记录下自己看platform驱动时体会,简单的说platform是一种虚拟总线,那么它也是一条总线,所以它分为3个部分,platform_bus,platform_device,platform_driver.在platform_device向platform_bus注册设备,platform_driver向platform_bus注册驱动,注

S3C2440 LCD驱动(FrameBuffer)实例开发&lt;一&gt;(转)

1. 背景知识 在多媒体的推动下,彩色LCD越来越多地应用到嵌入式系统中,PDA和手机等大多都采用LCD作为显示器材,因此学习LCD的应用很有实际意义! LCD工作的硬件需求:要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器.在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等.TQ2440是采用了S3C2440,S