• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

platform和设备树驱动蜂鸣器

武飞扬头像
豆丁熊
帮助1

目录

1.plat_fom介绍:

2.设备树介绍:

3.实现过程:

1.设备树:(以exynos-fs4412为例)

2.平台驱动:

3.驱动的启动函数:  

4.驱动卸载


1.platform介绍:

        从Linux2.6开始Linux加入了一套驱动管理和注册机制—platform总线驱动模型。platform总线是一条虚拟总线(只有一条),这类总线没有对应的硬件结构platform_device为相应的设备,platform_driver为相应的驱动。与传统的bus/device/driver机制相比,platform由内核统一进行管理,提高了代码的可移植性和安全性。

优点:

1.可以通过platform总线,可以遍历所有的platform总线设备;platform本质其实也是kset、  kobject,具有kobject的特性;
2.实现设备与驱动的分离,通过platform总线,设备与驱动是分开注册的,通过platform总线的  probe来随时检测与设备匹配的驱动,如匹配上即进行这个设备的驱动注册;
3.一个驱动可以供同类的几个设备使用;

2.设备树介绍:

          设备树是一种描述硬件得数据结构,在操作系统引导阶段进行设备初始化得时候,数据结构中得硬件信息被检测并传递给操作系统。

          Liunx内核从3.x开始引入设备树得概念,用于实现驱动代码与设备信息相分离。在设备树出现之前,所有关于设备得具体信息都要写在驱动里面,一旦外围设备变化,驱动代码就要重写。引入设备树后,驱动代码只负责处理驱动得逻辑,而关于设备具体信息要存放到设备树文件中。

          这样,如果只是硬件接口信息得变化而没有驱动逻辑得变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码。

3.实现过程:

1.设备树:(以exynos-fs4412为例)

        首先在设备树文件中添加蜂鸣器的设备节点,同时添加对应寄存器地址,由于设备树可以自动遍历查找地址,所以只需填写一个地址范围,包含所有的寄存器就行。compatible ="fs,mybee"而这句话就代表一种匹配规则。

  1.  
    mybee@11000ca0{
  2.  
    compatible ="fs,mybee";
  3.  
    reg = <0x11000a40 0x4>,<0x139d0000 0x14>;
  4.  
    };

2.平台驱动:

1)首先我们可以搭建一个平台驱动的基本框架,框架如下,我们在对应的位置填入对应的代码。

  1.  
    #include <linux/init.h>
  2.  
    #include <linux/module.h>
  3.  
    #include <linux/platform_device.h>
  4.  
    #include <linux/cdev.h>
  5.  
    #include <linux/fs.h>
  6.  
    #include <linux/err.h>
  7.  
    #include <asm/io.h>
  8.  
     
  9.  
    struct of_device_id of_matches[]={
  10.  
    //修改匹配规则,从设备树
  11.  
    //获取buzzer相关硬件信息
  12.  
    };
  13.  
    static struct platform_driver mydriver ={
  14.  
    //通过设备树匹配
  15.  
     
  16.  
    };
  17.  
    static int mod_init(void)
  18.  
    {
  19.  
    return platform_driver_register(&mydriver); //平台驱动注册
  20.  
    }
  21.  
    static void mod_exit(void)
  22.  
    {
  23.  
    platform_driver_unregister(&mydriver); //平台驱动注销
  24.  
    }
  25.  
     
  26.  
    module_init(mod_init);
  27.  
    module_exit(mod_exit);
  28.  
    MODULE_LICENSE("GPL");
学新通

2)我们修改匹配机制,从设备树匹配,配诶规则一定要和我们写的设备树中的规则一致。

  1.  
    struct of_device_id of_matches[]={
  2.  
    {.compatible="fs,mybee"}, //修改匹配规则,从设备树
  3.  
    {}, //获取buzzer相关硬件信息
  4.  
    };

3) paltform选择匹配方式:

  1.  
    static struct platform_driver mydriver ={
  2.  
    .probe = my_probe,
  3.  
    .remove = my_remove,
  4.  
    .driver = {
  5.  
    .name = "mytest",
  6.  
    .of_match_table = of_matches, //通过设备树匹配
  7.  
    },
  8.  
     
  9.  
    };

3.驱动的启动函数:  

      前面的准备工作完成后,从设备树中获取设备的信息,就需要将字符设备注册到内核中,首先将所需的寄存器物理地址映射为虚拟地址,然后进行字符设备的注册,首先申请设备号,然后cdev初始化,紧接着将cdev添加到内核,当所有步骤完成后就可以添加硬件操作的函数了。

  1.  
    int my_probe(struct platform_device *pdev)
  2.  
    {
  3.  
    int ret;
  4.  
    //通过设备树获取硬件资源
  5.  
    printk( "match\n");
  6.  
     
  7.  
    //0代表匹配的设备树第0个地址为基地址
  8.  
    rescon = platform_ get_ resource (pdev , IORESOURCE MEM, 0);
  9.  
    if ( rescon=-NULL){
  10.  
    goto failed_ getcon;
  11.  
    }
  12.  
    resdata = platform get_ resource (pdev , IORESOURCE MEM,1) ;
  13.  
    if ( resdata==NULL ){
  14.  
    goto failed_ getdata;
  15.  
    gpd0con = ioremap( rescon->start,4);
  16.  
    //利用设备树获取各个寄存器的地址
  17.  
    tcfg0 = ioremap( resdata->start,4) ;
  18.  
    tcfg1 = ioremap ( resdata->start 4,4) ;
  19.  
    tcon = ioremap( resdata->start 8,4);
  20.  
    tcntb0 = ioremap ( resdata->start 12,4);
  21.  
    tcmpb0 = ioremap( resdata->start 16,4);
  22.  
     
  23.  
    //字符设备注册
  24.  
    ret = alloc_chrdev_region(&devnum,0,1,name);//1.申请设备号
  25.  
    if(ret!=0){
  26.  
    goto failed_alloc;
  27.  
    }
  28.  
    cdev_init(&mycdev,&myops); //2.cdev初始化
  29.  
     
  30.  
    ret = cdev_add(&mycdev,devnum,1); //3.cdev添加到内核
  31.  
    if(ret!=0){
  32.  
    goto failed_add;
  33.  
    }
  34.  
    printk("register success %d,%d\n",MAJOR(devnum),MINOR(devnum));
  35.  
     
  36.  
    myclass = class_create(THIS_MODULE,"myclass");
  37.  
    if(IS_ERR(myclass)){
  38.  
    goto failed_class;
  39.  
    }
  40.  
    mydevice = device_create(myclass,NULL,devnum,NULL,"buzzer");
  41.  
    if(IS_ERR(mydevice)){
  42.  
    goto failed_device;
  43.  
    }
  44.  
    //硬件操作
  45.  
    buzzer_init();
  46.  
    buzzer_off();
  47.  
     
  48.  
    return 0;
  49.  
     
  50.  
    failed_device:
  51.  
    class_destroy(myclass);
  52.  
    failed_class:
  53.  
    cdev_del(&mycdev);
  54.  
    failed_add:
  55.  
    unregister_chrdev_region(devnum,1);
  56.  
    failed_alloc:
  57.  
    return -1;
  58.  
    }
学新通

4.驱动卸载

        现将所有的寄存器解除映射,释放设备号,释放设备对象,删除设备,将设备从内核中注销。

  1.  
    int my_remove(struct platform_device *pdev)
  2.  
    {
  3.  
    printk("driver remove\n");
  4.  
    iounmap(gpd0con);
  5.  
    iounmap(tcfg0);
  6.  
    iounmap(tcfg1);
  7.  
    iounmap(tcon);
  8.  
    iounmap(tcntb0);
  9.  
    iounmap(tcmpb0);
  10.  
     
  11.  
    device_destroy(myclass,devnum);
  12.  
    class_destroy(myclass);
  13.  
    cdev_del(&mycdev);
  14.  
    unregister_chrdev_region(devnum,1);
  15.  
     
  16.  
    return 0;
  17.  
    }
学新通

        这样就基本完成了整个蜂鸣器的驱动编写,希望有帮助!

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakfab
系列文章
更多 icon
同类精品
更多 icon
继续加载