S3C2410的一个LED的驱动程序

来源:互联网 发布:matlab 循环遍历数组 编辑:程序博客网 时间:2024/05/17 23:11

Environment: linux 2.6.22

Tools: arm-linux-gcc

platform:S3C2410 board

====================================分割线=======================================

#ifndef _LED_H_#define _LED_H_#ifdef LED_DEBUG#  ifdef __KERNEL__     /* This one if debugging is on, and kernel space */#    define PDEBUG(fmt, args...) printk( KERN_DEBUG "led: " fmt, ## args)#  else     /* This one for user space */#    define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)#  endif#else#  define PDEBUG(fmt, args...) /* not debugging: nothing */#endif// #define __MULTI_MIN__  //为了后面的拓展,将一个一个LED灯作为一个个的从设备#ifndef __MULTI_MIN__#ifndef LED_MAJOR#define LED_MAJOR 0   /* dynamic major by default */#endif#ifndef LED_NR_DEVS#define LED_NR_DEVS 1    /* led0 through ledx, LED1-3 as one device no min jor */#endif#else#ifndef LED_MAJOR#define LED_MAJOR 0   /* dynamic major by default */#endif#ifndef LED_NR_DEVS#define LED_NR_DEVS 3    /* led0 through ledx, LED1-3 as one device no min jor */#endif#endif#define LED1_ON  0x11#define LED1_OFF 0x10#define LED2_ON  0x21#define LED2_OFF 0x20#define LED3_ON  0x31#define LED3_OFF 0x30struct led_dev {char LedStatus;         //LED 的状态,未用到struct semaphore sem;     /* mutual exclusion semaphore     */  //互斥信号,没有用到struct cdev cdev;  /* Char device structure*/};#endif//====================================分割线=======================================//led.c//#include <linux/config.h>#include <linux/capability.h> //add by lqh#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/types.h> /* size_t */#include <linux/proc_fs.h>#include <linux/fcntl.h> /* O_ACCMODE */#include <linux/seq_file.h>#include <linux/cdev.h>#include <asm/system.h> /* cli(), *_flags */#include <asm/uaccess.h> /* copy_*_user */#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#include "led.h" /* local definitions */#define UNUSEND(param) #define LEDON 0x00#define LEDOFF 0x01int led_major =   LED_MAJOR;int led_minor =   0;int led_nr_devs = LED_NR_DEVS; /* number of bare led devices */module_param(led_major, int, S_IRUGO);module_param(led_minor, int, S_IRUGO);module_param(led_nr_devs, int, S_IRUGO);MODULE_AUTHOR("Liqinghan for LED control ");MODULE_LICENSE("Dual BSD/GPL");struct led_dev *led_devices; /* allocated in led_init_module */int led_open(struct inode *inode, struct file *filp){s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF5_OUTP);s3c2410_gpio_setpin(S3C2410_GPF4, LEDOFF);s3c2410_gpio_setpin(S3C2410_GPF5, LEDOFF);s3c2410_gpio_setpin(S3C2410_GPF6, LEDOFF);return 0;          /* success */}ssize_t led_read(struct file *filp, char __user *buf, size_t count,                loff_t *f_pos){UNUSEND(filp);UNUSEND(buf);UNUSEND(count);UNUSEND(f_pos);return count;}ssize_t led_write(struct file *filp, const char __user *buf, size_t count,                loff_t *f_pos){char val ;UNUSEND(filp);UNUSEND(count);UNUSEND(f_pos);if(copy_from_user(&val,buf,1))return -EFAULT;switch(val){case LED1_ON:s3c2410_gpio_setpin(S3C2410_GPF4, LEDON);break;case LED1_OFF:s3c2410_gpio_setpin(S3C2410_GPF4, LEDOFF);break;case LED2_ON:s3c2410_gpio_setpin(S3C2410_GPF5, LEDON);break;case LED2_OFF:s3c2410_gpio_setpin(S3C2410_GPF5, LEDOFF);break;case LED3_ON:s3c2410_gpio_setpin(S3C2410_GPF6, LEDON);break;case LED3_OFF:s3c2410_gpio_setpin(S3C2410_GPF6, LEDOFF);break;default: break;}return - EINVAL;}struct file_operations led_fops = {.owner =    THIS_MODULE,.read =     led_read,.write =    led_write,.open =     led_open,};/* * Set up the char_dev structure for this device. */static void led_setup_cdev(struct led_dev *dev, int index){int err, devno = MKDEV(led_major, led_minor + index);cdev_init(&dev->cdev, &led_fops);dev->cdev.owner = THIS_MODULE;dev->cdev.ops = &led_fops;err = cdev_add (&dev->cdev, devno, 1);if (err)printk(KERN_NOTICE "Error %d adding led%d", err, index);}void led_exit_module(void){cdev_del(&led_devices->cdev);kfree(led_devices);unregister_chrdev_region(MKDEV(led_major,led_minor),1);}int led_init_module(void){int result;dev_t dev = 0;/* * Get a range of minor numbers to work with, asking for a dynamic * major unless directed otherwise at load time. */if (led_major) {dev = MKDEV(led_major, led_minor);result = register_chrdev_region(dev, led_nr_devs, "led");} else{result = alloc_chrdev_region(&dev, led_minor, led_nr_devs,"led");led_major = MAJOR(dev);}if (result < 0) {printk(KERN_WARNING "led: can't get major %d\n", led_major);return result;}led_devices = kmalloc( sizeof(struct led_dev), GFP_KERNEL);if (!led_devices) {result = -ENOMEM;goto fail;  /* Make this more graceful */}memset(led_devices, 0, sizeof(struct led_dev));led_setup_cdev(led_devices, 0);dev = MKDEV(led_major, led_minor);return 0; /* succeed */  fail:  if(led_devices){kfree(led_devices);}unregister_chrdev_region(dev,led_minor);return result;}module_init(led_init_module);module_exit(led_exit_module);


====================================分割线=======================================

//note:本程序没有在板子上验证过,尚不知会不会有效,等我有空在去验证!

====================================分割线=======================================

Makefile:

KERN_DIR = /home/liqinghan/linux-2.6.22all:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m += led.o

====================================分割线=======================================

编译 make,没有问题。等待我去实验哈!!

总结:感觉驱动架构就是一个框框,然后让我们往里面填写我们需要都的功能!!!但是对于这个框框的理解也很费力啊!

对于给程序我是按照scull的程序改过来的,还未在我的板子试验过,有空再实验吧! Mark一下!!!


0 0
原创粉丝点击