日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

platform平台总线

發布時間:2025/3/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 platform平台总线 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

一、platform設備模型

從Linux 2.6起引入了一套新的驅動管理和注冊機制,platform_device和platform_driver,Linux中大部分的設備驅動都可以使用這套機制。platform是一條虛擬總線。設備用platform_device表示,驅動用platform_driver進行注冊,linux platform driver機制和傳統的device driver機制(通過driver_register進行注冊)相比,一個明顯的優勢在于platform機制將設備本身的資源注冊進內核,由內核統一管理,在驅動中使用這些資源時通過platform device提供的標準結構進行申請并使用。這樣提高了驅動和資源的獨立性,并且具有較好的可移植性和安全性(這些標準接口是安全的)。當我們將設備和驅動注冊到虛擬總線上(內核)時,會互相尋找一次對方。如果device和driver中的name這個字符串是想相同的話platform_bus就會調用driver中的.probe函數。設備和驅動的關系是多對一的關系,即多個相同設備可使用一個driver,靠device(設備)中的id號來區別。

通過platform機制開發底層驅動的大致流程為:

定義platform_deviece -->注冊platform_device -->定義platform_driver --> 注冊platform_driver。

?

二、注冊platform_device

在內核源碼中添加arch/arm/mach-s5pv210/include/mach/leds-gpio.h文件

/* arch/arm/mach-s5pv210/include/mach/leds-gpio.h** Copyright (c) 2006 Simtec Electronics* http://armlinux.simtec.co.uk/* Ben Dooks <ben@simtec.co.uk>** s5pv210 - LEDs GPIO connector** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation. */#ifndef __ASM_ARCH_LEDSGPIO_H #define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"#define S5PV210_LEDF_ACTLOW (1<<0) /* LED is on when GPIO low */ #define S5PV210_LEDF_TRISTATE (1<<1) /* tristate to turn off */struct s5pv210_led_platdata {unsigned int gpio;unsigned int flags;char *name;char *def_trigger; };#endif /* __ASM_ARCH_LEDSGPIO_H */

在內核arch/arm/mach-s5pv210/mach-x210.c文件中添加如下代碼

/* LEDS */ static struct s5pv210_led_platdata x210_led1_pdata = {.name = "led1",.gpio = S5PV210_GPJ0(3),.flags = S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger = "", };static struct s5pv210_led_platdata x210_led2_pdata = {.name = "led2",.gpio = S5PV210_GPJ0(4),.flags = S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger = "", };static struct s5pv210_led_platdata x210_led3_pdata = {.name = "led3",.gpio = S5PV210_GPJ0(5),.flags = S5PV210_LEDF_ACTLOW | S5PV210_LEDF_TRISTATE,.def_trigger = "", };static struct platform_device x210_led1 = {.name = "s5pv210_led",.id = 0,.dev = {.platform_data = &x210_led1_pdata,}, };static struct platform_device x210_led2 = {.name = "s5pv210_led",.id = 1,.dev = {.platform_data = &x210_led2_pdata,}, };static struct platform_device x210_led3 = {.name = "s5pv210_led",.id = 2,.dev = {.platform_data = &x210_led3_pdata,}, };static struct platform_device *smdkc110_devices[] __initdata = {...&x210_led1,&x210_led2,&x210_led3, };

重新編譯內核,三個led設備就會被注冊到platform中,在/sys/bus/platform/devices中可以進行查看

?

三、注冊platform_driver

#include <linux/module.h> #include <linux/init.h> #include <linux/leds.h> #include <mach/gpio.h> #include <linux/platform_device.h> #include <mach/leds-gpio.h> #include <linux/slab.h>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); }static void s5pv210_led_set(struct led_classdev *led_cdev, enum led_brightness value) {struct s5pv210_gpio_led *led = to_gpio(led_cdev);struct s5pv210_led_platdata *pd = led->pdata;printk(KERN_INFO "s5pv210_led_set\n");/* 設置gpio狀態 */if (value == LED_OFF)gpio_set_value(pd->gpio, 1);elsegpio_set_value(pd->gpio, 0); }static int s5pv210_led_probe(struct platform_device *dev) {struct s5pv210_led_platdata *pdata = dev->dev.platform_data;struct s5pv210_gpio_led *led;int ret = -1;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);/* 申請gpio資源 */if (gpio_request(pdata->gpio, pdata->name)){printk(KERN_ERR "gpio_request failed\n");return -EINVAL;}/* 設置gpio方向為輸出 */gpio_direction_output(pdata->gpio, 1);led->cdev.name = pdata->name;led->cdev.brightness = 0; led->cdev.brightness_set = s5pv210_led_set;led->pdata = pdata;/* 注冊led設備 */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 *led = pdev_to_gpio(dev);struct s5pv210_led_platdata *pd = led->pdata;/* 注銷led設備 */led_classdev_unregister(&led->cdev);/* 釋放gpio資源 */gpio_free(pd->gpio);kfree(led);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這種宏作用是用來添加模塊描述信息 MODULE_LICENSE("GPL"); // 描述模塊的許可證 MODULE_AUTHOR("lsm"); // 描述模塊的作者 MODULE_DESCRIPTION("s5pv210 led driver"); // 描述模塊的介紹信息 MODULE_ALIAS("s5pv210_led"); // 描述模塊的別名信息

加載驅動之后,在/sys/bus/platform/drivers中可以進行查看

?

四、測試

加載好led驅動之后,進入/sys/class/leds

?

?

新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的platform平台总线的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。