Linux--IIC驱动编程实验

对于 I2C 主机驱动,一旦编写完成就不需要再做修改,其他的 I2C 设备直接调用主机驱动提供的 API 函数完成读写操作即可。这个正好符合 Linux 的驱动分离与分层的思想,因此 Linux内核也将 I2C 驱动分为两部分:
①、 I2C 总线驱动, I2C 总线驱动就是 SOC I2C 控制器驱动,也叫做 I2C 适配器驱动。
②、 I2C 设备驱动, I2C 设备驱动就是针对具体的 I2C 设备而编写的驱动。

 总的来说,IIC的驱动分为IIC控制器(主机)的驱动和IIC设备驱动(从机),一般控制器的驱动芯片原厂已经写好,我们要做的就是根据自己要用的IIC设备写设备驱动。

一、I2C 设备驱动

I2C 设备驱动重点关注两个数据结构: i2c_client i2c_driver ,根据总线、设备和驱动模型。还剩下设备和驱动, i2c_client 就是描述设备信息的, i2c_driver 描述驱动内容,类似于platform_driver。

1.1  i2c_client 结构体

i2c_client 结构体定义在 include/linux/i2c.h 文件中,内容如下:
一个设备对应一个 i2c_client ,每检测到一个 I2C 设备就会给这个 I2C 设备分配一个i2c_client。

1.2   i2c_driver 结构体

i2c_driver 类似 platform_driver ,是我们编写 I2C 设备驱动重点要处理的内容, i2c_driver 结构体定义在 include/linux/i2c.h 文件中,内容如下:
示例代码 61.1.2.2 i2c_driver 结构体
161 struct i2c_driver {
162 unsigned int class;
163
164 /* Notifies the driver that a new bus has appeared. You should 
165 * avoid using this, it will be removed in a near future.
166 */
167 int (*attach_adapter)(struct i2c_adapter *) __deprecated;
168
169 /* Standard driver model interfaces */
170 int (*probe)(struct i2c_client *, const struct i2c_device_id *);
171 int (*remove)(struct i2c_client *);
172
173 /* driver model interfaces that don't relate to enumeration */
174 void (*shutdown)(struct i2c_client *);
175
176 /* Alert callback, for example for the SMBus alert protocol.
177 * The format and meaning of the data value depends on the 
178 * protocol.For the SMBus alert protocol, there is a single bit 
179 * of data passed as the alert response's low bit ("event 
180 flag"). */
181 void (*alert)(struct i2c_client *, unsigned int data);
182
183 /* a ioctl like command that can be used to perform specific 
184 * functions with the device.
185 */
186 int (*command)(struct i2c_client *client, unsigned int cmd,
void *arg);
187
188 struct device_driver driver;
189 const struct i2c_device_id *id_table;
190
191 /* Device detection callback for automatic device creation */
192 int (*detect)(struct i2c_client *, struct i2c_board_info *);
193 const unsigned short *address_list;
194 struct list_head clients;
195 };
170 行,当 I2C 设备和驱动匹配成功以后 probe 函数就会执行,和 platform 驱动一样。
188 行, device_driver 驱动结构体,如果使用设备树的话,需要设置 device_driver 的 of_match_table 成员变量,也就是驱动的兼容 (compatible) 属性。
对于我们 I2C 设备驱动编写人来说,重点工作就是构建 i2c_driver ,构建完成以后需要向Linux 内核注册这个 i2c_driver i2c_driver 注册函数为 int i2c_register_driver

二、I2C设备驱动编写流程

2.1   I2C 设备信息描述,此处主要叙述使用设备树的时候

使用设备树的时候 I2C 设备信息通过创建相应的节点就行了,比如 NXP 官方的 EVK 开发板在 I2C1 上接了 mag3110 这个磁力计芯片,因此必须在 i2c1 节点下创建 mag3110 子节点,然后在这个子节点内描述 mag3110 这个芯片的相关信息。
示例代码 61.3.1.4 mag3110 子节点
1 &i2c1 {
2 clock-frequency = <100000>;
3 pinctrl-names = "default"; 4 pinctrl-0 = <&pinctrl_i2c1>;
5 status = "okay"; 6 
7 mag3110@0e { 8 compatible = "fsl,mag3110"; 9 reg = <0x0e>;
10 position = <2>;
11 };
......
20 };
7~11 行,向 i2c1 添加 mag3110 子节点,第 7 行“ mag3110@0e ”是子节点名字,“ @ ” 后面“0e ”就是 mag3110 I2C 器件地址。第 8 行设置 compatible 属性值为“ fsl,mag3110 ”。
9 行的 reg 属性也是设置 mag3110 的器件地址的,因此值为 0x0e I2C 设备节点的创建重点 是 compatible 属性和 reg 属性的设置,一个用于匹配驱动,一个用于设置器件地址。
2.2   I2C 设备数据收发处理流程
I2C 设备驱动首先要做的就是初始化 i2c_driver 并向 Linux 内核注册。当设备和驱动匹配以后 i2c_driver 里面的 probe 函数就会执行, probe 函数里面所做的就是字符设备驱动那一套了。一般需要在 probe 函数里面初始化 I2C 设备,要初始化 I2C 设备就必须能够对 I2C 设备寄存器进行读写操作,这里就要用到 i2c_transfer 函数了。 i2c_transfer 函数最终会调用 I2C 适配器中 i2c_algorithm 里面的 master_xfer 函数,对于 I.MX6U 而言就是i2c_imx_xfer 这个函数。i2c_transfer 函数原型如下:
int i2c_transfer(struct i2c_adapter *adap, 
struct i2c_msg *msgs, 
int num)
adap 所使用的 I2C 适配器, i2c_client 会保存其对应的 i2c_adapter
msgs I2C 要发送的一个或多个消息。
num 消息数量,也就是 msgs 的数量。
返回值: 负值,失败,其他非负值,发送的 msgs 数量。
我们重点来看一下 msgs 这个参数,这是一个 i2c_msg 类型的指针参数, I2C 进行数据收发说白了就是消息的传递,Linux 内核使用 i2c_msg 结构体来描述一个消息。
使用 i2c_transfer 函数发送数据之前要先构建好 i2c_msg

三、实验程序编写(以AP3216C为例)

3.1     修改设备树

IO 修改或添加(配置要用到的总线的IO口)
首先肯定是要修改 IO AP3216C 用到了 I2C1 接口, I.MX6U-ALPHA 开发板上的 I2C1 接口使用到了 UART4_TXD UART4_RXD
示例代码 61.5.1.1 pinctrl_i2c1 子节点
1 pinctrl_i2c1: i2c1grp { 2 fsl,pins = < 3 MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
4 MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
5 >;
6 };
pinctrl_i2c1 就是 I2C1 IO 节点,这里将 UART4_TXD UART4_RXD 这两个 IO 分别复用为 I2C1_SCL I2C1_SDA
i2c1 节点追加 ap3216c 子节点
AP3216C 是连接到 I2C1 上的,因此需要在 i2c1 节点下添加 ap3216c 的设备子节点

3.2     AP3216C 驱动编写

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

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

相关文章

yum常用命令与lrzsz的在线安装

yum命令 yum&#xff08; Yellow dog Updater, Modified&#xff09;是一个在 Fedora 和 RedHat 以及 SUSE 中的 Shell 前端软件包管理器。 基于 RPM 包管理&#xff0c;能够从指定的服务器自动下载 RPM 包并且安装&#xff0c;可以自动处理依赖性关系&#xff0c;并且一次安装…

强化学习玩flappy_bird

强化学习玩flappy_bird&#xff08;代码解析&#xff09; 游戏地址&#xff1a;https://flappybird.io/ 该游戏的规则是&#xff1a; 点击屏幕则小鸟立即获得向上速度。 不点击屏幕则小鸟受重力加速度影响逐渐掉落。 小鸟碰到地面会死亡&#xff0c;碰到水管会死亡。&#…

Django开发实战之登录用户鉴权登录界面实现

Django自带的鉴权系统非常的安全&#xff0c;大家可以放心使用&#xff0c;那么如何使用呢&#xff1f; 1、首先需要检查settings文件种的INSTALLED_APPS&#xff0c;有没有这两部分内容&#xff1a; 2、检查中间件&#xff0c;比如这两个中间件&#xff0c;一个是用于登录&a…

【人工智能Ⅱ】实验6:目标检测算法

实验6&#xff1a;目标检测算法 一&#xff1a;实验目的与要求 1&#xff1a;了解两阶段目标检测模型 RCNN或Faster RCNN模型的原理和结构。 2&#xff1a;学习通过RCNN或Faster RCNN模型解决目标检测问题。 二&#xff1a;实验内容 常用的深度学习框架包括PyTorch和PaddleP…

企业邮箱是什么样子的?怎么弄一个企业邮箱

企业邮箱是什么样子的&#xff1f;企业使用的电子邮箱有特征&#xff1f;其实&#xff0c;企业邮箱的主要特征就在于电子邮箱域名的个性化&#xff0c;以及可扩展性的功能&#xff0c;在使用企业邮箱时能够提升公司的品牌形象。今天小编和大家仔细来聊聊。 一、企业邮箱是什么…

基于Springboot+Vue+Java的学生就业管理系统

&#x1f49e; 文末获取源码联系 &#x1f649; &#x1f447;&#x1f3fb; 精选专栏推荐收藏订阅 &#x1f447;&#x1f3fb; &#x1f380;《Java 精选实战项目-计算机毕业设计题目推荐-期末大作业》&#x1f618; 更多实战项目~ https://www.yuque.com/liuyixin-rotwn/ei3…

电子取证平航杯的复现

闻早起部分&#xff1a; 一、闻早起的windows10电脑 &#xff08;1&#xff09;.“闻早起”所使用的笔记本电脑使用何种加密程式&#xff1f; 1.在EFI文件中找到加密程式 &#xff08;2&#xff09; 教徒“闻早起”所使用的笔记本电脑中安装了一款还原软件&#xff0c;其版本…

大模型_DISC-MedLLM基于Baichuan-13B-Base医疗健康对话

文章目录 DISC-MedLLM介绍概述数据集部署推理流程 DISC-MedLLM 介绍 DISC-MedLLM 是一个专门针对医疗健康对话式场景而设计的医疗领域大模型&#xff0c;由复旦大学数据智能与社会计算实验室 (Fudan-DISC) 开发并开源。 该项目包含下列开源资源: DISC-Med-SFT 数据集 (不包…

对于子数组问题的动态规划

前言 先讲讲我对于这个问题的理解吧 当谈到解决子数组问题时&#xff0c;动态规划(DP)是一个强大的工具&#xff0c;它在处理各种算法挑战时发挥着重要作用。动态规划是一种思想&#xff0c;它通过将问题分解成更小的子问题并以一种递归的方式解决它们&#xff0c;然后利用这些…

9.媒体元素

视频元素 视频标签基本代码结构&#xff1a; <video src"" controls></video>其中src是视频资源的路径&#xff0c;这个路径有绝对路径和相对路径这里推荐用相对路径。&#xff08;这里可以回顾我html系列的第四篇图片标签&#xff09;&#xff0c;我们…

力扣每日一题111:二叉树的最小深度

题目 简单 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2示例 2&#x…

redis stream 作为消息队列的最详细的命令说明文档

简介 stream 作为消息队列&#xff0c;支持多次消费&#xff0c;重复消费&#xff0c;ack机制&#xff0c;消息异常处理机制。 涉及到以下几个概念&#xff0c;消息流&#xff0c;消费者组&#xff0c;消费者。 涉及到以下命令 # 添加消息到流中 XADD key [NOMKSTREAM] [&…