以下是在下针对device tree写的文章,若有误请不吝指正。
网志好读版:
http://gnitnawtw.blogspot.fr/2015/07/device-tree-overlayindustrial-io.html
终于把我第1个device tree overlay生出来了!要赶快把心得写下来。
Device tree的功用
想像若是没有device tree,为不同的处理器写kernel modules
会变成一件看起来复杂实际上很简单的事,举个例子,
以raspberry pi model B+跟raspberry pi 2来说,这两者只有
SoC、CPU、内存大小不一样,但是其他该外部设备(I2C、SPI等)都差不多。
可是若是没有device tree,写kernel module的时候就必须把以下步骤各做一次
- 弄一个machine type id
- 在kernel里面建立关于此id的相关文件,设定SoC的相关代码
(包括外部设备如interrupt、timer、memory mapping等等)还有board-specific文件
- 设定其他的driver
但是现今的SoC都大同小异,了不起就是pin(gpio、I2C等)的位置不一样,
为了这些小差异,要把上面那三件事重做一次,增加一倍的coding到kerenl,
使得kernel最后越来越肥搞到Linus本人都出来骂。
Device tree的作法就是把外设资讯(怎么连接、哪个memory mapping等)
以bootloader传送给kernel,让kernel把外设需要的module根据Device tree的
讯息连接起来。
实际做起来还挺有趣的。我自己写了两个可以在raspberry pi model B+
连接industrial i/o (iio) driver用的device tree
MCP3008(adc)
如果编译kernel的时候有勾选industrial i/o driver的时候就可以使用
可以在/lib/modules/{uname -r}/modules.alias找到这个module :
alias spi:mcp3008 mcp320x
根据kernel document 的说明
https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/mcp320x.txt
我写了mcp320x.dts:
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835", "brcm,bcm2708";
/* disable spi-dev for spi0.0 */
fragment@0 {
target = <&spi0>;
__overlay__ {
status = "okay";
spidev@0{
status = "disabled";
};
};
};
fragment@1 {
target = <&spi0>;
__overlay__ {
/* needed to avoid dtc warning */
#address-cells = <1>;
#size-cells = <0>;
mcp3x0x@0 {
compatible = "mcp3008";
reg = <0>;
spi-max-frequency = <1000000>;
};
};
};
};
dts写好后用dtc编译:
dtc -@ -I dts -O dtb -o mcp320x.dtb mcp320x.dts
然后把mcp320x.dtb copy到/boot/overlays/
最后在/boot/config.txt加上:dtoverlay=mcp320x (跟我写的mcp320x.dtb做连结)
重开机后,只要mcp3008有接对应该就没问题了。
MPU6050(六轴陀螺仪)
一样根据
https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
来编辑mpu6050.dts
// Definitions for MPU6050
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <&i2c1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
clock-frequency = <400000>;
inv-mpu6050@68 {
compatible = "invensense,mpu6050";
reg = <0x68>;
interrupts = <2 23>;
//这行要看情况改不然IRQ有可能会冲到
};
};
};
};
编译后放到/boot/overlays,/boot/config.txt上加入:dtoverlay=mpu6050
如果想要debug,可以在/boot/config.txt上加入:dtdebug=1
重开机后执行sudo vcdbg log msg 就可看device tree加载讯息:
参考资料:
Device Tree 背景介绍
http://www.wowotech.net/linux_kenrel/why-dt.html
Device Trees, Overlays and Parameters
https://www.raspberrypi.org/documentation/configuration/device-tree.md
https://patchwork.ozlabs.org/patch/464158/