嵌入式linux设备驱动编程

上传人:F****n 文档编号:88016902 上传时间:2019-04-16 格式:PPT 页数:45 大小:825KB
返回 下载 相关 举报
嵌入式linux设备驱动编程_第1页
第1页 / 共45页
嵌入式linux设备驱动编程_第2页
第2页 / 共45页
嵌入式linux设备驱动编程_第3页
第3页 / 共45页
嵌入式linux设备驱动编程_第4页
第4页 / 共45页
嵌入式linux设备驱动编程_第5页
第5页 / 共45页
点击查看更多>>
资源描述

《嵌入式linux设备驱动编程》由会员分享,可在线阅读,更多相关《嵌入式linux设备驱动编程(45页珍藏版)》请在金锄头文库上搜索。

1、嵌入式应用程序设计 第八章 嵌入式Linux设备驱动编程,2,8.1 设备驱动概述 8.2 字符设备驱动编程 8.3 GPIO驱动程序实例 8.4 4*4扫描按键驱动 8.5 小结 8.6 思考与练习,本章课程:,3,8.1.1 Linux设备驱动概述 设备驱动概念 操作系统是通过各种驱动程序来驾驭硬件设备的,它为用户屏蔽了各种各样的设备,驱动硬件是操作系统最基本的功能,并且提供统一的操作方式。设备驱动程序是操作系统最基本的组成部分之一,在Linux内核源程序中也占有60%以上。因此,熟悉驱动的编写是很重要的。 Linux的一个重要特点就是将所有的设备都当做文件进行处理,这一类特殊文件就是设备

2、文件(通常在/dev目录下),这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作,这样就大大方便了对设备的处理。,8.1 设备驱动编程基础,4,8.1.1 Linux设备驱动概述 Linux系统的设备分为三类:字符设备、块设备和网络设备。 字符设备通常指像普通文件或字节流一样,以字节为单位顺序读写的设备, 如并口设备、虚拟控制台等。 块设备通常指一些需要以块为单位随机读写的设备,如IDE硬盘、SCSI硬盘、光驱等。 网络设备通常是指通过网络能够与其他主机进行数据通信的设备,如网卡等。,8.1 设备驱动编程基础,5,8.1.1 Linux设备驱动概述

3、设备驱动程序的特点 内核代码 内核接口 内核机制和服务 可装载 可设置 动态性,8.1 设备驱动编程基础,6,8.1.1 Linux设备驱动概述 设备驱动程序与整个软硬件系统的关系,8.1 设备驱动编程基础,7,8.1.2 Linux内核模块编程 设备驱动和内核模块 Linux设备驱动属于内核的一部分,Linux内核的一个模块可以以两种方式被编译和加载。 直接编译进Linux内核,随同Linux启动时加载; 编译成一个可加载和删除的模块。,8.1 设备驱动编程基础,8,8.1.2 Linux内核模块编程 模块相关命令 Lsmod 列出当前系统中加载的模块 Rmmod 用于将当前模块卸载。 in

4、smod和modprobe 用于加载当前模块,8.1 设备驱动编程基础,9,8.1.2 Linux内核模块编程 Linux内核模块编程 (1)内核模块的程序结构 一个Linux内核模块主要由以下几个部分组成。 模块加载函数(必须) 模块卸载函数(必须) 模块许可证声明(必须 模块参数(可选) 模块导出符号(可选) 模块作者等信息声明(可选),8.1 设备驱动编程基础,10,8.1.2 Linux内核模块编程 Linux内核模块编程 (2)模块加载函数 static int _init initialization_function(void) /* 初始化代码 */ module_init(i

5、nitialization_function);,8.1 设备驱动编程基础,11,8.1.2 Linux内核模块编程 Linux内核模块编程 (3)模块卸载函数 static void _exit cleanup_function(void) /* 释放代码 */ module_exit(cleanup_function); 通常来说,模块卸载函数要完成与模块加载函数相反的功能 若模块加载函数注册XXX,则模块卸载函数应该注销XXX。 若模块加载函数动态申请了内存,则模块卸载函数应释放该内存。 若模块加载函数申请了硬件资源(中断、DMA通道、I/O端口和I/O内存等)的占用,则模块卸载函数应释

6、放这些硬件资源。 若模块加载函数开启了硬件,则卸载函数中一般要关闭硬件。,8.1 设备驱动编程基础,12,8.1.2 Linux内核模块编程 Linux内核模块编程 (4)模块参数 “module_param(参数名,参数类型,参数读/写权限)”为模块定义一个参数 static char *str_param = “Linux Module Program“; static int num_param = 4000; module_param(num_param, int, S_IRUGO); module_param(str_param, charp, S_IRUGO);,8.1 设备驱动编

7、程基础,13,8.1.2 Linux内核模块编程 Linux内核模块编程 (5)导出符号 EXPORT_SYMBOL(符号名); EXPORT_SYMBOL_GPL(符号名); (6)模块声明与描述 MODULE_AUTHOR(author); MODULE_DESCRIPTION(description); MODULE_VERSION(version_string); MODULE_DEVICE_TABLE(table_info); MODULE_ALIAS(alternate_name);,8.1 设备驱动编程基础,14,8.1.2 Linux内核模块编程 Linux内核模块编程 (7)

8、模块的使用计数 Linux 2.4内核中,模块自身通过MOD_INC_USE_COUNT、MOD_DEC_USE_COUNT宏来管理自己被使用的计数。 Linux 2.6内核提供了模块计数管理接口try_module_get( 该函数用于减少模块使用计数。,8.1 设备驱动编程基础,15,8.1.2 Linux内核模块编程 Linux内核模块编程 (8)模块编译 我们可以为HelloWorld模块程序编写一个简单的Makefile,如下所示: obj-m := hello.o 并使用如下命令编译HelloWorld模块,如下所示: $ make -C /usr/src/linux-2.6.15

9、.5/ M=/driver_study/ modules 如果当前处于模块所在的目录,以下命令与上述命令同等: $ make C /usr/src/linux-2.6.15.5 M=$(pwd) modules,8.1 设备驱动编程基础,16,8.1.2 Linux内核模块编程 Linux内核模块编程 (9)模块与GPL 对于自己编写的驱动等内核代码,如果不编译为模块则无法绕开GPL,编译为模块后企业在产品中使用模块。 在内核编译时应该选上“Enable loadable module support”,嵌入式产品一般不需要动态卸载模块,所以“可以卸载模块”不用选,当然选了也没关系,如果有项目

10、被选择“M”,则编译时除了make bzImage以外,也要make modules。 将我们编译的内核模块.ko文件放置在目标文件系统的相关目录中。 产品的文件系统中应该包含了支持新内核的insmod、lsmod、rmmod等工具,由于嵌入式产品中一般不需要建立模块间依赖关系,所以modprobe可以不要,一般也不需要卸载模块,所以rmmod也可以不要。 在使用中用户可使用insmod命令手动加载模块,如insmod xxx.ko。 但是一般而言,产品在启动过程中应该加载模块,在嵌入式Linux的启动过程中,加载企业自己的模块的最简单的方法是修改启动过程的rc脚本,增加insmod /./x

11、xx.ko这样的命令。,8.1 设备驱动编程基础,17,8.1.2 Linux内核模块编程 Linux内核模块编程 内核模块示例,8.1 设备驱动编程基础,18,8.2.1字符设备驱动编写流程,8.2 字符设备驱动编程,19,8.2.2 重要数据结构 file_operations struct file_operations loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *filp, char *buff, size_t count, loff_t *offp); ssize_t (*w

12、rite) (struct file *filp, const char *buff, size_t count, loff_t *offp); 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

13、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 (*fasync) (int, struct file *, int); int (*check_media_change) (kdev_t dev); int (*revalidate) (kdev_t dev)

14、; int (*lock) (struct file *, int, struct file_lock *); ;,8.2 字符设备驱动编程,20,8.2.2 重要数据结构 struct inode结构提供了关于设备文件/dev/driver(假设此设备名为driver)的信息,file结构提供关于被打开的文件信息,主要用于与文件系统对应的设备驱动程序使用。 struct file mode_t f_mode;/*标识文件是否可读或可写,FMODE_READ或FMODE_WRITE*/ dev_t f_rdev; /* 用于/dev/tty */ off_t f_pos; /* 当前文件位移

15、*/ unsigned short f_flags; /* 文件标志,如O_RDONLY、O_NONBLOCK和O_SYNC */ unsigned short f_count; /* 打开的文件数目 */ unsigned short f_reada; struct inode *f_inode; /*指向inode的结构指针 */ struct file_operations *f_op;/* 文件索引指针 */ ;,8.2 字符设备驱动编程,21,8.2.3设备驱动程序主要组成 1.早期版本的字符设备注册 register_chrdev() unregister_chrdev(),8.2

16、 字符设备驱动编程,22,8.2.3设备驱动程序主要组成 1.早期版本的字符设备注册 unregister_chrdev(),8.2 字符设备驱动编程,23,8.2.3设备驱动程序主要组成 2.设备号相关函数 获取设备号 MAJOR(dev_t dev); /*获得主设备号*/ MINOR(dev_t dev); /*获得次设备号*/ MKDEV(int major, int minor); 设备注册于注销,8.2 字符设备驱动编程,24,8.2.3设备驱动程序主要组成 2.设备号相关函数 获取设备号 MAJOR(dev_t dev); /*获得主设备号*/ MINOR(dev_t dev); /*获得次设备号*/ MKDEV(int major, int minor); 设备注册于注销,8.2 字符设备驱动编程,25,8.2.3设备驱动程序主要组成 3.新版本设备注册,8.2 字符设备驱动编程,26,8.2.3设备驱动程序主要组成 4.打开设备 int (*open) (struct

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > PPT模板库 > PPT素材/模板

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号