嵌入式设备驱动
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux抽象了对硬件的处理,所有的硬件 设备都可以作为普通文件一样来看待 可以使用和操作文件相同的、标准的系统 调用接口来完成打开、关闭、读写和I/O 控制操作 对用户来说,设备文件与普通文件并无区 别
5
1.3 主设备号和次设备号
主设备号:标识该设备的种类,也标识了 该设备所使用的驱动程序 次设备号:标识使用同一设备驱动程序的 不同硬件设备 所有已经注册(即已经加载了驱动程序) 的硬件设备的主设备号可以从 /proc/devices文件中得到
嵌入式设备驱动
陈文智 wzchen@ 浙江大学计算机学院 2005年4月
1
提纲
1、Linux下设备驱动程序简介 2、设备驱动程序结构 3、设备驱动实验
实验一:编写一个简单的驱动程序 实验二:设计和实现一个KED&LED驱动程序 实验三:静态编译驱动程序,连接到内核 实验四:使用中断方式的驱动程序设计
8
2、设备驱动程序结构
Linux的设备驱动程序与外界的接口可以分成三 部分:
与操作系统内核的接口 与系统引导的接口 与设备的接口
Linux设备驱动程序的代码结构大致可以分为如 下几个部分:
驱动程序的注册与注销、设备的打开与释放、设备 的读写操作、设备的控制操作、设备的中断和轮询 处理。
9
2.1驱动程序的注册与注销
wzchencadzjueducn浙江大学计算机学院2005年4月系统调用是操作系统内核和应用程序之间的接口设备驱动程序是操作系统内核和机器硬件之间的接口linux设备驱动的特点是可以以模块的形式加载各种设备类型因为嵌入式设备往往具有大量的独有外设开发人员需要把很多精力放在设备驱动方11linux设备的分类12linux设备文件linux抽象了对硬件的处理所有的硬件设备都可以作为普通文件一样来看待可以使用和操作文件相同的标准的系统调用接口来完成打开关闭读写和io控制操作13主设备号和次设备号主设备号
注:这种结构的声明方法是一种标记化格式声 明,便于移植。
18
实验一:编写简单的驱动程序(4)
xsbase_open()和xsbase_release()
static int xsbase_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; printk("This chrdev is opened!\n"); return 0; } static int xsbase_release(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; printk("this chrdev is released!\n"); return 0; }
注册
register_chrdev( );//在~fs/devices.c register_blkdev( );//在~fs/block_dev.c
注销
unregister_chrdev( ) unregister_blkdev( )
10
2.2 打开、释放、读、写、控制等
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, 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 file *, 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 *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*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 long, unsigned long, unsigned long); };
14
3、设备驱动试验
实验一:编写一个简单的驱动程序 实验二:设计和实现一个KED&LED实验 实验三:动态加载和静态编译驱动到内核 实验四:使用中断方式的驱动程序设计
15
实验一:编写简单的驱动程序(1)
1) 任务: 在XSBase开发板上编写一个简单的字符 设备驱动程序。该字符设备具备4个基本 操作:xsbase_open()、xsbase_write()、 xsbase_read() 、xsbase_release(),实 现向这个新建的字符设备先写入一些数 据,然后再从这个设备中读取这些数据。
编写cleanup_module()
…… unregister_chrdev(xsbase_major, "xsbase"); ……
22
实验一:编写简单的驱动程序(8)
4)驱动安装过程
新建xsbase.c文件,实现主要数据结构和函 数接口。 编译生成xsbase.o
$ arm-linux-gcc xsbase.c –I /usr/src/xscale-linux/include –c xsbase.c –D__KERNEL__ -DMODULE
11
Linux内核将通过file_operations结构访问 驱动程序提供的函数 字符设备的读写直接使用函数read( )和 write( ) 块设备需要调用函数block_read( )和 block_write( ) ioctl( )的用法与具体设备密切关联,因此 需要根据设备的实际情况进行具体分析
20
实验一:编写简单的驱动程序(6)
xsbase_write()
static ssize_t xsbase_write( struct file *file, const char *buffer, size_t count, loff_t *f_pos) { if(count < 0) return -EINVAL; kfree(data); data = (char *)kmalloc(sizeof(char)*(count+1), GFP_KERNEL); if(!data) return -ENOMEM; copy_from_user(data, buffer, count+1); return count; }
2
1、Linux下设备驱动程序简介
系统调用是操作系统内核和应用程序之间 的接口 设备驱动程序是操作系统内核和机器硬件 之间的接口 Linux设备驱动的特点是可以以模块的形 式加载各种设备类型 因为嵌入式设备往往具有大量的独有外 设,开发人员需要把很多精力放在设备驱 动方面
3
1.1 Linux设备的分类
[root@wzchent]# mknod /dev/lp0 c 6 0
6
1.4 Linux设备驱动代码的分布
~/block ~/char ~/cdrom ~/pci ~/scsi ~/net ~/sound 注:IDE接口的CD驱动位于drivers/block/ide-cd.c 中,而SCSI CD驱动位于drivers/scsi/scsi.c中
7
1.5 Linux设备驱动程序的特点
设备驱动是内核的一部分,影响内核稳定 为内核或其从属子系统提供一个标准接口 使用标准的内核服务如内存分配、中断和等待 队列等 大多数Linux设备驱动可以动态可加载 Linux设备驱动程序可配置 驱动程序维护其控制的设备,该设备即使不存 在也不影响系统的运行,此时设备驱动只是占 用少量系统内存,不会对系统造成什么危害
21
实验一:编写简单的驱动程序(7)
3)模块加载:是两种将驱动加入内核的方式之一
编写init_module()
…… res = register_chrdev(0, "xsbase", &chr_fops); …… if(xsbase_major == 0) xsbase_major = res;
创建一个xsbase.c文件,其中包含一些:编写简单的驱动程序(3)
主要接口函数
file_operations{ }结构的实例
static struct file_operations chr_fops = { read: xsbase_read, write: xsbase_write, open: xsbase_open, release: xsbase_release, };
25
实验二:编写KED&LED驱动(2)
#define EXT_KEY_CS EXT_PORT2 #define EXT_LED_CS EXT_PORT3 void led_off_on() { int i; EXT_LED_CS = 0xff; for(i =0 ; i<8;++i) { EXT_LED_CS = ~((1 << i) & 0xff); udelay(30000); } EXT_LED_CS = 0xff; }
12
2.3 设备的轮询和中断处理
轮询
内核定期对设备的状态进行查询 消耗不少的内核资源 如果设备驱动被连接进入内核,这时使用轮询方式 将会带来灾难性的后果
中断
设备驱动向内核注册其使用的中断 内核负责把硬件产生的中断传递给相应的设备驱动 设备驱动在其中断处理过程中做得越少越好
13
问题:
如何查看设备驱动所对应的中断号及类型 ?
16
实验一:编写简单的驱动程序(2)
2)主要数据结构和全局变量
系统~fs/devices.c的struc device_struct结构
struct device_struct { const char * name; struct file_operations * fops; }; static struct device_struct chrdevs[MAX_CHRDEV];
把目标文件加载到内核
在Minicom中使用ZMODEM协议发送文件 执行 $ insmod –f xsbase.o
23
实验一:编写简单的驱动程序(9)
创建一个设备文件
$ mknod /dev/xsbase c major minor
测试 OVER
24
实验二:编写KED&LED驱动(1)
在这个实验中,通过设计和实现一个 KED&LED驱动程序,来控制目标板上的 一组LED灯,在安装完驱动后,运行测试 程序,就能点亮LED灯。
字符设备
以字节为单位逐个进行I/O操作 字符设备中的缓存是可有可无 不支持随机访问 如串口设备/dev/cua0和/dev/cua1
块设备
块设备的存取是通过buffer、cache来进行 可以进行随机访问 例如IDE硬盘设备/dev/hda 可以支持可安装文件系统
网络设备
通过BSD套接口访问
4
1.2 Linux设备文件
19
实验一:编写简单的驱动程序(5)
xsbase_read()
static ssize_t xsbase_read(struct file *file, char *buf, size_t count, loff_t *f_pos) { int len; if(count < 0) return -EINVAL; len = strlen(data); if(len < count) count = len; copy_to_user(buf, data, count+1); return count; }
5
1.3 主设备号和次设备号
主设备号:标识该设备的种类,也标识了 该设备所使用的驱动程序 次设备号:标识使用同一设备驱动程序的 不同硬件设备 所有已经注册(即已经加载了驱动程序) 的硬件设备的主设备号可以从 /proc/devices文件中得到
嵌入式设备驱动
陈文智 wzchen@ 浙江大学计算机学院 2005年4月
1
提纲
1、Linux下设备驱动程序简介 2、设备驱动程序结构 3、设备驱动实验
实验一:编写一个简单的驱动程序 实验二:设计和实现一个KED&LED驱动程序 实验三:静态编译驱动程序,连接到内核 实验四:使用中断方式的驱动程序设计
8
2、设备驱动程序结构
Linux的设备驱动程序与外界的接口可以分成三 部分:
与操作系统内核的接口 与系统引导的接口 与设备的接口
Linux设备驱动程序的代码结构大致可以分为如 下几个部分:
驱动程序的注册与注销、设备的打开与释放、设备 的读写操作、设备的控制操作、设备的中断和轮询 处理。
9
2.1驱动程序的注册与注销
wzchencadzjueducn浙江大学计算机学院2005年4月系统调用是操作系统内核和应用程序之间的接口设备驱动程序是操作系统内核和机器硬件之间的接口linux设备驱动的特点是可以以模块的形式加载各种设备类型因为嵌入式设备往往具有大量的独有外设开发人员需要把很多精力放在设备驱动方11linux设备的分类12linux设备文件linux抽象了对硬件的处理所有的硬件设备都可以作为普通文件一样来看待可以使用和操作文件相同的标准的系统调用接口来完成打开关闭读写和io控制操作13主设备号和次设备号主设备号
注:这种结构的声明方法是一种标记化格式声 明,便于移植。
18
实验一:编写简单的驱动程序(4)
xsbase_open()和xsbase_release()
static int xsbase_open(struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; printk("This chrdev is opened!\n"); return 0; } static int xsbase_release(struct inode *inode, struct file *file) { MOD_DEC_USE_COUNT; printk("this chrdev is released!\n"); return 0; }
注册
register_chrdev( );//在~fs/devices.c register_blkdev( );//在~fs/block_dev.c
注销
unregister_chrdev( ) unregister_blkdev( )
10
2.2 打开、释放、读、写、控制等
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, 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 file *, 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 *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*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 long, unsigned long, unsigned long); };
14
3、设备驱动试验
实验一:编写一个简单的驱动程序 实验二:设计和实现一个KED&LED实验 实验三:动态加载和静态编译驱动到内核 实验四:使用中断方式的驱动程序设计
15
实验一:编写简单的驱动程序(1)
1) 任务: 在XSBase开发板上编写一个简单的字符 设备驱动程序。该字符设备具备4个基本 操作:xsbase_open()、xsbase_write()、 xsbase_read() 、xsbase_release(),实 现向这个新建的字符设备先写入一些数 据,然后再从这个设备中读取这些数据。
编写cleanup_module()
…… unregister_chrdev(xsbase_major, "xsbase"); ……
22
实验一:编写简单的驱动程序(8)
4)驱动安装过程
新建xsbase.c文件,实现主要数据结构和函 数接口。 编译生成xsbase.o
$ arm-linux-gcc xsbase.c –I /usr/src/xscale-linux/include –c xsbase.c –D__KERNEL__ -DMODULE
11
Linux内核将通过file_operations结构访问 驱动程序提供的函数 字符设备的读写直接使用函数read( )和 write( ) 块设备需要调用函数block_read( )和 block_write( ) ioctl( )的用法与具体设备密切关联,因此 需要根据设备的实际情况进行具体分析
20
实验一:编写简单的驱动程序(6)
xsbase_write()
static ssize_t xsbase_write( struct file *file, const char *buffer, size_t count, loff_t *f_pos) { if(count < 0) return -EINVAL; kfree(data); data = (char *)kmalloc(sizeof(char)*(count+1), GFP_KERNEL); if(!data) return -ENOMEM; copy_from_user(data, buffer, count+1); return count; }
2
1、Linux下设备驱动程序简介
系统调用是操作系统内核和应用程序之间 的接口 设备驱动程序是操作系统内核和机器硬件 之间的接口 Linux设备驱动的特点是可以以模块的形 式加载各种设备类型 因为嵌入式设备往往具有大量的独有外 设,开发人员需要把很多精力放在设备驱 动方面
3
1.1 Linux设备的分类
[root@wzchent]# mknod /dev/lp0 c 6 0
6
1.4 Linux设备驱动代码的分布
~/block ~/char ~/cdrom ~/pci ~/scsi ~/net ~/sound 注:IDE接口的CD驱动位于drivers/block/ide-cd.c 中,而SCSI CD驱动位于drivers/scsi/scsi.c中
7
1.5 Linux设备驱动程序的特点
设备驱动是内核的一部分,影响内核稳定 为内核或其从属子系统提供一个标准接口 使用标准的内核服务如内存分配、中断和等待 队列等 大多数Linux设备驱动可以动态可加载 Linux设备驱动程序可配置 驱动程序维护其控制的设备,该设备即使不存 在也不影响系统的运行,此时设备驱动只是占 用少量系统内存,不会对系统造成什么危害
21
实验一:编写简单的驱动程序(7)
3)模块加载:是两种将驱动加入内核的方式之一
编写init_module()
…… res = register_chrdev(0, "xsbase", &chr_fops); …… if(xsbase_major == 0) xsbase_major = res;
创建一个xsbase.c文件,其中包含一些:编写简单的驱动程序(3)
主要接口函数
file_operations{ }结构的实例
static struct file_operations chr_fops = { read: xsbase_read, write: xsbase_write, open: xsbase_open, release: xsbase_release, };
25
实验二:编写KED&LED驱动(2)
#define EXT_KEY_CS EXT_PORT2 #define EXT_LED_CS EXT_PORT3 void led_off_on() { int i; EXT_LED_CS = 0xff; for(i =0 ; i<8;++i) { EXT_LED_CS = ~((1 << i) & 0xff); udelay(30000); } EXT_LED_CS = 0xff; }
12
2.3 设备的轮询和中断处理
轮询
内核定期对设备的状态进行查询 消耗不少的内核资源 如果设备驱动被连接进入内核,这时使用轮询方式 将会带来灾难性的后果
中断
设备驱动向内核注册其使用的中断 内核负责把硬件产生的中断传递给相应的设备驱动 设备驱动在其中断处理过程中做得越少越好
13
问题:
如何查看设备驱动所对应的中断号及类型 ?
16
实验一:编写简单的驱动程序(2)
2)主要数据结构和全局变量
系统~fs/devices.c的struc device_struct结构
struct device_struct { const char * name; struct file_operations * fops; }; static struct device_struct chrdevs[MAX_CHRDEV];
把目标文件加载到内核
在Minicom中使用ZMODEM协议发送文件 执行 $ insmod –f xsbase.o
23
实验一:编写简单的驱动程序(9)
创建一个设备文件
$ mknod /dev/xsbase c major minor
测试 OVER
24
实验二:编写KED&LED驱动(1)
在这个实验中,通过设计和实现一个 KED&LED驱动程序,来控制目标板上的 一组LED灯,在安装完驱动后,运行测试 程序,就能点亮LED灯。
字符设备
以字节为单位逐个进行I/O操作 字符设备中的缓存是可有可无 不支持随机访问 如串口设备/dev/cua0和/dev/cua1
块设备
块设备的存取是通过buffer、cache来进行 可以进行随机访问 例如IDE硬盘设备/dev/hda 可以支持可安装文件系统
网络设备
通过BSD套接口访问
4
1.2 Linux设备文件
19
实验一:编写简单的驱动程序(5)
xsbase_read()
static ssize_t xsbase_read(struct file *file, char *buf, size_t count, loff_t *f_pos) { int len; if(count < 0) return -EINVAL; len = strlen(data); if(len < count) count = len; copy_to_user(buf, data, count+1); return count; }