本文说明了Zephyr对device tree的使用方法,并分析了Qemu_cortex_m3的device tree和对应生成的#define. 本文旨在帮助理解Zephyr的代码,不说明如何添加Zephyr的Device Tree和yaml,不分析python script.
Zephyr device tree概述
linux下DTS被DTC编译为DTB,DTB被放到Flash内,启动时DTB由bootloader送给kernel使用。但是这套机制太过庞大,不适合Zephyr作为iot终端节点的目标。
Zephyr采用buildin的方法来使用DTS,主要步骤如下:
- 使用DTC将DTS和C头文件一起预编译组合成.dts_compiled文件。
- python脚本按照YAML文件指定的一组规则从.dts_compiled文件中提取信息转换为define,合并板级描述的dts.fixup内的define放置在头文件generated_dts_board.h中
- Zephyr编译时头文件generated_dts_board.h参与编译被buildin入zephyr
Zephyr device tree基本元素说明
Zephyr Device Tree
Zephyr使用Device Tree来描述架构,板子,驱动信息,Device的文件分别放在1
2
3
4
5boards/<ARCH>/<BOARD>/
dts/
dts/common/
dts/<ARCH>/
dts/<ARCH>/<MANUFACTURER>/
Device Tree语法简述
Zephyr device tree遵循EPAPR document. 简要说明如下:
Device Tree
Device tree由node组成,包含根节点和子节点
节点node由节点名和节点内容组成,节点内容用{}扩起来1
2
3
4
5
6
7
8/{
node-name@unit-address{
property-name=property-value;
node-name@unit-address{
property-name=property-value;
};
}
}
节点
节点node在Device tree中以下面形式出现:1
node-name@unit-address
只能有一个根节点root node, 可以有多个子节点sub node。
一个node的内容有属性和自己的sub node
节点名
根节点名是/
子节点名node-name为长度小于31的字符串。对不同的device,EPAPR document有推荐的node-name(非强制)
当node有寄存器时,unit-address是第一个寄存器的地址。如果node没有寄存器,则无@unit-address
节点属性
属性用表达式以下面形式出现,分为属性名和属性值1
property-name=property-value
属性名
属性名分为标准属性名和非标属性名,对于非标属性名EPAPR document建议加前缀以示区分,例如1
2
3fsl,channel-fifo-len
ibm,ppc-interrupt-server#s
linux,network-index
注意以上只有3个属性名,属性名当中是允许出现 , 的
属性值
属性值有7种类型
- <empty>
空,没有值 <u32>
big-endian 32bit符号整形1
property = <0x11223344>
<u64>
big-endian 64bit符号整形,由两个32bit组成1
property = <0x11223344 0x55667788>
<string>
字符串1
device_type = "memory";
<prop-encoded-array>
任意数量的array1
reg = <0x3000 0x20 0xFE00 0x100>;
<phandle>
节点引用1
uart_0 = &uart0;
<stringlist>
字符串列表1
compatible = "ti,lm3s6965evb-qemu", "ti,lm3s6965";
标准属性
常用标准属性共12种:
- compatible
- model
- phandle
- status
- #address-cells
- #size-cells
- reg
- virtual-reg
- ranges
- dma-ranges
- name
- device_type
另外有6种中断用的属性
- interrupts
- interrupt-parent
- #interrupt-cells
- interrupt-controller
- interrupt-map
- interrupt-map-mask
属性名内容繁多,具体参考EPAPR document,后文QEMU_CORTEX_M3 Device Tree分析会做一些简要说明
YAML
YAML它是一种直观的能够被电脑识别的数据序列化格式,是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言.
Zephyr 使用YAML来定义Device tree转化为#define的生成规则,dts/bindings/device_node.yaml.template 是一个yaml的模板, zephyr的yaml放在1
2dts/bindings
boards/<ARCH>/<BOARD>/
Python Script
将Dts转化为头文件的脚本放在scripts\dts下。目前也还不计划阅读这部分。
Qemu_Cortex_m3 device tree分析
DTS文件组成
由下面文件include组成
- boards/arm/qemu_cortex_m3/qemu_cortex_m3.dts
#include <ti/lm3s6965.dtsi> - dts/arm/ti/lm3s6965.dtsi
#include <arm/armv7-m.dtsi> - dts/arm/armv7-m.dtsi
#include “skeleton.dtsi” - dts/common/skeleton.dtsi
将上面4个文件合并后如下分析:
1 | / { //根节点的属性,如果子节点有重新定义相同属性,子节点内属性使用重新定义后的值 |
Yaml组成
Qemu_cortex_m3使用的yaml有,生成规则待分析(可能要分析python script才能知道),目前能知道转换结果就不会影响Zephyr代码的分析了
- boards/arm/qemu_cortex_m3/qemu_cortex_m3.yaml
- dts/bindings/interrupt-controller/arm,v7m-nvic.yaml
- dts/bindings/serial/ti,stellaris-uart.yaml
- dts/bindings/serial/uart.yaml
转换结果
基本上可以看出就是将dts内的信息转换成device信息的#define,供Zephyr的代码使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72/**************************************************
* Generated include file for ti,lm3s6965evb-qemu
* DO NOT MODIFY
*/
#ifndef _DEVICE_TREE_BOARD_H
#define _DEVICE_TREE_BOARD_H
/* flash@0 */
#define CONFIG_FLASH_BASE_ADDRESS_0 0x0
#define CONFIG_FLASH_LOAD_OFFSET 0
#define CONFIG_FLASH_LOAD_SIZE 0
#define CONFIG_FLASH_SIZE_0 256
#define CONFIG_FLASH_BASE_ADDRESS CONFIG_FLASH_BASE_ADDRESS_0
#define CONFIG_FLASH_SIZE CONFIG_FLASH_SIZE_0
/* memory@20000000 */
#define CONFIG_SRAM_BASE_ADDRESS_0 0x20000000
#define CONFIG_SRAM_SIZE_0 64
#define CONFIG_SRAM_BASE_ADDRESS CONFIG_SRAM_BASE_ADDRESS_0
#define CONFIG_SRAM_SIZE CONFIG_SRAM_SIZE_0
/* interrupt-controller@e000e100 */
#define ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS 3
#define ARM_V7M_NVIC_E000E100_BASE_ADDRESS_0 0xe000e100
#define ARM_V7M_NVIC_E000E100_SIZE_0 3072
#define ARM_V7M_NVIC_E000E100_BASE_ADDRESS ARM_V7M_NVIC_E000E100_BASE_ADDRESS_0
#define ARM_V7M_NVIC_E000E100_SIZE ARM_V7M_NVIC_E000E100_SIZE_0
/* uart@4000C000 */
#define CONFIG_UART_CONSOLE_ON_DEV_NAME "UART_0"
#define TI_STELLARIS_UART_4000C000_BASE_ADDRESS_0 0x4000c000
#define TI_STELLARIS_UART_4000C000_CURRENT_SPEED 115200
#define TI_STELLARIS_UART_4000C000_IRQ_0 5
#define TI_STELLARIS_UART_4000C000_IRQ_0_PRIORITY 3
#define TI_STELLARIS_UART_4000C000_LABEL "UART_0"
#define TI_STELLARIS_UART_4000C000_SIZE_0 76
#define TI_STELLARIS_UART_4000C000_BASE_ADDRESS TI_STELLARIS_UART_4000C000_BASE_ADDRESS_0
#define TI_STELLARIS_UART_4000C000_SIZE TI_STELLARIS_UART_4000C000_SIZE_0
/* uart@4000D000 */
#define CONFIG_UART_PIPE_ON_DEV_NAME "UART_1"
#define TI_STELLARIS_UART_4000D000_BASE_ADDRESS_0 0x4000d000
#define TI_STELLARIS_UART_4000D000_CURRENT_SPEED 115200
#define TI_STELLARIS_UART_4000D000_IRQ_0 6
#define TI_STELLARIS_UART_4000D000_IRQ_0_PRIORITY 3
#define TI_STELLARIS_UART_4000D000_LABEL "UART_1"
#define TI_STELLARIS_UART_4000D000_SIZE_0 76
#define TI_STELLARIS_UART_4000D000_BASE_ADDRESS TI_STELLARIS_UART_4000D000_BASE_ADDRESS_0
#define TI_STELLARIS_UART_4000D000_SIZE TI_STELLARIS_UART_4000D000_SIZE_0
/* uart@4000E000 */
#define CONFIG_BT_MONITOR_ON_DEV_NAME "UART_2"
#define CONFIG_BT_UART_ON_DEV_NAME "UART_2"
#define TI_STELLARIS_UART_4000E000_BASE_ADDRESS_0 0x4000e000
#define TI_STELLARIS_UART_4000E000_CURRENT_SPEED 115200
#define TI_STELLARIS_UART_4000E000_IRQ_0 33
#define TI_STELLARIS_UART_4000E000_IRQ_0_PRIORITY 3
#define TI_STELLARIS_UART_4000E000_LABEL "UART_2"
#define TI_STELLARIS_UART_4000E000_SIZE_0 76
#define TI_STELLARIS_UART_4000E000_BASE_ADDRESS TI_STELLARIS_UART_4000E000_BASE_ADDRESS_0
#define TI_STELLARIS_UART_4000E000_SIZE TI_STELLARIS_UART_4000E000_SIZE_0
/* Following definitions fixup the generated include */
/* SoC level DTS fixup file */
#define CONFIG_NUM_IRQ_PRIO_BITS ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS
/* End of SoC Level DTS fixup file */
#endif
参考
http://docs.zephyrproject.org/devices/dts/device_tree.html
http://events17.linuxfoundation.org/sites/events/files/slides/Zephyr%20Device%20Tree%20-%20ELC2017.pdf
https://elinux.org/images/b/b8/DTWorkshop2017_Zephyr.pdf
https://www.devicetree.org/downloads/devicetree-specification-v0.1-20160524.pdf