【教学课件】第11课字符设备驱动.ppt

上传人:小飞机 文档编号:5657781 上传时间:2023-08-06 格式:PPT 页数:30 大小:469.97KB
返回 下载 相关 举报
【教学课件】第11课字符设备驱动.ppt_第1页
第1页 / 共30页
【教学课件】第11课字符设备驱动.ppt_第2页
第2页 / 共30页
【教学课件】第11课字符设备驱动.ppt_第3页
第3页 / 共30页
【教学课件】第11课字符设备驱动.ppt_第4页
第4页 / 共30页
【教学课件】第11课字符设备驱动.ppt_第5页
第5页 / 共30页
点击查看更多>>
资源描述

《【教学课件】第11课字符设备驱动.ppt》由会员分享,可在线阅读,更多相关《【教学课件】第11课字符设备驱动.ppt(30页珍藏版)》请在三一办公上搜索。

1、1,嵌入式系统An Introduction to Embedded System浙江大学计算机学院2012年4月,第11课 字符设备驱动,提纲,1、字符设备驱动框架2、字符设备驱动开发3、GPIO驱动概述4、串行总线概述5、I2C总线驱动开发,1、字符设备驱动框架,字符设备(Character Device)驱动程序是嵌入式Linux最基本、也是最常用的驱动程序。字符设备在Linux内核中使用struct cdev结构来表示,这个结构体在整个字符驱动程序设计中起着关键的作用。在struct cdev结构中包含着字符设备需要的全部信息,其中最主要的是设备号(dev_t)和文件操作(file_o

2、perations)。,字符设备驱动框架,2、字符设备驱动开发,设备类型和设备号关键数据结构字符设备的注册和注销,设备类型和设备号,对字符设备的访问是通过文件系统内的设备文件进行的,或者称为设备节点,位于/dev目录设备类型:字符设备/块设备主设备号:主设备号用来标识该设备的种类,也标识了该设备所使用的驱动程序次设备号:次设备号由内核使用,标识使用同一设备驱动程序的不同硬件设备,关键数据结构,file_operationsfileinode,file_operations(1),struct file_operations/指向拥有该结构的模块的指针,一般初始化为THIS_MODULEstru

3、ct module*owner;/用来改变文件中的当前读/写位置loff_t(*llseek)(struct file*,loff_t,int);/用来从设备中读取数据ssize_t(*read)(struct file*,char _user*,size_t,loff_t*);/用来向设备写入数据ssize_t(*write)(struct file*,const char _user*,size_t,loff_t*);/初始化一个异步读取操作ssize_t(*aio_read)(struct kiocb*,const struct iovec*,unsigned long,loff_t);

4、/初始化一个异步写入操作ssize_t(*aio_write)(struct kiocb*,const struct iovec*,unsigned long,loff_t);/用来读取目录,对于设备文件,该成员应当为NULLint(*readdir)(struct file*,void*,filldir_t);/轮询函数,查询对一个或多个文件描述符的读或写是否会阻塞unsigned int(*poll)(struct file*,struct poll_table_struct*);/用来执行设备I/O操作命令int(*ioctl)(struct inode*,struct file*,un

5、signed int,unsigned long);/不使用BKL文件系统,将使用此函数代替ioctl,file_operations(2),long(*unlocked_ioctl)(struct file*,unsigned int,unsigned long);/在64位系统上,使用32位的ioctl调用将使用此函数代替long(*compat_ioctl)(struct file*,unsigned int,unsigned long);/用来将设备内存映射到进程的地址空间int(*mmap)(struct file*,struct vm_area_struct*);/用来打开设备in

6、t(*open)(struct inode*,struct file*);/执行并等待设备的任何未完成的操作int(*flush)(struct file*,fl_owner_t id);/用来关闭设备int(*release)(struct inode*,struct file*);/用来刷新待处理的数据int(*fsync)(struct file*,struct dentry*,int datasync);/fsync的异步版本int(*aio_fsync)(struct kiocb*,int datasync);/通知设备FASYNC标志的改变int(*fasync)(int,stru

7、ct file*,int);/用来实现文件加锁,通常设备文件不需要实现此函数int(*lock)(struct file*,int,struct file_lock*);,file,file结构体在中定义fmode_t f_mode对文件的读写模式,对应系统调用open的mod_t mode参数。loff_t f_pos表示文件当前的读写位置。unsigned int f_flags表示文件标志,对应系统调用open的int flags参数。const struct file_operations*f_op指向和文件关联的操作void*private_data可以用于保存系统调用之间的信息。,

8、inode,Inode是一个内核文件系统索引节点对象,它包含了内核在操作文件或目录时所需要的全部信息。在内核中inode结构体用来表示文件,file是表示打开文件的结构体。重要成员dev_t i_rdev:对于设备文件而言,此成员包含实际的设备号。struct cdev*i_cdev:指向cdev结构的指针。,字符设备的注册和注销,定义struct cdev struct kobject kobj;/*内嵌的kobject对象*/struct module*owner;/*所属模块*/const struct file_operations*ops;/*文件操作函数*/struct list_

9、head list;dev_t dev;/*设备号*/unsigned int count;使用void cdev_init(struct cdev*,const struct file_operations*);struct cdev*cdev_alloc(void);void cdev_add(struct cdev*,dev_t,unsigned);void cdev_del(struct cdev*);,3、GPIO驱动概述,在ARM里,所有I/O都是通用的,称为GPIO(General Purpose Input/Output,通用输入输出)。每个GPIO端口一般包含8个引脚,例如P

10、A端口为PA0PA7。可以控制I/O接口作为输入或者输出。许多设备或电路通常只需要一位,即表示开/关两状态就够了,例如LED灯的亮和灭。GPIO接口一般至少会有两个寄存器,即控制寄存器和数据寄存器。数据寄存器的各位都直接引到芯片外部,而针对该寄存器的每一位的功能,则可以通过控制寄存器中相应的位来设置。,4、串行总线技术概述,串行相比于并行的主要优点是要求的线数较少,通常只需要使用2条、3条或4条数据/时钟总线连续传输数据。SPI总线I2C总线SMBus总线,SPI总线,同步外设接口(Serial Peripheral Interface,SPI)是由摩托罗拉公司推出的一种高速的、全双工、同步的

11、串行总线。SPI接口在CPU和外围低速器件之间进行同步的串行数据传输,在主器件的移位脉冲下,数据按位传输,并且高位在前、低位在后,是一种全双工通信。数据传输速度总体上来说比I2C总线要快,速度可以达到几Mbit/s。SPI 的工作模式有两种:主模式和从模式,无论哪种模式,都支持3Mbit/s的速率,并且还具有传输完成标志和写冲突保护标志。接口一般使用四条线:串行时钟线SCK、主器件输入/从器件输出数据线MISO、主器件输出/从器件输入数据线MOSI和从器件选择线SS。,I2C总线,Philips公司开发的二线式串行总线标准,内部集成电路(Internal Integrated Circuit)

12、,主要用于连接微控制器和外围设备。I2C总线是由串行数据信号线SDA和串行时钟信号线SCL构成的串行总线,可发送和接收数据。采用该总线连接的设备工作在主/从模式下,主器件既可以作为发送器,也可以作为接收器,能够发送和接收数据。I2C总线最主要的特点是它的简单性和高效性。在标准模式下,位速率可以达到100Kbit/s,在快速模式下则是400Kbit/s,在高速模式下可以达到3.4Mbit/s。,SMBus总线,系统管理总线(System Management Bus,SMBus)最初由Intel提出,应用于移动PC和桌面PC系统中的低速通讯。SMBus总线同I2C总线一样也是一种二线式串行总线,

13、它使用一条数据线(SMBDATA)和一条时钟线(SMBCLK)进行通信。SMBus的目标是通过一条廉价但功能强大的总线,来控制主板上的设备和收集设备的信息。虽然SMBus的数据传输率较慢,只有大约100kbit/s,却以其结构简单、造价低的特点,受到业界的普遍欢迎。SMBus总线大部分基于I2C总线规范,许多I2C设备也能够在SMBus上正常工作。SMBus与I2C总线之间在时序特性上存在一些差别。,5、I2C总线驱动开发,I2C驱动程序概况关键数据结构I2C核心I2C总线驱动I2C设备驱动,I2C总线驱动概况,Linux下的I2C驱动架构有相当的复杂度,主要由I2C核心、I2C总线驱动以及I

14、2C设备驱动三个部分组成。algos:包含了一些I2C总线适配器的algorithm实现。busses:包含了一些I2C总线的驱动,例如AT91的i2c-at91.c。chips:包含了一些I2C设备的驱动,例如Dallas公司的DS1682实时钟芯片。i2c-boardinfo.c:包含了一些板级信息。:实现了I2C核心的功能以及/proc/bus/i2c*接口。i2c-dev.c:这是一个通用的驱动,基本上大多数I2C驱动都可以通过调用它操作。,关键数据结构,i2c_adapteri2c_algorithmi2c_driveri2c_cflient,i2c_adapter,struct i

15、2c_adapter struct module*owner;/*所属模块*/unsigned int id;unsigned int class;/*用来允许探测的类*/const struct i2c_algorithm*algo;/*I2C algorithm结构体指针*/void*algo_data;/*algorithm所需数据*/*client注册和注销时调用*/int(*client_register)(struct i2c_client*)_deprecated;int(*client_unregister)(struct i2c_client*)_deprecated;int

16、 timeout;/*超时限制*/int retries;/*重试次数*/struct device dev;/*适配器设备*/int nr;struct list_head clients;/*client链表头*/char name48;/*适配器名称*/struct completion dev_released;,i2c_algorithm,struct i2c_algorithm/I2C传输函数指针int(*master_xfer)(struct i2c_adapter*adap,struct i2c_msg*msgs,int num);/SMBus传输函数指针int(*smbus_

17、xfer)(struct i2c_adapter*adap,u16 addr,unsigned short flags,char read_write,u8 command,int size,union i2c_smbus_data*data);/确定适配器所支持的功能u32(*functionality)(struct i2c_adapter*);struct i2c_msg _u16 addr;/*从设备地址*/_u16 flags;/*标志位*/_u16 len;/*消息长度*/_u8*buf;/*消息内容*/;,i2c_client,struct i2c_client unsigned

18、 short flags;/*标志*/unsigned short addr;/*芯片地址,注意:7位地址存储在低7位*/char nameI2C_NAME_SIZE;/*设备名字*/struct i2c_adapter*adapter;/*依附的i2c_adapter指针*/struct i2c_driver*driver;/*依附的i2c_driver指针*/struct device dev;/*设备结构体*/int irq;struct list_head list;/*链表头*/struct list_head detected;struct completion released;

19、/*用于同步*/;,i2c_driver,struct i2c_driver int id;/*唯一的驱动id*/unsigned int class;int(*attach_adapter)(struct i2c_adapter*);/*适配器添加函数(旧式)*/int(*detach_adapter)(struct i2c_adapter*);/*适配器删除函数(旧式)*/int(*detach_client)(struct i2c_client*)_deprecated;/*设备删除函数(旧式)*/int(*probe)(struct i2c_client*,const struct i

20、2c_device_id*);/*设备添加函数(新式)*/int(*remove)(struct i2c_client*);/*设备删除函数(新式)*/void(*shutdown)(struct i2c_client*);/*设备关闭函数*/int(*suspend)(struct i2c_client*,pm_message_t mesg);/*设备挂起函数*/int(*resume)(struct i2c_client*);/*设备恢复函数*/int(*command)(struct i2c_client*client,unsigned int cmd,void*arg);/*类似ioc

21、tl*/struct device_driver driver;/*设备驱动结构体*/const struct i2c_device_id*id_table;/*此驱动支持的I2C设备列表*/int(*detect)(struct i2c_client*,int kind,struct i2c_board_info*);/*检测函数*/const struct i2c_client_address_data*address_data;struct list_head clients;/*链表头*/;,I2C核心,提供了一套接口函数,允许一个I2C adapter、I2C driver和I2C

22、client在初始化时在I2C Core中进行注册,以及在退出时进行注销。int i2c_add_adapter(struct i2c_adapter*adapter);int i2c_del_adapter(struct i2c_adapter*adapter);int i2c_register_driver(struct module*owner,struct i2c_driver*driver);void i2c_del_driver(struct i2c_driver*driver);int i2c_attach_client(struct i2c_client*);int i2c_d

23、etach_client(struct i2c_client*);int i2c_transfer(struct i2c_adapter*adap,struct i2c_msg*msgs,int num);int i2c_master_send(struct i2c_client*client,const char*buf,int count);int i2c_master_recv(struct i2c_client*client,char*buf,int count);,I2C总线驱动,I2C总线驱动的任务,是为系统中各个I2C总线增加相应的读写方法。I2C总线驱动模块的加载函数负责初始化

24、I2C适配器所要使用的硬件资源,例如申请I/O地址、中断号等,然后通过i2c_add_adapter()函数注册i2c_adapter结构体,此结构体的成员函数指针已经被相应的具体实现函数初始化。当I2C总线驱动模块被卸载时,卸载函数需要释放I2C适配器所占用的硬件资源,然后通过i2c_del_adapter()函数注销i2c_adapter结构体。针对特定的I2C适配器,还需要实现适合其硬件特性的通信方法,即实现i2c_algorithm结构体。主要是实现其中的master_xfer()函数和functionality()函数。,I2C设备驱动(1),与I2C总线驱动对应的是I2C设备驱动,

25、I2C只有总线驱动是不够的,必须有设备才能正常工作。I2C设备驱动也分成两个模块,它们分别是i2c_driver和i2c_client结构体。drivers/i2c/chips目录下已经包含了部分设备的设备驱动代码,负责相应从设备的注册。i2c-dev.c文件中提供了一个通用的I2C设备驱动程序,实现了字符设备的文件操作接口,对设备的具体访问是通过I2C适配器来实现的。构造一个针对I2C核心层接口的数据结构,即i2c_driver结构体,通过接口函数向 I2C核心注册一个I2C设备驱动。同时构造一个对用户层接口的数据结构,并通过接口函数向内核注册一个主设备号为89的字符设备。,I2C设备驱动(

26、2),该文件提供了用户层对I2C设备的访问,包括 open、release、read、write、ioctl等常规文件操作,应用程序可以通过open函数打开 I2C的设备文件,通过ioctl函数设定要访问从设备的地址,然后就可以通过read和write函数完成对I2C设备的读写操作。i2c-dev.c中提供的i2cdev_read()和 i2cdev_write()函数分别实现了用户空间的read和write操作,这两个函数又分别会调用I2C核心的i2c_master_recv()和 i2c_master_send()函数来构造一条I2C消息,并且最终调用i2c_algorithm提供的函数接口来完成消息的传输。,Thanks!,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号