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

rtt设备驱动框架面向对象学习-i2c总线

本来想着i2c和spi是一样的,标题都想抄袭成《rtt设备驱动框架学习-i2c总线和设备》,然后看过源码发现,i2c没有分开总线和设备,我想着正常它和spi一样有总线和设备,设备存在竞争。估计是因为i2c设备可以通过i2c地址区分,所以不需要来个i2c设备了吧。

1.i2c总线

i2c总线分为硬件i2c总线和软件模拟i2c总线。
按照面向对象的思想,要抽象出硬件i2c总线和软件i2c总线的相同点和不同点。相同点就变成了i2c总线基类,不同点就是各个子类的私有特性。

rtt就是这么干的,共同点是什么?方法——都得有配置方法和数据传输方法等,于是抽象出了i2c的方法:
struct rt_i2c_bus_device_ops
{
rt_ssize_t (*master_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
rt_ssize_t (*slave_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num);
rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus, int cmd, void *args);};

抽象出3个公共方法,主设备通信接口,从设备通信接口和控制方法。

然后作为成员组成rt_i2c_bus_device类:
i2c.h中
struct rt_i2c_bus_device
{
struct rt_device parent;
const struct rt_i2c_bus_device_ops *ops; rt_uint16_t flags;
struct rt_mutex lock;
rt_uint32_t timeout;
rt_uint32_t retries;
void *priv;
};

缺图对象图,ops展开方法用纯虚方法表示或者指针,但ops展开后成为一个个纯虚方法更为贴切。

1.1硬件i2c

对于硬件i2c子类,则通过调用硬件sdk来实现rt_spi_bus的ops操作方法,实现完美闭环。

缺图对象图,ops展开的一个个方法用虚方法表示或者普通方法即可,意味着重写父类方法。

1.2 软件i2c总线

对于软件i2c总线,共同点就是软件gpio也要实现上面3个公共方法,差异点就是要用gpio模拟硬件i2c的2线通信接口——抽象出软件i2c通信接口。因为i2c通信时序是共同的,如果放到驱动层,每个bsp都要实现一样逻辑的通信函数——重复造轮子——对于这种“重复”性的,就抽象出来放到上层最合理。——就此我也知道了在c++中什么时候需要虚函数/纯虚函数那要看下层有没有共性的东西。

至于i2c软总线通信接口的实现需要哪些信息,rtt抽象出来的如下:
i2c-bit-ops.h 中
struct rt_i2c_bit_ops
{
void data; / private data for lowlevel routines */
void (*set_sda)(void *data, rt_int32_t state); void (*set_scl)(void *data, rt_int32_t state); rt_int32_t (*get_sda)(void *data);
rt_int32_t (*get_scl)(void *data);
void (udelay)(rt_uint32_t us);
rt_uint32_t delay_us; /
scl and sda line delay / rt_uint32_t timeout; / in tick */
};

为何如此抽象?i2c通信就用到2线,所以只要提供操作2线的高低电平接口即可控制通信了,其时序是共通的,再加上延时即可完成硬件无关的i2c通信时序,所以差异点在于操作硬件高低电平的函数,延时函数等的实现不同,于是把它们抽象出来。

模拟通信接口的方法在i2c-bit-ops.c中,从该c中可以看到它只提供了i2c主设备通信,其他两个i2c公共方法(从设备通信和控制方法)均没有支持。待开发。另外在i2c-bit-ops.c中可以看到i2c通信硬件无关的时序接口,要真正驱动引脚还得实现struct rt_i2c_bit_ops的接口。

为何还要抽象出来?同样的下面还有个子类——具体硬件厂家的软件i2c总线——因为各个硬件操作gpio具体实现是不同的,但是这些方法是都一样,所以抽象出来——跨硬件平台,这个框架才叫框架,这个框架才有意义。

rtt的h文件中没有关于抽象出的i2c软总线类,不过可以参考它的soft_i2c.c中抽象出i2c软总线类:

struct rt_soft_i2c
{
struct rt_i2c_bus_device i2c_bus;
struct rt_i2c_bit_ops ops;
};
就是继承i2c总线类后+软件i2c通信接口方法。

soft_i2c.c中的实现自洽的,啥叫自洽?就是它用到了pin设备,如果该bsp实现了pin框架对接,那么soft_i2c.c就完成了整个的软件i2c配置,只需要开启宏和定义下软件i2c引脚就行了,不需要bsp再进行创建软件i2c总线设备了。不过也可以,只要名字不一样也可以,不过结果一样,以我看来有pin对接就不要在bsp层重复实现了。

如果没有实现pin设备框架对接,那么就需要bsp驱动层实现软总线,各个厂家bsp创建各自的软i2c总线子类对象,实现软件i2c的ops方法即可。

缺图对象图,
(1)bus—>ops展开的一个个方法用虚方法表示或者普通方法即可,意味着重写父类i2c总线基类的方法。
(2)软i2c总线子类的ops展开的一个个方法用纯虚方法表示或者指针,但ops展开后成为一个个纯虚方法更为贴切。

/ components / drivers / i2c下有4个文件:
i2c-bit-ops.c
i2c_core.c
i2c_dev.c
soft_i2c.c
这4个文件的关系:
i2c_dev.c是重写/实现rt_device基类的方法的文件,也是初始化i2c基类的接口所在rt_i2c_bus_device_device_init。

i2c_core.c是中转站/中间人,因为i2c_dev.c中重写设备基类的方法,这些方法里调用了i2c_core.c提供的方法如rt_i2c_transfer,而i2c_core.c中这些方法比如 rt_i2c_transfer,实现内部是调用的i2c的3个公共方法比如bus->ops->master_xfer,而这3个公共方法对于硬件i2c总线则走硬件总线的实现,对于软件模拟i2c总线则走i2c-bit-ops.c中的方法比如i2c_bit_xfer,前面知道i2c-bit-ops.c中只实现了主设备通信即只有i2c_bit_xfer。以此来看,i2c_core.c可不就是中间人/岔路口/分发站/跳转点么?!
而i2c_bit_xfer函数里使用到i2c软总线抽象的那些延时2线高低电平接口,而这些接口可以是bsp的驱动层实现的,也可以是soft_i2c.c里实现的——通过pin设备框架控制2线高低电平(当然还需要实现us延时函数)。

而soft_i2c.c是对于支持pin设备的bsp的软总线实现实例,它已自洽的,不需要bsp再重复造轮子了。而它则可以作为参照对于没有支持pin和延时函数的bsp实现软总线的参考例子。它通过pin设备实现了软i2c总线的模拟接口,这样i2c-bit-ops.c中通信方法调用2线控制电平和延迟函数就有了落脚点。而pin设备就需要驱动层的gpio驱动支持的,gpio驱动就调用了硬件sdk,自然能驱动硬件引脚。这样屏蔽了硬件差异,实现跨硬件平台。

2.i2c设备

无。通过i2c从机地址就能区分i2c设备,就没有必要专门搞个设备累了,多余了。

3.使用

官方文档说的就是如何使用的i2c总线,而上面学的是注册/初始化/构造流程。

相关文章:

rtt设备驱动框架面向对象学习-i2c总线

本来想着i2c和spi是一样的,标题都想抄袭成《rtt设备驱动框架学习-i2c总线和设备》,然后看过源码发现,i2c没有分开总线和设备,我想着正常它和spi一样有总线和设备,设备存在竞争。估计是因为i2c设备可以通过i2c地址区分&…...

Golang 基础 Go Modules包管理

Golang 基础 Go Modules包管理 在 Go 项目开发中,依赖包管理是一个非常重要的内容,依赖包处理不好,就会导致编译失败,本文将系统介绍下 Go 的依赖包管理工具。 我会首先介绍下 Go 依赖包管理工具的历史,并详细介绍下…...

图数据库 之 Neo4j - 背景介绍(1)

引言 Neo4j是一种高性能的图数据库,它专门设计用于存储、管理和查询大规模的图数据。与传统的关系型数据库不同,Neo4j以图的形式存储数据,其中节点表示实体,边表示实体之间的关系。这种图数据模型非常适合表示复杂的关系和连接。…...

JAVA中的单例模式->饿汉式

一、步骤 1.构造器私有化>防止直接new // 步骤一、构造器私有化>防止直接new private GirlFriend(String name){System.out.println("构造器被调用");this.name name; } 2.类的内部创建对象 // 步骤二、类的内部创建对象(该对象是static&#x…...

从零开始手写mmo游戏从框架到爆炸(三)— 服务启动接口与网络事件监听器

导航:从零开始手写mmo游戏从框架到爆炸(零)—— 导航-CSDN博客 上一章我们完成了netty服务启动的相关抽象(https://blog.csdn.net/money9sun/article/details/136025471),这一章我们再新增一个全…...

git 合并多条提交记录

我要合并多条提交记录(合并前7条为一条),实现如下效果: 使用git rebase // 查看前10个commit git log -10 // 将7个commit压缩成一个commit;注意:vim编辑器 git rebase -i HEAD~4 // add已经跟踪的文件 g…...

C++多线程:this_thread 命名空间

std::this_thread 是 C 标准库中提供的一个命名空间,它包含了与当前线程相关的功能。这个命名空间提供了许多与线程操作相关的工具,使得在多线程环境中更容易进行编程。 源码类似于如下: namespace std{namespace this_thread{//...........…...

《山雨欲来-知道创宇 2023 年度 APT 威胁分析总结报告》

下载链接: https://pan.baidu.com/s/1eaIOyTk12d9mcuqDGzMYYQ?pwdzdcy 提取码: zdcy...

Qt信号和槽机制(什么是信号和槽,connect函数的形式,按钮的常用信号,QWidget的常用槽,自定义槽函数案例 点击按钮,输出文本)

一.什么是信号和槽 信号槽式Qt中的一个很重要的机制。信号槽实际上是观察者模式,当发生了感兴趣的事件,某一个操作就会被自动触发。当某个事件发生之后,比如按钮检测到自己被点击了一下,它就会发出一个信号。这种发出类似广播。如果有对象对…...

彻底弄懂mktemp命令的作用

mktemp 是一个在 Unix 和类 Unix 系统中用于创建临时文件或目录的命令行工具。它属于 GNU coreutils 套件的一部分。mktemp 的主要优点是它能够生成一个唯一的文件名,这有助于避免文件名冲突,并且可以安全地创建临时文件,因为这些文件通常只有…...

政安晨:示例演绎TensorFlow的官方指南(二){Estimator}

咱们接着演绎TensorFlow官方指南,我的这个系列的上一篇文章为: 政安晨:示例演绎TensorFlow的官方指南(一){基础知识}https://blog.csdn.net/snowdenkeke/article/details/136067030为什么要演绎官方指南,我…...

vue3:24—组件通信方式

目录 1、props 2、自定义事件 (emit) 3、mitt(任意组件的通讯) 4、v-model【封装ui组件库用的多,平时用的少。和vue2有点不同】 5、$attrs 6、$refs和$parent 7、provide和inject 8、pinia(即vue2中…...

WebGL+Three.js入门与实战——绘制水平移动的点、通过鼠标控制绘制(点击绘制、移动绘制、模拟画笔)

个人简介 👀个人主页: 前端杂货铺 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...

大数据环境搭建(一)-Hive

1 hive介绍 由Facebook开源的,用于解决海量结构化日志的数据统计的项目 本质上是将HQL转化为MapReduce、Tez、Spark等程序 Hive表的数据是HDFS上的目录和文件 Hive元数据 metastore,包含Hive表的数据库、表名、列、分区、表类型、表所在目录等。 根据Hive部署模…...

mac电脑上使用android studio创建flutter项目

mac电脑环境配置可以看这篇文章:https://xiaoshen.blog.csdn.net/article/details/136068650 配置玩环境之后,开始创建第一个flutter项目:点击new flutter project或者new project都可以 然后选择flutter: 并将sdk配置为解压后的…...

Excel——分类汇总

1.一级分类汇总 Q:请根据各销售地区统计销售额总数。 第一步:排序,我们需要根据销售地区汇总数据,我们就要对【销售地区】的内容进行排序。点击【销售地区】列中任意一个单元格,选择【数据】——【排序】&#xff0c…...

Backtrader 文档学习- Observers - Reference

Backtrader 文档学习- Observers - Reference 1.Benchmark class backtrader.observers.Benchmark() 观察器存储策略的回报和参考资产的回报,参考资产是传递给系统的数据之一。 参数: timeframe (default: None) ,如果None,则将…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Radio组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Radio组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Radio组件 单选框,提供相应的用户交互选择项。 子组件 无。 接口 …...

【go】结构体切片去重

场景 自定义结构体切片,去除切片中的重复元素(所有值完全相同) 代码 // 自定义struct去重 type AssetAppIntranets struct {ID string json:"id,omitempty"AppID string json:"app_id,omitempty"IP …...

百面嵌入式专栏(面试题)C语言面试题22道

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍C语言相关面试题 。 宏定义是在编译的哪个阶段被处理的?答案:宏定义是在编译预处理阶段被处理的。 解读:编译预处理:头文件包含、宏替换、条件编译、去除注释、添加行号。 写一个“标准”宏MIN,这个…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中&#xff0c;如何展示好看的实验结果图像非常重要&#xff01;&#xff01;&#xff01; 1、灰度原始图像 灰度图像每个像素点只有一个数值&#xff0c;代表该点的​​亮度&#xff08;或…...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...

数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)

目录 &#x1f50d; 若用递归计算每一项&#xff0c;会发生什么&#xff1f; Horners Rule&#xff08;霍纳法则&#xff09; 第一步&#xff1a;我们从最原始的泰勒公式出发 第二步&#xff1a;从形式上重新观察展开式 &#x1f31f; 第三步&#xff1a;引出霍纳法则&…...