U-Boot Driver Model领域模型设计
需求分析
在2014年以前,uboot没有一种类似于linux kernel的设备驱动模型,随着uboot支持的设备越来越多,其一直受到如下问题困扰:
- 设备初始化流程都独立实现,而且为了集成到系统,需要修改核心公共代码(如init_sequence)
- 很多子系统只允许一个驱动,比如无法同时支持USB2.0和USB3.0
- 子系统间的交互实现各异,开发难度大
- 没有个统一的设备视图(如linux的/sys)
uboot driver model(U-Boot驱动模型,以下简写dm)的提出就是为了解决这些问题,它的设计目标包括:
- 提供统一设备驱动框架,降低设备驱动的开发复杂度
- 提供设备树视图
- 支持设备组
- 支持设备lazy init
- 支持设备驱动沙盒测试
- 较小的系统开销(内存和CPU)
对象设计
对象的设计之所以区分静态形式和运行态形式,考量的出发点是设计模块化。
静态表达形式的对象是离散的,和系统和其他对象隔离开,减小对象的复杂度,利于模块化设计,遵循人类表达习惯。
运行态形式的对象是把所有对象组合成层次视图,有着清晰的数据关联视图。方便系统运行时数据的流动。
静态表达形式
device: FDT(设备树文本描述) 或者 静态数据结构U_BOOT_DEVICE(以数据段形式组织)
driver: 静态数据结构U_BOOT_DRIVER(以数据段形式组织)
运行态形式
udevice: 设备对象(以链表形式组织)
driver: 驱动对象。作为udevice的一个属性
uclass:设备组公共属性对象(以链表形式组织),外部顶层对象,作为udevice的一个属性
uclass_driver: 设备组公共行为对象,作为uclass的一个属性
领域建模
uboot设备模型中udevice为核心对象,以树型模型组织(如下),其为dm的顶层结构。
单个udevice建模如下,详细对象定义参见《附:核心数据结构》小节。
所有对象可以按udevice或者uclass进行遍历。
DM初始化流程
DM初始化流程包括:
- 模型初始化
- 静态对象初始化
- 运行态对象初始化
- 设备组公共初始化
- 设备初始化
DM初始化的总入口接口:dm_init_and_scan(),其主要由以下三块组成:
dm_init():创建udevice和uclass空链表,创建根设备(root device)
dm_scan_platdata():扫描U_BOOT_DEVICE定义的设备,创建对应的udevice和uclass对象,查找并绑定相应driver,并调用probe流程。
dm_scan_fdt():扫描由FDT设备树文件定义的设备,创建对应的udevice和uclass对象,查找并绑定相应driver,并调用probe流程。
附:核心数据结构
U_BOOT_DRIVER(demo_shape_drv) = {
.name = "demo_shape_drv",
.of_match = demo_shape_id,
.id = UCLASS_DEMO,
.ofdata_to_platdata = shape_ofdata_to_platdata,
.ops = &shape_ops,
.probe = dm_shape_probe,
.remove = dm_shape_remove,
.priv_auto_alloc_size = sizeof(struct shape_data),
.platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
}; #define U_BOOT_DRIVER(__name) \
ll_entry_declare(struct driver, __name, driver) #define ll_entry_declare(_type, _name, _list) \
_type _u_boot_list_2_##_list##_2_##_name __aligned() \
__attribute__((unused, \
section(".u_boot_list_2_"#_list"_2_"#_name))) struct driver {
char *name;
enum uclass_id id;
const struct udevice_id *of_match;
int (*bind)(struct udevice *dev);
int (*probe)(struct udevice *dev);
int (*remove)(struct udevice *dev);
int (*unbind)(struct udevice *dev);
int (*ofdata_to_platdata)(struct udevice *dev);
int (*child_post_bind)(struct udevice *dev);
int (*child_pre_probe)(struct udevice *dev);
int (*child_post_remove)(struct udevice *dev);
int priv_auto_alloc_size;
int platdata_auto_alloc_size;
int per_child_auto_alloc_size;
int per_child_platdata_auto_alloc_size;
const void *ops; /* driver-specific operations */
uint32_t flags;
}; U_BOOT_DEVICE(demo0) = {
.name = "demo_shape_drv",
.platdata = &red_square,
};
#define U_BOOT_DEVICE(__name) \
ll_entry_declare(struct driver_info, __name, driver_info)
struct driver_info {
const char *name;
const void *platdata;
#if CONFIG_IS_ENABLED(OF_PLATDATA)
uint platdata_size;
#endif
}; struct uclass {
void *priv;
struct uclass_driver *uc_drv;
struct list_head dev_head;
struct list_head sibling_node;
}; UCLASS_DRIVER(demo) = {
.name = "demo",
.id = UCLASS_DEMO,
};
#define UCLASS_DRIVER(__name) \
ll_entry_declare(struct uclass_driver, __name, uclass)
struct uclass_driver {
const char *name;
enum uclass_id id;
int (*post_bind)(struct udevice *dev);
int (*pre_unbind)(struct udevice *dev);
int (*pre_probe)(struct udevice *dev);
int (*post_probe)(struct udevice *dev);
int (*pre_remove)(struct udevice *dev);
int (*child_post_bind)(struct udevice *dev);
int (*child_pre_probe)(struct udevice *dev);
int (*init)(struct uclass *class);
int (*destroy)(struct uclass *class);
int priv_auto_alloc_size;
int per_device_auto_alloc_size;
int per_device_platdata_auto_alloc_size;
int per_child_auto_alloc_size;
int per_child_platdata_auto_alloc_size;
const void *ops;
uint32_t flags;
}; struct udevice {
const struct driver *driver;
const char *name;
void *platdata;
void *parent_platdata;
void *uclass_platdata;
int of_offset;
ulong driver_data;
struct udevice *parent;
void *priv;
struct uclass *uclass;
void *uclass_priv;
void *parent_priv;
struct list_head uclass_node;
struct list_head child_head;
struct list_head sibling_node;
uint32_t flags;
int req_seq;
int seq;
#ifdef CONFIG_DEVRES
struct list_head devres_head;
#endif
};
--EOF--
U-Boot Driver Model领域模型设计的更多相关文章
- U-Boot Driver Model领域模型设计 (转)
需求分析 在2014年以前,uboot没有一种类似于linux kernel的设备驱动模型,随着uboot支持的设备越来越多,其一直受到如下问题困扰: 设备初始化流程都独立实现,而且为了集成到系统,需 ...
- Apworks框架实战(五):EasyMemo的领域模型设计
在上一讲中,我们已经新建了一个聚合根对象Account,并已经可以开始设计领域模型了.在这一讲中,我们会着重介绍EasyMemo领域模型的分析和设计,并引入Visual Studio Ultimate ...
- 和S5933比较起来,开发PLX9054比较不幸,可能是第一次开发PCI的缘故吧。因为,很多PCI的例子都是对S5933,就连微软出版的《Programming the Microsoft Windows Driver Model》都提供了一个完整的S5933的例子。 在这篇有关DDK的开发论文里。
和S5933比较起来,开发PLX9054比较不幸,可能是第一次开发PCI的缘故吧.因为,很多PCI的例子都是对S5933,就连微软出版的<Programming the Microsoft Wi ...
- DDD(Domain Driver Designer) 领域驱动设计简介
领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...
- NHibernate实战详解(一)领域模型设计
关于NHibernate的资料本身就不多,中文的就更少了,好在有一些翻译文章含金量很高,另外NHibernate与Hibernate的使用方式可谓神似,所以也有不少经验可以去参考Hibernate. ...
- 一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?
写在前面 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repository(仓储)职责所在? Domain Model(领域模型)重新设计 Domain ...
- DDD 领域驱动设计-如何完善 Domain Model(领域模型)?
上一篇:<DDD 领域驱动设计-如何 DDD?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 阅读目录: ...
- DDD(领域驱动设计)应对具体业务场景,Domain Model(领域模型)到底如何设计?
DDD(领域驱动设计)应对具体业务场景,Domain Model(领域模型)到底如何设计? 写在前面 阅读目录: 迷雾森林 找回自我 开源地址 后记 毫无疑问,领域驱动设计的核心是领域模型,领域模型的 ...
- DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?
DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)? 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repositor ...
随机推荐
- CSS 常用基本功能整理
1.文字访问特权 点击前.点击时.点击后.下划线.跳转. <!DOCTYPE html> <html> <head> <meta charset=" ...
- 微信共享收货地址 edit_address:fail 吐白沫级解决方案
又被微信坑了一整天,看完官方文档怎么测试都不通过,我一直怀疑是新版本微信支付我没有设置“共享收货地址”开关造成的. 后来经过验证,新版本不需要做这件事了. 那么,我没错,是微信的文档没及时更新... ...
- http://www.sqlservercentral.com/articles/Failover+Clustered+Instance+(FCI)/92196/
http://www.sqlservercentral.com/articles/Failover+Clustered+Instance+(FCI)/92196/ http://blogs.msdn. ...
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- markdown编辑器sublime text3
安装包管理Package Control ctrl+`或者点击查看-->显示面板,复制下面的代码到面板里. import urllib.request,os; pf = 'Package Con ...
- CSS3中的px,em,rem,vh,vw辨析
1.px:像素,精确显示 2.em:继承父类字体的大小,相当于"倍",如:浏览器默认字体大小为16px=1em,始终按照div继承来的字体大小显示,进场用于移动端 em换算工具:h ...
- MySQL备份mydumper的原理
本文来自:http://baiyangtx.net/2016/09/04/mydumper-principle/ 相对于MySQL官方提供的逻辑备份工具 mysqldump , mydumper最大的 ...
- @rpath/libswiftCore.dylib问题
dyld: Library not loaded: @rpath/libswiftCore.dylib Referenced from: /private/var/containers/Bundle ...
- React学习笔记-5-初始化阶段介绍
初始化阶段可以使用的函数:getDefaultProps:只调用一次,实例之间共享引用.只有在组件的第一个实例被初始化的时候,才会调用他,然后react会把这个函数的返回结果保存起来,从第二个实例开始 ...
- js变量及其作用域(附例子及讲解)
Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量 工具/原料 Ch ...