Linux 内核驱动自动创建设备节点并挂载设备

2024-09-27  

一、首先需要在最开始定义两个数据结构:


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      //class_create  

      

    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<        writel(tmp, S3C64XX_GPECON); 

}


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<        writel(tmp, S3C64XX_GPEPUD); 

}


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)

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。