百度的网站哪来的/长尾关键词快速排名软件

百度的网站哪来的,长尾关键词快速排名软件,如何创建自媒体手机网站,找网络公司建网站每年收维护费相关文章 I2C驱动(一) – I2C协议 I2C驱动(二) – SMBus协议 I2C驱动(三) – 驱动中的几个重要结构 I2C驱动(四) – I2C-Tools介绍 I2C驱动(五) – 通用驱动i2c-dev.c分析 I2C驱动(六) – I2C驱动程序模型 I2C驱动(七) – 编写I2C设备驱动之i2c_driver I2C驱动(八) – 编写I2C…

相关文章

I2C驱动(一) – I2C协议
I2C驱动(二) – SMBus协议
I2C驱动(三) – 驱动中的几个重要结构
I2C驱动(四) – I2C-Tools介绍
I2C驱动(五) – 通用驱动i2c-dev.c分析
I2C驱动(六) – I2C驱动程序模型
I2C驱动(七) – 编写I2C设备驱动之i2c_driver
I2C驱动(八) – 编写I2C设备驱动之i2c_client
I2C驱动(九) – i2c_adapter控制器驱动框架编写
I2C驱动(十) – i2c_adapter控制器驱动完善与上机实验

文章目录

  • 相关文章
  • 参考资料
  • 一、平台-总线-设备驱动模型
  • 二、设备树分析
  • 三、驱动程序分析
    • 3.1 i2c-gpio驱动层次
    • 3.2 `bit_xfer`传输函数分析
  • 四、怎么使用i2c-gpio
  • 五、总结


参考资料

  • i2c_spec.pdf
  • Linux文档
    • Linux-4.9.88\Documentation\devicetree\bindings\i2c\i2c-gpio.txt
  • Linux驱动源码
    • Linux-4.9.88\drivers\i2c\busses\i2c-gpio.c

一、平台-总线-设备驱动模型

i2c-gpio.c也是基于万能框架:平台-总线-设备模型来写的。platform_device部分来自设备树,platform_driver就是i2c-gpio.c驱动。下面分析两边的代码。
在这里插入图片描述

二、设备树分析

设备树节点如下:

i2c_gpio: i2c-gpio {compatible = "i2c-gpio";#address-cells = <1>;#size-cells = <0>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_i2c_gpio>;gpios = <&gpio5 1 GPIO_ACTIVE_HIGH /* SDA */&gpio5 0 GPIO_ACTIVE_HIGH /* SCL */>;i2c-gpio,delay-us = <5>;	/* ~100 kHz */status = "okay";ds1339: rtc@68 {compatible = "dallas,ds1339";reg = <0x68>;status = "disabled";};};
  • compatible 属性用于和i2c-gpio.c程序中.of_match_table结构中的compatible 进行比较。
  • #address-cells #size-cells 属性用来指定 reg属性的地址和大小用多少个32位数据表示。reg属性在子节点中用了表示i2c设备地址。
  • pinctrl-namespinctrl-0属性表示使用pinctrl将引脚配置成gpio模式。
  • gpios 属性用于指定gpio引脚
  • i2c-gpio,delay-us属性表示时钟频率
  • status 属性节点使能状态
  • ds1339: rtc@68表示的是这个i2c总线下挂的设备,地址是0x68。

三、驱动程序分析

3.1 i2c-gpio驱动层次

从入口函数开始,入口函数注册了一个platform_driver结构。

tatic int __init i2c_gpio_init(void)
{
...ret = platform_driver_register(&i2c_gpio_driver);
...
}

platform_driver结构包含了of_match_table数组,probe函数。

static struct platform_driver i2c_gpio_driver = {.driver		= {.name	= "i2c-gpio",.of_match_table	= of_match_ptr(i2c_gpio_dt_ids), //和设备树比较},.probe		= i2c_gpio_probe,  //匹配成功调用.remove		= i2c_gpio_remove, //做一些和probe相反的工作
};

of_match_table数组中的compatible 和设备树匹配成功,调用probe函数。

static const struct of_device_id i2c_gpio_dt_ids[] = {{ .compatible = "i2c-gpio", }, //与设备树的compatible 比较{ /* sentinel */ }
};

来看probe函数:

  • of_i2c_gpio_get_pins从设备树获取gpio引脚。
  • adap = &priv->adap;分配的i2c_adapter
  • of_i2c_gpio_get_props从设备树获取属性值,用来设置硬件参数和i2c_adapter结构。
  • i2c_bit_add_numbered_bus注册i2c_adapter,这个是重点,这里面会有算法部分设置,下面继续分析。
static int i2c_gpio_probe(struct platform_device *pdev)
{
...unsigned int sda_pin, scl_pin; //sda 和 scl引脚int ret;/* First get the GPIO pins; if it fails, we'll defer the probe. */if (pdev->dev.of_node) {/* 从设备树中获取        sda 和 scl */ret = of_i2c_gpio_get_pins(pdev->dev.of_node,&sda_pin, &scl_pin);if (ret)return ret;} else {if (!dev_get_platdata(&pdev->dev))return -ENXIO;pdata = dev_get_platdata(&pdev->dev);sda_pin = pdata->sda_pin;scl_pin = pdata->scl_pin;}/*devm_gpio_request 可以自动处理清理工作 */ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");if (ret) {if (ret == -EINVAL)ret = -EPROBE_DEFER;	/* Try again later */return ret;}ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");if (ret) {if (ret == -EINVAL)ret = -EPROBE_DEFER;	/* Try again later */return ret;}priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);if (!priv)return -ENOMEM;/* 分配了i2c_adapter */	adap = &priv->adap;bit_data = &priv->bit_data;pdata = &priv->pdata;if (pdev->dev.of_node) {pdata->sda_pin = sda_pin;pdata->scl_pin = scl_pin;/*从设备树获取属性*/of_i2c_gpio_get_props(pdev->dev.of_node, pdata);} else {memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));}/* 根据获取的设备树属性值设置开漏情况 */if (pdata->sda_is_open_drain) {gpio_direction_output(pdata->sda_pin, 1);bit_data->setsda = i2c_gpio_setsda_val;} else {gpio_direction_input(pdata->sda_pin);bit_data->setsda = i2c_gpio_setsda_dir;}if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {gpio_direction_output(pdata->scl_pin, 1);bit_data->setscl = i2c_gpio_setscl_val;} else {gpio_direction_input(pdata->scl_pin);bit_data->setscl = i2c_gpio_setscl_dir;}/* 根据获取的设备树属性值设置时间参数 */if (!pdata->scl_is_output_only)bit_data->getscl = i2c_gpio_getscl;bit_data->getsda = i2c_gpio_getsda;if (pdata->udelay)bit_data->udelay = pdata->udelay;else if (pdata->scl_is_output_only)bit_data->udelay = 50;			/* 10 kHz */elsebit_data->udelay = 5;			/* 100 kHz */if (pdata->timeout)bit_data->timeout = pdata->timeout;elsebit_data->timeout = HZ / 10;		/* 100 ms */bit_data->data = pdata;/* 根据设备树解析的值设置i2c_adapter */adap->owner = THIS_MODULE;if (pdev->dev.of_node)strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));elsesnprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);adap->algo_data = bit_data;adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;adap->dev.parent = &pdev->dev;adap->dev.of_node = pdev->dev.of_node;adap->nr = pdev->id;/* 注册i2c_adapter */ret = i2c_bit_add_numbered_bus(adap);
...
}

进入i2c_bit_add_numbered_bus看看,这个函数在drivers\i2c\algos\i2c-algo-bit.c中定义,他调用__i2c_bit_add_bus__i2c_bit_add_bus里面设置了adap->algo = &i2c_bit_algo;,这就是i2c核心算法结构,下面继续看i2c_bit_algo

int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
{return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);
}static int __i2c_bit_add_bus(struct i2c_adapter *adap,int (*add_adapter)(struct i2c_adapter *))
{
.../* 核心算法 */adap->algo = &i2c_bit_algo;
...
}

i2c_bit_algo结构中bit_xfer就是gpio模拟i2c_adapter的传输函数。

const struct i2c_algorithm i2c_bit_algo = {.master_xfer	= bit_xfer,.functionality	= bit_func,
};

从上面的分析,可以知道I2C-GPIO的驱动层次如下:
在这里插入图片描述

3.2 bit_xfer传输函数分析

传输函数是根据i2c协议来完成的,i2c_start发起一个start信号,接着根据i2c_msg 来判断读写,readbytes读一个字节,sendbytes写一个字节。结束后i2c_stop发出停止信号。

static int bit_xfer(struct i2c_adapter *i2c_adap,struct i2c_msg msgs[], int num)
{struct i2c_msg *pmsg;struct i2c_algo_bit_data *adap = i2c_adap->algo_data;int i, ret;unsigned short nak_ok;if (adap->pre_xfer) {ret = adap->pre_xfer(i2c_adap);if (ret < 0)return ret;}bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");i2c_start(adap); //发出Start信号for (i = 0; i < num; i++) {pmsg = &msgs[i]; //循环取出i2c_msg nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;if (!(pmsg->flags & I2C_M_NOSTART)) {if (i) {bit_dbg(3, &i2c_adap->dev, "emitting ""repeated start condition\n");i2c_repstart(adap);}ret = bit_doAddress(i2c_adap, pmsg);if ((ret != 0) && !nak_ok) {bit_dbg(1, &i2c_adap->dev, "NAK from ""device addr 0x%02x msg #%d\n",msgs[i].addr, i);goto bailout;}}if (pmsg->flags & I2C_M_RD) {/* read bytes into buffer(读一个字节)*/ ret = readbytes(i2c_adap, pmsg);if (ret >= 1)bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",ret, ret == 1 ? "" : "s");if (ret < pmsg->len) {if (ret >= 0)ret = -EIO;goto bailout;}} else {/* write bytes from buffer (写一个字节)*/ret = sendbytes(i2c_adap, pmsg);if (ret >= 1)bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",ret, ret == 1 ? "" : "s");if (ret < pmsg->len) {if (ret >= 0)ret = -EIO;goto bailout;}}}ret = i;bailout:bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");i2c_stop(adap);if (adap->post_xfer)adap->post_xfer(i2c_adap);return ret;
}

字节读写再细分到位操作,在i2c_outb函数中实现。

static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
{int i;int sb;int ack;struct i2c_algo_bit_data *adap = i2c_adap->algo_data;/* assert: scl is low */for (i = 7; i >= 0; i--) {sb = (c >> i) & 1;setsda(adap, sb);udelay((adap->udelay + 1) / 2);if (sclhi(adap) < 0) { /* timed out */bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, ""timeout at bit #%d\n", (int)c, i);return -ETIMEDOUT;}/* FIXME do arbitration here:* if (sb && !getsda(adap)) -> ouch! Get out of here.** Report a unique code, so higher level code can retry* the whole (combined) message and *NOT* issue STOP.*/scllo(adap);}sdahi(adap);if (sclhi(adap) < 0) { /* timeout */bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, ""timeout at ack\n", (int)c);return -ETIMEDOUT;}/* read ack: SDA should be pulled down by slave, or it may* NAK (usually to report problems with the data we wrote).*/ack = !getsda(adap);    /* ack: sda is pulled low -> success */bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,ack ? "A" : "NA");scllo(adap);return ack;/* assert: scl is low (sda undef) */
}

四、怎么使用i2c-gpio

(1)设置设备树
在根节点添加一个节点,示例代码看上面"设备树分析"部分,也可以参考 Linux-4.9.88\Documentation\devicetree\bindings\i2c\i2c-gpio.txt
(2)内核选上CONFIG_I2C_GPIO配置项

五、总结

本文分析了gpio模拟的i2c_adapter驱动程序i2c-gpio.c。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/71191.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(KTransformers) RTX4090单卡运行 DeepSeek-R1 671B

安装环境为&#xff1a;ubuntu 22.04 x86_64 下载模型 编辑文件vim url.list 写入如下内容 https://modelscope.cn/models/unsloth/DeepSeek-R1-GGUF/resolve/master/DeepSeek-R1-Q4_K_M/DeepSeek-R1-Q4_K_M-00001-of-00009.gguf https://modelscope.cn/models/unsloth/Dee…

海康威视摄像头ISUP(原EHOME协议) 摄像头实时预览springboot 版本java实现,并可以在浏览器vue前端播放(附带源码)

1.首先说了一下为什么要用ISUP协议来取流 ISUP主要就是用来解决摄像头没有公网ip的情况,如果摄像头或者所在局域网的路由器有公网ip的话&#xff0c;其实采用rtsp直接取流是最方便也是性能最好的&#xff0c;但是项目的摄像头没有公网IP所以被迫使用ISUP&#xff0c;ISUP是海康…

SpringBoot原理-03.自动配置-方案

一.自动配置原理 探究自动配置原理&#xff0c;就是探究spring是如何在运行时将要依赖JAR包提供的配置类和bean对象注入到IOC容器当中。我们当前准备一个maven项目itheima-utils&#xff0c;这里面定义了bean对象以及配置类&#xff0c;用来模拟第三方提供的依赖&#xff0c;首…

高频 SQL 50 题(基础版)_2356. 每位教师所教授的科目种类的数量

高频 SQL 50 题&#xff08;基础版&#xff09;_2356. 每位教师所教授的科目种类的数量 select teacher_id ,count(distinct(subject_id)) as cnt from Teacher group by teacher_id

神经网络之词嵌入模型(基于torch api调用)

一、Word Embedding&#xff08;词嵌入&#xff09;简介 Word Embedding&#xff08;词嵌入&#xff09;&#xff1a; 词嵌入技术是自然语言处理&#xff08;NLP&#xff09;领域的一项重大创新&#xff0c;它极大地推动了计算机理解和处理人类语言的能力。 通过将单词、句子甚…

SpringBoot @Value 注解使用

Value 注解用于将配置文件中的属性值注入到Spring管理的Bean中。 1. 基本用法 Value 可以直接注入配置文件中的属性值。 配置文件 (application.properties 或 application.yml) 配置文件定义需要注入的数据。 consumer:username: lisiage: 23hobby: sing,read,sleepsubje…

Redis面试常见问题——使用场景问题

目录 Redis面试常见问题 如果发生了缓存穿透、击穿、雪崩&#xff0c;该如何解决&#xff1f; 缓存穿透 什么是布隆过滤器&#xff1f; 缓存击穿 缓存雪崩 双写一致性&#xff08;redis做为缓存&#xff0c;mysql的数据如何与redis进行同步呢&#xff1f;&#xff09; …

在Ubuntu 22.04 LTS 上安装 MySQL两种方式:在线方式和离线方式

Ubuntu安装MySQL 介绍&#xff1a; Ubuntu 是一款基于Linux操作系统的免费开源发行版&#xff0c;广受欢迎。它以稳定性、安全性和用户友好性而闻名&#xff0c;适用于桌面和服务器环境。Ubuntu提供了大量的软件包和应用程序&#xff0c;拥有庞大的社区支持和活跃的开发者社区…

用Java编写sql

1.概念 通过Java代码操作mysql数据库 数据库编程&#xff0c;是需要数据库服务器&#xff0c;提供一些API&#xff0c;供程序员调用的 2.安装 2.1下载 在程序中操作mysql需要先安装mysql的驱动包 并且要把驱动包引入到项目中 在中央仓库可以下载到驱动包(mvnrepository.…

Redis数据结构-List列表

1.List列表 列表类型适用于存储多个有序的字符串&#xff08;这里的有序指的是强调数据排列顺序的重要&#xff0c;不是升序降序的意思&#xff09;&#xff0c;列表中的每个字符串称为元素&#xff08;element&#xff09;&#xff0c;一个列表最多可以存储2^32-1个元素。在R…

Linux实操——在服务器上直接从百度网盘下载(/上传)文件

Linux Linux实操——在服务器上直接从百度网盘下载&#xff08;/上传&#xff09;文件 文章目录 Linux前言一、下载并安装bypy工具二、认证并授权网盘账号三、将所需文件转移至目的文件夹下四、下载文件五、上传文件六、更换绑定的百度云盘账户 前言 最近收到一批很大的数据&…

题解 | 牛客周赛82 Java ABCDEF

目录 题目地址 做题情况 A 题 B 题 C 题 D 题 E 题 F 题 牛客竞赛主页 题目地址 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 做题情况 A 题 判断字符串第一个字符和第三个字符是否相等 import java.io.*; import java.math.*; import java.u…

基金 word-->pdf图片模糊的解决方法

1. 首先需要Adobe或福昕等pdf阅读器。 2. word中 [文件]--[打印]&#xff0c;其中打印机选择pdf阅读器&#xff0c;例如此处我选择福昕阅读器。 3. 选择 [打印机属性]--[编辑]--[图像]&#xff0c;将所有的采样、压缩均设置为 关闭。点击[另存为]&#xff0c;保存为 基金报告…

基于RKNN的嵌入式深度学习开发(2)

上一个章节我们介绍的RKNN模型的模型转换和模型的推理&#xff0c;这一章节我们将介绍模型的量化和评估部分。 2.3 RKNN模型的量化 量化就是将浮点转换为定点运算的过程&#xff0c;或者训练后由rknn来量化。量化模型使用较低精度&#xff08;如int8/uint8/int16&#xff09;保…

Qt 中signals和slots、Q_SIGNAL和Q_LOT、Q_SIGNALS和Q_SLOTS的区别和使用

Qt 中signals和slots、Q_SIGNAL和Q_SLOT、Q_SIGNALS和Q_SLOTS的区别和使用 1.signals和slots 信号和槽函数需要在类的声明中明确声明。信号需要使用signals关键字&#xff0c;而槽函数可以使用slots关键字&#xff08;虽然在现代Qt中&#xff0c;槽函数也可以直接作为普通成员…

【极客时间】浏览器工作原理与实践-2 宏观视角下的浏览器- 2.1 Chrome架构:仅仅打开了1个页面,为什么有4个进程?

https://time.geekbang.org/column/article/113513 2.1 Chrome架构&#xff1a;仅仅打开了1个页面&#xff0c;为什么有4个进程&#xff1f; 前置&#xff1a;基于Chrome浏览器学习浏览器的工作原理 原因&#xff1a; 因为 Chrome、微软的 Edge 以及国内的大部分主流浏览器…

智能图像处理平台:图像处理配置类

这里我们先修改一下依赖&#xff0c;不用JavaCV&#xff0c;用openCV。 导入依赖&#xff1a; <!-- JavaCV 依赖&#xff0c;用于图像和视频处理 --> <!-- <dependency>--> <!-- <groupId>org.bytedeco</groupId>--> &l…

【Python 初级函数详解】—— 参数沙漠与作用域丛林的求生指南

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…

夜天之书 #106 Apache 软件基金会如何投票选举?

近期若干开源组织进行换届选举。在此期间&#xff0c;拥有投票权的成员往往会热烈讨论&#xff0c;提名新成员候选人和治理团队的候选人。虽然讨论是容易进行的&#xff0c;但是实际的投票流程和运作方式&#xff0c;在一个成员众多的组织中&#xff0c;可能会有不少成员并不清…

DeepSeek开源周 Day04:从DualPipe聊聊大模型分布式训练的并行策略

DualPipe简介 今天是DeepSeek开源周的第四天&#xff0c;官方开源了一种新型并行计算优化策略——DualPipe。 其实大家阅读过Deepseek-V3技术报告的同学&#xff0c;对这个技术并不陌生。 开源地址&#xff1a;https://github.com/deepseek-ai/DualPipe 核心亮点 DualPipe&…