您的位置:首页 > 其它

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

我也是刚刚开始学习,大家有问题多多交流。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: