需求分析

在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领域模型设计的更多相关文章

  1. U-Boot Driver Model领域模型设计 (转)

    需求分析 在2014年以前,uboot没有一种类似于linux kernel的设备驱动模型,随着uboot支持的设备越来越多,其一直受到如下问题困扰: 设备初始化流程都独立实现,而且为了集成到系统,需 ...

  2. Apworks框架实战(五):EasyMemo的领域模型设计

    在上一讲中,我们已经新建了一个聚合根对象Account,并已经可以开始设计领域模型了.在这一讲中,我们会着重介绍EasyMemo领域模型的分析和设计,并引入Visual Studio Ultimate ...

  3. 和S5933比较起来,开发PLX9054比较不幸,可能是第一次开发PCI的缘故吧。因为,很多PCI的例子都是对S5933,就连微软出版的《Programming the Microsoft Windows Driver Model》都提供了一个完整的S5933的例子。 在这篇有关DDK的开发论文里。

    和S5933比较起来,开发PLX9054比较不幸,可能是第一次开发PCI的缘故吧.因为,很多PCI的例子都是对S5933,就连微软出版的<Programming the Microsoft Wi ...

  4. DDD(Domain Driver Designer) 领域驱动设计简介

    领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...

  5. NHibernate实战详解(一)领域模型设计

    关于NHibernate的资料本身就不多,中文的就更少了,好在有一些翻译文章含金量很高,另外NHibernate与Hibernate的使用方式可谓神似,所以也有不少经验可以去参考Hibernate. ...

  6. 一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?

    写在前面 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repository(仓储)职责所在? Domain Model(领域模型)重新设计 Domain ...

  7. DDD 领域驱动设计-如何完善 Domain Model(领域模型)?

    上一篇:<DDD 领域驱动设计-如何 DDD?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 阅读目录: ...

  8. DDD(领域驱动设计)应对具体业务场景,Domain Model(领域模型)到底如何设计?

    DDD(领域驱动设计)应对具体业务场景,Domain Model(领域模型)到底如何设计? 写在前面 阅读目录: 迷雾森林 找回自我 开源地址 后记 毫无疑问,领域驱动设计的核心是领域模型,领域模型的 ...

  9. DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?

    DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)? 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repositor ...

随机推荐

  1. Linux学习之五--常用操作

    文件操作: rm命令 删除文件夹实例:rm -rf /var/log/httpd/access将会删除/var/log/httpd/access目录以及其下所有文件.文件夹 2 删除文件使用实例:rm ...

  2. mysql中的行转列

    //查看当前商品库存 function checkProductStock($product_id){ global $wpdb; $sql="SELECT post_id,max(if(( ...

  3. Nagios

    什么是Nagios? Nagios是一款用于系统和网络监控的应用程序.它可以在你设定的条件下对主机和服务进行监控, 在状态变差和变好的时候给出告警信息. Nagios更进一步的特征包括: 1. 监控网 ...

  4. 常用ADO.NET操作ACCESS数据库

    using System; using System.Collections.Generic; using System.Text; using System.Data;// using System ...

  5. 原生JS实现购物车结算功能代码+zepto版

    html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  6. PEAR安装

    看到PEAR章节,提到安装PEAR需要go-pear.bat,我机器上的PHP(v7.0.8)目录下,并没有go-pear.bat这个文件,网上查了一遍,怎么说的都有,最后还是在官网上找到解决方案. ...

  7. 【转】Java面试宝典2015版(绝对值得收藏超长版)(一)

    (转自:http://mp.weixin.qq.com/s?__biz=MjM5MTM0NjQ2MQ==&mid=206619070&idx=1&sn=fcb21001d442 ...

  8. 在nginx中配置ip直接访问的默认站点

    一台机子部署多个网站,我们直接访问ip (外网内网都一样)提示无法访问或404. 因为有多个网站,我们想指定某个网站为IP访问默认的网站,如何操作呢? 解:在Listen ip:port; 这个指令行 ...

  9. Notepad++正则表达式语法

    \   转义字符  如:要使用 “\” 本身, 则应该使用“\\” \t  Tab制表符  注:扩展和正则表达式都支持 \r  回车符CR   注:扩展支持,正则表达式不支持 \n  换行符LF   ...

  10. ethhdr、ether_header、iphdr、tcphdr、udphdr 结构介绍

    转自:http://blog.csdn.net/petershina/article/details/8573853 ************************eth的结构*********** ...