电源设计技术实用资料点击免费获取>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 开源硬件 » 芯灵思SinlinxA33开发板Linux总线设备驱动实现过程(附代码)

共1条 1/1 1 跳转至

芯灵思SinlinxA33开发板Linux总线设备驱动实现过程(附代码)

助工
2019-03-05 17:25:47    评分

开发平台 芯灵思Sinlinx A33
内存: 1GB   存储: 4GB

详细参数 https://m.tb.cn/h.3wMaSKm
开发板交流群 641395230


总线驱动设备模型:

  • 1、总线驱动设备模型只是提供一种机制,将驱动程序分为device和driver两部分并彼此建立联系

  • 2、注册device过程:

  •     a、将device放入bus的dev链表

  •     b、从bus的drv链表取出每一个driver,用bus的match函数判断取出的driver能否支持这个device(判断name)

  •     c、如果支持,调用该driver的probe函数(probe函数自由实现)

  • 3、注册driver过程:

  •     a、将driver放入bus的drv链表

  •     b、从bus的dev链表取出每一个device,用bus的match函数判断这个driver能否支持取出的device(判断name)

  •     c、如果支持,调用该driver的probe函数(probe函数自由实现)



在linux系统总线存在目录/sys/bus/

总线结构体:描述一个总线,管理device和driver,完成匹配
struct bus_type {
    const char        *name;                                                    /*总线名*/
    const char        *dev_name;
    struct device        *dev_root;
    struct bus_attribute    *bus_attrs;
    struct device_attribute    *dev_attrs;//设备属性
    struct driver_attribute    *drv_attrs;//驱动属性
    int (*match)(struct device *dev, struct device_driver *drv); //设备驱动匹配函数
    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
    int (*probe)(struct device *dev);
    int (*remove)(struct device *dev);
    void (*shutdown)(struct device *dev);
    int (*suspend)(struct device *dev, pm_message_t state);
    int (*resume)(struct device *dev);
    const struct dev_pm_ops *pm;
    struct iommu_ops *iommu_ops;
    struct subsys_private *p;

};
总线注册和注销
    int bus_register(struct bus_type *bus)
    void bus_unregister(struct bus_type *bus)

/=================================================================/
device对象
struct device {
    struct kobject kobj;  //所有对象的父类
    const char        *init_name; // 在总线中会有一个名字,用于做匹配
    struct bus_type    *bus; //指向该device对象依附于总线的对象
    void        *platform_data; // 自定义的数据,指向任何类型数据

device对象注册和注销的方法
    int device_register(struct device *dev)
    void device_unregister(struct device *dev)
/=================================================================/
driver对象:描述设备驱动的方法(代码逻辑)
struct device_driver {
    const char        *name;
    // 在总线中会有一个名字,用于做匹配,在/sys/bus/mybus/drivers/名字
    struct bus_type        *bus;//指向该driver对象依附于总线的对象
    int (*probe) (struct device *dev); // 如果device和driver匹配之后,driver要做的事情
    int (*remove) (struct device *dev); // 如果device和driver从总线移除之后,driver要做的事情
}
driver对象注册和注销
    int driver_register(struct device_driver *drv)
    void driver_unregister(struct device_driver *drv)

总线代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>


int mybus_match(struct device *dev, struct device_driver *drv)
{
    //如果匹配成功,match方法一定要返回一个1, 失败返回0
    if(!strncmp(drv->name, dev->kobj.name, strlen(drv->name)))
    {
        printk("match ok\n");
        return 1;
    }else{
        printk("match failed\n");
        return 0;

    }
    return 0;
}


//实例化一个bus对象
struct bus_type mybus = {
    .name = "mybus",
    .match = mybus_match,
};

EXPORT_SYMBOL(mybus);//使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用

static int __init mybus_init(void)
{
    printk("----------%s-------------\n", __FUNCTION__);
    int ret;

    //构建一个总线
    // /sys/bus/mybus
    ret = bus_register(&mybus);
    if(ret != 0)
    {
        printk("bus_register error\n");
        return ret;
    }
    return 0;
}

static void __exit mybus_exit(void)
{
    printk("----------%s-------------\n", __FUNCTION__);
    bus_unregister(&mybus);
    
}

module_init(mybus_init);
module_exit(mybus_exit);
MODULE_LICENSE("GPL");

driver代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/io.h>
int mydrv_probe(struct device *dev)
{
    printk("----------%s-------------\n", __FUNCTION__);
    
    return 0;
}

int mydrv_remove(struct device *dev)
{

    printk("----------%s-------------\n", __FUNCTION__);
    return 0;
}

extern struct bus_type mybus;

struct device_driver mydrv = {
    .name = "my_dev_drv",
    .bus = &mybus,
    .probe = mydrv_probe,
    .remove = mydrv_remove,
};


static int __init mydrv_init(void)
{
    printk("----------%s-------------\n", __FUNCTION__);
    //将driver注册到总线中
    int ret;
    ret  = driver_register(&mydrv);
    if(ret < 0)
    {
        printk("device_register error\n");
        return ret;
    }
    

    return 0;
}
static void __exit mydrv_exit(void)
{

    printk("----------%s-------------\n", __FUNCTION__);
    driver_unregister(&mydrv);
}





module_init(mydrv_init);
module_exit(mydrv_exit);
MODULE_LICENSE("GPL");

device代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include "dev_info.h"
extern struct bus_type mybus;
void    mydev_release(struct device *dev)
{

    printk("----------%s-------------\n", __FUNCTION__);
}

//构建一个device对象
struct device  mydev= {
    .init_name = "my_dev_drv",
    .bus = &mybus,
    .release = mydev_release,
};



static int __init mydev_init(void)
{
    printk("----------%s-------------\n", __FUNCTION__);
    //将device注册到总线中
    int ret;
    ret  = device_register(&mydev);
    if(ret < 0)
    {
        printk("device_register error\n");
        return ret;
    }
    

    return 0;
}

static void __exit mydev_exit(void)
{

    printk("----------%s-------------\n", __FUNCTION__);
    device_unregister(&mydev);

}



module_init(mydev_init);
module_exit(mydev_exit);
MODULE_LICENSE("GPL");






---------------------
参考文章https://blog.csdn.net/hfutyyj/article/details/80248904




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]