#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!");
}
}
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(这个是交叉编译生成的应用程序)
我也是刚刚开始学习,大家有问题多多交流。