当前位置: 首页 > 工具软件 > xBus > 使用案例 >

第五十讲 自定义总线(xbus)

白烨煜
2023-12-01

第五十讲 自定义总线(xbus)

一、概述

前面的几个驱动代码软件和硬件都是夹杂在一起的,这样就会使得驱动的复用性比较低。Bus是链接处理器和其他设备之间的通道。内核规定,系统中的每个设备都要连接在一个Bus上,这个Bus可以是一个内部Bus、虚拟Bus或者Platform Bus。前面的驱动通过引入驱动总线,将硬件相关与软件相关的代码进行分离,将结构体device关联硬件相关代码,将driver_devices关联软件代码,通过设置match匹配规则,使用bus_type对设备进行统一管理。

二、重要函数

1、buses_init

这个函数实在linux启动的时候就自动执行的,主要是建立Linux设备模型总线部分的顶级节点。buses_init函数建立了/sys/bus这个顶级容器节点,该节点是Linux内核中所有总线类型的父节点。

2、bus_register

  • 原型:int bus_register(struct bus_type *bus)

  • 作用:(添加一个新的总线类型)

    在/sys/bus下建立xbus目录项,并创建属性文件

    在/sys/bus/xbus下建立devices目录项,并创建属性文件

    在/sys/bus/xbus下建立drivers目录项,并创建属性文件

    初始化 priv->klist_devices链表头

    初始化priv->klist_drivers链表头

3、device_register

  • 原型:int device_register(struct device *dev)

  • 作用:(添加设备,关联硬件相关代码)

    在/sys/bus/xbus/devices下建立yyy目录项

    加入bus-> priv->devices_kset链表

    加入bus-> priv->klist_devices链表

    遍历bus-> priv->klist_drivers,执行bus->match()寻找合适的drv

    dev关联driv,执行drv->probe()

4、driver_register

  • 原型:int driver_register(struct device_driver *drv)

  • 作用:(添加驱动,关联软件相关代码)

    在/sys/bus/xbus/drivers下建立zzz目录项

    加入bus-> priv->drivers_kset链表

    加入bus-> priv->klist_drivers链表

    遍历bus-> priv->klist_klist_devices链表,执行bus->match()寻找合适的dev

    dev关联dev,执行drv->probe()

三、xbus实验

1、代码

xbus.c

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

/*
*本文件主要是添加一个新的总线类型
*/
/*
*match 规则
*/
int match(struct device *dev, struct device_driver *drv)
{
    if(strncmp(dev_name(dev), drv->name, strlen(drv->name)))
    {
        printk(KERN_ERR"xBus match failed!\r\n");
        return 0;
    }
    printk(KERN_ERR"xBus match successed!\r\n");
    return 1;
}
/*初始化设备*/
static struct bus_type xBus = 
{
    .name = "xBus",
    .match = match,
};
static int __init xBusInit(void)
{
    printk(KERN_ERR"Enter xBus init functions\r\n");
    if(bus_register(&xBus))
    {
        printk(KERN_ERR"Enter xBus init failed!\r\n");
        return -1;
    }
    return 0;
}
static void __exit xBusExit(void)
{
    printk(KERN_ERR"Exit xBus init functions\r\n");
    return ;
}

/*声明外部调用*/
EXPORT_SYMBOL (xBus);
/*声明函数*/
module_init(xBusInit);
module_exit(xBusExit);

/**/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("xBus module!");
MODULE_ALIAS("xBus_module");

xdev.c

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

extern struct bus_type xBus;
/**/
void xDevRelease(struct device *dev)
{
	printk("%s-%s\n", __FILE__, __func__);
}
/*
*本文件主要是添加一个新的设备(硬件相关)
*/
static struct device dev = 
{
    .init_name = "xbus_test",
    .bus = &xBus,
    .release = xDevRelease,
};
/*初始化设备*/
static int __init xDevInit(void)
{
    printk(KERN_ERR"Init xDev init functions\r\n");
    if(device_register(&dev))
    {
        printk(KERN_ERR"Init xDev init failed!\r\n");
        return -1;
    }
    return 0;
}

static void __exit xDevExit(void)
{
    printk(KERN_ERR"Exit xDev init functions\r\n");
    return ;
}

/*声明函数*/
module_init(xDevInit);
module_exit(xDevExit);

/**/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("xDev module!");
MODULE_ALIAS("xDev_module");

xdrv.c

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

extern struct bus_type xBus;

int xDrvProbe(struct device *dev)
{
    printk(KERN_ERR"Match success!\r\n");
    return 0;
}
int xDrvRemove(struct device *dev)
{
    printk(KERN_ERR"Close xbus_test derver!\r\n");
    return 0;
}
/*
*本文件主要是添加一个新的设备(硬件相关)
*/
static struct device_driver xDrv = 
{
    .name = "xbus_test",
    .bus = &xBus,
    //当驱动和设备匹配成功之后,便会执行驱动的probe函数
	.probe = xDrvProbe,
	//当注销驱动时,需要关闭物理设备的某些功能等
	.remove = xDrvRemove,
};
/*初始化设备*/
static int __init xDrvInit(void)
{
    printk(KERN_ERR"Init xDrv init functions\r\n");
    if(driver_register(&xDrv))
    {
        printk(KERN_ERR"Init xDrv init failed!\r\n");
        return -1;
    }
    printk(KERN_ERR"Init xDrv functions success!\r\n");
    return 0;
}

static void __exit xDrvExit(void)
{
    printk(KERN_ERR"Exit xDrv init functions\r\n");
    return ;
}

/*声明函数*/
module_init(xDrvInit);
module_exit(xDrvExit);

/**/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yeyu");
MODULE_DESCRIPTION("xDrv module!");
MODULE_ALIAS("xDrv_module");

Makefile

KERNEL_DIR=../../ebf_linux_kernel/build_image/build/

ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
export  ARCH  CROSS_COMPILE

obj-m := xbus.o xdev.o xdrv.o

all:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean copy

clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean	

copy:
	sudo  cp  *.ko  /home/dragon/nfsshare

2、实验步骤

  • 编译代码

    make

  • 将ko文件复制到共享文件夹

    make copy

  • 打开开发板

  • 登陆开发板

  • 连接到远程文件夹(nfs)

    sudo mount -t nfs 192.168.3.41:/home/dragon/nfsshare /mnt

  • 加载模块(注意顺序)

    命令

    sudo insmod /mnt/xbus.ko

    现象

    xbus: loading out-of-tree module taints kernel.
    Enter xBus init functions
    

    命令

    sudo insmod /mnt/xdev.ko

    现象

    Init xDev init functions
    

    命令

    sudo insmod /mnt/xdrv.ko

    现象

    [   94.381356] Init xDrv init functions
    [   94.391380] xBus match successed!
    [   94.398011] Match success!
    [   94.409179] Init xDrv functions success!
    
 类似资料: