驱动程序开发基础_第1页
驱动程序开发基础_第2页
驱动程序开发基础_第3页
驱动程序开发基础_第4页
驱动程序开发基础_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1TMCIDDCCIDDC Linux设备驱动程序设备驱动程序开发基础开发基础主讲人主讲人:TonyShen:TonyShen2TMCIDDC2Linux 驱 动 程 序 开 发 基 础课程目标课程目标nLinux设备驱动程序开发简介设备驱动程序开发简介nLinux设备驱动程序结构设备驱动程序结构nLinux设备驱动程序加载方式设备驱动程序加载方式n实验实验:编写一个字符设备驱动程序编写一个字符设备驱动程序(LED或蜂鸣器或蜂鸣器)分别用静态编译分别用静态编译,模块动态加载方法实现加入内核模块动态加载方法实现加入内核3TMCIDDC3Linux 驱 动 程 序 开 发 基 础设备驱动程序设备驱

2、动程序应应用用程程序序驱驱动动程程序序设设备备writereadioctlioctl4TMCIDDC4Linux 驱 动 程 序 开 发 基 础设备驱动程序特点设备驱动程序特点n核心代码:核心代码:设备驱动程序是核心的一部分,像核心中其他的代码一样,出错将导致系统的严重损伤。一个编写不当的设备驱动程序甚至能够使系统崩溃导致文件系统的破坏和数据的丢失;n标准接口:标准接口:设备驱动程序必须为Linux核心或者其从属的子系统提供一个标准的接口;n核心机制:核心机制:设备驱动程序可以使用标准的核心服务比如内存分配、中断发送和等待对列等;n动态可加载:动态可加载:多数的Linux设备驱动程序可以在核心

3、模块发出加载请求时进行加载,同时在不使用设备时进行卸载,这样核心可以有效地利用系统的资源n可配置:可配置:Linux设备驱动属于核心的一部分,用户可以根据自己的需要进行配置来选择适合自己的驱动5TMCIDDC5Linux 驱 动 程 序 开 发 基 础用户态与内核态用户态与内核态nLinux运转在两种模式下,一种是用户态,另一种是内核态。运转在两种模式下,一种是用户态,另一种是内核态。n内核态有较高的权限,可以控制处理器内存的映射和分配方内核态有较高的权限,可以控制处理器内存的映射和分配方式,访问外设空间和处理器状态寄存器,控制中断等。式,访问外设空间和处理器状态寄存器,控制中断等。n用户态只

4、能运行系统上的应用程序。用户态只能运行系统上的应用程序。n驱动程序作为系统内核的一部分,工作在内核态。驱动程序作为系统内核的一部分,工作在内核态。n通过通过get_user put_user copy_from_user copy_to_user等函数实现应用程序和驱动程序之间传送数据(指针)。等函数实现应用程序和驱动程序之间传送数据(指针)。6TMCIDDC6Linux 驱 动 程 序 开 发 基 础Linux设备的分类设备的分类n字符设备字符设备n以字节为单位逐个进行以字节为单位逐个进行I/O操作操作n字符设备中的缓存是可有可无字符设备中的缓存是可有可无n不支持随机访问不支持随机访问n如串

5、口设备如串口设备n块设备块设备n块设备的存取是通过块设备的存取是通过buffer、cache来进行来进行n可以进行随机访问可以进行随机访问n例如例如IDE硬盘设备硬盘设备n可以支持可安装文件系统可以支持可安装文件系统n网络设备网络设备n通过通过BSD套接口访问套接口访问7TMCIDDC7Linux 驱 动 程 序 开 发 基 础设备文件设备文件nLinux抽象了对硬件的处理,所有的硬件设备都可以作为普抽象了对硬件的处理,所有的硬件设备都可以作为普通文件一样来看待通文件一样来看待n可以使用和操作文件相同的、标准的系统调用接口来完成打可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读

6、写和开、关闭、读写和I/O控制操作控制操作n对用户来说,设备文件与普通文件并无区别对用户来说,设备文件与普通文件并无区别n字符设备和块设备是通过文件节点访问的。在字符设备和块设备是通过文件节点访问的。在Linux的文件的文件系统中,可以找到(或者使用系统中,可以找到(或者使用mknod创建)设备对应的文创建)设备对应的文件名,称这种文件为设备文件件名,称这种文件为设备文件。8TMCIDDC8Linux 驱 动 程 序 开 发 基 础设备文件设备文件n命令命令 ls l /dev 可列出系统的设备文件可列出系统的设备文件9TMCIDDC9Linux 驱 动 程 序 开 发 基 础主设备号和次设备

7、号主设备号和次设备号n主设备号:标识该设备的种类,也标识了该设备所使用的驱主设备号:标识该设备的种类,也标识了该设备所使用的驱动程序动程序n主设备号的范围只能是1-255nLinux内核支持动态分配主设备号n次设备号:标识使用同一设备驱动程序的不同硬件设备次设备号:标识使用同一设备驱动程序的不同硬件设备n同一个驱动程序可以管理多个设备,它们依靠次设备号来区同一个驱动程序可以管理多个设备,它们依靠次设备号来区别。次设备号只在驱动程序内部使用,系统内核直接把次设别。次设备号只在驱动程序内部使用,系统内核直接把次设备号传递给驱动程序,由驱动程序去管理。备号传递给驱动程序,由驱动程序去管理。10TMC

8、IDDC10Linux 驱 动 程 序 开 发 基 础设备文件系统设备文件系统nLinux内核自己管理设备文件,完成设备文件节点的创建、内核自己管理设备文件,完成设备文件节点的创建、删除。(删除。(devfs,device file system)n在在linux2.4/2.6内核中,设备文件系统可在配置内核时定制。内核中,设备文件系统可在配置内核时定制。nlinux2.4内核配置层次n File systems -/dev file system supportnlinux2.6内核配置层次 nFile systems -Pseudo file system -/dev file syste

9、m supportn系统驱动程序通过系统驱动程序通过CONFIG_DEVFS_FS宏定义判断系统是宏定义判断系统是否有对设备文件系统的支持。否有对设备文件系统的支持。11TMCIDDC11Linux 驱 动 程 序 开 发 基 础配置设备文件系统配置设备文件系统12TMCIDDC12Linux 驱 动 程 序 开 发 基 础Linux设备驱动程序结构设备驱动程序结构nLinux设备驱动程序的代码结构大致可以分为如下几个部分:设备驱动程序的代码结构大致可以分为如下几个部分:n驱动程序的注册与注销、设备的打开与释放、设备的读写操作、设驱动程序的注册与注销、设备的打开与释放、设备的读写操作、设备的控

10、制操作、设备的中断和轮询处理。备的控制操作、设备的中断和轮询处理。n一个最简单字符驱动程序,由下面一个最简单字符驱动程序,由下面5个函数和个函数和1个结构体就可组成。个结构体就可组成。static int my_open(struct inode * inode, struct file * filp) 设备打开时的操作设备打开时的操作 static int my_release(struct inode * inode, struct file * filp) 设备关闭时的操作设备关闭时的操作 static int my_write(struct file *file, const char

11、 * buffer, size_t count, loff_t * ppos) 设备写入时的操作设备写入时的操作 13TMCIDDC13Linux 驱 动 程 序 开 发 基 础驱动程序结构驱动程序结构static struct file_operations my_fops = 对文件操作结构体成员定义初始值对文件操作结构体成员定义初始值static int _init my_init(void)初始化硬件,注册设备,创建设备节点初始化硬件,注册设备,创建设备节点 static void _exit my_exit(void)删除设备节点,注销设备删除设备节点,注销设备 14TMCIDDC1

12、4Linux 驱 动 程 序 开 发 基 础头文件与系统定义头文件与系统定义#include #include #include #include #include #include #include #include 9200.h“#ifndef _KERNEL_#define _KERNEL_#endif#ifndef MODULE#define MODULE#endif#define LED AT91C_PIO_PB11static AT91PS_SYS AT91_SYS1 = (AT91PS_SYS) AT91C_VA_BASE_SYS;#define DEVICE_NAME = “m

13、y_led”static int Led_Major = 0;#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t Devfs_Led_Dir, Devfs_Led_Raw;#endif15TMCIDDC15Linux 驱 动 程 序 开 发 基 础打开和关闭操作打开和关闭操作nmy_open和和my_release函数会在设备打开和关闭时被调用,其工作很简单,仅函数会在设备打开和关闭时被调用,其工作很简单,仅仅执行两个宏:仅执行两个宏:”MOD_INC_USE_COUNT”,”MOD_DEC_USE_COUNT”。这。这两个宏负责记录(增加或者减少)设备模块

14、被使用的情况,防止当有应用程序两个宏负责记录(增加或者减少)设备模块被使用的情况,防止当有应用程序使用驱动程序时,此模块被意外地卸载。使用驱动程序时,此模块被意外地卸载。static int my_open(struct inode * inode, struct file * filp)MOD_INC_USE_COUNT;return 0; static int my_release(struct inode * inode, struct file * filp MOD_DEC_USE_COUNT return 0; 16TMCIDDC16Linux 驱 动 程 序 开 发 基 础写入操作

15、写入操作static int my_write(struct file *file, const char * buffer, size_t count, loff_t * ppos) char led_status = 0; copy_from_user(&led_status, buffer, sizeof(led_status); if(led_status = 0 x01)/如果应用程序传来的数据是如果应用程序传来的数据是0 x01AT91F_PIOB_SetOutput(LED);/打开打开LED elseAT91F_PIOB_ClearOutput(LED); /关闭关闭L

16、ED return 0;17TMCIDDC17Linux 驱 动 程 序 开 发 基 础文件操作结构体初始化文件操作结构体初始化static struct file_operations my_fops = open: my_open,write: my_write,release:my_release,;18TMCIDDC18Linux 驱 动 程 序 开 发 基 础struct file_operationsstruct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t(*read) (struct fi

17、le *, char *, size_t, loff_t*);ssize_t(*write) (struct file *, const char *, size_t, loff_t*);int(*readdir) (struct file *, void *, filldir_t);unsigned int(*poll) (struct file *, struct poll_table_struct *);int(*ioctl) (struct inode*, struct file *, unsigned int, unsigned long);int(*mmap) (struct fi

18、le *, struct vm_area_struct *);int(*open) (struct inode*, struct file *);int(*flush) (struct file *);int(*release) (struct inode*, struct file *);int(*fsync) (struct file *, struct dentry*, intdatasync);int(*fasync) (int, struct file *, int);int(*lock) (struct file *, int, struct file_lock*);ssize_t

19、(*readv) (struct file *, const struct iovec*, unsigned long, loff_t*);ssize_t(*writev) (struct file *, const struct iovec*, unsigned long, loff_t*);ssize_t(*sendpage) (struct file *, struct page *, int, size_t, loff_t*, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned l

20、ong, unsigned long, unsigned long);文件操作结构体文件操作结构体19TMCIDDC19Linux 驱 动 程 序 开 发 基 础设备初始化设备初始化static int _init my_init(void)/硬件初始化硬件初始化 AT91F_PIOB_Enable(LED);AT91F_PIOB_OutputEnable(LED);/字符设备注册字符设备注册Led_Major = register_chrdev(0, DEVICE_NAME, &my_fops);if (Led_Major 0)printk(DEVICE_NAME cant get

21、major numbern);return Led_Major;/ 创建设备文件创建设备文件#ifdef CONFIG_DEVFS_FS Devfs_Led_Dir = devfs_mk_dir(NULL, led, NULL); Devfs_Led_Raw = devfs_register(Devfs_Led_Dir, 0, DEVFS_FL_DEFAULT, Led_Major, 1, S_IFCHR|S_IRUSR|S_IWUSR,&my_fops, NULL);#endif20TMCIDDC20Linux 驱 动 程 序 开 发 基 础设备注销设备注销static void _

22、exit my_exit(void)/删除设备文件删除设备文件#ifdef CONFIG_DEVFS_FSdevfs_unregister(Devfs_Led_Raw);devfs_unregister(Devfs_Led_Dir);#endif/注销设备注销设备unregister_chrdev(Led_Major, DEVICE_NAME);module_init(my_init); /向向Linux系统记录设备初始化的函数名称系统记录设备初始化的函数名称module_exit(my_exit); /向向Linux系统记录设备退出的函数名称系统记录设备退出的函数名称21TMCIDDC21L

23、inux 驱 动 程 序 开 发 基 础驱动程序编译驱动程序编译nMakefile文件内容文件内容OBJ=io_led.oSOURCE=io_led.cCC=arm-linux-gccCOMP=-Wall -O2 -DMODULE -D_KERNEL_ -I /home/armlinux/linux-2.4.19-rmk7/include c$(OBJ):$(SOURCE)$(CC) $(COMP) $(SOURCE)clean:rm $(OBJ)n运行运行make 命令命令,编译通过后当前目录下就生成名为编译通过后当前目录下就生成名为io_led.o的驱动程序的驱动程序22TMCIDDC22

24、Linux 驱 动 程 序 开 发 基 础驱动程序加载驱动程序加载nLinux内核有内核有2种加载驱动程序的方法种加载驱动程序的方法:nLinux系统启动时系统启动时,通过代码自身加载模块通过代码自身加载模块.这种方式称为静态编译入这种方式称为静态编译入内核内核, 驱动程序开发完毕后一般使用这种方式驱动程序开发完毕后一般使用这种方式.nLinux系统启动后系统启动后,通过通过insmod等命令加载模块等命令加载模块.这种方式称为动态加这种方式称为动态加载载,驱动程序开发调试过程中一般使用这种方式驱动程序开发调试过程中一般使用这种方式.23TMCIDDC23Linux 驱 动 程 序 开 发 基 础模块动态加载模块动态加载n驱动程序模块插入内核驱动程序模块插入内核n查看是否载入查看是否载入,如果载入成功会显示你的设备名称如果载入成功会显示你的设备名称my_ledn从内核移除设备从内核移除设备#insmod io_led.o#cat /proc/devices#rmmod io_led24TMCIDDC

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论