Turn from https://edu.csdn.net/lecturer/505 Teacher Zhu Internet of things lecture hall
5.linux driver development - Part 5 - 5.5.linux device driver model
Part I contents of chapters
5.5.1. Introduction to Linux device driver model
5.5.2. Underlying architecture of device driven model
5.5.3. Bus device drive organization
5.5.4. Introduction to platform bus 1
5.5.5.platform platform bus working principle 2
5.5.6.platform platform bus working principle 3
5.5.7. Platform bus practice link 1
5.5.8. Platform bus practice link 2
5.5.9. Platform bus practice link 3
5.5.10. Platform bus practice 4
Part II chapter introduction
5.5.1. Introduction to Linux device driver model
This section introduces the reasons for the birth of linux device driver model, its technical characteristics, and its impact on driver development, writing and debugging. The main purpose is to make everyone feel what is linux device driver model in an all-round way.
5.5.2. Underlying architecture of device driven model
This section explains the lowest implementation module of the device driver model, mainly including three modules: kobject and kobj_type,kset.
5.5.3. Bus device drive organization
This section explains in detail the driver organization form connected by bus in linux kernel, and analyzes several concepts and their relationships such as class, bus, device and driver in detail.
5.5.4. Introduction to platform bus 1
This section describes the purpose, significance and working mode of platform bus. Note that the key of this section lies in the construction and working principle of platform itself. Next class will talk about how to use platform bus to organize devices and drivers.
5.5.5. Working principle of platform bus 2
This section first explains the workflow of the platform bus, and then focuses on the process of building the platform bus itself.
5.5.6.platform platform bus working principle 3
This section takes the LED driver source code based on platform bus written by Samsung 2440 in the internal core as an example to analyze how to write the driver on the platform bus.
5.5.7. Platform bus practice link 1
This section starts to write the LED Driver Based on platform bus under X210. This section rewrites the LED driver source code of the previous course into platform bus system, and first realizes the platform_driver.
5.5.8. Platform bus practice link 2
This section analyzes the mach file during system migration, and then finds and adds the LED related platform_device registration.
5.5.9. Platform bus practice 3
This section also debugs the platform_device and platform_driver for troubleshooting, code testing and explanation.
5.5.10. Platform bus practice 4
This section focuses on how the data in the hardware configuration information is transferred from the device end to the driver end and received by the driver for the operation method of the hardware.
Part III: in class records
5.5.1. Introduction to Linux device driver model
5.5.1.1 what is a device driven model
(1) class, bus, device, driver
(2)kobject and object lifecycle
(3)sysfs
(4)udev
5.5.1.2 why do you need a device driven model
(1) The early kernel (before 2.4) did not have a unified device driver model, but it can still be used
(2) The device driver model is formally introduced in version 2.6 to make the driver system easier to use and better when there are more and more devices and new characteristics such as power consumption requirements.
(3) The device driver model is responsible for the unified implementation and maintenance of some features, such as infrastructure such as power management, hot plug, object life cycle, user space and driver space interaction
(4) The purpose of device driver model is to simplify driver programming, but objectively, the design and implementation of device driver model itself is very complex.
5.5.1.3 two points of driving development
(1) The driver source code itself is written and debugged. The focus is on understanding the hardware.
(2) When the driver is installed and when the functions in the driver are called. It has nothing to do with hardware. It is completely related to the device driver model.
5.5.2. Underlying architecture of device driven model
5.5.2.1,kobject
(1) Defined in Linux / kobject H medium
(2) The most basic units of various objects provide some common services, such as object reference counting, maintaining object linked list, object locking, and representation of user space
(3) Various objects in the device driven model contain a kobject
(4) The status is equivalent to the total base class in object-oriented architecture
5.5.2.2,kobj_type
(1) In many books, it is referred to as ktype for short. Every kobject needs to bind a ktype to provide corresponding functions
(2) Key 1: sysfs_ops, which provides the operation methods (show and store) of the object in sysfs
(2) Key point 2: attribute, which provides attributes in the form of files in sysfs, is actually an application interface
5.5.2.3,kset
(1)kset is mainly used as the container class of top-level kobject
(2) The main purpose of kset is to organize various kobject s (representing various objects) into a directory hierarchy
(3) It can be considered that kset is to get a directory in sysfs, so that multiple objects in the device driven model can be organized hierarchically and logically
5.5.3. Bus device drive organization
5.5.3.1 bus
(1) Physical real bus and its function
(2) Bus design in driver framework
(3)bus_type structure. The key is the match function and uevent function
5.5.3.2 equipment
(1)struct device is the abstraction of hardware device in kernel driver framework
(2)device_register is used to register a device with the kernel driver framework
(3) Usually, the device is not used alone, but is contained in a specific device structure, such as struct usb_device
5.5.3.3 drive
(1)struct device_driver is the abstraction of driver in kernel driver framework
(2) Key element 1: name, the name of the driver, is very important and is often used as the matching basis between the driver and the device
(3) Key element 2: probe, the probe function of the driver, which is used to detect whether a device can be managed by the driver
5.5.3.4 class
(1) Related structures: struct class and struct class_device
(2) The use of udev is inseparable from class
(3) The real meaning of class is as a container for multiple devices belonging to the same class. In other words, class is an artificial concept, which aims to classify and manage various equipment. Of course, while class classifies, it also puts some "labels" on each class, which is also the infrastructure provided by the device driver model for us to write drivers.
5.5.3.5 summary
(1) The idea of model is very important. In fact, it is the idea of object-oriented
(2) They are all structural bodies, which require high basic skills (language skills and brain complexity)
5.5.4.platform platform bus working principle 1
5.5.4.1 what is platform bus
(1) Compared with usb, pci, i2c and other physical buses, platform bus is virtual and abstract.
(2) Review the two ways of communication between CPU and external in bare metal: address bus connection and special interface connection. The platform bus corresponds to the address bus connection device, that is, various internal peripherals integrated in the SoC.
(3) Thinking: why platform bus? Further thinking: why do we have the concept of bus?
5.5.4.2. Two senior generals managed under the platform bus
(1)platform working systems are defined in drivers / base / platform C medium
(2) Two structures: platform_device and platform_driver
(3) Two interface functions: platform_device_register and platform_driver_register
struct platform_device { const char * name; // Name of the device under the platform bus int id; struct device dev; // Attributes common to all devices u32 num_resources; // Number of resource s used by the device struct resource * resource; // The first address of the resource array used by the device const struct platform_device_id *id_entry; // Device ID table /* arch specific additions */ struct pdev_archdata archdata; // Private plot, used to provide expansibility }; struct platform_driver { int (*probe)(struct platform_device *); // Drive detection function int (*remove)(struct platform_device *); // Remove a device void (*shutdown)(struct platform_device *); // Turn off a device int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); struct device_driver driver; // Some properties common to all devices const struct platform_device_id *id_table; // Device ID table };
5.5.5. Working principle of platform bus 2
5.5.5.1 work flow of platform bus system
(1) Step 1: register the platform in the bus system when the system starts
(2) Step 2: the person responsible for kernel migration is responsible for providing platform_device
(3) Step 3: the person who writes the driver is responsible for providing the platform_driver
(4) fourth step: the match function of platform finds that after driver and device match, the probe function of driver is used to complete the initialization and installation of the driver, and then the device is working.
5.5.5.2 code analysis: the platform itself is registered
(1) Each bus (not only platform, but also usb and i2c) will be equipped with a match method, which is used to match the device and driver under the bus. Theoretically, the matching algorithm of each bus is different, but in fact, it generally depends on the name.
(2)platform_ The match function is the matching method of the platform bus. The working method of this function is: if there is id_table indicates that the driver may support multiple devices, so you need to compare IDS at this time_ All the names in the table will match as long as they find the same one. Don't look for it anymore. If you finish looking for the ID_ If the table has not been found, it means that each match; If there is no id_table or every match, directly compare the name of device and driver. If it matches, it matches. If it doesn't match, it fails.
5.5.6.platform platform bus working principle 3
5.5.6.1 take leds-s3c24xx C as an example to analyze the registration process of platform devices and drivers
(1)platform_driver_register
(2)platform_device_register
5.5.6.2 how to play platdata
(1)platdata is actually some data related to the device provided during device registration (such as gpio corresponding to the device, interrupt number used, device name...)
(2) After the device and driver match, these data will be transferred from the device to the driver. After the driver obtains these data, it knows the specific information of the device through these data, and then operates the device.
(3) The advantage of this is that the driver source code does not carry data, but is only responsible for the algorithm (the operation method of the hardware). Modern driver design concept is to separate algorithm and data, so as to maintain the independence and adaptability of driver to the greatest extent.
5.5.6.3 call trace of match function
5.5.6.4 function and significance of probe function
5.5.7. Platform bus practice link 1
5.5.7.1 review
5.5.7.2. Initially transform and add platform_driver
(1) Step 1: first modify the original code to only led1
(2) Step 2:
5.5.7.3 analysis of experimental phenomena
#include <linux/module.h> // module_init module_exit #include <linux/init.h> // __init __exit #include <linux/fs.h> #include <linux/leds.h> #include <mach/regs-gpio.h> #include <mach/gpio-bank.h> #include <linux/io.h> #include <linux/ioport.h> #include <mach/gpio.h> #include <linux/platform_device.h> #include <mach/leds-gpio.h> #include <linux/slab.h> #define X210_LED_OFF one // The LED in x210 is connected to the power supply at the positive pole and GPIO at the negative pole #define X210_LED_ON 0 // So 1 is off and 0 is on struct s5pv210_gpio_led { struct led_classdev cdev; struct s5pv210_led_platdata *pdata; }; static inline struct s5pv210_gpio_led *pdev_to_gpio(struct platform_device *dev) { return platform_get_drvdata(dev); } static inline struct s5pv210_gpio_led *to_gpio(struct led_classdev *led_cdev) { return container_of(led_cdev, struct s5pv210_gpio_led, cdev); } // This function is to complete the specific hardware reading and writing tasks static void s5pv210_led_set(struct led_classdev *led_cdev, enum led_brightness value) { struct s5pv210_gpio_led *p = to_gpio(led_cdev); printk(KERN_INFO "s5pv210_led_set\n"); // Here, the hardware is operated according to the value set by the user // The value set by the user is value if (value == LED_OFF) { // The user gave a 0 and hoped that the LED would go off gpio_set_value(p->pdata->gpio, X210_LED_OFF); } else { // The user gave a yes / No 0, hope the LED is on gpio_set_value(p->pdata->gpio, X210_LED_ON); } } static int s5pv210_led_probe(struct platform_device *dev) { // This function will be called when insmod installs the driver module // The main task of this function is to register a device using the device registration function provided by the led driver framework int ret = -1; struct s5pv210_led_platdata *pdata = dev->dev.platform_data; struct s5pv210_gpio_led *led; printk(KERN_INFO "----s5pv210_led_probe---\n"); led = kzalloc(sizeof(struct s5pv210_gpio_led), GFP_KERNEL); if (led == NULL) { dev_err(&dev->dev, "No memory for device\n"); return -ENOMEM; } platform_set_drvdata(dev, led); // Here you can apply for various resources used by the driver. The current driver is GPIO resources if (gpio_request(pdata->gpio, pdata->name)) { printk(KERN_ERR "gpio_request failed\n"); } else { // Set to output mode, and the default output 1 turns off the LED gpio_direction_output(pdata->gpio, 1); } // led1 led->cdev.name = pdata->name; led->cdev.brightness = 0; led->cdev.brightness_set = s5pv210_led_set; led->pdata = pdata; ret = led_classdev_register(&dev->dev, &led->cdev); if (ret < 0) { printk(KERN_ERR "led_classdev_register failed\n"); return ret; } return 0; } static int s5pv210_led_remove(struct platform_device *dev) { struct s5pv210_gpio_led *p = pdev_to_gpio(dev); led_classdev_unregister(&p->cdev); gpio_free(p->pdata->gpio); kfree(p); // kfee is the last step return 0; } static struct platform_driver s5pv210_led_driver = { .probe = s5pv210_led_probe, .remove = s5pv210_led_remove, .driver = { .name = "s5pv210_led", .owner = THIS_MODULE, }, }; static int __init s5pv210_led_init(void) { return platform_driver_register(&s5pv210_led_driver); } static void __exit s5pv210_led_exit(void) { platform_driver_unregister(&s5pv210_led_driver); } module_init(s5pv210_led_init); module_exit(s5pv210_led_exit); // MODULE_xxx macro is used to add module description information MODULE_LICENSE("GPL"); // Describe the license for the module MODULE_AUTHOR("aston <1264671872@qq.com>"); // Describe the author of the module MODULE_DESCRIPTION("s5pv210 led driver"); // Describe the introduction of the module MODULE_ALIAS("s5pv210_led"); // Describes the alias information for the module
5.5.8. Platform bus practice link 2
5.5.8.1 check mach-x210 Is there any led related platform in C_ device
5.5.8.2 refer to mach-mini2440 C add led platform_device definition
5.5.8.3 only platform is tested_ Device does not have a platform_ What is the driver
//**********kernel\arch\arm\mach-s5pv210/Mach-x210.c Documents***************// //**********************LED platform device*****************************// static struct s3c24xx_led_data x210_led1_pdata = { .name ="led0", .gpio =s3c2410_GPB(5), .flags = s3c24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, .def_trigger ="heartbeat" }; static struct platform_device real6410_device_eth = { .name = "s5pv210_led", .id = 1, //-1 can be automatically assigned by the system .dev = { .platform_data = &x210_led1_pdata, }, }; //Special note: This is not ok. You need to add one h file.
5.5.9. Platform bus practice 3
5.5.9.1 test platform_device and platform_ What happens when drivers meet
5.5.9.2 probe function
(1) What should the probe function do
(2) Where does the data of the probe function come from
(3) Programming practice
5.5.10. Platform bus practice 4
#include <linux/module.h> // module_init module_exit #include <linux/init.h> // __init __exit #include <linux/fs.h> #include <linux/leds.h> #include <mach/regs-gpio.h> #include <mach/gpio-bank.h> #include <linux/io.h> #include <linux/ioport.h> #include <mach/gpio.h> #include <linux/platform_device.h> #include <mach/leds-gpio.h> #include <linux/slab.h> #define X210_LED_OFF one // The LED in x210 is connected to the power supply at the positive pole and GPIO at the negative pole #define X210_LED_ON 0 // So 1 is off and 0 is on struct s5pv210_gpio_led { struct led_classdev cdev; struct s5pv210_led_platdata *pdata; }; static inline struct s5pv210_gpio_led *pdev_to_gpio(struct platform_device *dev) { return platform_get_drvdata(dev); } static inline struct s5pv210_gpio_led *to_gpio(struct led_classdev *led_cdev) { return container_of(led_cdev, struct s5pv210_gpio_led, cdev); } // This function is to complete the specific hardware read and write tasks static void s5pv210_led_set(struct led_classdev *led_cdev, enum led_brightness value) { struct s5pv210_gpio_led *p = to_gpio(led_cdev); printk(KERN_INFO "s5pv210_led_set\n"); // Here, the hardware is operated according to the value set by the user // The value set by the user is value if (value == LED_OFF) { // The user gave a 0 and hoped that the LED would go off gpio_set_value(p->pdata->gpio, X210_LED_OFF); } else { // The user gave a yes / No 0, hope the LED is on gpio_set_value(p->pdata->gpio, X210_LED_ON); } } static int s5pv210_led_probe(struct platform_device *dev) { // This function will be called when insmod installs the driver module // The main task of this function is to register a device using the device registration function provided by the led driver framework int ret = -1; struct s5pv210_led_platdata *pdata = dev->dev.platform_data; struct s5pv210_gpio_led *led; printk(KERN_INFO "----s5pv210_led_probe---\n"); led = kzalloc(sizeof(struct s5pv210_gpio_led), GFP_KERNEL); if (led == NULL) { dev_err(&dev->dev, "No memory for device\n"); return -ENOMEM; } platform_set_drvdata(dev, led); // Here you can apply for various resources used by the driver. The current driver is GPIO resources if (gpio_request(pdata->gpio, pdata->name)) { printk(KERN_ERR "gpio_request failed\n"); } else { // Set to output mode, and the default output 1 turns off the LED gpio_direction_output(pdata->gpio, 1); } // led1 led->cdev.name = pdata->name; led->cdev.brightness = 0; led->cdev.brightness_set = s5pv210_led_set; led->pdata = pdata; ret = led_classdev_register(&dev->dev, &led->cdev); if (ret < 0) { printk(KERN_ERR "led_classdev_register failed\n"); return ret; } return 0; } static int s5pv210_led_remove(struct platform_device *dev) { struct s5pv210_gpio_led *p = pdev_to_gpio(dev); led_classdev_unregister(&p->cdev); gpio_free(p->pdata->gpio); kfree(p); // kfee is the last step return 0; } static struct platform_driver s5pv210_led_driver = { .probe = s5pv210_led_probe, .remove = s5pv210_led_remove, .driver = { .name = "s5pv210_led", .owner = THIS_MODULE, }, }; static int __init s5pv210_led_init(void) { return platform_driver_register(&s5pv210_led_driver); } static void __exit s5pv210_led_exit(void) { platform_driver_unregister(&s5pv210_led_driver); } module_init(s5pv210_led_init); module_exit(s5pv210_led_exit); // MODULE_xxx macro is used to add module description information MODULE_LICENSE("GPL"); // Describe the license for the module MODULE_AUTHOR("aston <1264671872@qq.com>"); // Describe the author of the module MODULE_DESCRIPTION("s5pv210 led driver"); // Describe the introduction of the module MODULE_ALIAS("s5pv210_led"); // Describes the alias information for the module