UBOOT设备树研究
文章目录
- 1、介绍
- 2、设备树的获取与设置
- 3、uboot如何获取dtb
- 4、uboot设备树接口
1、介绍
在运行uboot的过程中可以对系统的某些硬件架构进行初步设置,在依据设置决定具体的硬件布局后
fdt具有极高的易用性,在配置与管理上表现出色;采用节点与属性作为核心配置手段,并通过层次化的管理方式实现系统的优化;当存在多种不同的硬件板时,则能够基于同一套源代码实现功能扩展,在实际应用中只需稍作修改即可完成对各层级硬件的匹配工作
2、设备树的获取与设置
设备树可通过 kernel 源码获取,在 uboot 引导下 kernel 启动。若将 kernel 中的设备树迁移至 uboot 中,则同样能直接使用。
通过以下代码进行配置设备树
#define CONFIG_DEFAULT_DEVICE_TREE “”
设备树通过构建(代替编译),不仅可以在uboot的尾部完成构建(代替编译),也可以嵌入到uboot内部。此外,在配置fdtcontroladdr环境变量的情况下,则可以使设备树被加载至特定地址的位置上。通过这种方式,在不同的板级信息下加载不同的设备树(代替方式),能够实现相同的代码在不同板子上的适配效果(代替目的)。
3、uboot如何获取dtb
[common/board_f.c]
static init_fnc_t init_sequence_f[] = {
···
#ifdef CONFIG_OF_CONTROL
fdtdec_setup,//获取设备树地址
#endif
···
#ifdef CONFIG_OF_CONTROL
fdtdec_prepare_fdt,//判断设备树地址是否正确
#endif
···
reserve_fdt,//为fdt分配内存
···
reloc_fdt,//重载fdt
···
NULL,
};
AI生成项目c

以上是board_init_f当中对于fdt的操作。
int fdtdec_setup(void)
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
# ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */
gd->fdt_blob = __dtb_dt_begin;//如果使用
# elif defined CONFIG_OF_SEPARATE
# ifdef CONFIG_SPL_BUILD
/* FDT is at end of BSS unless it is in a different memory region */
if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
gd->fdt_blob = (ulong *)&_image_binary_end;
else
gd->fdt_blob = (ulong *)&__bss_end;
# else
/* FDT is at end of image */
gd->fdt_blob = (ulong *)&_end;
# endif
# elif defined(CONFIG_OF_HOSTFILE)
if (sandbox_read_fdt_from_file()) {
puts("Failed to read control FDT\n");
return -1;
}
# endif
# ifndef CONFIG_SPL_BUILD
/* Allow the early environment to override the fdt address */
gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
(uintptr_t)gd->fdt_blob);
# endif
#endif
return fdtdec_prepare_fdt();
}
AI生成项目c

int fdtdec_prepare_fdt(void)
{
if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
fdt_check_header(gd->fdt_blob)) {
···//如果有错则打印一些信息,主要进行以上的判断
return -1;
}
return 0;//如果无错误,则直接返回0
}
AI生成项目c
对设备树的地址进行判断,检查设备树的头,确认设备树正确。
4、uboot设备树接口
该变量gd->fdt_blob已被成功配置为指向dtb地址
以下仅用于概述几个接口的作用。另外,在dtb中使用偏移地址的方式将节点表示为一个位置。即为node变量中存储了该节点的偏移地址位置。
在lib/fdtdec.c文件中,在# define FDT_PATH_OFFSET后,
函数int FDT_PATH_OFFSET(const struct fdt_node **fdt, const char *path)的功能是获取dtb中某个节点路径path相对于该节点的位置偏移量。
例如:
node = fdt_path_offset(gd->fdt_node, "subtree");
其中gd->fdt_node表示当前节点的FDX表头指针变量。
-
fdt_getprop
( const pointer to fdt object , int nodeoffset , const string name , pointer to int variable lenp )
eg: 获取节点node的mac地址,并将其赋值给变量mac.
功能: 该函数用于从指定节点中获取其对应属性的具体值.* **fdtdec_get_int_array、fdtdec_get_byte_array**
int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, u32 *array, int count)
eg: ret = fdtdec_get_int_array(blob, node, “interrupts”, cell, ARRAY_SIZE(cell));
功能:获得节点node的某个整形数组属性值。
fdtdec_get_addr
ftd\_addr\_t fdtdec\_get\_addr\left(const\ void\ *\*blob,\ int\ node,\ const\ char\ *\ prop\_name\right)
例如,在使用该函数时,请注意如下调用方式:eg.fdtdec_get_addr(blob, node, "reg");
功能:获取指定节点node的地址属性值。
- ftdtc_get_config_int, ftdtc_get_config_bool, ftdtc_get_config_string
功能:该模块用于获取配置节点下的整数值属性、布尔值属性以及字符串类型信息。
此为改写后的文本
-
fdtdec_get_chosen_prop
const char *fdtdec_get_chosen_prop(const void *blob, const char *name)
功能:返回指定名称的属性值- lib/fdtdec_common.c中
-
fdtdec_get_int
int fdtdec_get_int(const void *blob, int node, const char *prop_name, int default_val)
eg: bus->udelay = fdtdec_get_int(blob, node, “i2c-gpio,delay-us”, DEFAULT_UDELAY);
功能:获得节点node的某个整形属性值。 -
fdtdec_get_uint
功能:获得节点node的某个无符号整形属性值。
-
- lib/fdtdec_common.c中
该接口基于uboot的设备驱动模型进行设计后, 会使开发过程变得容易一些。后续将深入探讨基于设备树实现的驱动方案。
