当前位置: 首页 > news >正文

网站建设策划报告自己做网站服务器的备案方法

网站建设策划报告,自己做网站服务器的备案方法,帮企业做网站的公司,祥云平台 网站建设前面我们都是自己编写 LED 灯驱动,其实像 LED 灯这样非常基础的设备驱动, Linux 内核已经集成了。 Linux 内核的 LED 灯驱动采用 platform 框架,因此我们只需要按照要求在设备树文件中添加相应的 LED 节点即可,本章我们就来学习如…

前面我们都是自己编写 LED 灯驱动,其实像 LED 灯这样非常基础的设备驱动, Linux 内核已经集成了。 Linux 内核的 LED 灯驱动采用 platform 框架,因此我们只需要按照要求在设备树文件中添加相应的 LED 节点即可,本章我们就来学习如何使用 Linux 内核自带的 LED 驱动来驱动 I.MX6U-ALPHA 开发板上的 LED0。

Linux 内核自带 LED 驱动使能

上一章节我们编写基于设备树的 platform LED 灯驱动,其实 Linux 内核已经自带了 LED 灯驱动,要使用 Linux 内核自带的 LED 灯驱动首先得先配置 Linux 内核,使能自带的 LED 灯驱动,输入如下命令打开 Linux 配置菜单:

make menuconfig

按照如下路径打开 LED 驱动配置项:

-> Device Drivers-> LED Support (NEW_LEDS [=y])->LED Support for GPIO connected LEDs

按照上述路径,选择“LED Support for GPIO connected LEDs”,将其编译进 Linux 内核,也即是在此选项上按下“Y”键,使此选项前面变为“<*>”,如图所示:

 在“LED Support for GPIO connected LEDs”上按下‘?’ 可以打开此选项的帮助信息,如图所示:

从上图可以看出,把 Linux 内 部 自 带 的 LED 灯 驱 动 编 译 进 内 核 以 后 ,CONFIG_LEDS_GPIO 就会等于‘y’, Linux 会根据 CONFIG_LEDS_GPIO 的值来选择如何编译LED 灯驱动,如果为‘y’就将其编译进 Linux 内核。配置好 Linux 内核以后退出配置界面,打开.config 文件,会找到“CONFIG_LEDS_GPIO=y”这一行。重新编译 Linux 内核,然后使用新编译出来的 zImage 镜像启动开发板。

Linux 内核自带 LED 驱动简介

驱动框架分析

LED 灯驱动文件为/drivers/leds/leds-gpio.c,大家可以打开/drivers/leds/Makefile 这个文件,找到如下所示内容:

2 # LED Core
3 obj-$(CONFIG_NEW_LEDS) += led-core.o
.....
23 obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
24 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
25 obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
......

第 24 行,如果定义了 CONFIG_LEDS_GPIO 的话就会编译 leds-gpio.c 这个文件,在上一小节我们选择将 LED 驱动编译进 Linux 内核,在.config 文件中就会有“CONFIG_LEDS_GPIO=y”
这一行,因此 leds-gpio.c 驱动文件就会被编译。接下来我们看一下 leds-gpio.c 这个驱动文件,找到如下所示内容:

236 static const struct of_device_id of_gpio_leds_match[] = {
237     { .compatible = "gpio-leds", },
238     {},
239 };
......
290 static struct platform_driver gpio_led_driver = {
291     .probe = gpio_led_probe,
292     .remove = gpio_led_remove,
293     .driver = {
294         .name = "leds-gpio",
295         .of_match_table = of_gpio_leds_match,
296     },
297 };
298
299 module_platform_driver(gpio_led_driver);

第 236~239 行, LED 驱动的匹配表,此表只有一个匹配项, compatible 内容为“gpio-leds”,因此设备树中的 LED 灯设备节点的 compatible 属性值也要为“gpio-leds”,否则设备和驱动匹
配不成功,驱动就没法工作。
第 290~296 行, platform_driver 驱动结构体变量,可以看出, Linux 内核自带的 LED 驱动采用了 platform 框架。第 291 行可以看出 probe 函数为 gpio_led_probe,因此当驱动和设备匹配
成功以后 gpio_led_probe 函数就会执行。从 294 行可以看出,驱动名字为“leds-gpio”,因此会在/sys/bus/platform/drivers 目录下存在一个名为“leds-gpio”的文件,如图所示:

 第 299 行通过 module_platform_driver 函数向 Linux 内核注册 gpio_led_driver 这个 platform驱动。

module_platform_driver 函数

在上一小节中我们知道 LED 驱动会采用 module_platform_driver 函数向 Linux 内核注册platform 驱动,其实在 Linux 内核中会大量采用 module_platform_driver 来完成向 Linux 内核注册 platform 驱动的操作。 module_platform_driver 定义在 include/linux/platform_device.h 文件中,为一个宏,定义如下:

221 #define module_platform_driver(__platform_driver) \
222     module_driver(__platform_driver, platform_driver_register, \
223         platform_driver_unregister)

可以看出, module_platform_driver 依赖 module_driver, module_driver 也是一个宏,定义在include/linux/device.h 文件中,内容如下:

1260 #define module_driver(__driver, __register, __unregister, ...) \
1261 static int __init __driver##_init(void) \
1262 { \
1263     return __register(&(__driver) , ##__VA_ARGS__); \
1264 } \
1265 module_init(__driver##_init); \
1266 static void __exit __driver##_exit(void) \
1267 { \
1268     __unregister(&(__driver) , ##__VA_ARGS__); \
1269 } \
1270 module_exit(__driver##_exit);

因此module_platform_driver(gpio_led_driver)展开后:

static int __init gpio_led_driver_init(void)
{return platform_driver_register (&(gpio_led_driver));
}
module_init(gpio_led_driver_init);static void __exit gpio_led_driver_exit(void)
{platform_driver_unregister (&(gpio_led_driver) );
}
module_exit(gpio_led_driver_exit);

上面的代码不就是标准的注册和删除 platform 驱动吗?因此 module_platform_driver 函数的功能就是完成 platform 驱动的注册和删除。

gpio_led_probe 函数简析

当驱动和设备匹配以后 gpio_led_probe 函数就会执行,此函数主要是从设备树中获取 LED灯的 GPIO 信息,缩减后的函数内容如下所示:

243 static int gpio_led_probe(struct platform_device *pdev)
244 {
245     struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
246     struct gpio_leds_priv *priv;
247     int i, ret = 0;
248
249     if (pdata && pdata->num_leds) { /* 非设备树方式 *//* 获取 platform_device 信息 */......
268     } else { /* 采用设备树 */
269         priv = gpio_leds_create(pdev);
270         if (IS_ERR(priv))
271             return PTR_ERR(priv);
272     }
273
274     platform_set_drvdata(pdev, priv);
275
276     return 0;
277 }

第 269~271 行,如果使用设备树的话,使用 gpio_leds_create 函数从设备树中提取设备信息,获取到的 LED 灯 GPIO 信息保存在返回值中, gpio_leds_create 函数内容如下:

static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
{struct device *dev = &pdev->dev;struct fwnode_handle *child;struct gpio_leds_priv *priv;int count, ret;struct device_node *np;175	count = device_get_child_node_count(dev);if (!count)return ERR_PTR(-ENODEV);priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);if (!priv)return ERR_PTR(-ENOMEM);183	device_for_each_child_node(dev, child) {struct gpio_led led = {};const char *state = NULL;187		led.gpiod = devm_get_gpiod_from_child(dev, NULL, child);if (IS_ERR(led.gpiod)) {fwnode_handle_put(child);ret = PTR_ERR(led.gpiod);goto err;}np = of_node(child);196		if (fwnode_property_present(child, "label")) {fwnode_property_read_string(child, "label", &led.name);} else {if (IS_ENABLED(CONFIG_OF) && !led.name && np)led.name = np->name;if (!led.name)return ERR_PTR(-EINVAL);}
204		fwnode_property_read_string(child, "linux,default-trigger",&led.default_trigger);207		if (!fwnode_property_read_string(child, "default-state",&state)) {if (!strcmp(state, "keep"))led.default_state = LEDS_GPIO_DEFSTATE_KEEP;else if (!strcmp(state, "on"))led.default_state = LEDS_GPIO_DEFSTATE_ON;elseled.default_state = LEDS_GPIO_DEFSTATE_OFF;}if (fwnode_property_present(child, "retain-state-suspended"))led.retain_state_suspended = 1;ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],dev, NULL);if (ret < 0) {fwnode_handle_put(child);goto err;}}return priv;err:for (count = priv->num_leds - 2; count >= 0; count--)delete_gpio_led(&priv->leds[count]);return ERR_PTR(ret);
}

第 175 行,调用 device_get_child_node_count 函数统计子节点数量,一般在在设备树中创建一个节点表示 LED 灯,然后在这个节点下面为每个 LED 灯创建一个子节点。因此子节点数量也是 LED 灯的数量。
第 183 行,遍历每个子节点,获取每个子节点的信息。
第 187 行,获取 LED 灯所使用的 GPIO 信息。
第 196~197 行,读取子节点 label 属性值,因为使用 label 属性作为 LED 的名字。
第 204~205 行,获取“linux,default-trigger”属性值,可以通过此属性设置某个 LED 灯在Linux 系统中的默认功能,比如作为系统心跳指示灯等等。
第 207~215 行,获取“default-state”属性值,也就是 LED 灯的默认状态属性。
第 220 行,调用 create_gpio_led 函数创建 LED 相关的 io,其实就是设置 LED 所使用的 io为输出之类的。 create_gpio_led 函数主要是初始化 led_dat 这个 gpio_led_data 结构体类型变量,
led_dat 保存了 LED 的操作函数等内容。
关于 gpio_led_probe 函数就分析到这里, gpio_led_probe 函数主要功能就是获取 LED 灯的设备信息,然后根据这些信息来初始化对应的 IO,设置为输出等。
 

DTS节点格式

打开文档 Documentation/devicetree/bindings/leds/leds-gpio.txt,此文档详细的讲解了 Linux 自带驱动对应的设备树节点该如何编写,我们在编写设备节点的时候要注意以下几点:
①、创建一个节点表示 LED 灯设备,比如 dtsleds,如果板子上有多个 LED 灯的话每个 LED灯都作为 dtsleds 的子节点。
②、 dtsleds 节点的 compatible 属性值一定要为“gpio-leds”。
③、设置 label 属性,此属性为可选,每个子节点都有一个 label 属性, label 属性一般表示LED 灯的名字,比如以颜色区分的话就是 red、 green 等等。
④、每个子节点必须要设置 gpios 属性值,表示此 LED 所使用的 GPIO 引脚!
⑤、可以设置“linux,default-trigger”属性值,也就是设置 LED 灯的默认功能,可以查阅Documentation/devicetree/bindings/leds/common.txt 这个文档来查看可选功能,比如:
backlight: LED 灯作为背光。
default-on: LED 灯打开
heartbeat: LED 灯作为心跳指示灯,可以作为系统运行提示灯。
ide-disk: LED 灯作为硬盘活动指示灯。
timer: LED 灯周期性闪烁,由定时器驱动,闪烁频率可以修改
⑥、可以设置“default-state”属性值,可以设置为 on、 off 或 keep,为 on 的时候 LED 灯默认打开,为 off 的话 LED 灯默认关闭,为 keep 的话 LED 灯保持当前模式。
根据上述几条要求在 imx6ull-alientek-emmc.dts 中添加如下所示 LED 灯设备节点:

1 dtsleds {
2     compatible = "gpio-leds";
3 
4     led0 {
5         label = "red";
6         gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
7         default-state = "off";
8     };
9 };

运行测试

用新的zImage和imx6ull-alientek-emmc.dtb启动开发板,启动以后查看/sys/bus/platform/devices/dtsleds 这个目录是否存在,如果存在的话就如到此目录中,如图所示:

 进入到 leds 目录中,此目录中的内容如图所示:

从上图可以看出,在leds目录下有一个名为“red”子目录,这个子目录的名字就是我们在设备树中第 5 行设置的 label 属性值。我们的设置究竟有没有用,最终是要通过测试才能知道的,首先查看一下系统中有没有“sys/class/leds/red/brightness”这个文件,如果有的话就输入如下命令打开 RED 这个 LED 灯:

echo 1 > /sys/class/leds/red/brightness //打开 LED0

关闭 RED 这个 LED 灯的命令如下:

echo 0 > /sys/class/leds/red/brightness //关闭 LED0

如果能正常的打开和关闭 LED 灯话就说明我们 Linux 内核自带的 LED 灯驱动工作正常。我们一般会使用一个 LED 灯作为系统指示灯,系统运行正常的话这个 LED 指示灯就会一闪一
闪的。我们设置 LED0 作为系统指示灯,在 dtsleds 这个设备节点中加入“linux,default-trigger”属性信息即可,属性值为“heartbeat”,修改完以后的 dtsleds 节点内容如下:

1 dtsleds {
2     compatible = "gpio-leds";
3 
4     led0 {
5     label = "red";
6         gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
7         linux,default-trigger = "heartbeat";
8         default-state = "on";
9     };
10 };

第 7 行,设置 LED0 为 heartbeat。
第 8 行,默认打开 LED0。
重新编译设备树并且使用新的设备树启动 Linux 系统,启动以后 LED0 就会闪烁,作为系统心跳指示灯,表示系统正在运行。

http://www.yayakq.cn/news/678374/

相关文章:

  • 网站做二级登录页面容易吗移动互联网开发考试
  • 那个网站上有打码的任务做微信公众号设计方案
  • 如何在网站做电子杂志收费的网站如何免费
  • 网站宽屏图片怎么做wordpress打开速度很慢
  • 网站做短信验证需要多少钱站长权重
  • 网站网页怎么做网站关键词排名优化技巧
  • 南阳做网站多少钱自己编写网站
  • 轻淘客 轻网站怎么做广州市住房住建局网站
  • 手机网站制作招聘网站建设费可以计入办公费用么
  • 百度网站的网址是什么青海教育厅门户网站
  • pc端和移动端的网站区别是什么意思烟台网站建设在哪
  • 网站推广找品牌设计公司排名广州设计
  • 网站优化排名网站设计网站怎么做的
  • 网站大全免费完整版网站主机租用多少钱
  • 无锡网站优化推广方案百度经验官方网站登录入口
  • 东莞怎么制作网站云南网站推广的目的
  • 沈阳公司做网站wordpress 自适应cms主题
  • 游戏网站平台大全游戏网王建设的网站
  • 郑州市建设厅官方网站建设网站公司哪里好相关的热搜问题解决方案
  • 谷歌优化网站链接怎么做西安做网站朋朋
  • 一个网站开发小组如何做翻唱网站
  • 网站访客qq系统答题卡在线制作网站
  • html网站作业网站logo在线设计
  • 信科网络广州建网站网站开发硬件环境
  • 保之友微网站怎么建东莞建设网企业沟通平台
  • 手机网站的特点新浪博客
  • 重庆营销网站建设平台网上商城系统开发
  • 专门做黄昏恋的网站seo查询网站
  • 长沙企业网站建立ui设计是做啥的
  • 三角镇建网站公司python做网站快么