s3c2440第一个流水灯驱动程序(JZ2440)
2016-03-22 08:34
225 查看
<span style="font-family:SimSun;">#include<linux/module.h> #include<linux/init.h> #include<linux/types.h> #include<linux/fs.h> #include<linux/mm.h> #include<linux/cdev.h> #include<linux/slab.h> #include<linux/timer.h> #include<linux/jiffies.h> #include<asm/io.h> #include<asm/uaccess.h> #include <linux/kernel.h> #include <linux/delay.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #define LED_MAJOR 244 #define LED_ON 0 #define LED_OFF 1 #define LED1_PIN S3C2410_GPF4 #define LED2_PIN S3C2410_GPF5 #define LED3_PIN S3C2410_GPF6 static unsigned long led_major = LED_MAJOR; struct led_dev { struct cdev cdev; struct timer_list s_timer; atomic_t led_no; //LED编号 atomic_t sec_counter; //秒计时数 }; struct led_dev *led_devp; void led_control(int led_no) { switch(led_no) { case 1:s3c2410_gpio_setpin(LED1_PIN,LED_ON); s3c2410_gpio_setpin(LED2_PIN,LED_OFF); s3c2410_gpio_setpin(LED3_PIN,LED_OFF); break; case 2:s3c2410_gpio_setpin(LED1_PIN,LED_OFF); s3c2410_gpio_setpin(LED2_PIN,LED_ON); s3c2410_gpio_setpin(LED3_PIN,LED_OFF); break; case 3:s3c2410_gpio_setpin(LED1_PIN,LED_OFF); s3c2410_gpio_setpin(LED2_PIN,LED_OFF); s3c2410_gpio_setpin(LED3_PIN,LED_ON); break; default:break; } } //定时器处理函数 static void sec_timer_handler(unsigned long arg) { int num; mod_timer(&led_devp->s_timer,jiffies+HZ); num = atomic_read(&led_devp->led_no); if(num == 3) { atomic_set(&led_devp->led_no,1); } else { atomic_inc(&led_devp->led_no); } num = atomic_read(&led_devp->led_no); led_control(num); atomic_inc(&led_devp->sec_counter); num = atomic_read(&led_devp->sec_counter); printk(KERN_INFO "sec_count:%d\n",num); } static int led_open(struct inode *inode,struct file *filp) { struct timer_list *timer; timer = &led_devp->s_timer; init_timer(timer); timer->function = sec_timer_handler; timer->expires = jiffies+HZ; //计时频率为HZ add_timer(timer); atomic_set(&led_devp->sec_counter,0); atomic_set(&led_devp->led_no,0); return 0; } static int led_release(struct inode *inode, struct file *filp) { del_timer(&led_devp->s_timer); return 0; } static ssize_t led_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) { int count,led_no; int result; count = atomic_read(&led_devp->sec_counter); led_no = atomic_read(&led_devp->led_no); result = (count<<3)+led_no; if(put_user(result,(int*)buf)) { return -EFAULT; } else { return sizeof(int); } } static const struct file_operations led_fops = { .owner = THIS_MODULE, .read = led_read, .open = led_open, .release = led_release, }; static void led_setup_cdev(struct led_dev *dev, int index) { int err,devno = MKDEV(led_major,index); cdev_init(&dev->cdev,&led_fops); dev->cdev.owner = THIS_MODULE; err = cdev_add(&dev->cdev,devno,1); if(err) { printk(KERN_NOTICE "Error %d adding %d\n",err,index); } } static int led_init(void) { int result; dev_t devno = MKDEV(led_major,0); //获取设备号 /*注册设备*/ if(led_major) result = register_chrdev_region(devno,1,"led"); else { result = alloc_chrdev_region(&devno,0,1,"led"); led_major = MAJOR(devno); } if(result<0) { printk("register failed!"); return result; } led_devp =(struct led_dev*)kmalloc(sizeof(struct led_dev),GFP_KERNEL); if(!led_devp) { result = -ENOMEM; unregister_chrdev_region(devno,1); } memset(led_devp, 0 ,sizeof(struct led_dev)); led_setup_cdev(led_devp,0); /*配置IO口*/ s3c2410_gpio_cfgpin(LED1_PIN,S3C2410_GPF4_OUTP); s3c2410_gpio_cfgpin(LED2_PIN,S3C2410_GPF5_OUTP); s3c2410_gpio_cfgpin(LED3_PIN,S3C2410_GPF6_OUTP); /*初始化IO电平*/ s3c2410_gpio_setpin(LED1_PIN,LED_OFF); s3c2410_gpio_setpin(LED2_PIN,LED_OFF); s3c2410_gpio_setpin(LED3_PIN,LED_OFF); return 0; } static void led_exit(void) { cdev_del(&led_devp->cdev); kfree(led_devp); unregister_chrdev_region(MKDEV(led_major,0),1); } MODULE_LICENSE("GPL"); MODULE_AUTHOR("Vanbreaker"); module_init(led_init); module_exit(led_exit); </span>
测试程序:
<span style="font-family:SimSun;">#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #include<stdlib.h> int main() { int fd; fd = open("/dev/led_timer",O_RDWR); if(fd != -1) { printf("open /dev/led_timer\n"); while(1); } else { printf("cannot open /dev/led_timer!"); } } </span>
Makefile:
<span style="font-family:SimSun;">KERN_DIR = /work/system/linux-2.6.22.6 all: make -C $(KERN_DIR) M=`pwd` modules clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m += led_timer_drv.o</span>Makefile中的最后一句
led_timer_drv.o是执行make命令生成的驱动模块
最后:
#mknod /dev/led_timer c 244 0
#insmod led_timer_drv.ko
#./led_timer(这个是交叉编译生成的应用程序)
我也是刚刚开始学习,大家有问题多多交流。
相关文章推荐
- (语法)内存地址和指针<一>
- Integer Inquiry(大数)
- 学习JS的第二天
- 桶排序
- update语句的执行步骤及commit语句的执行顺序
- Rebirth 认认真真的成为Android大拿!
- POJ_P2728 Desert King(最优比率生成树)
- [Android]Fragment源代码分析(二) 状态
- 表单2
- flask upload file
- 快速排序
- AC自动机+DP(POJ2778&&POJ3691)
- 谁说理工男不浪漫?电子工程师的恋爱神器
- 表单
- EventBus3.0的使用
- Android Https相关完全解析 当OkHttp遇到Https
- html 基础代码
- Java数据库——处理大数据对象
- 编程实现通过状态图确定句子
- Android图片海报制作-自定义文字排版控件组件