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

硬件资源从硬编码到设备树

1. 硬编码

在没有设备树的系统中,硬件设备通常由板级代码(如 board.c 文件)硬编码注册到内核中。
比如这样:

// SPDX-License-Identifier: GPL-2.0
/** Renesas Technology Europe RSK+ 7203 Support.** Copyright (C) 2008 - 2010  Paul Mundt*/
#include <linux/init.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/smsc911x.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/leds.h>
#include <asm/machvec.h>
#include <asm/io.h>
#include <cpu/sh7203.h>//以太网控制器
static struct smsc911x_platform_config smsc911x_config = {.phy_interface	= PHY_INTERFACE_MODE_MII,.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,.flags		= SMSC911X_USE_32BIT | SMSC911X_SWAP_FIFO,
};static struct resource smsc911x_resources[] = {[0] = {.start		= 0x24000000,.end		= 0x240000ff,.flags		= IORESOURCE_MEM,},[1] = {.start		= 64,.end		= 64,.flags		= IORESOURCE_IRQ,},
};static struct platform_device smsc911x_device = {.name		= "smsc911x",.id		= -1,.num_resources	= ARRAY_SIZE(smsc911x_resources),.resource	= smsc911x_resources,.dev		= {.platform_data = &smsc911x_config,},
};//LED
static struct gpio_led rsk7203_gpio_leds[] = {{.name			= "green",.gpio			= GPIO_PE10,.active_low		= 1,}, {.name			= "orange",.default_trigger	= "nand-disk",.gpio			= GPIO_PE12,.active_low		= 1,}, {.name			= "red:timer",.default_trigger	= "timer",.gpio			= GPIO_PC14,.active_low		= 1,}, {.name			= "red:heartbeat",.default_trigger	= "heartbeat",.gpio			= GPIO_PE11,.active_low		= 1,},
};static struct gpio_led_platform_data rsk7203_gpio_leds_info = {.leds		= rsk7203_gpio_leds,.num_leds	= ARRAY_SIZE(rsk7203_gpio_leds),
};static struct platform_device led_device = {.name		= "leds-gpio",.id		= -1,.dev		= {.platform_data	= &rsk7203_gpio_leds_info,},
};//按键
static struct gpio_keys_button rsk7203_gpio_keys_table[] = {{.code		= BTN_0,.gpio		= GPIO_PB0,.active_low	= 1,.desc		= "SW1",}, {.code		= BTN_1,.gpio		= GPIO_PB1,.active_low	= 1,.desc		= "SW2",}, {.code		= BTN_2,.gpio		= GPIO_PB2,.active_low	= 1,.desc		= "SW3",},
};static struct gpio_keys_platform_data rsk7203_gpio_keys_info = {.buttons	= rsk7203_gpio_keys_table,.nbuttons	= ARRAY_SIZE(rsk7203_gpio_keys_table),.poll_interval	= 50, /* default to 50ms */
};static struct platform_device keys_device = {.name		= "gpio-keys-polled",.dev		= {.platform_data	= &rsk7203_gpio_keys_info,},
};static struct platform_device *rsk7203_devices[] __initdata = {&smsc911x_device,&led_device,&keys_device,
};static int __init rsk7203_devices_setup(void)
{/* Select pins for SCIF0 */gpio_request(GPIO_FN_TXD0, NULL);gpio_request(GPIO_FN_RXD0, NULL);/* Setup LAN9118: CS1 in 16-bit Big Endian Mode, IRQ0 at Port B */__raw_writel(0x36db0400, 0xfffc0008); /* CS1BCR */gpio_request(GPIO_FN_IRQ0_PB, NULL);return platform_add_devices(rsk7203_devices,ARRAY_SIZE(rsk7203_devices));
}
device_initcall(rsk7203_devices_setup);

2. 要将硬编码的驱动程序转换为使用设备树的方式,主要涉及以下几个步骤:

2.1 编写设备树源文件(DTS)

首先,你需要为你的硬件平台创建一个设备树源文件(DTS)。这个文件描述了硬件的结构,包括每个设备的节点及其属性。例如,描述 LED 和按键的 DTS 文件如下:

/dts-v1/;
/ {compatible = "your,board-name";  // 替换为你的板子名称leds {compatible = "gpio-leds";green {label = "Green LED";gpios = <&gpio PE10 GPIO_ACTIVE_LOW>;};orange {label = "Orange LED";gpios = <&gpio PE12 GPIO_ACTIVE_LOW>;default-trigger = "nand-disk";};};gpio_keys {compatible = "gpio-keys";key0 {label = "SW1";gpios = <&gpio PB0 GPIO_ACTIVE_LOW>;};key1 {label = "SW2";gpios = <&gpio PB1 GPIO_ACTIVE_LOW>;};key2 {label = "SW3";gpios = <&gpio PB2 GPIO_ACTIVE_LOW>;};};
};

2.2 生成设备树二进制文件(DTB)

编写好 DTS 文件后,可以使用设备树编译器(DTC)将其编译为 DTB 文件:

dtc -I dts -O dtb -o your_board.dtb your_board.dts

2.3 修改内核驱动程序

接下来,你需要修改你的驱动程序,以便它可以从设备树中读取设备的信息。主要涉及以下几个步骤:

  • 包含设备树相关的头文件

    #include <linux/of.h>
    #include <linux/of_device.h>
    
  • 在驱动的 probe 函数中,使用 of_device_get_match_data() 获取设备树信息

    static int your_driver_probe(struct platform_device *pdev)
    {struct device_node *np = pdev->dev.of_node;struct gpio_led *led;// 获取 GPIO LED 的信息led = devm_kmalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);if (!led)return -ENOMEM;if (of_property_read_u32(np, "gpio", &led->gpio)) {dev_err(&pdev->dev, "No GPIO defined\n");return -EINVAL;}// 继续初始化 LED 等
    }
    
  • platform_device 的初始化改为使用 of_match_table

    static const struct of_device_id your_device_ids[] = {{ .compatible = "your,leds-gpio", },{ /* sentinel */ }
    };MODULE_DEVICE_TABLE(of, your_device_ids);static struct platform_driver your_driver = {.probe = your_driver_probe,.remove = your_driver_remove,.driver = {.name = "your_driver",.of_match_table = your_device_ids,},
    };
    

2.4 修改 Makefile 和 Kconfig

确保你的驱动程序可以被编译和配置。通常需要在 Kconfig 中添加一个选项,以便选择你的驱动程序:

config YOUR_DRIVERtristate "Your Driver"depends on OFhelpSay Y here to enable support for your driver.

并在 Makefile 中添加你的源文件:

obj-m += your_driver.o

2.5 测试和验证

  • 将编译生成的 DTB 文件拷贝到你的设备的启动分区中。
  • 重新启动设备,确保内核可以加载新的设备树。
  • 使用 dmesg 查看内核日志,确认驱动程序正确加载。

2.6 调试

如果驱动程序没有按预期工作,可以通过以下方式进行调试:

  • 检查设备树的匹配是否正确。
  • 查看 GPIO 是否正确配置和初始化。
  • 使用 printkdev_info 调试信息。

总结

转换到设备树的主要好处是提高了可移植性和灵活性,使你能够更容易地支持不同版本的硬件。如果你在这个过程中遇到具体问题,随时可以问我!


http://www.mrgr.cn/news/30220.html

相关文章:

  • 【leetcode练习·二叉树】用「分解问题」思维解题 II
  • 如何将Nop平台与Solon框架集成
  • C++初阶——list
  • 【大数据学习 | HBASE高级】storeFile文件的合并
  • 机器学习(七)——集成学习(个体与集成、Boosting、Bagging、随机森林RF、结合策略、多样性增强、多样性度量、Python源码)
  • Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
  • 深入解析NVIDIA GH200:Grace Hopper的多样性与性能挑战
  • 基于SpringBoot+Vue的篮球馆会员信息管理系统
  • nodejs child_process 操作git 提交记录 提取git commit信息
  • Vue:加载本地视频
  • C++和OpenGL实现3D游戏编程【连载9】——纹理的镂空显示
  • 电子书号和纸质书号的ISBN 号有什么不同?
  • 《高等代数》行列式转置(应用)
  • 如何让零售巨头在营销拓客中旗开得胜?新增企业API自动输出客户名单!
  • git 压栈存储当前分支修改,出栈使用保存
  • Fiddler 工具使用教程
  • platform
  • Linux系统查看硬件配置教程
  • Android U 多任务启动分屏——Launcher流程(下分屏 更新中)
  • 电力电容器、电子电容器的区别
  • shell脚本中的if语句、shell脚本中的if条件语句介绍和使用案例(非常全面)
  • DDoS对策是什么?详细解说DDoS攻击难以防御的理由和对策方法
  • 高等数学 3.3 泰勒公式
  • SpringCloud微服务实现服务降级的最佳实践
  • 数据结构-排序(冒泡,选择,插入,希尔,快排,归并,堆排)
  • 人工智能时代,程序员如何保持核心竞争力?