一、首先需要在最开始定义两个数据结构:
static struct class *firstdrv_class;
static struct device *firstdrv_device;
二、在init函数里通过class_create和device_create函数创建相应的设备节点,示例代码如下:
static int first_drv_init(void)
{
/* 主设备号设置为0表示由系统自动分配主设备号 */
major = register_chrdev(0, 'first_drv', &first_drv_fops);
/* 创建firstdrv类 */
firstdrv_class = class_create(THIS_MODULE, 'firstdrv');
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, 'xxx');
return 0;
}
三、在exit函数里通过device_destroy、class_unregister、class_destroy函数对设备进行卸载
static void first_drv_exit(void)
{
device_destroy(firstdrv_class,MKDEV(major,0));
class_unregister(firstdrv_class);
class_destroy(firstdrv_class);
unregister_chrdev(major, 'first_drv');
}
参考代码一、
#include
#include
#include
#include
#include
#include
#include
#include
#include
static struct class *firstdrv_class;
static struct device *firstdrv_device;
int major;
static int first_drv_open(struct inode * inode, struct file * filp)
{
printk('first_drv_openn');
return 0;
}
static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
{
printk('first_drv_writen');
return 0;
}
/* File operations struct for character device */
static const struct file_operations first_drv_fops = {
.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,
};
/* 驱动入口函数 */
static int first_drv_init(void)
{
/* 主设备号设置为0表示由系统自动分配主设备号 */
major = register_chrdev(0, 'first_drv', &first_drv_fops);
/* 创建firstdrv类 */
firstdrv_class = class_create(THIS_MODULE, 'firstdrv');
/* 在firstdrv类下创建xxx设备,供应用程序打开设备*/
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, 'xxx');
return 0;
}
/* 驱动出口函数 */
static void first_drv_exit(void)
{
unregister_chrdev(major, 'first_drv');
device_unregister(firstdrv_device); //卸载类下的设备
class_destroy(firstdrv_class); //卸载类
}
module_init(first_drv_init); //用于修饰入口函数
module_exit(first_drv_exit); //用于修饰出口函数
MODULE_AUTHOR('LWJ');
MODULE_DESCRIPTION('Just for Demon');
MODULE_LICENSE('GPL'); //遵循GPL协议
参考代码二
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#define DEBUG
/* 相关引脚定义,方便以后移植 */
#define DEVICE_NAME 'ds18b20'
#define DQ 2
#define CFG_IN 0
#define CFG_OUT 1
// ds18b20主次设备号(动态分配)
int ds18b20_major = 0;
int ds18b20_minor = 0;
int ds18b20_nr_devs = 1;
// 定义设备类型
static struct ds18b20_device {
struct cdev cdev;
};
struct ds18b20_device ds18b20_dev;
static struct class *ds18b20_class;
/* 函数声明 */
static int ds18b20_open(struct inode *inode, struct file *filp);
static int ds18b20_init(void);
static void write_byte(unsigned char data);
static unsigned char read_byte(void);
static ssize_t ds18b20_read(struct file *filp, char __user *buf,
size_t count, loff_t *f_pos);
void ds18b20_setup_cdev(struct ds18b20_device *dev, int index);
void s3c6410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
//s3c_gpio_cfgpin(pin,function);
unsigned int tmp;
tmp = readl(S3C64XX_GPECON);
tmp = (tmp & ~(0XF<
}
void s3c6410_gpio_pullup(unsigned int pin, unsigned int to)
{
//s3c_gpio_setpull(pin,to);
unsigned int tmp;
tmp = readl(S3C64XX_GPEPUD);
tmp = (tmp & ~(3<
}
unsigned int s3c6410_gpio_getpin(unsigned int pin)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPEDAT);
tmp = tmp & (1 << (pin));
return tmp;
}
void s3c6410_gpio_setpin(unsigned int pin, unsigned int dat)
{
unsigned int tmp;
tmp = readl(S3C64XX_GPEDAT);
tmp &= ~(1 << (pin));
tmp |= ( (dat) << (pin) );
writel(tmp, S3C64XX_GPEDAT); ;
}
/******************************************************************************************************
** 函数名称: ds18b20_open()
** 函数功能: 打开设备,初始化ds18b20
** 入口参数: inode:设备文件信息; filp: 被打开的文件的信息
** 出口参数: 成功时返回0,失败返回-1
** 备 注:
******************************************************************************************************/
static int ds18b20_open(struct inode *inode, struct file *filp)
{
int flag = 0;
/*struct ds18b20_device *dev;
dev = container_of(inode->i_cdev, struct ds18b20_device, cdev);
filp->private_data = dev;*/
flag = ds18b20_init();
if(flag & 0x01)
{
#ifdef DEBUG
printk(KERN_WARNING 'open ds18b20 failedn');
#endif
return -1;
}
#ifdef DEBUG
printk(KERN_NOTICE 'open ds18b20 successfuln');
#endif
return 0;
}
/******************************************************************************************************
** 函数名称: ds18b20_init()
** 函数功能: 复位ds18b20
** 入口参数: 无
** 出口参数: retval:成功返回0,失败返回1
** 备 注: 操作时序见ds18b20 datasheet
******************************************************************************************************/
static int ds18b20_init(void)
{
int retval = 0;
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 0);
s3c6410_gpio_setpin(DQ, 1);
udelay(2);
s3c6410_gpio_setpin(DQ, 0); // 拉低ds18b20总线,复位ds18b20
udelay(500); // 保持复位电平500us
s3c6410_gpio_setpin(DQ, 1); // 释放ds18b20总线
udelay(60);
// 若复位成功,ds18b20发出存在脉冲(低电平,持续60~240us)
s3c6410_gpio_cfgpin(DQ, CFG_IN);
retval = s3c6410_gpio_getpin(DQ);
udelay(500);
s3c6410_gpio_cfgpin(DQ, CFG_OUT);
s3c6410_gpio_pullup(DQ, 0);
s3c6410_gpio_setpin(DQ, 1); // 释放总线
return retval;
}
/******************************************************************************************************
** 函数名称: write_byte()
** 函数功能: 向18b20写入一个字节数据
** 入口参数: data
** 出口参数: 无
** 备 注:
******************************************************************************************************/
static void write_byte(unsigned char data)