S3C2440 驱动分层概念

发布时间:2023-08-10  

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


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


  以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_openn");

    *gpio_con &= ~(0x3<     *gpio_con |= (0x1<     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_writen");

 

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


    if (val == 1)

    {

        *gpio_dat &= ~(1<     }

     else

     {

        *gpio_dat |= (1<    }

 

    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 ledn");


    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 ledn");

 

     class_device_destroy(cls, MKDEV(major, 0));

    class_destroy(cls);

    unregister_chrdev(major, "myled");

     iounmap(gpio_con);

  

     return 0;

 }


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


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

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>