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


<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(这个是交叉编译生成的应用程序)

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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值