转载:搞定一个简单的LED驱动
今天去买了一条排线,方便利用板子上的那个GPIO口
于是照葫芦画瓢搞出了一个驱动
利用GPIO口的GPF5,第14针,LED一端在GPF5上,一端在GND上,OK~~就这么简单
驱动代码
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "miniled"
#define LED_MAJOR 254
static int led_major = LED_MAJOR;
struct mini_led_dev
{
struct cdev cdev;
};
struct mini_led_dev *devp;
static unsigned long mini_led_table[] = {
S3C2410_GPF5,
};
static unsigned long mini_led_cfg_table[] = {
S3C2410_GPF5_OUTP,
};
int led_on(int arg)
{
s3c2410_gpio_setpin(mini_led_table[arg], 0);
return 0;
}
int led_off(int arg)
{
s3c2410_gpio_setpin(mini_led_table[arg], 1);
return 0;
}
static int mini_led_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 0:
led_off(arg);
break;
case 1:
led_on(arg);
break;
default:
return -1;
}
}
static int mini_led_open(struct inode *inode, struct file *filp)
{
struct mini_led_dev *devp;
devp = container_of(inode->i_cdev, struct mini_led_dev,cdev);
filp->private_data = devp;
return 0;
}
static int mini_led_release(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations mini_led_fops = {
.owner = THIS_MODULE,
.ioctl = mini_led_ioctl,
.open = mini_led_open,
.release = mini_led_release,
};
static void led_setup_cdev(struct mini_led_dev *dev, int index)
{
int err;
int devno = MKDEV(led_major, index);
cdev_init(&dev->cdev, &mini_led_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &mini_led_fops;
err = cdev_add(&dev->cdev, devno, 1);
if (err)
{
printk(KERN_NOTICE "Error %d adding led %d", err, index);
}
}
int mini_led_init(void)
{
int result;
int i;
dev_t devno = MKDEV(led_major, 0);
if (led_major)
{
result = register_chrdev_region(devno, 0, DEVICE_NAME);
}
else
{
result = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);
}
if (result < 0)
{
return result;
}
devp = kmalloc(sizeof(struct mini_led_dev), GFP_KERNEL);
if (! devp)
{
result = -1;
goto fail_malloc;
}
s3c2410_gpio_cfgpin(mini_led_table[0], mini_led_cfg_table[0]);
s3c2410_gpio_setpin(mini_led_table[0], 1);
memset(devp, 0, sizeof(struct mini_led_dev));
led_setup_cdev(devp, 0);
return 0;
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
void mini_led_exit(void)
{
cdev_del(&devp->cdev);
kfree(devp);
unregister_chrdev_region(MKDEV(led_major, 0), 1);
}
MODULE_AUTHOR("more&high");
MODULE_LICENSE("Dual BSD/GPL");
module_init(mini_led_init);
module_exit(mini_led_exit);
Makefile:
obj-m := testled.o
KDIR := /home/martian/linux-2.6.29
PWD := $(shell pwd)
CC = arm-linux-gcc
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.o
rm -rf *.ko
rm -rf .*.cmd
rm -rf *.mod.*
中途出现过一些问题,这里记录一下。
1、make时候提示出现找不到linux/bounds.h
这个需要进相应的内核源代码文件夹,执行
make mrproper
make prepare
将生成linux/bounds.h
如果不行,有可能是因为内核未配置过,此时先执行make menuconfig,生成.config之后,再来执行上面两条
2、make提示缺少modpost
进入相应内核源代码文件夹,执行
make scripts
将声称modpost
OK,编译完成之后,拷贝过去,执行
mknod /dev/testled c 254 0
insmod led.ko
测试程序:
#include
#include
#include
#include
int main()
{
int fd;
int num;
int ope;
fd = open("/dev/testled", 0);
if (fd < 0)
{
perror("open miniled fail");
exit(1);
}
while(1)
{
ioctl(fd, 1, 0);
sleep(1);
ioctl(fd, 0, 0);
sleep(1);
}
close(fd);
return 0;
}
执行后,LED闪动~成功