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 驱动分离分层概念到此结束。


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

相关文章

    机控制板一个 ** ②** 、二相四线步进电机一个 ** ③** 、稳压电源一个 ** ④** 、TB6600****步进电机驱动器一个 ** 连接完成图:** ** 硬件连接图说明:** ①51单片机控制板与TB6600......
    ) ②USB转TTL模块1个(图2) ③稳压电源1个(图3) ④TB6600步进电机驱动器1个 (图4) ⑤二相四线步进电机1个(图5) ⑥电线若干 二、接线 2.1原理图 2.2实物连接图 三......
    方案。 4:步进电机的控制驱动方案介绍。 步进电机驱动器设计教程 1:常见步进电机的接线形式(两相四线,四相五线 ,四相六线,四相八线,三相步进电机 )以及运行原理。 2:详细介绍步进电机的多种驱动......
    器上的设置参数,以下图DM542两相四线步进电机驱动器为例。   八个拨码按顺序开关以sw1~sw8表示。从左侧图标看出,其中sw1~sw3的不同开关状态组合可以调节电机驱动......
    步进电机的常用驱动方式;步进电机的驱动 stm32为例,使用ULN2003,TB6600电机驱动板,介绍步进电机的常用驱动方式。 步进电机 我使用的是一个教学用的小步进电机驱动电压只有5V,所有的步进电机驱动原理......
    ,具体而言是两相四线步进电机。它由定子和转子两个主要部件组成(见图 1)。 图1: 双极性步进电机的结构示意图 定子 定子是电机的静止部分。8 个定......
    林顿功率管TIP142组成的电路作为驱动器,电路结构简单,设计思路清晰。 如上图,单极性驱动电路。 如上图,双极性驱动电路。三相反应式步进电机驱动电路 四线步进电机驱动......
    供电。 步进电机外观图 电机驱动原理图及控制接线关系 本次电机驱动芯片采用TOSHIBA的TB67S109AFTG芯片来驱动双极性步进电机,该芯片支持最大驱动电压为50V,最大驱动电流为5A,最大......
    出同一绕组简单方法是,将任意一根线分别与其他的线接触,同时转动电机轴,感觉有卡滞时两根线就是同一绕组,将两个绕组接驱动器的A+、A-、B+、B-、端子即可。   步进电机怎么接线   一般的6线步进电机......
    ,具体而言是两相四线步进电机。它由定子和转子两个主要部件组成(见图1)。 图1:双极性步进电机的结构示意图 定子 定子是电机的静止部分。8个定子上分别绕有两相双极性绕组,每个......

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

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

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

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

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

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

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