内核驱动开发最简单的就是字符设备,字符设备的驱动模型就是学习其他设备的前提,这里我用一个最简单的设备led,来做字符设备,写作一个最简单的字符设备驱动模型,可以供大家参考:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#define LED_REGISTER 0x7f008000
MODULE_LICENSE("GPL");
struct up_led{
struct cdev cdev;
unsigned long virt,phys;
unsigned long *gpmcon,*gpmdat;
dev_t devno;
void (*led_init)(struct up_led *this);
void (*led_exit)(struct up_led *this);
void (*led_on)(struct up_led *this);
void (*led_off)(struct up_led *this);
};
struct cdev cdev;
unsigned long virt,phys;
unsigned long *gpmcon,*gpmdat;
dev_t devno;
void (*led_init)(struct up_led *this);
void (*led_exit)(struct up_led *this);
void (*led_on)(struct up_led *this);
void (*led_off)(struct up_led *this);
};
void my_led_init(struct up_led *this);
void my_led_exit(struct up_led *this);
void my_led_on(struct up_led *this);
void my_led_off(struct up_led *this);
int my_open(struct inode *no,struct file *fp);
int my_release(struct inode *no,struct file *fp);
ssize_t my_read(struct file *fp,char *buff,size_t len,off_t *off);
ssize_t my_write(struct file *fp,const char *buff,size_t len,off_t *off);
int my_ioctl(struct inode *no,struct file *fp,unsigned int cmd,unsigned long arg);
void my_led_exit(struct up_led *this);
void my_led_on(struct up_led *this);
void my_led_off(struct up_led *this);
int my_open(struct inode *no,struct file *fp);
int my_release(struct inode *no,struct file *fp);
ssize_t my_read(struct file *fp,char *buff,size_t len,off_t *off);
ssize_t my_write(struct file *fp,const char *buff,size_t len,off_t *off);
int my_ioctl(struct inode *no,struct file *fp,unsigned int cmd,unsigned long arg);
struct file_operations fops = {
.open = my_open,
.write = my_write,
.release = my_release,
.read = my_read,
.ioctl = my_ioctl
};
.open = my_open,
.write = my_write,
.release = my_release,
.read = my_read,
.ioctl = my_ioctl
};
struct up_led led;
int up_init(void)
{
led.led_init = my_led_init;
led.led_exit = my_led_exit;
led.led_init(&led);
{
led.led_init = my_led_init;
led.led_exit = my_led_exit;
led.led_init(&led);
return 0;
}
}
void up_exit(void)
{
led.led_exit(&led);
}
{
led.led_exit(&led);
}
module_init(up_init);
module_exit(up_exit);
module_exit(up_exit);
void my_led_init(struct up_led *this)
{
this->led_on = my_led_on;
this->led_off = my_led_off;
{
this->led_on = my_led_on;
this->led_off = my_led_off;
this->phys = LED_REGISTER;
this->virt = ioremap(this->phys,SZ_4K);
this->gpmcon = this->virt + 0x820;
this->gpmdat = this->virt + 0x824;
this->devno = MKDEV(9,1);
cdev_init(&(this->cdev),&fops);
cdev_add(&(this->cdev),this->devno,1);
}
this->virt = ioremap(this->phys,SZ_4K);
this->gpmcon = this->virt + 0x820;
this->gpmdat = this->virt + 0x824;
this->devno = MKDEV(9,1);
cdev_init(&(this->cdev),&fops);
cdev_add(&(this->cdev),this->devno,1);
}
void my_led_exit(struct up_led *this)
{
cdev_del(this);
iounmap(this->virt);
}
{
cdev_del(this);
iounmap(this->virt);
}
void my_led_on(struct up_led *this)
{
*this->gpmcon &= ~0xf;
*this->gpmcon |= 1;
*this->gpmdat &= ~1;
}
{
*this->gpmcon &= ~0xf;
*this->gpmcon |= 1;
*this->gpmdat &= ~1;
}
void my_led_off(struct up_led *this)
{
*this->gpmcon &= ~0xf;
*this->gpmcon |= 1;
*this->gpmdat |= 1;
}
{
*this->gpmcon &= ~0xf;
*this->gpmcon |= 1;
*this->gpmdat |= 1;
}
int my_open(struct inode *no,struct file *fp)
{
printk("%x\n",no->i_cdev);
printk("%x\n",&led.cdev);
struct up_led *this = container_of(no->i_cdev,struct up_led,cdev);
fp->private_data = this;
return 0;
}
{
printk("%x\n",no->i_cdev);
printk("%x\n",&led.cdev);
struct up_led *this = container_of(no->i_cdev,struct up_led,cdev);
fp->private_data = this;
return 0;
}
int my_release(struct inode *no,struct file *fp)
{
return 0;
}
{
return 0;
}
ssize_t my_read(struct file *fp,char *buff,size_t len,off_t *off)
{
return 0;
}
{
return 0;
}
ssize_t my_write(struct file *fp,const char *buff,size_t len,off_t *off)
{
return 0;
}
{
return 0;
}
int my_ioctl(struct inode *no,struct file *fp,unsigned int cmd,unsigned long arg)
{
struct up_led *this = fp->private_data;
if(cmd == 1)
{
printk("led-on\n");
this->led_on(this);
}
else if(cmd == 0)
{
printk("led-off\n");
this->led_off(this);
}
else
printk("command is err\n");
return 0;
}
{
struct up_led *this = fp->private_data;
if(cmd == 1)
{
printk("led-on\n");
this->led_on(this);
}
else if(cmd == 0)
{
printk("led-off\n");
this->led_off(this);
}
else
printk("command is err\n");
return 0;
}