全部博文(156)
分类:
2010-10-19 19:33:44
编译模块的Makefile文件、
注:如果一个模块由多个*.c文件编译而成,那么应该如下编写Makefile文件:
obj-m := led_drv.o
module-objs := file1.o file2.o
驱动程序详细设计:
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
#define rGPFDAT 0x56000054 //实际IO的物理地址
#define rGPFCON 0x56000050
#define LED_ON 0x1
#define LED_OFF 0x2
//static dev_t my_led_id;
static int led_major = 257; //主设备号
struct __my_led
{
struct cdev dev;
unsigned char *vrGPFDAT;
unsigned short int *vrGPFCON;
}my_led;
static int my_led_open(struct inode *inode, struct file *filp)
{
struct __my_led *p = container_of(inode->i_cdev, struct __my_led, dev);
filp->private_data = p;
//实际物理地址映射到内核虚拟地址
p->vrGPFDAT = (unsigned char *)ioremap(rGPFDAT, 0x1);
p->vrGPFCON = (unsigned short int *)ioremap(rGPFCON, 0x2);
*p->vrGPFCON = (*p->vrGPFCON) & 0x00ff |(0x55<<8);
// *p->vrGPFDAT = 0x30;
// printk("open my_led, p->vrGPFDAT = 0x%x, p->vrGPFCON = 0x%x\n", p->vrGPFDAT, p->vrGPFCON);
return 0;
}
static int my_led_release(struct inode *inode, struct file *filp)
{
printk("close my_led\n");
filp->private_data = NULL;
//解除映射
iounmap(my_led.vrGPFDAT);
iounmap(my_led.vrGPFCON);
return 0;
}
static int my_led_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct __my_led *p = filp->private_data;
int ret = 0;
// printk("in ioctl_dri func , cmd = %d, p->vrGPFDAT = 0x%x\n", cmd, p->vrGPFDAT);
switch (cmd)
{
case LED_ON:
*p->vrGPFDAT &= 0x0f; //GPF4,5,6,7 置为低电平
break;
case LED_OFF:
*p->vrGPFDAT |= 0xf0;//GPF4,5,6,7 置为高电平
break;
default:
ret = EINVAL;
break;
}
return ret;
}
static const struct file_operations my_led_fops =
{
.owner = THIS_MODULE,
.open = my_led_open,
.release = my_led_release,
.ioctl = my_led_ioctl,
};
static void my_led_setup_cdev(void)
{
int err;
int devno=MKDEV(led_major, 0);
//是字符设备关联一个my_led_fops
cdev_init(&my_led.dev, &my_led_fops);
my_led.dev.owner = THIS_MODULE;
//添加字符设备
err = cdev_add(&my_led.dev, devno, 1);
if (err)
{
printk("add my_led device error, err = %d \n", err);
return ;
}
return;
}
int __init my_led_init(void)
{
int ret;
dev_t dev = MKDEV(led_major,0);
//注册设备号
memset(&my_led, 0, sizeof(my_led));
ret = alloc_chrdev_region(&dev, 0, 1, "my_led");
if (ret < 0)
{
printk("alloc led device id error \n");
return ret;
}
my_led_setup_cdev();
printk("add my_led device ok!\n");
printk(KERN_NOTICE"[DEBUG] adc device major is %d\n",led_major);
return 0;
}
void __exit my_led_exit(void)
{
//注意顺序不能颠倒,要和加载设备时步骤相反
cdev_del(&my_led);
unregister_chrdev_region(MKDEV(led_major,0) ,1);
printk("my-adc device uninstalled\n");
}
module_init(my_led_init);
module_exit(my_led_exit);