当前位置: 首页 > news >正文

uboot - 驱动开发 - 驱动模型

说明

  • 类似于linux,为了规范、统一驱动适配和驱动接口调用,uboot定义了一套驱动模型(Driver Model),简称DM。
  • 本文基于:u-boot-2021.10。

优点

  1. 为同一类ip的驱动定义了统一的操作接口,DM在软件层面做了一定的抽象。
  2. 分层设计,将上层使用、设备以及驱动实现区分开来,降低了耦合性。

核心概念/数据结构

  • DM模型抽象出了以下四个概念/数据结构。
  1. uclass
  2. uclass_driver
  3. udevice
  4. driver

uclass

  • uclass(uboot class)是同一类外设(I2C、GPIO等)总的组织结构体,定义如下:
// file:include/dm/uclass.h
/*** struct uclass - a U-Boot drive class, collecting together similar drivers** A uclass provides an interface to a particular function, which is* implemented by one or more drivers. Every driver belongs to a uclass even* if it is the only driver in that uclass. An example uclass is GPIO, which* provides the ability to change read inputs, set and clear outputs, etc.* There may be drivers for on-chip SoC GPIO banks, I2C GPIO expanders and* PMIC IO lines, all made available in a unified way through the uclass.** @priv_: Private data for this uclass (do not access outside driver model)* @uc_drv: The driver for the uclass itself, not to be confused with a* 'struct driver'* @dev_head: List of devices in this uclass (devices are attached to their* uclass when their bind method is called)* @sibling_node: Next uclass in the linked list of uclasses*/
struct uclass {void *priv_;struct uclass_driver *uc_drv;struct list_head dev_head;struct list_head sibling_node;
};
  • uclass 包含
  1. uc_drv: uclass driver。
  2. dev_head: udevice list(设备列表)。
  3. sibling_node: 链表的下一个uclass结构。

uclass_driver

  • uclass_driver是uclass的驱动,并不是具体硬件驱动,做一些uclass通用的的准备/回收等工作。
// file:include/dm/uclass.h
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 (*child_post_probe)(struct udevice *dev);int (*init)(struct uclass *class);int (*destroy)(struct uclass *class);int priv_auto;int per_device_auto;int per_device_plat_auto;int per_child_auto;int per_child_plat_auto;uint32_t flags;
};
  • 使用宏UCLASS_DRIVER定义一个uclass driver,每一类ip会定义一个,如下:
//file: drivers/timer/timer-uclass.c
UCLASS_DRIVER(timer) = {.id             = UCLASS_TIMER,.name           = "timer",.pre_probe      = timer_pre_probe,.flags          = DM_UC_FLAG_SEQ_ALIAS,.post_probe     = timer_post_probe,.per_device_auto        = sizeof(struct timer_dev_priv),
};
  • 预定义的uclass id。
//file: include/dm/uclass-id.h
enum uclass_id {/* These are used internally by driver model */UCLASS_ROOT = 0,UCLASS_DEMO,UCLASS_TEST,UCLASS_TEST_FDT,UCLASS_TEST_FDT_MANUAL,UCLASS_TEST_BUS,UCLASS_TEST_PROBE,UCLASS_TEST_DUMMY,UCLASS_TEST_DEVRES,UCLASS_TEST_ACPI,...
}

udevice

  • udevice是具体硬件的实例,例如:dts中配置了两个timer,就会有两个timer udevice,uboot会将udevice和它所属的uclass以及具体的驱动driver绑定起来。
//file:include/dm/device.h 
struct udevice {const struct driver *driver;const char *name;void *plat_;void *parent_plat_;void *uclass_plat_;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;
#if !CONFIG_IS_ENABLED(OF_PLATDATA_RT)u32 flags_;
#endifint seq_;
#if !CONFIG_IS_ENABLED(OF_PLATDATA)ofnode node_;
#endif
#ifdef CONFIG_DEVRESstruct list_head devres_head;
#endif
#if CONFIG_IS_ENABLED(DM_DMA)ulong dma_offset;
#endif
};

driver

  • 具体硬件的驱动,对应每个硬件的驱动实现,例如:dw wdt(drivers/watchdog/designware_wdt.c), mtk wdt(drivers/watchdog/mtk_wdt.c) 。
//file: include/dm/device.h 
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 (*of_to_plat)(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;int plat_auto;int per_child_auto;int per_child_plat_auto;const void *ops;        /* driver-specific operations */uint32_t flags;
#if CONFIG_IS_ENABLED(ACPIGEN)struct acpi_ops *acpi_ops;
#endif
};* const void *ops; 是该驱动支持的接口。
  • ops 指向该类ip统一驱动接口结构体,在include目录的头文件中有各种ip需要支持的ops接口,例如:
include/thermal.h //温度传感器需要支持的接口(ops)
include/wdt.h //wdt需要支持的ops
include/timer.h //timer需要支持的ops
* include/timer.h
struct timer_ops {/*** @get_count: Get the current timer count** @dev: The timer device** This function may be called at any time after the driver is probed.* All necessary initialization must be completed by the time probe()* returns. The count returned by this functions should be monotonic.* This function must succeed.** Return: The current 64-bit timer count*/u64 (*get_count)(struct udevice *dev);
};
  • 新思定时器(dw apb timer)定义:
static const struct timer_ops dw_apb_timer_ops = {.get_count      = dw_apb_timer_get_count,
};U_BOOT_DRIVER(dw_apb_timer) = {.name           = "dw_apb_timer",.id             = UCLASS_TIMER,.ops            = &dw_apb_timer_ops,.probe          = dw_apb_timer_probe,.of_match       = dw_apb_timer_ids,.of_to_plat = dw_apb_timer_of_to_plat,.remove         = dw_apb_timer_remove,.priv_auto      = sizeof(struct dw_apb_timer_priv),
};
  • 使用宏U_BOOT_DRIVER定义一个驱动实例
/* Declare a new U-Boot driver */
#define U_BOOT_DRIVER(__name)                                           \ll_entry_declare(struct driver, __name, driver)

联系

  • uclass和udevice是动态生成的。
  • udevice在解析fdt中的设备的时候自动生成,然后udevice找到对应的driver,driver中保存了uclass_id,根据它找到uclass_driver_id,从uclass链表中查找对应的uclass是否已经生成,若没有生成,则动态生成,重点是解析设备树,生成udevice,并找到对应的driver。

代码流程

  • 模型的全局数据结构,包含根节点。
typedef struct global_data {// dts中的根节点,第一个创建的udevicestruct udevice  *dm_root;// relocation之前的根设备struct udevice  *dm_root_f;// uclass的链表, 挂的是有udevice的uclassstruct list_head uclass_root;  
} gd_t;
  • 初始化与扫描设备树
int dm_init_and_scan(bool pre_reloc_only)
{int ret;ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));if (ret) {debug("dm_init() failed: %d\n", ret);return ret;}if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) {ret = dm_scan(pre_reloc_only);if (ret) {log_debug("dm_scan() failed: %d\n", ret);return ret;}}return 0;
}

DM模型初始化(dm_init)

int dm_init(bool of_live)
{gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;//初始化uclass_root链表头INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);//创建一个device dm_root并将其绑定到driver name “root_driver”。device_bind_by_name(NULL, false, &root_info,&DM_ROOT_NON_CONST);//探测设备udevice dm_root并激活它ret = device_probe(DM_ROOT_NON_CONST);
}
  • 待补充

DM模型Device Tree节点的设备初始化(dm_scan)

  • 待补充

绑定udevice和driver(device_bind_common)

  • 待补充

使用

  1. 整体使能
配置:CONFIG_DM
  1. 不同类型外设需要专门使能
串口配置:CONFIG_DM_SERIAL
wdt配置:CONFIG_WDT

相关文章:

uboot - 驱动开发 - 驱动模型

说明 类似于linux,为了规范、统一驱动适配和驱动接口调用,uboot定义了一套驱动模型(Driver Model),简称DM。本文基于:u-boot-2021.10。 优点 为同一类ip的驱动定义了统一的操作接口,DM在软件层面做了一定的抽象。分…...

windows 操作系统命令积累

1. 按 "prt sc" 键 截屏 2. 按 "fn" 键让浏览器进入全屏模式,再次按 "fn" 键让浏览器退出全屏模式( ps:惠普笔记本上是 "fn" "f11" ) 3. ipconfig 查看ip信息 4. 查看指定端口被什么进程占用...

数据结构单链表的实现(C语言)

目录 1.实现的接口和功能2.代码块 1.实现的接口和功能 //打印链表 void SLTPrint(SLTNode** phead); //头插 void PushFont(SLTNode** phead, SLTDataType x); //尾插 void PushBack(SLTNode** phead, SLTDataType x); //头删 void PopFont(SLTNode** phead); //尾删 void Pop…...

Postman的高级使用,傻瓜式学习【下】

目录 前言 1、全局变量、环境变量 1.1、概念: 1.2、如何设置全局变量、环境变量 1.3、获取全局变量、环境变量 1.4、案例1:手动设置变量,请求参数获取 1.5、案例2:代码设置变量,代码获取变量 2、Postman读取外部…...

Qt:关闭对话框,动画实现窗体逐渐缩小到消失

关键技术: 1、使用QPropertyAnimation对象,实现动画效果,逐渐缩小窗体尺寸,以及透明度; 2、在对话框缩小时,要将界面中的控件都隐藏起来,并且将对话框布局的Margin修改成0 代码如下&#xff…...

在Windows上 ciphey安装(详细版)

文章目录 前言 一、不想卸载原有的python版本? 二、安装步骤 1.安装python 2.创建虚拟环境vnev 3.在ciphey的虚拟环境中进行激活 4.安装ciphey 三、参数列表 总结 前言 提示:安装了好几次,但是都没安装成功,我使用了三个电脑p…...

【lesson2】数据库的库操作

文章目录 库操作创建数据库删除数据库字符集和校验规则手动设置字符集和校验集不同字符集和校验集之间的区别修改数据库字符集和校验集备份和恢复数据库 库操作 创建数据库 删除数据库 字符集和校验规则 创建数据库的时候,有两个编码集: 1.数据库编码集…...

Android Studio Giraffe解决gradle reload failed问题

settings.gradle.kts中 pluginManagement {repositories {google()mavenCentral()gradlePluginPortal()} } dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()} } 各增加三行内容&#x…...

刷题笔记day06-哈希表

242.有效的字母异位词 // 思路2:排序后在比较是否相等import ("sort""fmt""io""strings""os" )func isAnagram(s string, t string) bool {s1, s2 : []byte(s), []byte(t)// 从小到大排序sort.Slice(s1, func(i…...

springboot项目中如何实现过滤器鉴权

通常来说鉴权都是写在网关当中,对于单体应用也可以在后台服务中通过一个过滤器实现。其实过程与网关当中的没什么不同,只是在gateway当中目前是基于netty响应式的。过程如下: 一、实现Filter接口 定义自己的过滤器,并且实现Filt…...

【rust/esp32】在idf中使用embedded-graphics控制st7789 LCD屏幕

文章目录 说在前面模块详情准备工作开始编译烧录结果 说在前面 esp32版本:s3运行环境:esp-idf(std)开发环境:wsl2LCD模块:ST7789V2 240*280 LCDgithub地址:这里 模块详情 某宙的esp32s3开发板 某雪的1.69inch LCD模块…...

YOLOv8如何添加注意力模块?

分为两种:有参注意力和无参注意力。 eg: 有参: import torch from torch import nnclass EMA(nn.Module):def __init__(self, channels, factor8):super(EMA, self).__init__()self.groups factorassert channels // self.groups > 0self.softmax …...

用LibreOffice在excel中画折线图

数据表格如下。假设想以x列为横坐标,y1和y2列分别为纵坐标画折线图。 选择插入-》图表: 选择折线图-》点和线,然后点击“下一步”: 选择:列中包含数据序列,然后点击完成(因为图挡住了数据…...

RabbitMQ 链接管理-发布者-消费者

RabbitMQ连接管理器 using RabbitMQ.Client; using System; public class RabbitMQConnectionManager { private readonly IConnectionFactory _connectionFactory; private IConnection _connection; public RabbitMQConnectionManager(string hostName) { …...

JAVA中的垃圾回收器(3)----ZGC

一)ZGC介绍:是JAVA11新引入的低延迟垃圾收集器 ZGC是一款基于Regin的,暂时没有分代概念的,使用了读屏障,颜色指针等技术来实现并发的标记清除和标记整理算法,一低延迟为主要目标的一款垃圾回收器 ZGC的regin可以分为是下图中具有大…...

IDEA 如何运行 SpringBoot 项目

步骤一:配置 Maven 第一步:用 IDEA 打开项目,准备配置 maven 环境 ,当然如果本地没有提前配置好 maven,就用 IDEA 默认的配置即可 配置 maven 步骤 情况 1:如果本地没有配置过 maven,可以保持如…...

Linux MeterSphere测试平台远程访问你不会?来试试这篇文章

🎬 鸽芷咕:个人主页 🔥 个人专栏:《粉丝福利》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网…...

15.k8s集群防火墙配置

防火墙配置 ######################## # master节点防火墙设置 ######################### 所有master节点开放相关防火墙端口 $ firewall-cmd --zonepublic --add-port6443/tcp --permanent $ firewall-cmd --zonepublic --add-port2379-2380/tcp --permanent $ firewall-cmd…...

Python beautifulsoup网络抓取和解析cnblog首页帖子数据

视频版教程:一天掌握python爬虫【基础篇】 涵盖 requests、beautifulsoup、selenium 我们抓取下https://www.cnblogs.com/ 首页所有的帖子信息,包括帖子标题,帖子地址,以及帖子作者信息。 首先用requests获取网页文件&#xff0…...

Java集成腾讯云OCR身份证识别接口

一、背景 项目用到身份证识别获取人员信息的功能,于是想到了腾讯云提供这样的API。在整合代码过程都很顺利,利用腾讯云官方SDK很快集成进来。但是在上测试环境部署时有了新的问题,通过Nginx代理后的环境无法访问到目标腾讯云接口,…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

Java中栈的多种实现类详解

Java中栈的多种实现类详解&#xff1a;Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...