资源预览内容
第1页 / 共28页
第2页 / 共28页
第3页 / 共28页
第4页 / 共28页
第5页 / 共28页
第6页 / 共28页
第7页 / 共28页
第8页 / 共28页
第9页 / 共28页
第10页 / 共28页
亲,该文档总共28页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
嵌入式系统原理及应用教程主讲内容第8章 嵌入式系统Boot Loader技术第9章 嵌入式Linux操作系统移植第10章 嵌入式Linux设备驱动程序开发第11章 嵌入式Linux应用程序设计10.1 嵌入式Linux驱动程序开发基础10.1 嵌入式Linux驱动程序开发基础10.1.1 嵌入式Linux设备驱动程序分类l静态加载的驱动程序l动态加载的驱动程序Linux将设备按照功能特性划分为三种类型:字符设 备,块设备和网络设备。 10.1.2 最简单的内核模块 1helloworld模块源代码 2模块的编译 3模块的加载和卸载10.1 嵌入式Linux驱动程序开发基础10.1 嵌入式Linux驱动程序开发基础10.2 嵌入式Linux设备驱动重要技术 10.2.1 内存与I/O端口(1)内核空间和用户空间 (2)内核中内存分配内核中获取内存的几种方式如下。 通过伙伴算法分配大片物理内存 通过slab缓冲区分配小片物理内存 非连续内存区分配 高端内存映射 固定线性地址映射10.1 嵌入式Linux驱动程序开发基础(3)I/O端口 根据CPU体系结构的不同,CPU对IO端口的编址方式 有两种:I/O映射方式(I/O-mapped)和内存映射方 式(Memory-mapped)。下面主要讨论一下内存映射方式访问I/O端口的方法 ,我们称之为I/O内存操作。l I/O 内存区必须在使用前分配l I/O内存映射 l 访问I/O内存l 映射到用户空间 10.1 嵌入式Linux驱动程序开发基础10.1 嵌入式Linux驱动程序开发基础10.2.2 同步机制Linux内核中包含的同步机制包括:原子操作、信号量(semaphore)、读写信号量(rw_semaphore)、自旋锁(spinlock)、大内核锁(Big Kernel Lock,BKL)、读写锁(rwlock)、读拷贝更新(Read-Copy Update,RCU)和seqlock(顺序锁)等。10.1 嵌入式Linux驱动程序开发基础1.原子操作原子操作主要用于实现资源计数,很多引用计数(refcnt)就是 通过原子操作实现的。 原子类型定义如下: typedef struct volatile int counter; atomic_t;原子操作通常用于实现资源的引用计数 2.信号量信号量在创建时需要设置一个初始值. 3.读写信号量 读写信号量有两种实现:l一种是通用的,不依赖于硬件架构 l 一种是架构相关的10.1 嵌入式Linux驱动程序开发基础读写信号量的相关API有: DECLARE_RWSEM(name) 该宏声明一个读写信号量name并对其进行初始化。 void init_rwsem(struct rw_semaphore *sem); 该函数对读写信号量sem进行初始化。 void down_read(struct rw_semaphore *sem); 在Linux中,每一个进程都用一个类型为task_t或struct task_struct的结构来描述 10.1 嵌入式Linux驱动程序开发基础4.自旋锁一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。 自旋锁的API有:spin_lock_init(x);10.1 嵌入式Linux驱动程序开发基础10.2.3 阻塞与非阻塞 1.阻塞操作 2.非阻塞操作 10.2.4 时间问题 1.延时操作: (1)长延时。 (2)短延时 2.内核定时器内核提供给驱动许多函数来声明、注册、以及去除内核定时器。 3.工作队列 采用缺省工作者线程来实现工作队列 的API: INIT_WORK(_work, _func, _data)10.1 嵌入式Linux驱动程序开发基础 int schedule_work(struct work_struct *work)int schedule_delayed_work(struct work_struct *work, unsigned long delay)void flush_scheduled_work(void)int cancel_delayed_work(struct work_struct *work) 创建自己的工作者线程和工作队列,API:struct workqueue_struct *create_workqueue(const char *name) int queue_work(struct workqueue_struct *wq, struct work_struct *work) int queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) void flush_workqueue(struct workqueue_struct *wq) void destroy_workqueue(struct workqueue_struct *wq)10.1 嵌入式Linux驱动程序开发基础10.2.5 中断处理在Linux系统里,对中断的处理是属于系统核心部分, 因而如果设别与系统之间以中断方式进行数据交换, 就必须把该设备的驱动程序作为系统核心的一部分。 设备驱动程序通过调用request_irq函数来申请中断, 通过free_irq来释放中断。它们被定义为: #include int request_irq(unsigned int irq, void (*handler)(int irq, void dev_id, struct pt_regs *regs),unsigned long flags,const char *device,void *dev_id); void free_irq(unsigned int irq, void *dev_id);10.1 嵌入式Linux驱动程序开发基础函数的参数如下。 unsigned int irq:请求的中断号。 irqreturn_t (*handler) :安装的中断处理函数指针。 unsigned long flags:中断处理的属性。const char *dev_name:这个传递给request_irq的字串 用 在/proc/interrupts来显示中断的拥有者。void *dev_id:用作共享中断的指针。 10.1 嵌入式Linux驱动程序开发基础10.3 字符设备驱动程序字符设备驱动程序可以分为三个主要组成部分: ,自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和 是否能正常工作。 ,服务于I/O请求的子程序,又称为驱动程序的上半部分。,中断服务子程序,又称为驱动程序的下半部分。 10.3.1 字符设备驱动结构1.主次设备号 :字符设备和块设备通过文件系统中的名子来存取。 主编号标识设备相连的驱动。 次编号被内核用来决定引用哪个设备。 设备编号在驱动程序的内部具有固定的表示方式。 在建立驱动时,需要做的第一件事是获取一个或多个设备编号来使用。 在驱动程序执行的过程中,如果不希望在使用该设备,要及时的将设备编 号释放:10.1 嵌入式Linux驱动程序开发基础2.驱动相关数据结构大部分的基础性的驱动操作包括3个重要的内核数据结构,它 们是file_operations,file,和inode。 (1)文件操作(file_operations) file_operation 结构表示了用户程序怎样对设备进行操作。 这个结构,定义在中,是一个函数指针的集合 struct module *owner。 (2)文件结构 struct file定义于,是设备驱动中第二个最重要的数据结构。 (3)inode 结构 inode 结构由内核在内部用来表示文件。 10.1 嵌入式Linux驱动程序开发基础3.自动配置和初始化 (1)初始化。当驱动程序将被加载的时候,首先会调 用初始函数进行自动配置。 (2)清除处理。 4.中断处理如果需要驱动程序具有中断处理的能力,必须进行中 断申请。 l从request_irq返回给请求函数的返回值是0指示成功, 为负表示错误码。 l中断处理可以在驱动初始化时安装或者在设备第一次 打开时。 l在中断的使用过程中还可以对其进行使能和禁止操作 10.1 嵌入式Linux驱动程序开发基础10.3.2 字符设备驱动实例LED驱动1.LED驱动程序分析本驱动程序文件名为led2440.c 2.驱动模块加入内核l使用命令:cp -f led2440.c /linux-2.6.32.4/drivers/char/ l编辑Kconfig文件:l修改Makefile文件:l配置、编译内核执行make zImage内核映像和驱动程序模块会先后被 编译完毕。将内核下载至开发板;将驱动程序模块加 入到根文件系统后,下载至开发板。这样就可以调用 驱动程序进行演示了。10.1 嵌入式Linux驱动程序开发基础3.LED驱动演示 (1)驱动程序模块加载到内核。进入驱动程序模块所在目录,执行: insmod -f led2440.ko (2)建立设备节点。也就是建立用户程序关联到驱动程序的途径 (3)演示程序。 建立一个LED控制的简单演示程序led2440test 10.1 嵌入式Linux驱动程序开发基础10.4 网络设备驱动程序10.4.1 Linux 网络设备简介 1.Linux网络驱动基础 2.DM9000控制器 10.4.2 网络驱动核心数据结构分成几个方面对其进行介绍 l通用信息l硬件描述信息l协议相关信息l设备操作函数接口10.1 嵌入式Linux驱动程序开发基础10.4.3 网络驱动程序分析1.初始化、清理网络设备网络设备初始化的工作主要是确定硬件设备的存在,以及将硬件设备加载到设备链表中,为网络设备的激活做准备 。需要注意这两个变量:name和owner。 2.打开和关闭网络设备open函数主要用来完成对网络设备中断进行注册、通过配置物理接口初始化设备,以及为发送数据准备队列。10.1 嵌入式Linux驱动程序开发基础3.中断处理网络驱动程序的中断处理函数在网络设备激活时进行注册,主要用于 完成:现场保护及中断屏蔽、读取网络设备寄存器信息及判断中断原 因并处理、恢复中断现场。函数首先需要获得自旋锁,然后将当前的寄存器地址保存下来,以便返回的时候继续进行被打断的作业;接着就是屏蔽所有的中断,读取 中断状态寄存器并清除中断状态寄存器,然后就开始真正的中断处理 了。当发生接收中断时,中断函数调用dm9000_rx()函数。4.sk_buff结构sk_buff的数据成员分为两部分:l一部分是实际在网络中要传输的部分,数据区(Packet date storage);l一部分由内核管理服务于结构链表。 10.1 嵌入式Linux驱动程序开发基础还有一些常用的成员如:sk_buff-tstamp: sk_buff-dev: sk_buff-protocol: 内核提供了一系列用于操作sk_buff数据结构的函数,用于分配、释放、复制、克隆、扩展等功能,下面介绍些常用的。struct sk_buff *alloc_skb(unsigned int len,int priority) struct sk_buff *dev_alloc_skb(unsigned int len)10.1 嵌入式Linux驱动程序开发基础5.数据发送处理6.数据接收处理数据接收的主要工作有:检查接收的到的数据包是否正确;根据数据被长度在内核空间为数据包申请sk_buff;把数据包复制到sk_buff
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号