From 373a081c64f950998d99120768c6c568604fc585 Mon Sep 17 00:00:00 2001 From: Zhao Maosheng Date: Tue, 19 Sep 2023 19:18:43 +0800 Subject: [PATCH 1/6] add device tree doc --- .../rt-thread-smart/device/device-tree/dtb.md | 610 ++++++++++++++++++ 1 file changed, 610 insertions(+) create mode 100644 rt-thread-version/rt-thread-smart/device/device-tree/dtb.md diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md b/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md new file mode 100644 index 0000000..54dcbab --- /dev/null +++ b/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md @@ -0,0 +1,610 @@ +## 设备树 + +[TOC] + +设备树(Device Tree)是一种用于描述嵌入式系统硬件配置的数据结构,它为不同的硬件平台和操作系统提供了一种通用的方式来配置和管理硬件资源。设备树将硬件描述与操作系统内核分离,使得相同的内核可以在不同的硬件平台上运行,从而提高了嵌入式系统的可移植性。设备树多用于基于ARM的系统,但在其他各种架构中也有应用。 + +### 为rt-thread指定设备树文件 + +在使用设备树运行rt-thread前需要将设备树源文件编译为二进制文件,使用如下命令即可编译: + +``` +dtc -I dts -O dtb -o mydtb.dtb mydts.dts +``` + +#### qemu环境 + +在qemu环境下,可以使用`-dtb mydtb.dtb`来指定使用的dtb文件。aarch64下,内核启动时可从r2寄存器读到设备树文件地址。 + +#### uboot环境 + +uboot的bootcmd环境变量添加加载设备树命令,并设置环境变量fdtaddr,例如(具体需要根据设备情况而定): + +``` +// bootcmd中加入加载设备树的命令,这里以从mmc加载为例,${fdt_addr}替换为加载到内存的地址 +setenv bootcmd "load mmc 0:1 ${fdt_addr} mydtb.dtb; [other cmd]" +setenv fdtaddr ${fdt_addr} +``` + +aarch64下,内核启动时可从r2寄存器读到设备树文件地址。 + +### rt-thread设备树使用场景 + +#### 系统初始化 + +该部分主要是根据设备树系统结点信息进行设备的初始化,包含如下方面: + +- 解析设备树根节点,获得系统信息; +- 内存初始化,对设备树指定的预留内存、内核、fdt等区域保留,其它加入伙伴系统管理; +- 对启动参数进行处理,包括挂载根文件系统,设置早期控制台等; +- 初始化directfs,从而可以在正常运行时获得设备信息; +- 解压缩设备树,方便之后对设备树的访问; +- 根据/cpus结点信息对cpu进行初始化; +- 根据中断控制器结点进行中断初始化; +- 在设备初始化完毕后设置正常运行下的控制台; + +#### 设备初始化 + +设备树环境下设备初始化依赖于平台(platform)总线设备驱动(bus-device-driver)。下面是其架构图: + +```plantuml +@startuml +class rt_bus +class rt_device +class rt_driver +class platform_bus +class rt_platform_device +class rt_platform_driver +class rt_ofw_node +class rt_ofw_node_id + +rt_bus "1" --> "N" rt_device +rt_bus "1" --> "N" rt_driver + +platform_bus --|> rt_bus +rt_device <|-- rt_platform_device +rt_driver <|-- rt_platform_driver + +rt_platform_device --> rt_ofw_node +rt_platform_driver "1" --> "N" rt_ofw_node_id +@enduml +``` + +- rt_device: 提供 app 调用的接口; +- rt_driver: 提供操作底层硬件的能力; +- rt_bus: 为虚拟的总线,挂载了多个 device 和 driver, device 和 driver可以通过 bus 进行匹配和其他操作; +- platform_bus: 是rt_bus的一个单例,设备树中的设备和驱动设备树的驱动程序挂载在platform_bus上; +- rt_platform_device:继承自rt_device,设备树上的设备经解析后得到,挂载在platform_bus上; +- rt_platform_driver: 继承自rt_driver,是挂载在platform_bus上的驱动; +- rt_ofw_node:是设备树经过解压缩后得到的设备结点信息,每个rt_platform_device均对应一个rt_ofw_node; +- rt_ofw_node_id:是rt_platform_driver用于与rt_platform_device进行匹配的信息; + +设备初始化是在rt_thread的组件初始化`rt_components_board_init`时期,主要包含如下方面: + +- 注册平台总线`platform_bus`; +- 将代码中的平台驱动`rt_platform_driver`挂载在平台总线上; +- 给设备树解析得到的各设备分配一个平台设备`rt_platform_device`,并将其挂载在平台总线上; +- 当平台驱动和平台设备相符(兼容属性或者名称相同)时,两者相匹配,并调用驱动的probe函数进行初始化; + +#### 正常运行下 + +系统正常运行时可以通过查看directFS(挂载在/direct上)来了解平台设备树信息,该文件系统中与设备树相关的文件及目录如下: + +- /direct/firmware/devicetree:以目录结构展示了设备树的结构,该目录对应了根结点,以子目录代表子结点,文件代表结点下属性,可通过`cat`、`ls`等命令查看; +- /direct/firmware/fdt:读取该文件内容则会读取到设备树编译后的二进制文件; +- /direct/bus/platform:读取该目录可了解系统平台总线上的设备和驱动; + +同时设备树运行时保留在内存中,应用程序仍可以通过访问设备树来了解系统信息。 + +### rt-thread中设备树编写 + +#### 设备树系统结点编写 + +设备树的系统结点用于rt-thread的系统初始化过程以及提供对设备结点解析所需的部分参数。 + +##### 根节点 + +根节点说明整个设备的情况,对应属性编写如下: + +| 属性 | 解释 | +| --- | --- | +| #size-cells | 子结点使用多少个32位整数来表示大小属性,rt-thread中如未指定使用默认值1 | +| #address-cells | 子结点使用多少个32位整数表示地址属性,rt-thread中如未指定使用默认值1 | +| compatible | 指定平台名称,格式为"<厂商>,<型号>",用于选择正确平台特定程序来初始化设备或判断设备是否有某些特性 | +| model | 设备型号,该属性仅用于为用户提供设备描述,不用于设备匹配 | + +##### /aliases结点 + +该节点可以为其它结点指定别名,以简化书写。其属性名为结点别名,值为对应的结点全称。 + +##### 内存结点 + +内存结点指定系统的可用内存,对应属性编写如下: + +| 属性 | 解释 | +| --- | --- | +| device_type | 属性值必须为"memory" | +| reg | 指定内存范围,格式为<地址 大小>,地址和大小的表示需满足根节点指定的`#address-cells`和`#size-cells` | +| initial-mapped-area | 指定初始化映射区域,目前rt-thread不支持该属性 | +| hotpluggable | 指定该内存区域可以热插拔,目前rt-thread不支持该属性 | + +注意事项: + +- 该类型结点必须位于根节点`/`之下; +- 该类型结点必须指定属性名`device_type`的值为`memory`; +- 该类型结点必须使用`reg`属性指定内存范围; +- 该类型结点命名方式一般为`memory@start-address`; + +##### /reserved-memory + +该结点下的子结点用来保存系统的一系列预留内存区域,其内存区域均不会加入伙伴系统。属性编写如下: + +| 属性 | 解释 | +| --- | --- | +| #size-cells | 必须指定为根节点的#size-cells | +| #address-cells | 必须指定为根节点的#address-cells | +| ranges | 指定reserved-memory结点下地址空间如何向cpu物理地址空间转换 | + +- 以上三个属性均必须明确指定; + +###### /reserved-memory的子结点 + +目前仅支持以下属性 + +| 属性 | 解释 | +| --- | --- | +| reg | 预留内存区域在reserved-memory地址空间下地址范围 | + +普通设备结点可以使用`memory-region`来指定其使用的预留内存区域,值为对/reserved-memory的子结点的引用。 +##### /chosen结点 + +该节点描述了系统固件所指定的初始化参数,对应属性编写如下: + +| 属性 | 解释 | +| --- | --- | +| bootargs | 一串指定启动参数的字符串 | +| stdout-path | 系统正常运行时标准输出重定向到的设备,支持两种格式"serialN:bbbbpnf"和"/serial-path" | +| linux,initrd-start | 一个整数值,表示initrd在内存中的起始地址 | +| linux,initrd-end | 一个整数值,表示initrd在内存中的结束地址 | + +rt-thread中bootargs支持的参数如下: + +| 参数 | 值 | +| --- | --- | +| earlycon | 指定系统早期的控制台输出方式 | +| console | 指定系统控制台 | +| root | 指定挂载根文件系统的设备 | +| rootfstype | 指定根文件系统的类型 | +| rootwait | 是否等待根文件系统设备初始化 | + +/chosen中bootargs属性的console参数和stdout-path属性均可以指定系统输出设备,优先级console参数大于stdout-path属性。 + +##### /cpus结点 + +该结点包含系统的所有cpu,对应属性编写如下 + +| 属性 | 解释 | +| --- | --- | +| #address-cells | cpu子结点使用多少个32位整数来表示大小属性 | +| #size-cells | 该值应为0,cpu的reg没有size属性 | + +###### /cpus/cpu*结点 + +该结点描述一个具体的cpu实例,对应属性编写如下 + +| 属性 | 解释 | +| --- | --- | +| device_type | 必须指定为"cpu" | +| reg | 这里表示cpu的硬件编号,用一个32位无符号整型数表示 | +| enable-method | 指定禁用状态cpu的启动方法,rt-thread支持"psci"和"spin-table"两种方式 | +| cpu-release-addr | 如果`enable-method`属性指定为"spin-table",则需要该属性,其值指定了一个spin-table条目的物理地址,用于解除辅助CPU的阻塞状态,以便其可以继续执行任务 | + +#### rt-thread中设备结点编写 + +对于设备结点的编写,这里介绍如何编写设备结点: + +##### compatible属性 + +该属性用于设备和驱动的绑定。以下是编写该属性注意事项: + +- 设备结点必须拥有该属性,否则该设备无效; +- 如果含有下表属性值之一,则忽略该结点,转而处理子节点; + +| 属性值 | 含义 | +| --- | --- | +| "simple-bus" | 用于表示基本的硬件总线节点,描述设备之间的连接和资源分配 | +| "simple-mfd" | 用于描述多功能设备(Multifunction Device,MFD),包括多个子设备 | +| "isa" | 表示 ISA 总线,是一种古老的总线标准,通常不太常见,用于连接一些旧的外部设备 | +| "arm,amba-bus" | 用于表示 AMBA 总线,是 ARM 架构中常见的总线标准,用于连接各种外部设备和内核总线 | + +- 如果compatible不为空且不为上表之一,则注册为平台设备,不再处理子结点; +- 注册为平台设备后,如果和某平台驱动相匹配,则调用其probe函数,其子节点也交由对应的驱动处理; + +##### 中断相关属性 + +中断控制器属性 + +| 属性 | 解释 | +| --- | --- | +| #interrupt-cells | 用于指定中断控制器在设备树中的中断表示方式 | +| interrupt-controller | 如果某设备结点包含该属性,则该设备是中断控制器 | + +设备的中断相关属性 + +| 属性 | 解释 | +| --- | --- | +| interrupt-parent | 该设备向哪个中断控制器发送中断,值为phandle或中断控制器路径 | +| interrupts | 为设备描述中断信息,一个中断所使用的单元格用#interrupt-cells属性描述 | +| interrupts-extended | 为设备描述中断信息,该设备会向不同中断控制器发送中断 | +| interrupt-map | 用于描述多个设备之间的中断映射关系 | +| interrupt-mask | 用于对中断号进行过滤、匹配、多路复用 | +| interrupt-affinity | 设置中断向哪个cpu发送,值为cpu对应的设备树结点,该属性非设备树标准属性 | +| interrupt-names | 指定中断名称,是数个字符串,每个字符串对应一个中断资源,该属性非设备树标准属性 | + +相应驱动程序需要提供解析这些属性的支持。 + +##### IO相关属性 + +| 属性 | 解释 | +| --- | --- | +| reg | 描述该硬件所使用的物理地址资源,驱动程序需要对该区域调用ioremap | +| reg-names | 指定区域名称,是数个字符串,每个字符串对应一个IO资源,该属性非设备树标准属性 | +| ranges | 通常用于总线类型设备,描述总线结点和父节点的地址空间如何映射 | +| memory-region | 所使用的预留内存区域,目前暂无API处理该属性 | + +### rt-thread下驱动程序编写 + +#### 驱动兼容性 + +设备需要指定其可以与何种设备相匹配。以pl061驱动为例,指定方法如下: + +```c +// 定义rt_ofw_node_id结构体,其中指定了兼容设备在设备中compatible属性 +static const struct rt_ofw_node_id pl061_ofw_ids[] = +{ + { .compatible = "arm,pl061" }, + { /* sentinel */ } +}; + +static struct rt_platform_driver pl061_driver = +{ + // 驱动名称,假如设备名是"pin-pl061"也可以匹配 + .name = "pin-pl061", + // 指定了该驱动的ids,可判断其可以与何种设备相匹配 + .ids = pl061_ofw_ids, + + // probe函数,在驱动探测到相匹配的设备时对其调用的函数 + .probe = pl061_probe, +}; +RT_PLATFORM_DRIVER_EXPORT(pl061_driver); +``` + +- 如上所示,pl061_driver可以与设备名为"pin-pl061"或compatible属性含有"arm,pl061"的设备相匹配; +- `RT_PLATFORM_DRIVER_EXPORT(pl061_driver)`让系统在启动时注册该驱动; + +#### probe函数编写 + +probe函数是driver探测到相匹配的设备时对其调用的函数。具体需要做如下工作: + +- 需要获取设备所需的中断及IO资源; +- 对设备IO资源,需要映射至系统的虚拟地址空间,对IO资源,需要配置中断控制器及设置中断服务例程; +- 需要对设备其它属性进行处理,如设备的配置信息; +- 需要向系统注册该设备; + +对中断及IO资源处理可以使用的API如下: + +##### 中断资源处理 + +如果设备驱动程序需要对设备的中断资源进行处理,需要包含头文件: + +```c +#include +``` + +以下是中断资源处理接口介绍 + +```c +int rt_ofw_irq_cells(struct rt_ofw_node *np); +``` + +该函数获取设备结点`#interrupt-cells`属性 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| int | 设备结点对应的`#interrupt-cells`属性值 | +| -RT_EEMPTY | 设备结点没有该属性 | +| -RT_EINVAL | 设备不合法 | + +```c +rt_err_t rt_ofw_parse_irq_map(struct rt_ofw_node *np, struct rt_ofw_cell_args *irq_args); +``` + +该函数处理设备结点`interrupt-map`属性 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| irq_args | 传递参数及存放解析`interrupt-map`属性结果 | +| **返回** | **描述** | +| 0 | 解析成功 | +| 错误码 | 解析失败 | + +```c +rt_err_t rt_ofw_parse_irq_cells(struct rt_ofw_node *np, int index, struct rt_ofw_cell_args *out_irq_args); +``` + +该函数解析设备中断资源,其首先检查参数`interrupts-extended`,如果没有该参数则检查`interrupts`参数。可以获取中断号及对应中断控制器信息。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| index | 设备第几个中断资源 | +| out_irq_args | 存储获得的中断信息 | +| **返回** | **描述** | +| 0 | 获取中断信息成功 | +| 错误码 | 获取失败 | + +```c +struct rt_ofw_node *rt_ofw_find_irq_parent(struct rt_ofw_node *np, int *out_interrupt_cells); +``` + +该函数获取设备对应中断控制器的结点信息。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| out_interrupt_cells | 中断控制器的`#interrupt-cells`属性 | +| **返回** | **描述** | +| rt_ofw_node结点 | 获取的中断控制器结点 | +| RT_NULL | 找不到对应的中断控制器结点 | + +```c +int rt_ofw_map_irq(struct rt_ofw_cell_args *irq_args); +``` + +该函数将设备的中断信息应用于中断控制器中。一般在使用`rt_ofw_parse_irq_map`或`rt_ofw_parse_irq_cells`获取到设备中断信息后,调用该函数使能对应中断。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| irq_args | 获取到的设备中断信息 | +| **返回** | **描述** | +| 大于0整数 | 设置的中断编号 | +| 错误码 | 执行错误 | + + +```c +int rt_ofw_get_irq_count(struct rt_ofw_node *np); +``` + +该函数返回设备指定的中断资源数目。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| 一个非负整数 | 设备中断资源数目 | +| -RT_EINVAL | 传入的np不合法 | + +```c +int rt_ofw_get_irq(struct rt_ofw_node *np, int index); +``` + +该函数获取设备树结点的指定中断资源中断号并进行处理。具体地,该函数将调用`ofw_map_irq`使能中断,并根据设备的`interrupt-affinity`属性设置应当响应中断的cpu,最后返回设置的中断号。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| index | 需要处理的设备中断资源编号 | +| **返回** | **描述** | +| 一个非负整数 | 指定中断资源的中断号 | +| 错误码 | 执行错误 | + +```c +int rt_ofw_get_irq_by_name(struct rt_ofw_node *np, const char *name); +``` + +该函数作用与`rt_ofw_get_irq`相同,不过使用名称来指定中断。该函数会通过name参数,根据设备的`interrupt-names`属性来获得对应的中断资源编号,最后调用`rt_ofw_get_irq`。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| name | 需要处理的设备中断名称 | +| **返回** | **描述** | +| 一个非负整数 | 指定中断资源的中断号 | +| 错误码 | 执行错误 | + +```c +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name) +``` + +该函数设置中断向量表,用于指定某中断号对应的中断服务例程。需要包含头文件`` + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| vector | 需要设置的中断号,可以由`rt_ofw_get_irq`或`rt_ofw_get_irq_by_name`获得 | +| handler | 需要设置成的中断服务例程 | +| param | 中断服务例程参数 | +| name | 中断服务例程名称 | +| **返回** | **描述** | +| RT_NULL | 该中断号原来无中断服务例程 | +| old_handler | 之前该中断号对应的中断服务例程 | + +##### IO资源处理 + +如果设备驱动程序需要对设备的IO资源进行处理,需要包含头文件: + +```c +#include +``` + +以下是IO资源处理接口介绍 + +```c +int rt_ofw_bus_addr_cells(struct rt_ofw_node *np); +``` + +获取总线设备的`#address-cells`属性。它会从总线设备结点遍历parent结点,获取到第一个`#address-cells`则返回。如果未获得则使用默认值1。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| 一个正整数 | 设备的`#address-cells`属性 | +| -RT_EINVAL | np不合法 | + +```c +int rt_ofw_bus_size_cells(struct rt_ofw_node *np); +``` + +获取总线设备的`#size-cells`属性。它会从总线设备结点遍历parent结点,获取到第一个`#size-cells`则返回。如果未获得则使用默认值1。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| 一个正整数 | 设备的`#size-cells`属性 | +| -RT_EINVAL | np不合法 | + +```c +int rt_ofw_io_addr_cells(struct rt_ofw_node *np); +``` + +获取普通设备的`#address-cells`属性。其优先获取所在总线(即其父节点)的该属性。如果未获得则使用默认值1。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| 一个正整数 | 设备的`#address-cells`属性 | +| -RT_EINVAL | np不合法 | + +```c +int rt_ofw_io_size_cells(struct rt_ofw_node *np); +``` + +获取普通设备的`#size-cells`属性。其优先获取所在总线(即其父节点)的该属性。如果未获得则使用默认值1。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| 一个正整数 | 设备的`#size-cells`属性 | +| -RT_EINVAL | np不合法 | + +```c +int rt_ofw_get_address_count(struct rt_ofw_node *np); +``` + +该函数获取设备结点的`reg`属性中地址的数量。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| **返回** | **描述** | +| 一个非负整数 | 设备结点的`reg`属性中地址的数量 | +| -RT_EINVAL | np不合法 | + +```c +rt_err_t rt_ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_address, rt_uint64_t *out_size); +``` + +该函数获取设备结点的`reg`属性中指定编号的以address-size对表示的IO资源。获得的地址是转换到cpu地址空间的地址。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| index | 需要获得的address-size对的编号 | +| out_address | 存储获得的address转换到cpu地址空间的值 | +| out_size | 存储获得的size值 | +| **返回** | **描述** | +| RT_EOK | 执行成功 | +| -RT_EINVAL | 参数不合法 | + +```c +rt_err_t rt_ofw_get_address_by_name(struct rt_ofw_node *np, const char *name, rt_uint64_t *out_address, rt_uint64_t *out_size) +``` + +该函数作用与`rt_ofw_get_address`相同,不过使用名称来指定address-size对表示的IO资源。该函数会通过name参数,根据设备的`reg-names`属性来获得对应的IO资源编号,之后过程与`rt_ofw_get_address`相同。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| name | 需要获得的IO资源名称 | +| out_address | 存储获得的address转换到cpu地址空间的值 | +| out_size | 存储获得的size值 | +| **返回** | **描述** | +| RT_EOK | 执行成功 | +| -RT_EINVAL | 参数不合法 | + +```c +int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_regs); +``` + +该函数获取设备结点前nr个IO资源属性。地址值会转换到cpu物理地址空间。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| nr | 需要获得的IO资源个数 | +| out_regs | 存储获得的以address-size对表示的IO资源 | +| **返回** | **描述** | +| 一个非负整数 | 实际获得的IO资源个数 | +| -RT_EINVAL | 参数不合法 | + +```c +rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address); +``` + +将某一地址从设备所属总线的地址空间转换到cpu的物理地址空间。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| range_type | 映射类型,不指定时默认为"ranges",该函数从该属性来获得映射方式 | +| address | 设备所属总线下的某一地址 | +| **返回** | **描述** | +| 最大64位正整数 | 转换失败 | +| 一个合法物理地址 | 设备映射到的物理地址 | + +```c +void *rt_ofw_iomap(struct rt_ofw_node *np, int index) +``` + +将设备的一个IO资源重映射到系统内核地址空间的虚拟地址。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| index | 指定的IO资源编号 | +| **返回** | **描述** | +| RT_NULL | 执行失败 | +| 一个合法的内核虚拟地址 | 设备映射到的内核虚拟地址 | + +```c +void *rt_ofw_iomap_by_name(struct rt_ofw_node *np, const char *name) +``` + +与`rt_ofw_iomap`作用相同,但使用名称来指定设备IO资源。该函数会通过name参数,根据设备的`reg-names`属性来获得对应的IO资源编号,之后过程与`rt_ofw_iomap`相同。 + +| 参数 | 描述 | +|:------------------|:------------------------------------| +| np | 设备结点 | +| name | 指定的IO资源名称 | +| **返回** | **描述** | +| RT_NULL | 执行失败 | +| 一个合法的内核虚拟地址 | 设备映射到的内核虚拟地址 | + +##### 其它属性处理 + +在`components/drivers/include/drivers/ofw.h`中定义了一系列可以处理不同属性值格式的函数,驱动程序可以调用这些函数来获得并处理这些属性。 + +#### 说明编写 + +驱动编写者需要提供该驱动如何与设备绑定相关说明,告知设备树编写者如何编写该驱动支持的设备结点。 + +说明需要包含如下方面: + +- 驱动所支持的`compatible`属性或可以匹配的设备名称; +- 设备必须指定及可以指定的属性,并给出属性含义及属性值的形式; -- Gitee From 3f01cbb9d1ac82d828b27a7abbca2f141fafb726 Mon Sep 17 00:00:00 2001 From: Zhao Maosheng Date: Tue, 19 Sep 2023 19:25:35 +0800 Subject: [PATCH 2/6] replace plantuml to image --- .../rt-thread-smart/device/device-tree/dtb.md | 23 +----------------- .../device-tree/figures/bus-dev-drv.png | Bin 0 -> 20793 bytes 2 files changed, 1 insertion(+), 22 deletions(-) create mode 100644 rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.png diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md b/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md index 54dcbab..6c22b64 100644 --- a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md +++ b/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md @@ -47,28 +47,7 @@ aarch64下,内核启动时可从r2寄存器读到设备树文件地址。 设备树环境下设备初始化依赖于平台(platform)总线设备驱动(bus-device-driver)。下面是其架构图: -```plantuml -@startuml -class rt_bus -class rt_device -class rt_driver -class platform_bus -class rt_platform_device -class rt_platform_driver -class rt_ofw_node -class rt_ofw_node_id - -rt_bus "1" --> "N" rt_device -rt_bus "1" --> "N" rt_driver - -platform_bus --|> rt_bus -rt_device <|-- rt_platform_device -rt_driver <|-- rt_platform_driver - -rt_platform_device --> rt_ofw_node -rt_platform_driver "1" --> "N" rt_ofw_node_id -@enduml -``` +![devtree](figures/bus-dev-drv.png) - rt_device: 提供 app 调用的接口; - rt_driver: 提供操作底层硬件的能力; diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.png b/rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.png new file mode 100644 index 0000000000000000000000000000000000000000..b5d022fc547c554c10059ebcc117e210746c2ddc GIT binary patch literal 20793 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

vBZ!>)5f2%ZqKy0lOZeQ^%p3R9p5F0EM|c0Xio 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 D@wZxw literal 0 HcmV?d00001 -- Gitee From 335750f97073d7a3e8d3b876f6e6c422bfafc13c Mon Sep 17 00:00:00 2001 From: Zhao Maosheng Date: Tue, 19 Sep 2023 19:29:48 +0800 Subject: [PATCH 3/6] remove toc --- rt-thread-version/rt-thread-smart/device/device-tree/dtb.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md b/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md index 6c22b64..c05735a 100644 --- a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md +++ b/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md @@ -1,7 +1,5 @@ ## 设备树 -[TOC] - 设备树(Device Tree)是一种用于描述嵌入式系统硬件配置的数据结构,它为不同的硬件平台和操作系统提供了一种通用的方式来配置和管理硬件资源。设备树将硬件描述与操作系统内核分离,使得相同的内核可以在不同的硬件平台上运行,从而提高了嵌入式系统的可移植性。设备树多用于基于ARM的系统,但在其他各种架构中也有应用。 ### 为rt-thread指定设备树文件 -- Gitee From d24069238b0730de77a4cf2191de2d5e7f37eb66 Mon Sep 17 00:00:00 2001 From: Zhao Maosheng Date: Tue, 19 Sep 2023 19:33:21 +0800 Subject: [PATCH 4/6] add plantuml.txt --- .../device-tree/figures/bus-dev-drv.txt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.txt diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.txt b/rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.txt new file mode 100644 index 0000000..b7ee513 --- /dev/null +++ b/rt-thread-version/rt-thread-smart/device/device-tree/figures/bus-dev-drv.txt @@ -0,0 +1,22 @@ +```plantuml +@startuml +class rt_bus +class rt_device +class rt_driver +class platform_bus +class rt_platform_device +class rt_platform_driver +class rt_ofw_node +class rt_ofw_node_id + +rt_bus "1" --> "N" rt_device +rt_bus "1" --> "N" rt_driver + +platform_bus --|> rt_bus +rt_device <|-- rt_platform_device +rt_driver <|-- rt_platform_driver + +rt_platform_device --> rt_ofw_node +rt_platform_driver "1" --> "N" rt_ofw_node_id +@enduml +``` -- Gitee From 5bcf0c35f39e9486d50d374be02b785656211f2b Mon Sep 17 00:00:00 2001 From: Zhao Maosheng Date: Fri, 22 Sep 2023 10:48:00 +0800 Subject: [PATCH 5/6] delete directfs temporarily, and revise format --- rt-thread-version/rt-thread-smart/_sidebar.md | 1 + .../device-tree/{dtb.md => device-tree.md} | 346 +++++++++--------- 2 files changed, 174 insertions(+), 173 deletions(-) rename rt-thread-version/rt-thread-smart/device/device-tree/{dtb.md => device-tree.md} (48%) diff --git a/rt-thread-version/rt-thread-smart/_sidebar.md b/rt-thread-version/rt-thread-smart/_sidebar.md index 092c707..8c0fc6b 100644 --- a/rt-thread-version/rt-thread-smart/_sidebar.md +++ b/rt-thread-version/rt-thread-smart/_sidebar.md @@ -11,6 +11,7 @@ - [QEMU快速上手(Linux)](/rt-thread-version/rt-thread-smart/quick-start/qemu-linux/quickstart.md) - 设备和驱动 - [DevFS设备管理](/rt-thread-version/rt-thread-smart/device/DevFS/DevFS.md) + - [设备树使用](/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md) - 开发调试 - [使用VSCode调试用户态应用(Win)](/rt-thread-version/rt-thread-smart/debug/qemu-arm-win/qemu-arm-win.md) - [使用VSCode调试用户态应用(Linux)](/rt-thread-version/rt-thread-smart/debug/qemu-arm-linux/qemu-arm-linux.md) diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md b/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md similarity index 48% rename from rt-thread-version/rt-thread-smart/device/device-tree/dtb.md rename to rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md index c05735a..e4ace31 100644 --- a/rt-thread-version/rt-thread-smart/device/device-tree/dtb.md +++ b/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md @@ -1,186 +1,187 @@ -## 设备树 +# 设备树 -设备树(Device Tree)是一种用于描述嵌入式系统硬件配置的数据结构,它为不同的硬件平台和操作系统提供了一种通用的方式来配置和管理硬件资源。设备树将硬件描述与操作系统内核分离,使得相同的内核可以在不同的硬件平台上运行,从而提高了嵌入式系统的可移植性。设备树多用于基于ARM的系统,但在其他各种架构中也有应用。 +设备树(Device Tree)是一种用于描述嵌入式系统硬件配置的数据结构,它为不同的硬件平台和操作系统提供了一种通用的方式来配置和管理硬件资源。设备树将硬件描述与操作系统内核分离,使得相同的内核可以在不同的硬件平台上运行,从而提高了嵌入式系统的可移植性。设备树多用于基于 ARM 的系统,但在其他各种架构中也有应用。 -### 为rt-thread指定设备树文件 +## 为 rt-thread 指定设备树文件 -在使用设备树运行rt-thread前需要将设备树源文件编译为二进制文件,使用如下命令即可编译: +在使用设备树运行 rt-thread 前需要将设备树源文件编译为二进制文件,使用如下命令即可编译: ``` dtc -I dts -O dtb -o mydtb.dtb mydts.dts ``` -#### qemu环境 +### 使用 qemu -在qemu环境下,可以使用`-dtb mydtb.dtb`来指定使用的dtb文件。aarch64下,内核启动时可从r2寄存器读到设备树文件地址。 +在 qemu 环境下,可以使用`-dtb mydtb.dtb`来指定使用的 dtb 文件,也可以不指定,使用默认的 dtb 文件。aarch64 下,内核启动时可从 r2 寄存器读到设备树文件地址。 -#### uboot环境 +### 使用 uboot -uboot的bootcmd环境变量添加加载设备树命令,并设置环境变量fdtaddr,例如(具体需要根据设备情况而定): +uboot 的 bootcmd 环境变量添加加载设备树命令,并设置环境变量 fdtaddr,例如(具体需要根据设备情况而定): ``` -// bootcmd中加入加载设备树的命令,这里以从mmc加载为例,${fdt_addr}替换为加载到内存的地址 +// bootcmd 中加入加载设备树的命令,这里以从 mmc 加载为例,${fdt_addr}替换为加载到内存的地址 setenv bootcmd "load mmc 0:1 ${fdt_addr} mydtb.dtb; [other cmd]" setenv fdtaddr ${fdt_addr} ``` -aarch64下,内核启动时可从r2寄存器读到设备树文件地址。 +aarch64 下,内核启动时可从 r2 寄存器读到设备树文件地址。 -### rt-thread设备树使用场景 +## rt-thread 设备树使用场景 -#### 系统初始化 +### 系统初始化 -该部分主要是根据设备树系统结点信息进行设备的初始化,包含如下方面: +该部分需要根据设备树系统结点信息进行设备的初始化,包含如下方面: - 解析设备树根节点,获得系统信息; -- 内存初始化,对设备树指定的预留内存、内核、fdt等区域保留,其它加入伙伴系统管理; -- 对启动参数进行处理,包括挂载根文件系统,设置早期控制台等; -- 初始化directfs,从而可以在正常运行时获得设备信息; +- 内存初始化,对设备树指定的预留内存、内核、fdt 等区域保留,其它部分内存加入伙伴系统管理; +- 对启动参数 bootargs 进行处理,包括挂载根文件系统,设置早期控制台等; +- 初始化 directfs,从而可以在正常运行时获得设备信息; - 解压缩设备树,方便之后对设备树的访问; -- 根据/cpus结点信息对cpu进行初始化; +- 根据/cpus 结点信息对 cpu 进行初始化; - 根据中断控制器结点进行中断初始化; - 在设备初始化完毕后设置正常运行下的控制台; -#### 设备初始化 +### 设备初始化 -设备树环境下设备初始化依赖于平台(platform)总线设备驱动(bus-device-driver)。下面是其架构图: +设备树环境下设备初始化依赖于平台 (platform) 总线设备驱动 (bus-device-driver)。下面是其架构图: ![devtree](figures/bus-dev-drv.png) - rt_device: 提供 app 调用的接口; - rt_driver: 提供操作底层硬件的能力; -- rt_bus: 为虚拟的总线,挂载了多个 device 和 driver, device 和 driver可以通过 bus 进行匹配和其他操作; -- platform_bus: 是rt_bus的一个单例,设备树中的设备和驱动设备树的驱动程序挂载在platform_bus上; -- rt_platform_device:继承自rt_device,设备树上的设备经解析后得到,挂载在platform_bus上; -- rt_platform_driver: 继承自rt_driver,是挂载在platform_bus上的驱动; -- rt_ofw_node:是设备树经过解压缩后得到的设备结点信息,每个rt_platform_device均对应一个rt_ofw_node; -- rt_ofw_node_id:是rt_platform_driver用于与rt_platform_device进行匹配的信息; +- rt_bus: 为虚拟的总线,挂载了多个 device 和 driver, device 和 driver 可以通过 bus 进行匹配和其他操作; +- platform_bus: 是 rt_bus 的一个单例,设备树中的设备和驱动设备树的驱动程序挂载在 platform_bus 上; +- rt_platform_device:继承自 rt_device,设备树上的设备经解析后得到,挂载在 platform_bus 上; +- rt_platform_driver: 继承自 rt_driver,是挂载在 platform_bus 上的驱动; +- rt_ofw_node:是设备树经过解压缩后得到的设备结点信息,每个 rt_platform_device 均对应一个 rt_ofw_node; +- rt_ofw_node_id:是 rt_platform_driver 用于与 rt_platform_device 进行匹配的信息; -设备初始化是在rt_thread的组件初始化`rt_components_board_init`时期,主要包含如下方面: +设备初始化是在 rt_thread 的组件初始化 rt_components_board_init 时期,主要包含如下方面: -- 注册平台总线`platform_bus`; -- 将代码中的平台驱动`rt_platform_driver`挂载在平台总线上; -- 给设备树解析得到的各设备分配一个平台设备`rt_platform_device`,并将其挂载在平台总线上; -- 当平台驱动和平台设备相符(兼容属性或者名称相同)时,两者相匹配,并调用驱动的probe函数进行初始化; +- 注册平台总线 platform_bus; +- 将代码中的平台驱动 rt_platform_driver 挂载在平台总线上; +- 给设备树解析得到的各设备分配一个平台设备 rt_platform_device,并将其挂载在平台总线上; +- 当平台驱动和平台设备相符(兼容属性或者名称相同)时,两者相匹配,并调用驱动的 probe 函数进行初始化; -#### 正常运行下 +### 正常运行下 -系统正常运行时可以通过查看directFS(挂载在/direct上)来了解平台设备树信息,该文件系统中与设备树相关的文件及目录如下: +系统正常运行时可以通过在 msh 中查看 directFS(挂载在 /direct 上)来了解平台设备树信息,该文件系统中与设备树相关的文件及目录如下: -- /direct/firmware/devicetree:以目录结构展示了设备树的结构,该目录对应了根结点,以子目录代表子结点,文件代表结点下属性,可通过`cat`、`ls`等命令查看; +- /direct/firmware/devicetree:以目录结构展示了设备树的结构,该目录对应了根结点,以子目录代表子结点,文件代表结点下属性,可通过 cat、ls 等命令查看; - /direct/firmware/fdt:读取该文件内容则会读取到设备树编译后的二进制文件; - /direct/bus/platform:读取该目录可了解系统平台总线上的设备和驱动; 同时设备树运行时保留在内存中,应用程序仍可以通过访问设备树来了解系统信息。 -### rt-thread中设备树编写 +## rt-thread 中设备树编写 -#### 设备树系统结点编写 +### 设备树系统结点编写 -设备树的系统结点用于rt-thread的系统初始化过程以及提供对设备结点解析所需的部分参数。 +设备树的系统结点用于 rt-thread 的系统初始化过程以及提供对设备结点解析所需的部分参数。 -##### 根节点 +#### 根节点 根节点说明整个设备的情况,对应属性编写如下: | 属性 | 解释 | | --- | --- | -| #size-cells | 子结点使用多少个32位整数来表示大小属性,rt-thread中如未指定使用默认值1 | -| #address-cells | 子结点使用多少个32位整数表示地址属性,rt-thread中如未指定使用默认值1 | +| #size-cells | 子结点使用多少个 32 位整数来表示大小属性,rt-thread 中如未指定使用默认值 1 | +| #address-cells | 子结点使用多少个 32 位整数表示地址属性,rt-thread 中如未指定使用默认值 1 | | compatible | 指定平台名称,格式为"<厂商>,<型号>",用于选择正确平台特定程序来初始化设备或判断设备是否有某些特性 | | model | 设备型号,该属性仅用于为用户提供设备描述,不用于设备匹配 | -##### /aliases结点 +#### /aliases 结点 该节点可以为其它结点指定别名,以简化书写。其属性名为结点别名,值为对应的结点全称。 -##### 内存结点 +#### 内存结点 内存结点指定系统的可用内存,对应属性编写如下: | 属性 | 解释 | | --- | --- | -| device_type | 属性值必须为"memory" | -| reg | 指定内存范围,格式为<地址 大小>,地址和大小的表示需满足根节点指定的`#address-cells`和`#size-cells` | -| initial-mapped-area | 指定初始化映射区域,目前rt-thread不支持该属性 | -| hotpluggable | 指定该内存区域可以热插拔,目前rt-thread不支持该属性 | +| device_type | 属性值必须为 "memory" | +| reg | 指定内存范围,格式为<地址 大小>,地址和大小的表示需满足根节点指定的 #address-cells 和 #size-cells | +| initial-mapped-area | 指定初始化映射区域,目前 rt-thread 不支持该属性 | +| hotpluggable | 指定该内存区域可以热插拔,目前 rt-thread 不支持该属性 | 注意事项: -- 该类型结点必须位于根节点`/`之下; -- 该类型结点必须指定属性名`device_type`的值为`memory`; -- 该类型结点必须使用`reg`属性指定内存范围; -- 该类型结点命名方式一般为`memory@start-address`; +- 该类型结点必须位于根节点/之下; +- 该类型结点必须指定属性名 device_type 的值为 "memory"; +- 该类型结点必须使用 reg 属性指定内存范围; +- 该类型结点命名方式一般为 memory@start-address; -##### /reserved-memory +#### /reserved-memory -该结点下的子结点用来保存系统的一系列预留内存区域,其内存区域均不会加入伙伴系统。属性编写如下: +该结点下的子结点用来保存系统的一系列预留内存区域,其内存区域均不会加入伙伴系统。属性编写如下: | 属性 | 解释 | | --- | --- | | #size-cells | 必须指定为根节点的#size-cells | | #address-cells | 必须指定为根节点的#address-cells | -| ranges | 指定reserved-memory结点下地址空间如何向cpu物理地址空间转换 | +| ranges | 指定 reserved-memory 结点下地址空间如何向 cpu 物理地址空间转换 | - 以上三个属性均必须明确指定; -###### /reserved-memory的子结点 +##### /reserved-memory 的子结点 目前仅支持以下属性 | 属性 | 解释 | | --- | --- | -| reg | 预留内存区域在reserved-memory地址空间下地址范围 | +| reg | 预留内存区域在 reserved-memory 地址空间下地址范围 | -普通设备结点可以使用`memory-region`来指定其使用的预留内存区域,值为对/reserved-memory的子结点的引用。 -##### /chosen结点 +普通设备结点可以使用 memory-region 来指定其使用的预留内存区域,值为对 /reserved-memory 的子结点的引用,但需要对应驱动程序的支持。 -该节点描述了系统固件所指定的初始化参数,对应属性编写如下: +#### /chosen 结点 + +该节点描述了系统固件所指定的初始化参数,对应属性编写如下: | 属性 | 解释 | | --- | --- | | bootargs | 一串指定启动参数的字符串 | -| stdout-path | 系统正常运行时标准输出重定向到的设备,支持两种格式"serialN:bbbbpnf"和"/serial-path" | -| linux,initrd-start | 一个整数值,表示initrd在内存中的起始地址 | -| linux,initrd-end | 一个整数值,表示initrd在内存中的结束地址 | +| stdout-path | 系统正常运行时标准输出重定向到的设备,支持两种格式 serialN:bbbbpnf 和 /serial-path | +| linux,initrd-start | 一个整数值,表示 initrd 在内存中的起始地址 | +| linux,initrd-end | 一个整数值,表示 initrd 在内存中的结束地址 | -rt-thread中bootargs支持的参数如下: +rt-thread 中 bootargs 支持的参数如下: | 参数 | 值 | | --- | --- | -| earlycon | 指定系统早期的控制台输出方式 | -| console | 指定系统控制台 | +| earlycon | 指定系统初始化阶段的控制台输出方式 | +| console | 指定系统正常运行时控制台 | | root | 指定挂载根文件系统的设备 | | rootfstype | 指定根文件系统的类型 | | rootwait | 是否等待根文件系统设备初始化 | -/chosen中bootargs属性的console参数和stdout-path属性均可以指定系统输出设备,优先级console参数大于stdout-path属性。 +/chosen 中 bootargs 属性的 console 参数和 stdout-path 属性均可以指定系统输出设备,优先级 console 参数大于 stdout-path 属性。 -##### /cpus结点 +#### /cpus 结点 -该结点包含系统的所有cpu,对应属性编写如下 +该结点包含系统的所有 cpu,对应属性编写如下: | 属性 | 解释 | | --- | --- | -| #address-cells | cpu子结点使用多少个32位整数来表示大小属性 | -| #size-cells | 该值应为0,cpu的reg没有size属性 | +| #address-cells | cpu 子结点使用多少个 32 位整数来表示大小属性 | +| #size-cells | 该值应为 0,cpu 的 reg 没有 size 属性 | -###### /cpus/cpu*结点 +##### /cpus/cpu *结点 -该结点描述一个具体的cpu实例,对应属性编写如下 +该结点描述一个具体的 cpu 实例,对应属性编写如下: | 属性 | 解释 | | --- | --- | | device_type | 必须指定为"cpu" | -| reg | 这里表示cpu的硬件编号,用一个32位无符号整型数表示 | -| enable-method | 指定禁用状态cpu的启动方法,rt-thread支持"psci"和"spin-table"两种方式 | -| cpu-release-addr | 如果`enable-method`属性指定为"spin-table",则需要该属性,其值指定了一个spin-table条目的物理地址,用于解除辅助CPU的阻塞状态,以便其可以继续执行任务 | +| reg | 这里表示 cpu 的硬件编号,用一个 32 位无符号整型数表示 | +| enable-method | 指定禁用状态 cpu 的启动方法,rt-thread 支持"psci"和"spin-table"两种方式 | +| cpu-release-addr | 如果 enable-method 属性指定为"spin-table",则需要该属性,其值指定了一个 spin-table 条目的物理地址,用于解除辅助 CPU 的阻塞状态,以便其可以继续执行任务 | -#### rt-thread中设备结点编写 +### rt-thread 中设备结点编写 对于设备结点的编写,这里介绍如何编写设备结点: -##### compatible属性 +#### compatible 属性 该属性用于设备和驱动的绑定。以下是编写该属性注意事项: @@ -194,49 +195,49 @@ rt-thread中bootargs支持的参数如下: | "isa" | 表示 ISA 总线,是一种古老的总线标准,通常不太常见,用于连接一些旧的外部设备 | | "arm,amba-bus" | 用于表示 AMBA 总线,是 ARM 架构中常见的总线标准,用于连接各种外部设备和内核总线 | -- 如果compatible不为空且不为上表之一,则注册为平台设备,不再处理子结点; -- 注册为平台设备后,如果和某平台驱动相匹配,则调用其probe函数,其子节点也交由对应的驱动处理; +- 如果 compatible 不为空且不为上表之一,则注册为平台设备,不再处理子结点; +- 注册为平台设备后,如果和某平台驱动相匹配,则调用其 probe 函数,其子节点也交由对应的驱动处理; -##### 中断相关属性 +#### 中断相关属性 -中断控制器属性 +中断控制器属性: | 属性 | 解释 | | --- | --- | | #interrupt-cells | 用于指定中断控制器在设备树中的中断表示方式 | | interrupt-controller | 如果某设备结点包含该属性,则该设备是中断控制器 | -设备的中断相关属性 +设备的中断相关属性: | 属性 | 解释 | | --- | --- | -| interrupt-parent | 该设备向哪个中断控制器发送中断,值为phandle或中断控制器路径 | -| interrupts | 为设备描述中断信息,一个中断所使用的单元格用#interrupt-cells属性描述 | -| interrupts-extended | 为设备描述中断信息,该设备会向不同中断控制器发送中断 | +| interrupt-parent | 该设备向哪个中断控制器发送中断,值为 phandle 或中断控制器路径 | +| interrupts | 为设备描述中断信息,一个中断所使用的单元格用#interrupt-cells 属性描述 | +| interrupts-extended | 为设备描述中断信息,该设备会向不同中断控制器发送中断 | | interrupt-map | 用于描述多个设备之间的中断映射关系 | | interrupt-mask | 用于对中断号进行过滤、匹配、多路复用 | -| interrupt-affinity | 设置中断向哪个cpu发送,值为cpu对应的设备树结点,该属性非设备树标准属性 | +| interrupt-affinity | 设置中断向哪个 cpu 发送,值为 cpu 对应的设备树结点,该属性非设备树标准属性 | | interrupt-names | 指定中断名称,是数个字符串,每个字符串对应一个中断资源,该属性非设备树标准属性 | 相应驱动程序需要提供解析这些属性的支持。 -##### IO相关属性 +#### IO 相关属性 | 属性 | 解释 | | --- | --- | -| reg | 描述该硬件所使用的物理地址资源,驱动程序需要对该区域调用ioremap | -| reg-names | 指定区域名称,是数个字符串,每个字符串对应一个IO资源,该属性非设备树标准属性 | +| reg | 描述该硬件所使用的物理地址资源,驱动程序需要对该区域调用 ioremap | +| reg-names | 指定区域名称,是数个字符串,每个字符串对应一个 IO 资源,该属性非设备树标准属性 | | ranges | 通常用于总线类型设备,描述总线结点和父节点的地址空间如何映射 | -| memory-region | 所使用的预留内存区域,目前暂无API处理该属性 | +| memory-region | 所使用的预留内存区域,目前暂无 API 处理该属性 | -### rt-thread下驱动程序编写 +## rt-thread 下驱动程序编写 -#### 驱动兼容性 +### 驱动兼容性 -设备需要指定其可以与何种设备相匹配。以pl061驱动为例,指定方法如下: +设备需要指定其可以与何种设备相匹配。以 pl061 驱动为例,指定方法如下: ```c -// 定义rt_ofw_node_id结构体,其中指定了兼容设备在设备中compatible属性 +// 定义 rt_ofw_node_id 结构体,其中指定了可以兼容的设备应有的 compatible 属性 static const struct rt_ofw_node_id pl061_ofw_ids[] = { { .compatible = "arm,pl061" }, @@ -247,30 +248,30 @@ static struct rt_platform_driver pl061_driver = { // 驱动名称,假如设备名是"pin-pl061"也可以匹配 .name = "pin-pl061", - // 指定了该驱动的ids,可判断其可以与何种设备相匹配 + // 指定了该驱动的 ids,可判断其可以与何种设备相匹配 .ids = pl061_ofw_ids, - // probe函数,在驱动探测到相匹配的设备时对其调用的函数 + // probe 函数,在驱动探测到相匹配的设备时对其调用的函数 .probe = pl061_probe, }; +// 在系统启动时注册该平台驱动 RT_PLATFORM_DRIVER_EXPORT(pl061_driver); ``` -- 如上所示,pl061_driver可以与设备名为"pin-pl061"或compatible属性含有"arm,pl061"的设备相匹配; -- `RT_PLATFORM_DRIVER_EXPORT(pl061_driver)`让系统在启动时注册该驱动; +- 如上所示,pl061_driver 可以与设备名为"pin-pl061"或 compatible 属性含有"arm,pl061"的设备相匹配; -#### probe函数编写 +### probe 函数编写 -probe函数是driver探测到相匹配的设备时对其调用的函数。具体需要做如下工作: +probe 函数是 driver 探测到相匹配的设备时对其调用的函数。具体需要做如下工作: -- 需要获取设备所需的中断及IO资源; -- 对设备IO资源,需要映射至系统的虚拟地址空间,对IO资源,需要配置中断控制器及设置中断服务例程; +- 需要获取设备所需的中断及 IO 资源; +- 对设备 IO 资源,需要映射至系统的虚拟地址空间,对 IO 资源,需要配置中断控制器及设置中断服务例程; - 需要对设备其它属性进行处理,如设备的配置信息; -- 需要向系统注册该设备; +- 需要向系统注册该设备,使之可以使用; -对中断及IO资源处理可以使用的API如下: +对中断及 IO 资源处理可以使用的 API 如下: -##### 中断资源处理 +#### 中断资源处理 如果设备驱动程序需要对设备的中断资源进行处理,需要包含头文件: @@ -278,41 +279,41 @@ probe函数是driver探测到相匹配的设备时对其调用的函数。具体 #include ``` -以下是中断资源处理接口介绍 +以下是中断资源处理接口介绍: ```c -int rt_ofw_irq_cells(struct rt_ofw_node *np); +int rt_ofw_irq_cells(struct rt_ofw_node *np) ``` -该函数获取设备结点`#interrupt-cells`属性 +该函数获取设备结点#interrupt-cells 属性 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | | **返回** | **描述** | -| int | 设备结点对应的`#interrupt-cells`属性值 | +| int | 设备结点对应的#interrupt-cells 属性值 | | -RT_EEMPTY | 设备结点没有该属性 | | -RT_EINVAL | 设备不合法 | ```c -rt_err_t rt_ofw_parse_irq_map(struct rt_ofw_node *np, struct rt_ofw_cell_args *irq_args); +rt_err_t rt_ofw_parse_irq_map(struct rt_ofw_node *np, struct rt_ofw_cell_args *irq_args) ``` -该函数处理设备结点`interrupt-map`属性 +该函数处理设备结点 interrupt-map 属性 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| irq_args | 传递参数及存放解析`interrupt-map`属性结果 | +| irq_args | 传递参数及存放解析 interrupt-map 属性结果 | | **返回** | **描述** | | 0 | 解析成功 | | 错误码 | 解析失败 | ```c -rt_err_t rt_ofw_parse_irq_cells(struct rt_ofw_node *np, int index, struct rt_ofw_cell_args *out_irq_args); +rt_err_t rt_ofw_parse_irq_cells(struct rt_ofw_node *np, int index, struct rt_ofw_cell_args *out_irq_args) ``` -该函数解析设备中断资源,其首先检查参数`interrupts-extended`,如果没有该参数则检查`interrupts`参数。可以获取中断号及对应中断控制器信息。 +该函数解析设备中断资源,其首先检查参数 interrupts-extended,如果没有该参数则检查 interrupts 参数。可以获取中断号及对应中断控制器信息。 | 参数 | 描述 | |:------------------|:------------------------------------| @@ -324,7 +325,7 @@ rt_err_t rt_ofw_parse_irq_cells(struct rt_ofw_node *np, int index, struct rt_ofw | 错误码 | 获取失败 | ```c -struct rt_ofw_node *rt_ofw_find_irq_parent(struct rt_ofw_node *np, int *out_interrupt_cells); +struct rt_ofw_node *rt_ofw_find_irq_parent(struct rt_ofw_node *np, int *out_interrupt_cells) ``` 该函数获取设备对应中断控制器的结点信息。 @@ -332,27 +333,26 @@ struct rt_ofw_node *rt_ofw_find_irq_parent(struct rt_ofw_node *np, int *out_inte | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| out_interrupt_cells | 中断控制器的`#interrupt-cells`属性 | +| out_interrupt_cells | 中断控制器的#interrupt-cells 属性 | | **返回** | **描述** | -| rt_ofw_node结点 | 获取的中断控制器结点 | +| rt_ofw_node 结点 | 获取的中断控制器结点 | | RT_NULL | 找不到对应的中断控制器结点 | ```c -int rt_ofw_map_irq(struct rt_ofw_cell_args *irq_args); +int rt_ofw_map_irq(struct rt_ofw_cell_args *irq_args) ``` -该函数将设备的中断信息应用于中断控制器中。一般在使用`rt_ofw_parse_irq_map`或`rt_ofw_parse_irq_cells`获取到设备中断信息后,调用该函数使能对应中断。 +该函数将设备的中断信息应用于中断控制器中。一般在使用 rt_ofw_parse_irq_map 或 rt_ofw_parse_irq_cells 获取到设备中断信息后,调用该函数使能对应中断。 | 参数 | 描述 | |:------------------|:------------------------------------| | irq_args | 获取到的设备中断信息 | | **返回** | **描述** | -| 大于0整数 | 设置的中断编号 | +| 大于 0 整数 | 设置的中断编号 | | 错误码 | 执行错误 | - ```c -int rt_ofw_get_irq_count(struct rt_ofw_node *np); +int rt_ofw_get_irq_count(struct rt_ofw_node *np) ``` 该函数返回设备指定的中断资源数目。 @@ -362,13 +362,13 @@ int rt_ofw_get_irq_count(struct rt_ofw_node *np); | np | 设备结点 | | **返回** | **描述** | | 一个非负整数 | 设备中断资源数目 | -| -RT_EINVAL | 传入的np不合法 | +| -RT_EINVAL | 传入的 np 不合法 | ```c -int rt_ofw_get_irq(struct rt_ofw_node *np, int index); +int rt_ofw_get_irq(struct rt_ofw_node *np, int index) ``` -该函数获取设备树结点的指定中断资源中断号并进行处理。具体地,该函数将调用`ofw_map_irq`使能中断,并根据设备的`interrupt-affinity`属性设置应当响应中断的cpu,最后返回设置的中断号。 +该函数获取设备树结点的指定中断资源中断号并进行处理。具体地,该函数将调用 ofw_map_irq 使能中断,并根据设备的 interrupt-affinity 属性设置应当响应中断的 cpu,最后返回设置的中断号。 | 参数 | 描述 | |:------------------|:------------------------------------| @@ -379,10 +379,10 @@ int rt_ofw_get_irq(struct rt_ofw_node *np, int index); | 错误码 | 执行错误 | ```c -int rt_ofw_get_irq_by_name(struct rt_ofw_node *np, const char *name); +int rt_ofw_get_irq_by_name(struct rt_ofw_node *np, const char *name) ``` -该函数作用与`rt_ofw_get_irq`相同,不过使用名称来指定中断。该函数会通过name参数,根据设备的`interrupt-names`属性来获得对应的中断资源编号,最后调用`rt_ofw_get_irq`。 +该函数作用与 rt_ofw_get_irq 相同,不过使用名称来指定中断。该函数会通过 name 参数,根据设备的 interrupt-names 属性来获得对应的中断资源编号,最后调用 rt_ofw_get_irq。 | 参数 | 描述 | |:------------------|:------------------------------------| @@ -400,7 +400,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, v | 参数 | 描述 | |:------------------|:------------------------------------| -| vector | 需要设置的中断号,可以由`rt_ofw_get_irq`或`rt_ofw_get_irq_by_name`获得 | +| vector | 需要设置的中断号,可以由 rt_ofw_get_irq 或 rt_ofw_get_irq_by_name 获得 | | handler | 需要设置成的中断服务例程 | | param | 中断服务例程参数 | | name | 中断服务例程名称 | @@ -408,93 +408,93 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, v | RT_NULL | 该中断号原来无中断服务例程 | | old_handler | 之前该中断号对应的中断服务例程 | -##### IO资源处理 +#### IO 资源处理 -如果设备驱动程序需要对设备的IO资源进行处理,需要包含头文件: +如果设备驱动程序需要对设备的 IO 资源进行处理,需要包含头文件: ```c #include ``` -以下是IO资源处理接口介绍 +以下是 IO 资源处理接口介绍 ```c -int rt_ofw_bus_addr_cells(struct rt_ofw_node *np); +int rt_ofw_bus_addr_cells(struct rt_ofw_node *np) ``` -获取总线设备的`#address-cells`属性。它会从总线设备结点遍历parent结点,获取到第一个`#address-cells`则返回。如果未获得则使用默认值1。 +获取总线设备的#address-cells 属性。它会从总线设备结点遍历 parent 结点,获取到第一个#address-cells 则返回。如果未获得则使用默认值 1。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | | **返回** | **描述** | -| 一个正整数 | 设备的`#address-cells`属性 | -| -RT_EINVAL | np不合法 | +| 一个正整数 | 设备的#address-cells 属性 | +| -RT_EINVAL | np 不合法 | ```c -int rt_ofw_bus_size_cells(struct rt_ofw_node *np); +int rt_ofw_bus_size_cells(struct rt_ofw_node *np) ``` -获取总线设备的`#size-cells`属性。它会从总线设备结点遍历parent结点,获取到第一个`#size-cells`则返回。如果未获得则使用默认值1。 +获取总线设备的#size-cells 属性。它会从总线设备结点遍历 parent 结点,获取到第一个#size-cells 则返回。如果未获得则使用默认值 1。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | | **返回** | **描述** | -| 一个正整数 | 设备的`#size-cells`属性 | -| -RT_EINVAL | np不合法 | +| 一个正整数 | 设备的#size-cells 属性 | +| -RT_EINVAL | np 不合法 | ```c -int rt_ofw_io_addr_cells(struct rt_ofw_node *np); +int rt_ofw_io_addr_cells(struct rt_ofw_node *np) ``` -获取普通设备的`#address-cells`属性。其优先获取所在总线(即其父节点)的该属性。如果未获得则使用默认值1。 +获取普通设备的#address-cells 属性。其优先获取所在总线(即其父节点)的该属性。如果未获得则使用默认值 1。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | | **返回** | **描述** | -| 一个正整数 | 设备的`#address-cells`属性 | -| -RT_EINVAL | np不合法 | +| 一个正整数 | 设备的#address-cells 属性 | +| -RT_EINVAL | np 不合法 | ```c -int rt_ofw_io_size_cells(struct rt_ofw_node *np); +int rt_ofw_io_size_cells(struct rt_ofw_node *np) ``` -获取普通设备的`#size-cells`属性。其优先获取所在总线(即其父节点)的该属性。如果未获得则使用默认值1。 +获取普通设备的#size-cells 属性。其优先获取所在总线(即其父节点)的该属性。如果未获得则使用默认值 1。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | | **返回** | **描述** | -| 一个正整数 | 设备的`#size-cells`属性 | -| -RT_EINVAL | np不合法 | +| 一个正整数 | 设备的#size-cells 属性 | +| -RT_EINVAL | np 不合法 | ```c -int rt_ofw_get_address_count(struct rt_ofw_node *np); +int rt_ofw_get_address_count(struct rt_ofw_node *np) ``` -该函数获取设备结点的`reg`属性中地址的数量。 +该函数获取设备结点的 reg 属性中地址的数量。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | | **返回** | **描述** | -| 一个非负整数 | 设备结点的`reg`属性中地址的数量 | -| -RT_EINVAL | np不合法 | +| 一个非负整数 | 设备结点的 reg 属性中地址的数量 | +| -RT_EINVAL | np 不合法 | ```c -rt_err_t rt_ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_address, rt_uint64_t *out_size); +rt_err_t rt_ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_address, rt_uint64_t *out_size) ``` -该函数获取设备结点的`reg`属性中指定编号的以address-size对表示的IO资源。获得的地址是转换到cpu地址空间的地址。 +该函数获取设备结点的 reg 属性中指定编号的以 address-size 对表示的 IO 资源。获得的地址是转换到 cpu 地址空间的地址。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| index | 需要获得的address-size对的编号 | -| out_address | 存储获得的address转换到cpu地址空间的值 | -| out_size | 存储获得的size值 | +| index | 需要获得的 address-size 对的编号 | +| out_address | 存储获得的 address 转换到 cpu 地址空间的值 | +| out_size | 存储获得的 size 值 | | **返回** | **描述** | | RT_EOK | 执行成功 | | -RT_EINVAL | 参数不合法 | @@ -503,38 +503,38 @@ rt_err_t rt_ofw_get_address(struct rt_ofw_node *np, int index, rt_uint64_t *out_ rt_err_t rt_ofw_get_address_by_name(struct rt_ofw_node *np, const char *name, rt_uint64_t *out_address, rt_uint64_t *out_size) ``` -该函数作用与`rt_ofw_get_address`相同,不过使用名称来指定address-size对表示的IO资源。该函数会通过name参数,根据设备的`reg-names`属性来获得对应的IO资源编号,之后过程与`rt_ofw_get_address`相同。 +该函数作用与 rt_ofw_get_address 相同,不过使用名称来指定 address-size 对表示的 IO 资源。该函数会通过 name 参数,根据设备的 reg-names 属性来获得对应的 IO 资源编号,之后过程与 rt_ofw_get_address 相同。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| name | 需要获得的IO资源名称 | -| out_address | 存储获得的address转换到cpu地址空间的值 | -| out_size | 存储获得的size值 | +| name | 需要获得的 IO 资源名称 | +| out_address | 存储获得的 address 转换到 cpu 地址空间的值 | +| out_size | 存储获得的 size 值 | | **返回** | **描述** | | RT_EOK | 执行成功 | | -RT_EINVAL | 参数不合法 | ```c -int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_regs); +int rt_ofw_get_address_array(struct rt_ofw_node *np, int nr, rt_uint64_t *out_regs) ``` -该函数获取设备结点前nr个IO资源属性。地址值会转换到cpu物理地址空间。 +该函数获取设备结点前 nr 个 IO 资源属性。地址值会转换到 cpu 物理地址空间。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| nr | 需要获得的IO资源个数 | -| out_regs | 存储获得的以address-size对表示的IO资源 | +| nr | 需要获得的 IO 资源个数 | +| out_regs | 存储获得的以 address-size 对表示的 IO 资源 | | **返回** | **描述** | -| 一个非负整数 | 实际获得的IO资源个数 | +| 一个非负整数 | 实际获得的 IO 资源个数 | | -RT_EINVAL | 参数不合法 | ```c -rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address); +rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_type, rt_uint64_t address) ``` -将某一地址从设备所属总线的地址空间转换到cpu的物理地址空间。 +将某一地址从设备所属总线的地址空间转换到 cpu 的物理地址空间。 | 参数 | 描述 | |:------------------|:------------------------------------| @@ -542,19 +542,19 @@ rt_uint64_t rt_ofw_translate_address(struct rt_ofw_node *np, const char *range_t | range_type | 映射类型,不指定时默认为"ranges",该函数从该属性来获得映射方式 | | address | 设备所属总线下的某一地址 | | **返回** | **描述** | -| 最大64位正整数 | 转换失败 | +| 最大 64 位正整数 | 转换失败 | | 一个合法物理地址 | 设备映射到的物理地址 | ```c void *rt_ofw_iomap(struct rt_ofw_node *np, int index) ``` -将设备的一个IO资源重映射到系统内核地址空间的虚拟地址。 +将设备的一个 IO 资源重映射到系统内核地址空间的虚拟地址。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| index | 指定的IO资源编号 | +| index | 指定的 IO 资源编号 | | **返回** | **描述** | | RT_NULL | 执行失败 | | 一个合法的内核虚拟地址 | 设备映射到的内核虚拟地址 | @@ -563,25 +563,25 @@ void *rt_ofw_iomap(struct rt_ofw_node *np, int index) void *rt_ofw_iomap_by_name(struct rt_ofw_node *np, const char *name) ``` -与`rt_ofw_iomap`作用相同,但使用名称来指定设备IO资源。该函数会通过name参数,根据设备的`reg-names`属性来获得对应的IO资源编号,之后过程与`rt_ofw_iomap`相同。 +与 rt_ofw_iomap 作用相同,但使用名称来指定设备 IO 资源。该函数会通过 name 参数,根据设备的 reg-names 属性来获得对应的 IO 资源编号,之后过程与 rt_ofw_iomap 相同。 | 参数 | 描述 | |:------------------|:------------------------------------| | np | 设备结点 | -| name | 指定的IO资源名称 | +| name | 指定的 IO 资源名称 | | **返回** | **描述** | | RT_NULL | 执行失败 | | 一个合法的内核虚拟地址 | 设备映射到的内核虚拟地址 | -##### 其它属性处理 +#### 其它属性处理 在`components/drivers/include/drivers/ofw.h`中定义了一系列可以处理不同属性值格式的函数,驱动程序可以调用这些函数来获得并处理这些属性。 -#### 说明编写 +### 说明编写 驱动编写者需要提供该驱动如何与设备绑定相关说明,告知设备树编写者如何编写该驱动支持的设备结点。 说明需要包含如下方面: -- 驱动所支持的`compatible`属性或可以匹配的设备名称; +- 驱动所支持的 compatible 属性或可以匹配的设备名称; - 设备必须指定及可以指定的属性,并给出属性含义及属性值的形式; -- Gitee From 2ea4cb152362be2cf4f120748430799012175b88 Mon Sep 17 00:00:00 2001 From: Zhao Maosheng Date: Fri, 22 Sep 2023 11:56:15 +0800 Subject: [PATCH 6/6] correct reg x0 --- .../rt-thread-smart/device/device-tree/device-tree.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md b/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md index e4ace31..6e28c55 100644 --- a/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md +++ b/rt-thread-version/rt-thread-smart/device/device-tree/device-tree.md @@ -12,7 +12,7 @@ dtc -I dts -O dtb -o mydtb.dtb mydts.dts ### 使用 qemu -在 qemu 环境下,可以使用`-dtb mydtb.dtb`来指定使用的 dtb 文件,也可以不指定,使用默认的 dtb 文件。aarch64 下,内核启动时可从 r2 寄存器读到设备树文件地址。 +在 qemu 环境下,可以使用`-dtb mydtb.dtb`来指定使用的 dtb 文件,也可以不指定,使用默认的 dtb 文件。aarch64 下,内核启动时可从 x0 寄存器读到设备树文件地址。 ### 使用 uboot @@ -24,7 +24,7 @@ setenv bootcmd "load mmc 0:1 ${fdt_addr} mydtb.dtb; [other cmd]" setenv fdtaddr ${fdt_addr} ``` -aarch64 下,内核启动时可从 r2 寄存器读到设备树文件地址。 +aarch64 下,内核启动时可从 x0 寄存器读到设备树文件地址。 ## rt-thread 设备树使用场景 -- Gitee