device tree
最近在搞wota艺,虽然不如岛国那么有底蕴,但是更疯狂, 我不知道该怎么说,说啥好。。。
1、随便说一下
我有一种感觉就是配置表。。。废话,如果比较暴力一点的调试直接用 io 指令,你们配完没有,一个指令也可以完成
io -4 -w 0xff7b0004 0x00ff000f 。。。类似这种,这就是一种方法,一种方法
最常使用的是引脚,也有其它各种寄存器
按照probe的最先加载的一次性初始化,或者针对引脚rfkill中的block管理,这也是一种方法,方法归方法,最终是要module来实现的
按照最原始的方法,比如以前的单机游戏写一个 gpio.c gpio.h 再写一个pinctrl.c pinctrl.h 就是对pin脚的两个module了,然后其它module要初始自己要用的引脚时,直接调用就可以了,对着dts表来设置
说了那么久,还是不知道dts是什么,是一个表,一个文件,打包放在emmc的boot分区,或者其它分区。。反正要放
名字有各种
比如xxx.dtb
在kernel
make xxx.dtb 就可以得到
在kernel我一般看是
./scripts/dtc/dtc -I dtb -O dts -o xxx.dts arch/arm/boot/dts/xxx.dtb
这个dts由dtb反编译出来看,就是真正的dts了,纯净的,没有包各种dtsi那么恶心,看着很舒服,看看
拿串口来说,都是数字了,其它什么引用板级测试也净化了xxx:[email protected] 比如xxx这种乱七八糟的。。
vi xxx.dts
[email protected] {
compatible = "rockchip,serial";
reg = <0xff180000 0x100>;
interrupts = <0x0 0x37 0x4>;
clock-frequency = <0x16e3600>;
clocks = <0x9a 0x8f 0x8>;
clock-names = "sclk_uart", "pclk_uart";
reg-shift = <0x2>;
reg-io-width = <0x4>;
dmas = <0x90 0x1 0x90 0x2>;
#dma-cells = <0x2>;
pinctrl-names = "default";
pinctrl-0 = <0x9b 0x9c>;
status = "okay";
dma-names = "!tx", "!rx";
};
compatible很重要,属于查询第一条件,但是reg更重要,类似我的io了,多个匹配的时候,就用reg来区分了
串口的moudle会去读
interrupts = <0x0 0x37 0x4>;
clock-frequency = <0x16e3600>;
clocks = <0x9a 0x8f 0x8>;
pinctrl module会去读
pinctrl-names = "default";
pinctrl-0 = <0x9b 0x9c>;
也都很简单的,就是读一下而已,没什么感觉
2、单独说一下pinctrl(复用)
复用就是说引脚不够用,一个引脚充当多个角色的意思
pinctrl-names = "default"; 这个有点调皮,多了一个自己的形态,不过也不难,
default 意思是状态,意思是状态,意思是状态,意思是状态,意思是状态,意思是状态!
就是默认状态,
pinctrl-0 = <0x9b 0x9c>;
uart0-xfer {
rockchip,pins = <0x4c01 0x4c11>;
rockchip,pull = <0x4>;
rockchip,drive = <0x0>;
linux,phandle = <0x9b>;
phandle = <0x9b>;
};
反编译过来真好,直接就看到0x9b 是设置tx rx 引脚
<0x4c01 0x4c11>
这两个数字有没有什么逻辑。。。pinctrl module有什么感觉
答案是没有
XDD,只是一个宏而已
。。。。这个就无解了,毕竟是宏,给pinctrl module看就可以了
0x4c00的时候tx引脚就是设置成为gpio 0x4c01就是设置成为uart了
再看一个其他的
pinctrl-names = "default", "rts_gpio";
pinctrl-0 = <0x114>;
pinctrl-1 = <0x115>;
这个就是两种状态了喔
看一个rfkill的代码
if (!IS_ERR(data->pinctrl)) {
data->rts_gpio.default_state = pinctrl_lookup_state(data->pinctrl, "default");
data->rts_gpio.gpio_state = pinctrl_lookup_state(data->pinctrl, "rts_gpio");
} else {
data->pinctrl = NULL;
LOG("%s: dts does't define the uart rts iomux.\n", __func__);
//return -EINVAL;
}
pinctrl_lookup_state!!!!!!
会去查找状态,比如说状态1 的时候设置成为普通的串口,状态2 设置成为普通的gpio
好比两种选择,吃猪肚鸡或者吃椰子鸡,两种状态都是它,功能不一样,补肾或者补心,我比较喜欢吃椰子鸡,香甜,脆嫩
pinctrl_lookup_state就是会去找这种状态,要用就module上写好了
最后
pinctrl_select_state(pinctrl, rts->gpio_state);
gpio_direction_output(rts->io, !rts->enable);
直接调用pinctrl_select_state,就会去设置引脚复用寄存器了,没了
是不是搞了那么多还不如我一个io指令下去,别,这是上层
3、我还是比较喜欢io指令。。。。
用这个就要抛开所有,直接看手册了,不过dts上面的reg还是可以参考一下