比较暴力一点的调试直接用 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了,纯净的,
串口都是数字,其它什么引用板级测试也净化了xxx:serial@ff180000
vi xxx.dts
serial@ff180000 {
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>;
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有什么感觉
答案是没有
一个宏而已
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指令下去
io指令
用这个就要抛开所有,直接看手册了,不过dts上面的reg还是可以参考一下