一、绪言
缔造树是每一个Linux驱动工程师齐必须掌合手的一个常识点,有许多之前作念单片机的一又友刚战役Linux驱动时,会一脸懵!
其实缔造树的使用并莫得巨匠念念像的那么复杂,对于大部单干程师来说,惟有会修改即可。
许多粉丝留言说,但愿彭安分提供一个缔造树到驱动默契的实例。
必须安排!
在学习缔造树之前,巨匠一定要搞明晰什么是platform总线,请详备学习底下这篇著述:
《手把手教Linux驱动10-platform总线详解》
对于缔造树表面部天职容请学习底下这篇著述:
《手把手教linux驱动11-linux缔造驱动长入模子》
对于驱动基础著述,不错去B站学习一口君的初学视频:
《从学Linux驱动初学视频》
https://www.bilibili.com/video/BV1d5411A7VJ?spm_id_from=333.999.0.0
有了这些基础常识后,咱们就不错来编写一个缔造树的实例,
底下彭安分就给巨匠教养怎么我方添加一个缔造树节点,并如安在驱动中索求出缔造树的信息。
老规章,代码从0开端编写,何况一说念考证通过,并共享给巨匠。
皇冠账号 二、测试平台本次测试在设备板上操作,操作环境如下:
皇冠网址登入 1. 编译环境ubuntu 足球录像回放网址16.042. 交叉编译用具
root@ubuntu:/home/peng/linux-3.14# arm-none-linux-gnueabi-gcc -v Using built-in specs. COLLECT_GCC=arm-none-linux-gnueabi-gcc COLLECT_LTO_WRAPPER=/home/peng/toolchain/gcc-4.6.4/bin/../libexec/gcc/arm-arm1176jzfssf-linux-gnueabi/4.6.4/lto-wrapper Target: arm-arm1176jzfssf-linux-gnueabi ……………… gcc version 4.6.4 (crosstool-NG hg+default-2685dfa9de14 - tc0002)3. 设备板
设备板:fs4412 soc:exynos44124. 内核版块
Linux kernel 3.14.0三、内核默契缔造树一般历程
系统启动后,uboot会从收罗大致flash、sd卡中读取缔造树文献(具体由uboot大叫给出),
训诫linux内核启动后,会把缔造树镜像保存到的内存地址传递给Linux内核,Linux内核会默契缔造树镜像,从缔造树中索求硬件信息并一一运行化。
其中缔造树信息会被转化成struct platform_device类型变量。
而驱动要默契缔造树,必须界说 struct platform_driver类型结构体变量,并通过函数platform_driver_register()注册。
这两者齐会注册到platform总线,当驱动和缔造树节点匹配奏凯后,就调用 struct platform_driver中.probe设施。
其中缔造树节点会封装在struct device_node结构体变量中 各个属性信息会封装在 struct property结构体变量中, 他们与struct platform_device结构体之间关系如下:

以下是一口君编写的驱动架构,皇冠注册
咱们只需要将测试代码填充到hello_probe()中即可:
static int hello_probe(struct platform_device *pdev) { printk("match ok \n"); //默契代码编写 return 0; } static int hello_remove(struct platform_device *pdev) { printk("hello_remove \n"); return 0; } static struct of_device_id beep_table[] = { {.compatible = "yikoulinux"}, }; static struct platform_driver hello_driver = { .probe = hello_probe, .driver.name = "duang", .remove = hello_remove, .driver = { .name = "yikoupeng", .of_match_table = beep_table, }, }; static int hello_init(void) { printk("hello_init \n"); return platform_driver_register(&hello_driver); } static void hello_exit(void) { printk("hello_exit \n"); platform_driver_unregister(&hello_driver); return; } MODULE_LICENSE("GPL"); module_init(hello_init); module_exit(hello_exit);
五、缔造树节点
底下是给出的缔造树信息:
yikou_node{ compatible = "yikoulinux"; reg = <0x114000a0 0x4 0x139D0000 0x20>; reg-names = "peng"; interrupt-parent=<&gpx1>; interrupts =<1 2>,<2 2>; csm_gpios=<&gpx2 3 0 &gpx2 4 0 &gpx2 5 0 &gpx2 6 0>; crl0_gpio=<&gpx0 5 0>; crl1_gpio=<&gpx0 6 0>; rst_gpio=<&gpx0 7 0>; cfg_gpio=<&gpx0 4 0>; phy_ref_freq = <26000>; /* kHz */ suspend_poweroff; clock-names = "xusbxti", "otg"; yikou_node { compatible = "leadcore,dsi-panel"; panel_name = "lcd_rd_rm67295"; refresh_en = <1>; bits-per-pixel = <32>; }; };
其中包括常见reg、中断、整型值、bool值、字符串、子节点、时钟等属性。
兰博彩票下载www.wuyru.com一定要厚重,许多属性的给出会因为使用的SOC平台的不同有所各别, 底下先容下GPIO和中断编写旨趣:
1. GPIOgpio信息的给出有以下两种设施:
csm_gpios=<&gpx2 3 0 &gpx2 4 0 &gpx2 5 0 &gpx2 6 0>;
crl0_gpio=<&gpx0 5 0>; crl1_gpio=<&gpx0 6 0>; rst_gpio=<&gpx0 7 0>; cfg_gpio=<&gpx0 4 0>;
第1种是公用归并个名字,第2种是每一个gpio单独使用1个名字。
gpio需要指明父节点,对于gpio父节点的证明下证明文档(频频linux-3.14\Documentation下联系于该内核版块的一些模块证明,很首要):
linux-3.14\Documentation\devicetree\bindings\gpio.txt
For example, the following could be used to describe gpios pins to use as chip select lines; with chip selects 0, 1 and 3 populated, and chip select 2 left empty: gpio1: gpio1 { gpio-controller #gpio-cells = <2>; }; gpio2: gpio2 { gpio-controller #gpio-cells = <1>; }; [...] chipsel-gpios = <&gpio1 12 0>, <&gpio1 13 0>, <0>, /* holes are permitted, means no GPIO 2 */ <&gpio2 2>; Note that gpio-specifier length is controller dependent. In the above example, &gpio1 uses 2 cells to specify a gpio, while &gpio2 only uses one. gpio-specifier may encode: bank, pin position inside the bank, whether pin is open-drain and whether pin is logically inverted. Exact meaning of each specifier cell is controller specific, and must be documented in the device tree binding for the device. Example of the node using GPIOs: node { gpios = <&qe_pio_e 18 0>; }; In this example gpio-specifier is "18 0" and encodes GPIO pin number, and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
翻译回归成如下几点:
gpio父节点需要包含属性
皇冠客服飞机:@seo3687gpio-controller、 暗意是gpi逝世器 #gpio-cells = <2>; 暗意子节点包括2个属性
对于子节点是2个属性的函数 比如:
gpios = <&qe_pio_e 18 0>;
父节点是qe_pio_e 其中18暗意GPIO pin值,便是gpio底下解决的pin脚序号,该pin值一般就需要查询用户手册&电路图。

中断属性节点如下:
interrupt-parent=<&gpx1>; interrupts =<1 2>,<2 2>;
其中
interrupt-parent=<&gpx1>;: 该中断信号所述的中断逝世器 interrupts =<1 2>,<2 2>; :形色中断属性,其中<>中第一个值暗意该中断所述中断逝世器index,第二个值暗意中断触发方式
中断子节点步地如下:
linux-3.14\Documentation\devicetree\bindings\gpio.txt
Example of a peripheral using the GPIO module as an IRQ controller: funkyfpga@0 { compatible = "funky-fpga"; ... interrupt-parent = <&gpio1>; #父节点 interrupts = <4 3>; #节点属性 };
中断子节点证明文档如下:
linux-3.14\Documentation\devicetree\bindings\interrupt-controller\interrupts.txt
b) two cells ------------ The #interrupt-cells property is set to 2 and the first cell defines the index of the interrupt within the controller, while the second cell is used to specify any of the following flags: - bits[3:0] trigger type and level flags 1 = low-to-high edge triggered 飞腾沿 2 = high-to-low edge triggered 下跌沿 4 = active high level-sensitive 高电平灵验 8 = active low level-sensitive 低电平灵验
咱们所填写的中断父节点gpx1界说如下(该文献由三星厂家出厂定制好):
linux-3.14\arch\arm\boot\dts\exynos4x12-pinctrl.dtsi
gpx1: gpx1 { gpio-controller; #gpio逝世器 #gpio-cells = <2>; #子节点有2个属性 interrupt-controller; #中断逝世器 interrupt-parent = <&gic>; #父节点gic interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, #子节点属性约束 <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; #interrupt-cells = <2>; };
可见三星的exynos4412平台中gpx1,既不错作念gpio逝世器又不错作念中断逝世器,而gpx1当作中断逝世器则路由到gic上。其中interrupts属性证明如下:
linux-3.14\Documentation\devicetree\bindings\arm\gic.txt
Main node required properties: - compatible : should be one of: "arm,gic-400" "arm,cortex-a15-gic" "arm,cortex-a9-gic" "arm,cortex-a7-gic" "arm,arm11mp-gic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The type shall be a <u32> and the value shall be 3. The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI interrupts. The 2nd cell contains the interrupt number for the interrupt type. SPI interrupts are in the range [0-987]. PPI interrupts are in the range [0-15]. The 3rd cell is the flags, encoded as follows: bits[3:0] trigger type and level flags. 1 = low-to-high edge triggered 2 = high-to-low edge triggered 4 = active high level-sensitive 8 = active low level-sensitive bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of the 8 possible cpus attached to the GIC. A bit set to '1' indicated the interrupt is wired to that CPU. Only valid for PPI interrupts.
翻译回归:
interrupts = <0 24 0>
第1个0 暗意该中断是SPI类型中断,要是是1暗意PPI类型中断
24暗意中断号(通过查询电路图和datasheet获取)
第三个0暗意中断触发方式
再强调一遍 不同的平台gpio、中断逝世器解决可能不相同,是以填写设施可能会有各别,不能教条
欧博注册平台推荐 六、驱动索求缔造树信息设施驱动默契代码与缔造树节点之间关系如下,代码与属性用交流感情框出:

of泉源的函数请参考《手把手教linux驱动11-linux缔造驱动长入模子》
七、编译(ubuntu中操作)驱动编译:

厚重,内核必须提前编译好
缔造树编译:

编译缔造树大叫,各个厂家的SDK齐不尽交流,本例制作参考。
金卡官网除此除外驱动模块文献、缔造树文献怎么导入给设备板,分裂也比拟大,本文不再给出法子。
八、加载模块(设备板上操作)加载模块后施行效果如下:
[root@peng test]# insmod driver.ko [ 26.880000] hello_init [ 26.880000] match ok [ 26.880000] mem_res1 : [0x114000a0] mem_res2:[0x139d0000] [ 26.885000] irq_res1 : [168] irq_res2:[169] [ 26.890000] mem_resp:[114000a0] [ 26.890000] [ 26.895000] phy_ref_freq:26000 [ 26.900000] suspend_poweroff [true] [ 26.900000] suspend_poweroff_test [false] [ 26.900000] [ 26.905000] csm_gpios :[231][232][233][234] [ 26.910000] CTL0:[217] CTL1:[218] RST:[219] CFG:[216] [ 26.915000] bits_per_pixel:32 [ 26.920000] panel_name:lcd_rd_rm67295 [ 26.925000] refresh_en [true]
其中打印的信息便是最终咱们默契出的缔造树里的硬件信息, 咱们就不错证实这些信息进行关系资源肯求、运行化。
XXX已经成为一名顶尖体育明星,表现惊叹不已。曾,成功得益于一直以来努力坚持。同期缔造树中的信息,会以文献节点神气创建在一下目次中:

本文转载自微信公众号「一口Linux」
透明