Lao Cha's ARM study notes: chapter-2 (Detailed explanation of Linux bus device driver)

Publisher:BlossomWhisperLatest update time:2022-05-26 Source: eefocusKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1 Overview of Bus Device Driver Model

With the continuous advancement of technology, the system topology is becoming more and more complex, and the requirements for intelligent power management and hot-swap support are becoming higher and higher. The 2.3 kernel can no longer meet these requirements. In order to adapt to this situation, the Linux 2.6 kernel provides a new kernel device model.

The function of the bus is to sense whether the device is connected to USB, network card, etc. The bus device driver model better supports hot-plug devices and provides better portability.

In the device model, we will see that the device driver is mainly composed of three parts: bus, driver, and device. Through these three standard components, various complex devices are grouped together to simplify the writing of device drivers. Next, we will study the three parts of bus, driver, and device.

Write the picture description here

2 Bus

1 Bus Description

In the Linux kernel, the bus is represented by the bus_type structure, the most important of which is the bus name and matching function.


struct bus_type {

const char *name; /*bus name*/

int (*match) (struct device *dev, struct device_driver *drv); /*Driver and device matching function*/

………

}


2 Bus Registration

The bus registration uses the following function

bus_register(struct bus_type *bus)

If successful, the new bus will be added to the system and the corresponding directory can be seen under /sys/bus.


3 Bus deregistration

The bus deregistration uses the following function

void bus_unregister(struct bus_type *bus)

Code example bus.c:


#include

#include

#include

#include //for bus_type



int my_match (struct device *dev, struct device_driver *drv) //Match the newly added bus and the newly added device. If they match, return non-zero, otherwise return zero

{


    return 0;

}


struct bus_type my_bus_type = { //define bus

    .name="my_bus",

    .match=my_match,    

};


int my_bus_init()

{

    int ret;

    ret=bus_register(&my_bus_type);//Register a bus

    return right;

}


void my_bus_exit()

{

    bus_unregister(&my_bus_type); //Unregister bus

}


module_init(my_bus_init);

module_exit(my_bus_exit);

MODULE_LICENSE("GPL");


After compiling the code, copy the bus.ko code to the development board. After loading the module, you can view the bus we added to the Linux system through the ls /sys/bus command.

Write the picture description here

driver

1 Driver Description

In the Linux kernel, drivers are represented by the device_driver structure.


struct device_driver {

{

const char *name; /*Driver name*/

struct bus_type *bus; /*The bus where the driver is located*/

int (*probe) (struct device *dev);

………

}


When a device is added to the bus, the probe function will be called to process the device accordingly when the bus and the device match.


2 Driver Registration

The driver registration uses the following function

int driver_register(struct device_driver *drv)


3 Driver deregistration

The driver's deregistration uses the following function

void driver_unregister(struct device_driver *drv)

Code example driver.c


#include

#include

#include  

#include


extern struct bus_type my_bus_type; //Use an external module


int my_probe(struct device *dev)

{

    printk(KERN_WARNING"driver found the device !n");

    return 0;

}


struct device_driver  my_driver = {

    .name="my_dev", //This name is very important and must be the same as the device name

    .bus=&my_bus_type, //The bus to be mounted

    .probe=my_probe, //When the device name and the driver name are the same, call the probe function

};

int my_driver_init()

{

    int ret;

    ret = driver_register(&my_driver); //Register driver

    return right;


}


void my_driver_exit()

{

    driver_unregister(&my_driver); //Unregister the driver

}


module_init(my_driver_init);

module_exit(my_driver_exit);

MODULE_LICENSE("GPL");


After the code is numbered, copy the driver.ko code to the development board. After loading the insmod driver.ko module, you can view the bus we added to the Linux system through the ls /sys/bus command. From the experimental results, we have mounted the drivers driver on the my_bus bus. Enter drivers and you can see the driver name my_dev we created.

Write the picture description here

4 Equipment

1. Description of the device

In the Linux kernel, devices are represented by the struct device structure.


struct device {

{

const char *init_name; /*Device name*/

struct bus_type *bus; /*The bus where the device is located*/

………

}


The name of the device should be consistent with the name of the driver under the driver.


2. Device Registration

The device registration uses the following function

int device_register(struct device *dev)


3. Device deregistration

The device deregistration uses the following function

void device_unregister(struct device *dev)

Code example:

device.c


#include

#include

#include

#include


extern struct bus_type my_bus_type; //Call the my_bus_type bus in bus.c


struct device my_dev={


    .init_name="my_dev", /*The name of the device should be the same as the driver name*/

    .bus=&my_bus_type, /*The bus where the device is located*/  

};


int my_device_init()

{

    int ret;

    ret = device_register(&my_dev); //Device registration

    return right;


}


void my_device_exit()

{

    device_unregister(&my_dev); //Deregister the device

}


module_init(my_device_init);

module_exit(my_device_exit);

MODULE_LICENSE("GPL");


bus.c


#include

#include

#include

#include //for bus_type


int my_match (struct device *dev, struct device_driver *drv) //Match the newly added bus and the newly added device. If they match, return non-zero, otherwise return zero

{

//Match the name in the driver module with the name in the device module

    //return !strncmp(dev->init_name,drv->name,strlen(drv->name));

    /*In the Core.c file in the kernel source code, dev->init_name = NULL in the device_register() function will be cleared.

    The following matches will match a null pointer. */

    return !strncmp(dev->kobj_name,drv->name,strlen(drv->name)); 

    /*Actually, init_name is assigned to kobj.name. So in the strncmp() function, it should be dev->kobj.name*/

    //return 0;

}


struct bus_type my_bus_type = {

    .name="my_bus",

    .match=my_match,    

};

EXPORT_SYMBOL(my_bus_type); //Export module to driver.c device.c


int my_bus_init()

{

    int ret;

    ret=bus_register(&my_bus_type);

    return right;

}


void my_bus_exit()

{

    bus_unregister(&my_bus_type);

}


module_init(my_bus_init);

module_exit(my_bus_exit);

MODULE_LICENSE("GPL");


driver.c


#include

#include

#include  

#include


extern bus_type my_bus_type; //Use an external module


int my_probe(struct device *dev)

{

    printk(KERN_WARNING"driver found the device it can handle!n");

    return 0;

}


struct device_driver = my driver{

    .name="my_dev"; //This name is very important and must be the same as the device name

    .bus=&my_bus_type; //The bus to be mounted

    .probe=my_probe; //When the device name and the driver name are the same, call the probe function

};

int my_driver_init()

{

    int ret;

    ret = driver_register(&my_driver); //Register driver

    return right;


}


void my_driver_exit()

{

    void driver_unregister(&my_driver); //Unregister the driver

}


module_init(my_driver_init);

module_exit(my_driver_exit);

MODULE_LICENSE("GPL");


Makefile


obj-m := bus.o device.o driver.o


KDIR :=/home/S5-driver/lesson7/linux-ok6410


all:

    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm


clean:

    rm -f *.of *.ko *.bak


Because the matching function in bus.c has modified the code, see the match code in bus.c for details, so after compiling the module here, you need to restart the development board and copy bus.ko, driver.ko and device.ko to the development board. We see the result we expect, "driver found the device!", which means that the match function on the bus has matched the driver and the device, and then calling the probe function will result in the expected result.

Write the picture description here

5 Platform Bus Device Design

1 Platform Bus Overview

Platform bus: Platform bus is a virtual bus added to the Linux 2.6 kernel. Its advantage is that it uses the bus model to manage devices and drivers, which improves the portability of programs. With the platform bus, we don't need to create a bus ourselves, we just need to mount it on the platform bus.

In the kernel code platform.c, there is a structure struct bus_type platform_bus_type. In this structure, there is a matching function match. Match is mainly used to match the device name and the driver name. This is the same as the match function mentioned above, both of which match the device name and the driver name.

Write the picture description here
Write the picture description here

2 Description of the platform bus

Platform devices are described using struct platform_device


struct platform_device {

const char *name; /*Device name*/

int id; /*Device number, used together with the device name*/

struct device dev;

u32 num_resources;

struct resource *resource; /*Device resources, including base address and interrupt number*/

}


struct resource {

resource_size_t start;

resource_size_t end;

const char *name;

unsigned long flags; /*resource type*/

struct resource *parent, *sibling, *child;

};


3 Platform bus registration

Register platform devices using the platform_device_register function

int platform_device_register(struct platform_device *pdev)


4. Deregistration of platform bus

Unregister the platform device using the platform_device_register function

int platform_device_register(struct platform_device *pdev)


Combined with the above basic knowledge, modify the key driver in the previous section to the platform driver mode. The module code key_dev.c of the platform device is given below


#include

#include

#include //for platform_device

#include


#define GPNCON 0x7f008830

[1] [2]
Keywords:ARM Reference address:Lao Cha's ARM study notes: chapter-2 (Detailed explanation of Linux bus device driver)

Previous article:Lao Cha's ARM study notes: chapter-1 (button driver design)
Next article:Character Device Driver (II)

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号