s3c2440第一个流水灯驱动程序(JZ2440)


#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include 
#include 

#include 
#include 
#include 
#include 

  
  
#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);  


测试程序:

#include  
#include  
#include  
#include  
#include  
    
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!");  
    }  
}  


Makefile:

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
Makefile中的最后一句 

led_timer_drv.o是执行make命令生成的驱动模块

最后:

#mknod /dev/led_timer c 244 0

#insmod led_timer_drv.ko

#./led_timer(这个是交叉编译生成的应用程序)

我也是刚刚开始学习,大家有问题多多交流。

你可能感兴趣的:(linux)