语言实践2-驱动学习(2)驱动程序框架

来源:互联网 发布:程序员薪资城市排行榜 编辑:程序博客网 时间:2024/06/13 06:59


完成一个驱动需要两部分内容:

       (1)驱动程序.c文件:关于设备的函数

       (2)应用程序,打开设备文件并进行操作

 这篇文章是关于(1)

 

本来想先试着写继电器的驱动程序,从简单的学起,但发现首先是找不到继电器的驱动程序,其次因为这个太简单,很难搞清楚驱动程序的架构。所以先看难的ds18b20驱动程序,网上很多。

参考: http://www.linuxidc.com/Linux/2012-02/54677.htm

 

1.static struct ds18b20_device  

{  

    struct cdev cdev;  

};  

 

2. static int ds18b20_open:调用ds_18b20_init

 

3. static int ds18b20_init:设置引脚

 

4.static struct file_operations ds18b20_dev_fops = {  

    .owner = THIS_MODULE,  

    .open = ds18b20_open,  

    .read = ds18b20_read,  

};  连接设备号和驱动程序操作

 

5. static void write_byte

static unsigned char read_byte设备具体操作

static ssize_t ds18b20_read

 

6. void ds18b20_setup_cdev:设置cdev ( cdev_init ,cdev_add)

 

7. static int __init ds18b20_dev_init :

    (1)注册设备号(动态、静态)

     (2)为设备分配内存kmalloc(sizeof(struct ds18b20_device),GFP_KERNEL) memset

      (3)创建cdev(调用5 ds18b20_setup_cdev)

      (4)创建设备节点 class_createdevice_create

 

8.static void __exit ds18b20_dev_exit:

       注销所有创建的东西:

cdev_del  /*注销cdev */  

    kfree       /*释放设备结构体内存 */  

    unregister_chrdev_region /*释放设备号 */  

    device_unregister

    class_destroy

整体流程如下:(网图侵删)http://blog.csdn.net/zqixiao_09/article/details/50839042


  

我仿照写了一个简单的hello.c文件

#include <linux/init.h>    

#include <linux/module.h>    

#include <linux/delay.h>    

#include <linux/kernel.h>    

#include<linux/moduleparam.h>    

#include <linux/types.h>    

#include <linux/fs.h>        

#include <linux/cdev.h>    

#include <asm/uaccess.h>    

#include <linux/errno.h>    

#include <linux/gpio.h>    

#include <linux/device.h> 

#include <linux/slab.h>

 

MODULE_LICENSE("DualBSD/GPL");

MODULE_AUTHOR("LYL");

MODULE_DESCRIPTION("Hello worldtest");

MODULE_VERSION("V1.0");

static int hello_major=0;

static int hello_minor=0;

static struct hello_dev{

     structcdev cdev;

};

struct hello_dev* hello_devp;

 

static int hello_open(struct inode*inode,struct file *filep){

     printk("hello_open\n");

     return0;

}

 

struct file_operations hello_fops={

     .owner=THIS_MODULE,

     .open=hello_open,

};

 

 

static   dev_tdev;

static struct class *cls;

static struct device *test_device;

 

static int __init hello_init(void){

     intresult;

     printk("HelloWord!\n");

     dev=MKDEV(hello_major,hello_minor); 

   if (hello_major)   

   {   

       result = register_chrdev_region(dev,1, "hello");   

   }   

   else   

   {   

       result =alloc_chrdev_region(&dev,hello_minor, 1, "hello");   

       hello_major = MAJOR(dev);   

   }   

   if (result < 0)   

   {   

       printk(KERN_WARNING"error\n");   

       return result;   

   }   

     hello_devp=kmalloc(sizeof(structhello_dev),GFP_KERNEL);

     memset(hello_devp,0,sizeof(structhello_dev));

     cdev_init(&hello_devp->cdev,&hello_fops);

     cdev_add(&hello_devp->cdev,dev,1);

     cls=class_create(THIS_MODULE,"myclass");

     test_device=device_create(cls,NULL,dev,NULL,"hello");

     return0;

}

 

static void __exithello_exit(void){//order??

     printk("Goodbye,cruelworld!\n");

     cdev_del(&hello_devp->cdev);

     kfree(hello_devp);

     unregister_chrdev_region(dev,1);

     device_unregister(test_device);

     class_destroy(cls);

}

 

module_init(hello_init);

module_exit(hello_exit);

 

开始一直出错,每次make正确,但insmod就会出现killed。百度以后,发现是内存问题,加上DEMO_devices = kmalloc(sizeof(struct DEMO_dev), GFP_KERNEL);

加上以后还有错误,检查了很久发现是建了两个hello_dev指针,一个用来分配内存,一个用来init,很撒撒。

 

更改后运行成功。


关于设备节点:(网摘)

首先,类unix系统对设备的访问都是基于文件形式的。
在类unix系统中,你要访问一个硬件设备。一般和访问一个普通文件差不多。
因此,/dev下的设备节点就被作为这样的一类特殊文件来存在。
在驱动程序中同样需要实现各种文件的操作调用,如open,release,read,write,ioctl等。
应用程序通过open("/dev/xxx",O_RDWR)这样的代码来打开设备。
驱动程序通过这样的节点向应用程序提供各种服务:如read,write,ioctl

 

两种方法设置:

1.      手动:mknod设备名设备类型(字符:c,块:b)主设备号从设备号

http://blog.csdn.net/chuanzhilong/article/details/65936746

2.      自动: class_create , device_create

 

疑问:设备节点是什么东西

原创粉丝点击