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(4)                    __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--

时间: 2024-10-28 10:55:25

U-Boot Driver Model领域模型设计分析的相关文章

Windows Driver Model

http://en.wikipedia.org/wiki/Windows_Driver_Model In computing, the Windows Driver Model (WDM) — also known at one point as the Win32 Driver Model — is a framework for device drivers that was introduced with Windows 98 and Windows 2000 to replace VxD

Spring Boot使用thymeleaf模板

Thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用.Thymeleaf的主要目标在于提供一种可被浏览器正确显示的.格式良好的模板创建方式,因此也可以用作静态建模.可以完全替代JSP. Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果.这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式.浏览器解释 html 时会忽略未定

linux driver module

本文将对Linux系统中的sysfs进行简单的分析,要分析sysfs就必须分析内核的driver-model(驱动模型),两者是紧密联系的.在分析过程中,本文将以platform总线和spi主控制器的platform驱动为例来进行讲解.其实,platform机制是基于driver-model的,通过本文,也会对platform机制有个简单的了解. 内核版本:2.6.30 1. What is sysfs? 个人理解:sysfs向用户空间展示了驱动设备的层次结构.我们都知道设备和对应的驱动都是由内

PatentTips - Universal RAID Class Driver

BACKGROUND OF THE INVENTION The present invention relates to the field of data storage devices. Computers often store large quantities of data, including data such as music, video, games, applications, and other valuable information, on hard disk dri

beego——模型(model)

beego ORM是一个强大的Go语言ORM框架.她的灵感主要来自Django ORM和SQLAlchemy. 已经支持的数据库驱动: MySQL:https://github.com/go-sql-driver/mysql PostgreSQL:https://github.com/lib/pq Sqlite3:https://github.com/mattn/go-sqlite3 ORM的特性: 支持 Go 的所有类型存储 轻松上手,采用简单的 CRUD 风格 自动 Join 关联表 跨数据

Windows操作系统

Microsoft Windows,是美国微软公司研发的一套操作系统,它问世于1985年,起初仅仅是Microsoft-DOS模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统. Windows采用了图形化模式GUI,比起从前的DOS需要键入指令使用的方式更为人性化.随着电脑硬件和软件的不断升级,微软的Windows也在不断升级,从架构的16位.32位再到64位, 系统版本从最初的Windows 1.0 到大家熟知的Windows 95.Windo

USB组合设备 Interface Association Descriptor (IAD)

Communication Device Class,简称CDCUSB Compound Device,USB复合设备USB Composite Device,USB组合设备 摘要USB复合设备 Compound Device内嵌Hub和多个Function,每个Function都相当于一个独立的USB外设,有自己的PID/VID.USB组合设备Composite Device内只有一个Function,只有一套PID/VID,通过将不同的interface定义为不同的类来实现多个功能的组合.

Linux内核 Documentation下的00-INDEX文档翻译

This is a brief list of all the files in ./linux/Documentation and what they contain. If you add a documentation file, please list it here in alphabetical order as well, or risk being hunted down like a rabid dog. Please try and keep the descriptions

驱动开发读书笔记. 0.04 linux 2.6 platform device register 平台设备注册 1/2 共2篇

驱动开发读书笔记. 0.04  linux 2.6 platform device register 平台设备注册  1/2 共2篇下面这段摘自 linux源码里面的文档 : Documentation/driver-model/platform.txt Device Enumeration 82 ~~~~~~~~~~~~~~~~~~ 83 As a rule, platform specific (and often board-specific) setup code will 84 reg