openwrt DTS介绍
1、概述
DTS是Device Tree Source的缩写,用来描述设备的硬件细节。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。为了去掉这些垃圾代码,Linux采用DTS这种新的数据结构来描述硬件设备。采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。
2、DTS节点解析
Linux在启动后,到C入口时,会执行以下操作,加载系统平台上的总线和设备:
start_kernel() --> setup_arch() --> unflatten_device_tree()
unflatten_device_tree()的代码如下:
1 2 3 4 5 6 7 8 | void __init unflatten_device_tree(void) { __unflatten_device_tree(initial_boot_params, &allnodes, early_init_dt_alloc_memory_arch); /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */ of_alias_scan(early_init_dt_alloc_memory_arch); } |
在执行完unflatten_device_tree()后,DTS节点信息被解析出来,保存到allnodes链表中,allnodes会在后面被用到。
随后,当系统启动到board文件时,会调用.init_machine,高通8974平台对应的是msm8974_init()。接着调用of_platform_populate(....)接口,加载平台总线和平台设备。至此,系统平台上的所有已配置的总线和设备将被注册到系统中。注意:不是dtsi文件中所有的节点都会被注册,在注册总线和设备时,会对dts节点的状态作一个判断,如果节点里面的status属性没有被定义,或者status属性被定义了并且值被设为“ok”或者“okay”,其他情况则不被注册到系统中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 例如:dts文件定义led GPIO的结构对象 leds { compatible = "gpio-leds" ; pwr_led { label = "green:pwr" ; gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; default-state = "on" ; }; status_led { label = "red:status" ; gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; default-state = "on" ; }; }; |
LED device注册后,会在/sys/devices/platform/leds-gpio/目录中,产生对应的led灯的控制目录:(红灯和绿灯)
通过 echo 1 > brightness,就可以控制灯亮; echo 0 > brightness,就可以控制灯灭 。
//openwrt/build_dir/target-arm_cortex-a7+neon-vfpv4_musl_eabi/linux-sunxi_cortexa7/linux-4.14.25/drivers/leds/leds-gpio.c
leds-gpio.c驱动文件会定义了对于led灯的操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | static inline struct gpio_led_data * cdev_to_gpio_led_data( struct led_classdev *led_cdev) static void gpio_led_set( struct led_classdev *led_cdev, enum led_brightness value) static int gpio_led_set_blocking( struct led_classdev *led_cdev, enum led_brightness value) static int gpio_blink_set( struct led_classdev *led_cdev, unsigned long *delay_on, unsigned long *delay_off) static int create_gpio_led( const struct gpio_led * template , struct gpio_led_data *led_dat, struct device *parent, struct device_node *np, gpio_blink_set_t blink_set) static struct gpio_leds_priv *gpio_leds_create( struct platform_device *pdev) static int gpio_led_probe( struct platform_device *pdev) static void gpio_led_shutdown( struct platform_device *pdev) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)