平台 | 内核版本 | 安卓版本 |
---|---|---|
RK3399 | Linux4.4 | Android7.1 |
一、背景及问题
Linus Torvalds
在 2011
年 3
月 17
日的 ARM Linux
邮件列表宣称“this whole ARM thing is a f*cking pain in the ass
” , 引发 ARM Linux
社区的地震, 随后 ARM
社区进行了一系列的重大修正。 在过去的ARM Linux
中, arch/arm/plat-xxx
和 arch/arm/mach-xxx
中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节, 而这些板级细节对于内核来讲,不过是垃圾, 如板上的 platform
设备、resource
、i2c_board_info
、 spi_board_info
以及各种硬件的platform_data
。读者有兴趣可以统计下常见的 s3c2410
、 s3c6410
等板级目录,代码量在数万行。
垃圾代码 | |
---|---|
platform 设备 |
|
resource |
|
i2c_board_info |
|
spi_board_info |
|
platform_data |
社区为了改变这种局面,就引入了
DTS
即Device Tree Source
设备树源码;Device Tree
是一种描述硬件的数据结构,它起源于OpenFirmware (OF)
。在Linux 2.6
中,ARM
架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx
和arch/arm/mach-xxx
,采用Device Tree
后,许多硬件的细节可以直接透过它传递给Linux
,而不再需要在kernel
中进行大量的冗余编码。
那么上文提到的DTS
与我们的DTB
有什么关系呢。其实DTB
是dts
文件的二进制表现形式是通过DTC
(Device tree compiler)
工具将对应DTS
(Device tree source
)文件转换成DTB
文件;所以要修改DTB
的内容就是通过修改.dts
文件来达到修改DTB
目的。.dts
文件一般放在内核的arch/arm/boot/dts/
或者arch/arm64/boot/dts/amlogic
目录
文件 | 意义 |
---|---|
DTS | 设备树源码 |
DTC | 工具 |
DTB | 文件的二进制表 |
二、思路和方法
1.驱动程序与dts的关联:
假如我们某个项目中增加了一个外设设备,这个外设设备也没有相应的驱动程序来驱动。这时我们就需要为这个外设设备重新添加一个驱动程序,并且还要修改相应的.dts
文件。下面我们以在瑞芯微平台下添加一个camera
的驱动为例:
a.我们在写驱动程序的时候,所需要与之匹配的设备的资源都需要在DTB
中描述出来。这时就需要在相应的.dts
文件中添加我们的设备描述。如:
aml_cams{
compatible = "amlogic,cams_prober"; //与驱动匹配的设备描述
status = "disabled";
pinctrl-names = "gpio","csi";
pinctrl-0 = <&aml_cam_gpio_pins> ;
pinctrl-1 = <&aml_cam_csi_pins> ;
……
cam_1{
cam_name = "ov5647"; //camera的型号
front_back = <0>; //前camera或者后camera 标志
i2c_bus = "i2c_bus_d"; //挂载 i2c 总线的位置。
gpio_pwdn = "GPIOH_5"; //电源开关的gpio
gpio_rst = "GPIOH_4"; //复位控制的gpio
mirror_flip = <0>; //左右镜像 控制
vertical_flip = <0>; //上下翻转 控制
config_path = "/system/etc/camera_isp_cfg/ov5647_cw0767"; // isp 配置文件位置
bt_path = "csi"; //csi 控制器
interface = "mipi"; //接口属性
clk_channel = "b"; //clk的通道
status = "okay";
};
……
};
b.在程序中:设备和驱动的匹配
static const struct of_device_id cams_prober_dt_match[] = {{
.compatible =
"amlogic, cams_prober", //与dts文件中的aml_cams ->compatible 进行匹配 找到amlogic camera的设备
}, {},
};
static struct platform_driver aml_cams_prober_driver = {
.probe = aml_cams_probe, .remove = aml_cams_remove, .driver = {
.name = "aml_cams_prober",
.owner = THIS_MODULE,
.of_match_table = cams_prober_dt_match,
},
};
static struct i2c_driver ov5647_i2c_driver = {
.driver = {
.name = "ov5647", //在i2c总线上 与dts文件中cam_1->cam_name 进行匹配找到 ov5647的sensor
},
.probe = ov5647_probe,
.remove = ov5647_remove,
.id_table = ov5647_id,
};
在程序中需要获取到dts 中的属性值的方法:调用系统提供的api (common\include\linux\of.h)
I2c_bus → of_property_read_string(p_node, "i2c_bus", &str);
Cam_name → of_property_read_string(p_node, "cam_name", &cam_dev->name);
Front_back → of_property_read_u32(p_node, "front_back", &cam_dev->front_back);
Mirror_flip → of_property_read_u32(p_node, "mirror_flip", &cam_dev->m_flip);
这样我们的驱动程序就和我们的dtb即.dts关联起来。
2.编译:
在平台中单独编译 dtb
方法:
source build/envsetup.sh
lunch 选择自己的项目平台 xxx
make dtbimage
在out\target\product\xxx\
目录下就会生成dtb.img
3.烧录:
在sd
卡的更目录下放dtb.img
文件 插入要烧录的平台。
在平台的uboot
下用命令烧录:
Uboot$: mmc dev 0
Uboot$: mmcinfo
Uboot$: fatload mmc 0 $loadaddr dtb.img
Uboot$: store dtb write $loadaddr
4.DTB的调试方法:
1. 假如我们烧错了dtb
文件,在进入uboot
的时候会提示
在uboot
启动的时候会根据
soc:gxl platform: stvs9 variant:1g
与我们打包的dts
文件中的amlogic-dt-id
的值进行对比。如:gxl_stvs9_normal_1g.dts
如果能找到 gxl_stvs9_1g
系统就可以正常启动。如果不能找到就会提示:
get_partition_from_dts: FDT_ERR_BADMAGIC
!!!!get dts FAILED
机器就会停止在uboot
,不能进入系统。这种情况就是我们的dtb
文件烧录错误;需要检测核对dts
文件。
如果dtb
没有错误:就会找出现 “ Find match dtb: 0
”系统就会启动
2. 在uboot
中对dtb
进行检查核对
执行:
S9BOX # fdt addr 0x1000000
S9BOX # fdt print
就会打印当前的 所用的 dtb
对应的文本。我们就可以检查我们的dtb
文件配置时候有错误。
3. 利用工具将烧录的dtb.img
反向提取dts
文件
4. 在什么情况下要修改dtb
文件
- 在编写驱动程序的时候,要获取硬件设备资源;需要修改
dts
文件。
如前面所提到的增加一个camera驱动。 - 在有些项目中所用的硬件平台修改了一些
gpio
的控制,其他和以前的一样。例如:原来用GPIOH_5
控制camera
的电源,而现在硬件电路改成了GPIOH_6.
控制那么这时候我们就只需要修改dtb
即(dts
)。而不需要修改内核的程序。 - .当发现内核启动过程中,设备的驱动没有加载,或者加载出错的时候。我们也要去检查我们的
dtb
文件配置是否有错误。
三. 技术总结
1.在编写外设驱动的时候要更新对应的dts文件。
2.在内核支持外挂的设备时,pcb板做了一些修改,或者外挂的一些设备发生改变,要修改dts文件