一个LED驱动的编写
来源:互联网 发布:java项目开发难点 编辑:程序博客网 时间:2024/04/28 01:11
#include <linux/kernel.h>#include <linux/module.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/miscdevice.h>#include <linux/kdev_t.h>#include <linux/device.h>#include<linux/io.h>#include<linux/uaccess.h>#include<linux/export.h>#include<linux/types.h>#define GPM4CON 0x110002E0volatile unsigned long *baseaddr = 0; //地址必须要 volatile 修饰,volatile 是防止优化,就是避免某次计算中间值存放在寄存器中没有存入flash,这会导致以后读取的值不是想要的#define rGPM4CON (*((volatile unsigned long *)(baseaddr + 0)))#define rGPM4DAT (*((volatile unsigned long *)(baseaddr + 1)))#define MYLED_MAJOR 0#define MYLED_NAME "led"#define MYLED_DRVNUM 1#define MYLED_NUM 4dev_t myled_devt; //设备号int myled_major;struct class *myled_class; //设备结构体struct cdev *myled; //设备驱动核心结构char led_status[MYLED_NUM]={-1,-1,-1,-1};loff_t led_lseek (struct file *fp, loff_t off, int whence){ loff_t newoff=0; switch(whence) { case SEEK_SET: newoff=off; break; case SEEK_CUR: newoff = fp->f_pos+off; break; case SEEK_END: newoff = 4 + off; default: return -EINVAL; } if(newoff<0) newoff = 0; else if(newoff>4) newoff = 4; fp->f_pos=newoff; return newoff;}ssize_t led_read (struct file *fp, char __user *buf, size_t size, loff_t *off){ int i=0; unsigned long ret; if(*off>4) return -EINVAL; if(*off+size>4) size = 4-*off; for(i=0;i<MYLED_NUM;i++) led_status[i]= !(rGPM4DAT&(0x1<<i)); ret = copy_to_user(buf,&led_status[*off],size); //copy_to_user 还是 copy_from_user 都是到前一个参数,且使用的都是地址 *off = *off+size; printk("led_read is called\n"); return 0;}ssize_t led_write (struct file *fp, const char __user *buf, size_t size, loff_t *off){ int i; unsigned long temp; if(*off>4) return -EINVAL; if(*off + size >4) size = 4 - *off; temp = copy_from_user(&led_status[*off],buf,size); for(i=0;i<MYLED_NUM;i++) { if(led_status[i] == 0) rGPM4DAT |= (0x1<<i); else if(led_status[i] == 1) rGPM4DAT &= ~(0x1<<i); else return -EINVAL; } *off = *off + size; printk("led_write is called \n"); return 0;}int led_open (struct inode *node, struct file *fp){ int i=0; fp->private_data =(void *) MINOR(node->i_rdev); rGPM4CON &= ~(0xffff); rGPM4CON |= (0x1111); for(i=0;i<MYLED_NUM;i++) { led_status[i] = !(rGPM4DAT&(0x1<<i)); } printk("led_open is called \n"); return 0;}int led_close (struct inode *node, struct file *fp){ printk("led_close is called \n"); return 0;}struct file_operations led_fops={ .owner=THIS_MODULE, .open =led_open, .release = led_close, .read=led_read, .write = led_write, .llseek = led_lseek,};static int __init myled_init(void) //形参不能为空{ int i=0;#if MYLED_MAJOR //如果不为 0,则设备号就是自主分配 myled_major = MYLED_MAJOR; myled_devt = MKDEV(myled_major,0); if(register_chrdev_region(myled_devt,MYLED_DRVNUM,MYLED_NAME)) //静态注册设备号#else if(alloc_chrdev_region(&myled_devt,0,MYLED_DRVNUM,MYLED_NAME)) //主设备号为 0 ,动态注册设备号#endif { printk("注册失败\n"); return -EBUSY; } myled = cdev_alloc(); //分配设备空间 /* 这里多说两句,每一个设备都是一个结构体,这个结构体包括 struct kobject kobj; の,忘了干嘛的 struct module *owner; 所属的模块 const struct file_operations *ops; 所使用的文件操作函数 struct list_head list; 链表,向内和联表添加 dev_t dev; 设备号 unsigned int count; 设备数目 */ cdev_init(myled,&led_fops); //初始化设备 /* 这个初始化这是把文件函数结构体添加到设备结构体 */ if(cdev_add(myled,myled_devt,MYLED_DRVNUM)) //添加设备空间 { printk("注册成功\n"); return -EBUSY; } printk("注册成功\n"); myled_class = class_create(THIS_MODULE,MYLED_NAME); //产生一个设备类 for(i=0;i<MYLED_DRVNUM;i++) //添加设备类进内核 device_create(myled_class,NULL,myled_devt+i,NULL,"myled%d",i); baseaddr = ioremap(GPM4CON, 8); //硬件地址映射到虚拟地址 return 0;}static void __exit myled_exit(void) //形参不能为空,必须有个void{ iounmap(baseaddr); //取消地址映射 device_destroy(myled_class, myled_devt); //销毁在内核的设备 class_destroy(myled_class); //销毁设备类 cdev_del(myled); //删除设备 unregister_chrdev_region(myled_devt,MYLED_DRVNUM); //注销设备 printk("注销成功\n");}module_init(myled_init);module_exit(myled_exit);MODULE_LICENSE("GPL");
阅读全文
0 0
- 一个LED驱动的编写
- LED灯驱动的编写
- 一个简单的LED驱动
- led驱动编写
- 树莓派LED驱动编写
- 基于sysfs的LED驱动编写以及应用程序的编写
- 一个led-platfrom设备驱动的例子
- [TED] 一个简单的LED驱动
- 一个led-platfrom设备驱动的例子
- LED灯驱动编写全过程
- 基于mini2440的led驱动编写的总结
- 编写基于stm32f407-uclinux下的led灯驱动
- led驱动编写并非使用led 子系统(实际led驱动编写)
- 基于arm的一个简单的led驱动
- 基于sysfs的LED驱动编写以及应用程序的编写(定时器操作)
- 自己动手写最简单的Android驱动---LED驱动的编写
- 自己动手写最简单的Android驱动---LED驱动的编写
- 自己动手写最简单的Android驱动---LED驱动的编写
- 【bzoj1391】[Ceoi2008]order
- SpringAOP的实现原理
- 一种公认提供toString的方法_JAVA核心技术卷轴Ⅰ
- 隐写术
- HDU1166
- 一个LED驱动的编写
- 分析器错误消息: 此实现不是 Windows 平台 FIPS 验证的加密算法的一部分
- 离开和进入trusted os的过程
- pl/sql提高开发效率
- Mybatis中的update动态SQL语句
- redis编译安装
- config.js配置页面中的样式和图片路径
- Java 中 【this】关键字的用法
- 42 linux内核里的输入子系统分析