S3C2440 驱动分层概念

  为自己的坚持加油!

  切入正题,今天要学习的是驱动的分层/分离概念。

  分离分层的目的是将硬件相关的代码和系统中比较稳定的代码分离开,并且按照一定的框架联系到一起。这样我们在写一个驱动的时候能够更加灵活,顶层的应用程序也能更加稳定的调用底层的接口。对驱动开发者而言,这样写驱动程序将更有逻辑性。纯粹时个人理解哈。

  以input.c框架为例,从图中可以看到系统把硬件相关的代码放在一起,把纯软件的相对稳定的部分放在一起,如evdev.c  最后他们通过input.c相连接。

  除了输入子系统之外,设备总线也遵循这一原则。接下来我们一起分析设备总线的分层分离。

插入图片。

  从设备总线的框架中,了解到 硬件相关的部分为device,相对而言比较稳定的部分是driver。  driver 部分通过driver_register 把driver的结构体放入drv链表中, device除了通过device_add 把device结构体放入到总线的drv链表中以外,还会将device从drv中取出来,通过drv中的math函数与driver 进行比较,看driver可不可以支持device, 可以的话就调用probe函数。那怎么知道是不是匹配的呢????  在平台的platform_match中通过比较device的名字和driver的名字是否匹配,如果匹配,系统就认为是匹配的,就会调用probe函数。

  这是一种左右两边建立链接的机制。

                 1、 把device 放入bus的drv链表                  |        1、 把driver 放入bus的drv链表

  dev       2、 从bus的drv链表取出每一个driver,用match函数判断是否支持dev   |     driver      2、 从bus的drv链表取出每一个dev,用match函数判断是否支持driver

                 3、 若支持,则调用 driver 的probe函数                                                  |                             3、 若支持,则调用probe函数

  下面进行led驱动的源码分析。

  前面我们所说的driver 和device 他们指的是结构体。device的结构体中定义了device 的名字,资源,id,release。我们着重关注的是device的名字。 led_resource 是什么呢?

static struct platform_device led_dev = {
      .name         = "myled",
      .id       = -1,
      .num_resources    = ARRAY_SIZE(led_resource),
      .resource     = led_resource,
      .dev = {
          .release = led_release,
      },
  };

  led_resource结构体

 static struct resource led_resource[] = {
      [0] = {                    //寄存器地址
          .start = 0x56000050,
         .end   = 0x56000050 + 8 - 1,
          .flags = IORESOURCE_MEM,       //使用MEM资源
      },
      [1] = {                    //第5个引脚,
          .start = 5,
          .end   = 5,
          .flags = IORESOURCE_IRQ,        //使用IRQ资源
      }

  };

  led_release、 入口出口函数

static void led_release(struct device * dev)
  {
  }

//入口 出口函数static int led_dev_init(void)
  {
      platform_device_register(&led_dev);
      return 0;
  }

  static void led_dev_exit(void)
  {
      platform_device_unregister(&led_dev);
  }

  driver部分: 先建立好基本的框架 入口出口函数+修饰

 static int led_drv_init(void)
 {
     platform_driver_register(&led_drv);
     return 0;
 }

 static void led_drv_exit(void)
 {
     platform_driver_unregister(&led_drv);
 }

 module_init(led_drv_init);
 module_exit(led_drv_exit);

 MODULE_LICENSE("GPL");

  建立file_operlation 为访问提供接口

static struct file_operations led_fops = {
    .owner  =   THIS_MODULE,
     .open   =   led_open,
     .write  =   led_write,
 };

  创建open、 write 函数

static int led_open(struct inode *inode, struct file *file)
  {
    //printk("first_drv_open\n");
    *gpio_con &= ~(0x3<<(pin*2));
     *gpio_con |= (0x1<<(pin*2));
     return 0;
 }

 static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
    int val;

     //printk("first_drv_write\n");

   copy_from_user(&val, buf, count); //    copy_to_user();

    if (val == 1)
    {
        *gpio_dat &= ~(1<<pin);
     }
     else
     {
        *gpio_dat |= (1<<pin);
    }

    return 0;
 }

  构造一个平台驱动结构体

struct platform_driver led_drv = {
     .probe      = led_probe,
     .remove     = led_remove,
     .driver     = {
         .name   = "myled",   //名字要和之前led_dev的保持一致
     }
 };

  创建probe函数, 调用device提供的资源进行硬件相关的配置  这些配置都是固定不变的,只要改变device的资源就可以改变 probe的硬件配置,这部分时不用进行修改的。

static int led_probe(struct platform_device *pdev)
 {
    struct resource     *res;

     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    gpio_con = ioremap(res->start, res->end - res->start + 1);
    gpio_dat = gpio_con + 1;

    res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    pin = res->start;

      printk("led_probe, found led\n");

    major = register_chrdev(0, "myled", &led_fops);

     cls = class_create(THIS_MODULE, "myled");

     class_device_create(cls, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led */

    return 0;
 }

  最后为卸载驱动提供函数

static int led_remove(struct platform_device *pdev)
 {
    /* iounmap */
    printk("led_remove, remove led\n");

     class_device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);
    unregister_chrdev(major, "myled");
     iounmap(gpio_con);

     return 0;
 }

  S3C2440 驱动分离分层概念到此结束。

  

  

  

时间: 2024-10-18 19:50:13

S3C2440 驱动分层概念的相关文章

驱动程序分层概念

写一下个人对驱动分层的理解,简单的说将驱动分层也就是将驱动中硬件操作的代码和软件处理的代码分为两部分,软件相关的代码较稳定,硬件相关的代码可能因硬件的变动而做出相应调整.这样做的好处是便于编写大型的驱动,好比我们的编程中写的函数将功能模块化,模块化的好处这里就不说了. 以JZ2440开发板的点亮led的操作做一下总结,驱动分为led_dev.c,led_drv两部分,另外还有一个测试程序led_test.c led_dev:硬件资源 led_dev是和硬件设备相关的代码,其功能是包含.上报可供调

osgi实战学习之路:3. osgi分层概念及相互合作demo

源代码下载 分层: modual: 主要作用于包级管理与共享代码 lifecycle: 主要作用于运行期间的模块管理与访问osgi底层框架 service: 主要作用于多模块之间的相互通信 demo: hello-provider/pom.xml <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.or

Java分层概念(转)

layout: default title: Java分层概念(转) category: [技术, Java, 代码学习] comments: true --- Java分层概念(转) 对于分层的概念,似乎之间简单的三层,多了,就有点难以区分了,所以收藏了这个. ervice是业务层 action层即作为控制器 DAO (Data Access Object) 数据访问 1.JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分?(下面所描述的service层就是b

Linux驱动之平台设备驱动模型简析(驱动分离分层概念的建立)

Linux设备模型的目的:为内核建立一个统一的设备模型,从而有一个对系统结构的一般性抽象描述.换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同的属性在内核中实现,而为需要新添加设备或驱动提供一般性的统一接口,这使得驱动程序的开发变得更简单了,而程序员只需要去学习接口就行了. 对于整个设备总线驱动模型的样子,如下图.简单来说,bus 负责维护注册进来的devcie 与 driver,每注册进来一个device 或者 driver 都会调用 Bus->match 函数

linux驱动的分离分层概念

bus_drv_dev模型:功能改写只需改dev硬件代码即可,drv不需改写. LED例子 下面用一个点亮LED的例子来说明这个分离的的例子: led_dev.c  定义这个平台设备的资源: static struct resource led_resource[] = {  [0] = { .start  = 0x56000010, //GPFCON的物理地址  .end    = 0x56000010 + 8 - 1,   .flags  = IORESOURCE_MEM, },  [1] 

[Java]Java分层概念(转)

service是业务层 action层即作为控制器 DAO (Data Access Object) 数据访问 1.JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分?(下面所描述的service层就是biz)       首先这是现在最基本的分层方式,结合了SSH架构.modle层就是对应的数据库表的实体类. Dao层是使用了Hibernate连接数据库.操作数据库(增删改查). Service(biz)层:引用对应的Dao数据库操作,在这里可以编写自己需要的

[Java]Java分层概念

service是业务层 action层即作为控制器 DAO (Data Access Object) 数据访问 1.JAVA中Action层, Service层 ,modle层 和 Dao层的功能区分?(下面所描述的service层就是biz)       首先这是现在最基本的分层方式,结合了SSH架构.modle层就是对应的数据库表的实体类. Dao层是使用了Hibernate连接数据库.操作数据库(增删改查). Service(biz)层:引用对应的Dao数据库操作,在这里可以编写自己需要的

[windows驱动]基本概念

https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff554721 1.设备节点和设备堆栈 在windows中,设备通过即插即用设备树中的设备节点表示.典型地,当设备接受到一个I/O请求,数个驱动帮忙处理这个请求,这些驱动各自与一个设备对象相关,这些设备对象在堆栈中有序排列.一个设备对象序列以及它们各自相关的驱动称为设备堆栈.每个设备节点拥有一个它们自己的设备堆栈. 1.2.设备对象和设备堆栈 一个设备对象是一个DEVICE_OB

进程管理和终端驱动基本概念

一.前言 对于任何一种OS,终端部分的内容总是令人非常的痛苦和沮丧,GNU/linux也是如此.究其原因主要有两个,一是终端驱动和终端相关的系统软件承载了太多的内容:各种虚拟终端. 伪终端.串口通信.modem.printer等.其次可能是终端和信号处理.进程关系等耦合在一起加大了理解终端驱动的难度.本文的目标是希望能够理清这些内容. 在第二章,本文会简单介绍终端的一些基础知识,这些知识在wowo的终端基本概念文档中也有描述,我这里也重复一次,加深印象(呵呵,其实这一章的内容一年前就写了,后来暂