Linux驱动程序设备,Linux设备驱动程序

《Linux设备驱动程序》由会员分享,可在线阅读,更多相关《Linux设备驱动程序(39页珍藏版)》请在人人文库网上搜索。

1、Linux设备驱动程序,内容,设备分类 设备驱动程序的框架 字符型设备 网络设备 文件系统 User Space File System USB设备 FrameBuffer例子和使用 Debug原理和Debug方法 常用设备/fb/ram/loopback/zero,设备驱动程序的任务,设备初始化 硬件操作和管理 外部硬件和内核空间的数据传递 内核空间和用户空间的数据传递,设备驱动程序的功能,外部硬件,设备驱动程序,用户程序,存储缓冲,用户空间,内核空间,用户态程序 vs 内核态程序,用户程序 权限受限 虚拟运行环境 逻辑地址 关键资源访问受监管 函数调用由用户控制,内核程序 最高权限 实际的。

2、运行环境 物理地址 可访问所有资源 函数由内核直接调用 可以运行驱动程序,设备操作和管理能运行在用户态吗?,地址映射与物理地址访问,物理地址空间,用户进程1,用户进程2,用户进程3,虚拟地址映射,用户利用指针访问的是虚地址,不是物理地址,IO设备的物理地址可能是用户进程不可触及的,虚拟地址映射,虚拟地址映射,直接访问内核内存(/dev/kmem),kmfd=open(/dev/kmem,O_RDONLY);lseek(kmfd,offset,SEEK_SET);read(kmfd,byteArray,byteArrayLen);close(kmfd);,直接访问内核地址(内核态的虚地址) 一般。

3、内核地址起始于0 xC0000000,直接访问物理地址(/dev/mem),mem_fd=open(/dev/mem,O_RDONLY);b=mmap(0, 0 x10000, PROT_READ|PROT_WRITE,MAP_SHARED, mem_fd,0 xA0000) close(memfd);,0 xA0000,0 xB0000,Pointer b,mmap将文件中的数据映射成数组 这里是将物理内存(由特殊文件/dev/mem访问)映射成指针b指向的数组。 注意,指针b的值不一定是0 xA0000,它是和物理地址0 xA0000对应的用户态的虚拟地址 Linux中/dev/mem主要。

4、是用于设备内存的访问(比如显卡内存),而不是普通存储器,直接访问IO端口(/dev/port),port_fd=open(/dev/port, O_RDWR);lseek(port_fd,port_addr,SEEK_SET);read(port_fd,); write(port_fd,); close(port_fd);,注意:不能用fopen/fread/fwrite/fclose因为它们有数据缓冲,对读写操作不是立即完成的,outb()/outw()/inb()/inw()函数,#include #include #include #define BASEPORT 0 x378 / pr。

5、inter int main() ioperm(BASEPORT, 3, 1);/ get access permission outb(0, BASEPORT); usleep(100000); printf(status: %dn, inb(BASEPORT + 1); ioperm(BASEPORT, 3, 0);/ give up exit(0); ,ioperm(from,num,turn_on) 用ioperm申请的操作端口地址在0 x0000 x3FF,利用iopl()可以申请所有的端口地址 必须以root运行 用 “gcc -02 o xxx.elf xxx.c” 编译,out。

6、b(value, port); inb(port); / 8-bit outw(value, port); inw(port); / 16-bit 访问时间大约1us,设备驱动程序内访问设备地址,设备驱动程序可以通过指针访问设备地址 设备驱动程序接触到的还是虚拟地址,但对于外界设备有固定的设备地址映射(设备的地址在移植Linux时候确定),物理内存地址空间,设备驱动程序,虚拟地址映射,设备地址空间,设备地址映射,设备驱动程序,虚拟地址映射,设备地址映射,直接访问IO端口 vs 设备驱动程序,IO直接访问 用户态 程序编写/调试简单 查询模式,响应慢 设备共享管理困难,设备驱动访问 核心态 编程。

7、调试困难 可用中断模式访问、快 设备共享管理简单(由内核帮助完成),设备分类,字符设备 鼠标、串口、游戏杆 块设备 磁盘、打印机 网络设备 由BSD Socket访问,字符设备 vs 块设备,字符设备 字符设备发出读/写请求时,对应的硬件I/O一般立即发生。 数据缓冲可有可无 ADC/DAC、按钮、LED、传感器等,块设备 利用一块系统内存作缓冲区,一般读写由缓冲区直接提供,尽量减少IO操作 针对磁盘等慢速设备,可装卸的设备驱动程序和静态连接到内核的设备驱动程序,静态连接到内核的设备驱动程序 修改配置文件、重新编译和安装内核 可装卸的设备驱动程序 insmod装载 rmmod卸载 lsmod查。

8、询,Linux对硬件设备的抽象,设备文件 Open/Close/Read/Write 例子 /dev/mouse /dev/lp0,驱动程序与设备文件,设备驱动程序,设备 文件,用mknod命令创建,用insmod命令安装, 或直接编译到内核中,用户程序,用open/read/write/close等命令访问,通过主设备号找到设备驱动,驱动程序代码结构,驱动程序注册与注销,设备文件的操作函数 (*open)() (*write)() (*flush)() (*llseek)() ,中断服务程序,LED设备驱动程序的例子,CPU,struct file_operations LED_fops =。

9、 read: LED_read, write: LED_write, open: LED_open, release: LED_release, ; int LED_init_module(void) SET_MODULE_OWNER(,程序列表 (1),程序列表 (2),int LED_open(struct inode *inode, struct file *filp) printk(LED_open()n); MOD_INC_USE_COUNT; return 0; int LED_release(struct inode *inode, struct file *filp) prin。

10、tk(“LED_release()n“); MOD_DEC_USE_COUNT; return 0;,程序列表 (3),ssize_t LED_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) int i; for (i=0; iLED_on(); else Data-LED_off(); return count;,(*(volatile unsigned int *)(0 xXXXXXXXX) |= MASK;(*(volatile unsigned int *)(0 xXXXXXXXX) ,#ifndef _。

11、_KERNEL__ #define __KERNEL__#endif#ifndef MODULE #define MODULE#endif#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_AUTHOR(Rendong Ying);int LED_major, LED_status;,程序列表 (4),头文件,程。

12、序编译 (Makefile),CC = arm-elf-linux-gcc LD = arm-elf-linux-ld INCLUDE = /usr/local/src/bspLinux/include LIB_INC = /usr/local/lib/gcc-lib/arm-elf-linux/2.95.3/include CFLAGS = -O6 -Wall -DCONFIG_KERNELD -DMODULE -D__KERNEL__ -DLinux -nostdinc -I- -I . -I$(INCLUDE) -idirafter $(LIB_INC) LED.o: LED.c $(C。

13、C) $(CFLAGS) -c LED.c clean: rm -f LED.o,生成o文件,设备装载和设备文件建立,chmod +x /tmp/LED.o /sbin/insmod -f ./LED.o cat /proc/devices得到装入内核的主设备号 mknod /dev/Lamp c Num1 Num2 Num1为主设备号Num2为次设备号,强制安装,忽略版本检查,设备的测试和使用,命令行 echo 8 /proc/sys/kernel/printk cat /dev/Lamp cat /dev/Lamp 程序void main() int fd=open(“/dev/Lamp,。

14、 O_RDWR); write(fd, ,开启printk,也可以从/var/log/messages看printk的记录,设备卸载,/sbin/rmmod LEDrm -f /dev/Lamp,Function of MOD_INC_USE_COUNT; MOD_DEC_USE_COUNT;,复杂的设备驱动程序,驱动程序注册与注销 (注册/注销 设备、中断),设备文件的操作函数 (*open)() (*write)() (*flush)() (*llseek)() ,中断服务程序,内核数据 缓冲区,用户数 据空间,复杂设备驱动程序的例子(USB Device),中断资源申请和释放 if (r。

15、equest_irq(USB_INTR_SOURCE1, usb_ep1_int, SA_INTERRUPT, USB EP1, 0) 0) printk(Int. req. failed !n); free_irq(USB_INTR_SOURCE0, 0);,cat /proc/interrupts,中断服务程序,没有返回参数 简短快速 void usb_ep1_int(int irq, void *dev_id, struct pt_regs *regs) /,数据接收中断服务程序,void usb_ep1_int(int irq, void *dev_id, struct pt_regs。

16、 *regs) read_data_from_hardware_FIFO(); put_data_into_data_buffer(); ,数据发送中断服务程序,void usb_ep2_int(int irq, void *dev_id, struct pt_regs *regs) read_data_from_buffer(); send_data_hardware_FIFO (); ,设备文件接口函数(read),ssize_t usb_ep1_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) if (dat。

17、a_buffer_empty() return 0; else copy_data_to_user_space(); return data_copyed;,copy_to_user(user_buf, device_driver_buf, size);,设备文件接口函数(read, blocking mode),ssize_t usb_ep1_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) while(device_driver_buf_empty() if (wait_event_interruptible(。

18、q_ep2, device_driver_buf_not_empty) return -ERESTARTSYS; copy_data_to_user_space(); return data_copyed;,wait_queue_head_t rq_EP2;init_waitqueue_head(,设备文件接口函数(write),ssize_t usb_ep2_write (struct file *filp, char *buf, size_t count, loff_t *f_pos) if (data_buffer_full() return 0; else copy_data_to_d。

19、evice_driver_buf(); if (no_transmission_now) send_1st_data(); return data_copyed;,copy_from_user(device_driver_buf, user_buf, size);,内存申请,malloc ? X kmalloc kfree vmalloc vfree,禁止设备打开多次,int LED_flag;int LED_init_module(void) LED_flag=0; int LED_open(struct inode *inode, struct file *filp) if (LED_fl。

20、ag=0) LED_flag=1; MOD_INC_USE_COUNT; return 0; else return -ENODEV;int LED_release(struct inode *inode, struct file *filp) LED_flag=0; MOD_DEC_USE_COUNT; return 0;,同一设备驱动管理几个接口,Serial Port Device Driver,UART 0,UART 0,应用程序,同一设备驱动管理几个接口,int dev_open(struct inode *inode, struct file *filp) int minor = MINOR(inode-i_rdev); filp-private_data=sub_dev_datminor; ssize_t dev_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) switch(*(filp-private_data)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值