ImageVerifierCode 换一换
格式:DOCX , 页数:27 ,大小:24.24KB ,
资源ID:7305516      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7305516.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(linux驱动程序设计方案实例.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

linux驱动程序设计方案实例.docx

1、linux驱动程序设计方案实例封面作者:PanHongliang仅供个人学习AT91SAM9G20驱动程序设计开发环境:Vmware + ubuntu10.04硬件平台:AT91SAM9G20Linux版本:linux2.6.27一:led驱动说明:因为设计的开发板上没有led灯,便通过PC0来演示,通过示波器来观察引脚端的电平变化。1.驱动程序:my_led.c#include #include #include #include #include #include #include #define MY_LED_MAJOR 250 /定义主设备号#define LED_ON 0#defin

2、e LED_OFF 1struct global_dev struct cdev cdev。 /定义设备结构体struct global_dev *global_devp。 /定义一个指向设备结构体的指针static int my_led_open(struct inode *inode, struct file *filp) filp-private_data = global_devp。 return 0。static int my_led_release(struct inode *inode, struct file *file) return 0。static int my_led_

3、ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) switch(cmd) case LED_ON: at91_set_gpio_value(AT91_PIN_PC0, 0)。 /将PC0引脚置低 break。 case LED_OFF: at91_set_gpio_value(AT91_PIN_PC0, 1)。 /将PC1引脚置高 break。 default: printk(no valid cmd input!n)。 break。 return 0。struct file_

4、operations my_led_ctl_ops = .owner = THIS_MODULE, .open = my_led_open, .release = my_led_release, .ioctl = my_led_ioctl,。/*初始化设备结构体*/static void my_led_setup(struct global_dev *dev, int index) int err。 int devno = MKDEV(MY_LED_MAJOR, index)。 cdev_init(&dev-cdev, &my_led_ctl_ops)。 dev-cdev.owner = TH

5、IS_MODULE。 dev-cdev.ops = &my_led_ctl_ops。 err = cdev_add(&dev-cdev, devno, 1)。 if(err) printk(add my led setup failed!n)。static int my_led_init(void) int ret。 dev_t devno = MKDEV(MY_LED_MAJOR, 0)。 /创建设备号 printk(my first driver-led!n)。 at91_set_GPIO_periph(AT91_PIN_PC0, 1)。 at91_set_gpio_output(AT91

6、_PIN_PC0, 1)。 /对PC0引脚的初始化 ret = register_chrdev_region(devno, 1, my_led)。 /申请设备号 if( ret cdev)。 /删除设备 kfree(global_devp)。 /释放内存 unregister_chrdev_region(MKDEV(MY_LED_MAJOR, 0), 1)。 /释放设备号MODULE_LICENSE(MYGPL)。MODULE_AUTHOR(FANY)。module_init(my_led_init)。 /注册设备module_exit(my_led_cleanup)。 /卸载设备2:如何将驱

7、动驱动程序编译成模块在drivers目录下新建led目录,并在该目录下添加Kconfig,Makefile文件。Kconfig:Menu My driver supportConfig Trisate led driver!Help Led driverEndmenu:Makefile:Obj-$(CONFIG_MY_LED) += my_led.o修改linux/drivers目录下的Kconfig,Makefile文件Kconfig:Source drivers/led/KconfigMakefile:Obj-y += my_led/修改体系结构目录arch/arm目录下的Kconfig文

8、件,否则在配置菜单中将无法看到led的配置选项。(如果是在drivers目录下新建一文件夹,并在其中添加驱动程序,必须相应的体系结构目录下添加配置选项)。Kconfig:Source driver/led/Kconfig3.测试程序:my_led_test.c#include #include #include #include #include #define DEVICE_NAME /dev/my_led#define LED_ON 0#define LED_OFF 1int main(void) int fd。 int ret。 int i。 printf(my_led_driver t

9、est!n)。 fd = open(DEVICE_NAME, O_RDONLY)。 if(fd = -1) printf(open device %s error!n, DEVICE_NAME)。 for(i = 0。 i 50。 i+) ioctl(fd, LED_OFF)。 sleep(1)。 ioctl(fd, LED_ON)。 sleep(1)。 ret = close(fd)。 printf(ret = %dn, ret)。 printf(close my_led_driver!n)。 return 0。将测试程序编译成目标平台的可执行文件,并下载到开发板GCC=/home/zzq/

10、9G20/arm-2007q1/bin/arm-none-linux-gnueabi-gcc #交叉编译器的路径My_led_test:my_led_test.c $(GCC) -o my_led_test my_led_test.cclean: rm -f my_led_test学习总结:熟悉驱动程序的架构,如何将驱动程序添加到内核即如何写测试程序。二:按键驱动设计1.硬件部分:PC4接按键。2.驱动程序:#include #include #include #include #include #include #include #include #include #include #inc

11、lude #include #include #include #include #include #include #include #define BUTTON_MAJOR 245#define DEVICE_NAME /dev/buttonstatic volatile int ev_press = 0。static struct cdev button_cdev。static void button_do_tasklet(unsigned long n)。DECLARE_TASKLET(button_tasklet, button_do_tasklet, 0)。/定义tasklet并与

12、处理函数关联起来static DECLARE_WAIT_QUEUE_HEAD(button_waitq)。/静态的初始化一个等待队列struct button_irq_desc int irq。 int irq_type。 int pin。 int number。 char *name。static struct button_irq_desc button_irq1 = AT91_PIN_PB22, AT91_AIC_SRCTYPE_LOW, AT91_PIN_PB22, 0, KEY0 。static int key_values1=0。/中断处理底半部static void button

13、_do_tasklet(unsigned long n) wake_up_interruptible(&button_waitq)。 /唤醒队列 printk(button press!n)。 /中断处理顶半部static irqreturn_t button_interrupt(int irq, void *dev_id, struct pt_regs *regs) int up。 static int press_down。 up = gpio_get_value(button_irq0.pin)。 printk(irqn)。 /*按键消抖*/ if(up) press_down = 1。

14、 /当按键没有按下,置标志位为1. if(!up & (press_down = 1) press_down = 0。 /当按键按下,置标志位为0. ev_press = 1。 at91_set_gpio_value(button_irq0.pin, 1)。 key_valuesbutton_irq0.number = !up。tasklet_schedule(&button_tasklet)。 return IRQ_RETVAL(IRQ_HANDLED)。static int button_open(struct inode *inode, struct file *filp) return

15、 0。static int button_release(struct inode *inode, struct file *filp) return 0。static int button_read(struct file *filp, char _user *buff, size_t count, loff_t *offp) int ret。 if(!ev_press) /当按键没有按下时,读进程挂起,知道按键按下。 wait_event_interruptible(button_waitq, ev_press)。 ev_press = 0。 ret = copy_to_user(buff

16、, (const void *)key_values, min(sizeof(key_values), count)。 memset(void _user *)key_values, 0, sizeof(key_values)。 return ret ? -EFAULT:min(sizeof(key_values), count)。 static struct file_operations button_fops = .owner = THIS_MODULE, .open = button_open, .release = button_release, .read = button_rea

17、d,。static int irq_init(void) int err。 at91_set_gpio_input(button_irq0.pin, 1)。 at91_set_deglitch(button_irq0.pin, 1)。/将PC0设置为中断功能 set_irq_type(button_irq0.irq, button_irq0.irq_type)。/设置中断类型 at91_set_gpio_value(button_irq0.pin, 1)。 err = request_irq( button_irq0.irq, button_interrupt, IRQF_DISABLED,

18、button_irq0.name, (void *)&button_irq0)。/申请中断 if ( err ) disable_irq(button_irq0.irq)。 free_irq(button_irq0.irq, (void *)&button_irq0)。 return -EBUSY。 return 0。static int _init button_init(void) int ret, err。 ret = register_chrdev_region(MKDEV(BUTTON_MAJOR, 0), 1, DEVICE_NAME)。 if(ret 0) printk(butt

19、on init failed with %dn, ret)。 return ret。 cdev_init(&button_cdev, &button_fops)。 button_cdev.owner = THIS_MODULE。 button_cdev.ops = &button_fops。 err = cdev_add(&button_cdev, MKDEV(BUTTON_MAJOR, 0), 1)。 if( err0 ) printk(key add failedn)。 return err。 irq_init()。 printk(key driver add success!n)。 re

20、turn 0。static void _exit button_exit(void) cdev_del(&button_cdev)。 unregister_chrdev_region(MKDEV(BUTTON_MAJOR, 0), 1)。 disable_irq(button_irq0.irq)。 free_irq(button_irq0.irq, (void *)&button_irq0)。 printk(unregister key driver!n)。module_init(button_init)。module_exit(button_exit)。MODULE_AUTHOR(fany)

21、。MODULE_DESCRIPTION(Atmel9g20 key Driver)。MODULE_LICENSE(GPL)。3.测试程序:#include #include #include #include #include #include #define DEVICE_NAME /dev/buttonint main(void) int fd,i。 int ret。 int key_value1。 printf(key test!n)。 fd = open(DEVICE_NAME, O_RDWR)。 if(fd 0) printf(open device %s error!n, DEVI

22、CE_NAME)。 else printf(open device success!n)。 while(1) ret = read(fd, key_value, 1)。 if( !ret ) printf(button not press!n)。 else printf(button press!n)。 printf(key_value %dn, key_value)。 close(fd)。 printf(close key driver!n)。 return 0。4.学习总结:在linux设备驱动程序中,中断处理程序通常分为两部分:上半部和下半部。上半部处理比较紧急的的硬件操作,比如简单的读

23、取寄存器中的状态并清除中断标志后,进行登记中断的工作。剩下的工作就由下半部来实现。对阻塞与非阻塞进程的理解,阻塞:在执行设备操作时,若不能获取设备资源则挂起,直到满足可操作的条件后再进行操作。非阻塞操作:在执行设备操作时,若不能获取设备资源则立即返回。三:总线驱动AT91SAM9G20存储器映射图(截取部分),片选4接外设,利用总线对外设进行访问。但是在linux驱动,不能对物理地址进行操作,可通过内存访问的机制实现对物理地址的访问。将一段物理地址空间映射到虚拟地址空间中,然后对虚拟地址的操作即是对物理地址的操作。3.1:总线驱动#include #include #include #incl

24、ude #include #include #include #include #include #include #include #include #include #include #include #include atmel9g20_liu.hstruct gr_liu_info void _iomem *virtbase。 void _iomem *regbase。 struct resource *res。 u32 flags。static struct gr_liu_info liu_info。static struct cdev atmel9g20_liu_cdev。unsi

25、gned short liu_read(unsigned addr) addr &= ATMEL9G20_LIU_MASK。 addr = addr 1。 addr += (unsigned long)liu_info.regbase。 printk(read the virtual addr is 0x%xn, addr)。 return readw(addr) & 0xff。 /读IO内存。EXPORT_SYMBOL(liu_read)。int liu_write(unsigned addr, unsigned val) addr &= ATMEL9G20_LIU_MASK。 addr =

26、 addr 1。 addr += (unsigned long)liu_info.regbase。 printk(write the virtual addr is 0x%xn, addr)。 writew(val&0xff, addr)。 /写IO内存 return 0。EXPORT_SYMBOL(liu_write)。static int atmel9g20_liu_open(struct inode *inode, struct file *filp) return 0。static int atmel9g20_liu_release(struct inode *inode, struct file *filp) return 0。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1