(一) XXXX — 内核加载驱动模块是调用:XXXX_init() 方法:
a) 调用gsensor_fetch_sysconfig_para()解析sys_config1.fex文件,读取到IIC的地址等,并赋值给u_i2c_addr.normal_i2c;
b) 调用总线的设备驱动加载函数–i2c_add_driver开始向IIC注册driver i2c_add_driver(&XXXX _driver);
c) 完成注册后将调用XXXX_probe()方法 — 针对设备做初始化:
i. 初始化一些变量,为(struct XXXX_data *data) (私有数据)结构体申请内存;
ii. 初始化私有(XXXX_data)数据、初始化设备的寄存器等;
iii. 调用IIC接口i2c_smbus_read_word_data()读取IIC上bma250的chip id;
iv. 将设备驱动的私有数据(XXXX_data)连接到设备client(i2c_client)中 i2c_set_clientdata(client, data);
v. 创建工作队列,创建的工作队列,就是在一个工作者线程,通过IIC不断的去查询读取controller上的数据–INIT_DELAYED_WORK(&data->work, XXXX _work_func):
vi. XXXX _work_func是自定义的功能函数,用于查询读取Sensor数据的,并上报Input子系统:

static void XXXX _work_func(struct work_struct *work){通过work得到整个私有数据(work也在私有数据中,描述的是定时工作之类的信息);
定义上报的数据变量—包括x y z;
通过i2c读取设备上的数据;
通过input_report_abs上报数据 ,使用input_sync通知input;
schedule_delayed_work(&bma250->work, delay); //设定delay时间后再次执行这个函数。
}

vii. 将XXXX驱动注册到linux input子系统

XXXX_input_init(data):
static int bma250_input_init(struct  _data * XXXX){申请一个新的input设备,即为一个input_dev申请内存空间 input_allocate_device
设置input设备支持的数据类型  input_set_abs_params
向input系统注册   input_register_device
}

viii. 创建sysfs接口 — 在驱动层创建了sysfs接口,HAL层通过这些sysfs接口,对Sensor进行操作,如使能、设置delay等。

sysfs_create_group(&data->input->dev.kobj, &bma250_attribute_group);
#define  DEVICE_ATTR(_name, _mode, _show, _store)  struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法:

当然_ATTR不是独生子女,他还有一系列的姊妹__ATTR_RO宏只有读方法,__ATTR_NULL等等:
对设备的使用 DEVICE_ATTR
对驱动使用 DRIVER_ATTR
对总线使用 BUS_ATTR
对类别 (class) 使用 CLASS_ATTR
对于DEVICE_ATTR(_name, _mode, _show, _store)的四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。

static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR, show_polling, set_polling);

当你想要实现的接口名字是polling的时候,需要实现结构体struct attribute *dev_attrs[]。其中成员变量的名字必须是&dev_attr_polling.attr。

static struct attribute *dev_attrs[] = {&dev_attr_polling.attr,NULL,
};

然后再封装:

static struct attribute_group dev_attr_grp = {.attrs = dev_attrs,
};

在利用sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);创建接口

XXXX驱动sysfs接口建立,上面介绍的三个步骤来实现。

1、调用宏DEVICE_ATTR完成对功能函数的注册

static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR|S_IWGRP, XXXX _delay_show,
XXXX _delay_store);
static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP, XXXX _enable_show, XXXX _enable_store);
static struct attribute * XXXX _attributes[] = {&dev_attr_delay.attr,&dev_attr_enable.attr,NULL
};

对于XXXX Gsensor,用到的接口是对Gsensor使能和设置delay。设置delay的功能函数——读、写分别是XXXX _delay_show、XXXX _delay_store。使能的功能函数——读写分别是XXXX _enable_show、XXXX _enable_store。这里提到的四个函数,是需要在Gsensor驱动中实现的。

2、封装bma250_attributes数据结构

static struct attribute_group bma250_attribute_group = {.attrs = bma250_attributes
};

3、真正创建接口
在XXXX的初始化函数probe中——XXXX _probe(),调用:
err = sysfs_create_group(&data->input->dev.kobj,& XXXX _attribute_group);
到此,完成了sysfs接口的创建,我们可以在根文件系统中看/sys/class/input/input3/目录,在该目录下我们可以看到多个节点,其中就包含了enable和delay。我们以enable为例子,可以有两种方法完成对Gsensor的使能工作:

  1. 直接使用shell命令
$cd /sys/class/input/input3
$echo 1 > enable

将1写到enable节点,那么将“1”作为参数调用到驱动的XXXX _enable_store()方法,完成对Gsensor的使能工作。
2) 代码写设备节点

char buffer[20];
int len = sprintf(buffer, "%d\n", 1);
fd = open(“/sys/class/input/input3/enable”, O_RDWR);
write(fd, value, len);

(二) 在Android的HAL层,通过对/sys/class/input/input3/enable节点的写操作,使能Gsensor。调用到的方法是XXXX _enable_store():
a)

static ssize_t XXXX _enable_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count){……
XXXX_set_enable(dev,data);
……
return count;
}
static void XXXX_set_enable(struct device *dev, int enable){struct i2c_client *client = to_i2c_client(dev);
struct XXXX_data * XXXX= i2c_get_clientdata(client);
int pre_enable = atomic_read(&XXXX->enable);
mutex_lock(&XXXX->enable_mutex);
if (enable) {if (pre_enable ==0) {XXXX_set_mode(XXXX-> XXXX_client,                                                                                                 XXXX_MODE_NORMAL);
schedule_delayed_work(&XXXX->work,msecs_to_jiffies(atomic_read(&XXXX->delay)));
atomic_set(&XXXX->enable, 1);
}
}……
}

我们看到了,在使能函数中,调用了schedule_delayed_work()开始工作队列,于是调用了功能函数XXXX_work_func()

static void XXXX_work_func(struct work_struct *work){struct XXXX_data * XXXX= container_of((struct delayed_work *)work,                                          struct XXXX_data, work);
static struct XXXXacc acc;
unsigned long delay = msecs_to_jiffies(atomic_read(&XXXX->delay));
XXXX _read_accel_xyz(XXXX-> XXXX _client, &acc);//读取数据
input_report_abs(XXXX->input, ABS_X, acc.x);  //上报数据
input_report_abs(XXXX->input, ABS_Y, acc.y);
input_report_abs(XXXX->input, ABS_Z, acc.z);
bma_dbg("acc.x %d, acc.y %d, acc.z %d\n", acc.x, acc.y, acc.z);
input_sync(XXXX->input);
mutex_lock(&XXXX->value_mutex);
XXXX ->value = acc;
mutex_unlock(&XXXX->value_mutex);
schedule_delayed_work(&XXXX->work, delay); //继续开始下一个工作队列
}

在上面代码中,调用XXXX _read_accel_xyz()方法读取Gsensor的三个数据,然后调用Input系统的接口函数input_report_abs()进行数据的上报。可以看到,当读取一次数据后,继续调用schedule_delayed_work()开始下一个工作队列,由此,功能函数XXXX_work_func()将会按照一个的频率被执行。
b) 那么对于HAL层,将通过/dev/input/event3设备节点读取到Gsensor数据。到此,Gsensor驱动的工作流程完毕。

(三) 模块的卸载XXXX_exit:i2c_del_driver(&XXXX_driver);

Gsensor的驱动流程 -- 基于IIC相关推荐

  1. STM32驱动MPU6050基于IIC协议

    一. 简介 MPU6050是一款六轴陀螺仪,可以通过IIC协议输出三个方向上的加速度和角速度,在平衡车和飞控中较为常见.一般情况下,模块有用的引脚只有四个(其它的不常用),即VCC,GND,SDA和S ...

  2. linux内核下网络驱动流程,基于Linux内核驱动的网络带宽测速方法与流程

    本发明涉及一种测速方法,尤其是一种网络带宽测速方法. 背景技术: :电信运营商为客户提供一定带宽的Internet接入:为了检验带宽是否达标,一般均由客户使用个人电脑在网页上直接测速.但是随着智能网关 ...

  3. 基于51单片机的OLED驱动方式(iic通讯方式)

    基于51单片机的OLED驱动方式(iic通讯方式) 前言: 本人从事硬件开发,自学软件,因为发现在学习过程中,有很多问题对于没有项目实战经验的新手来讲太难解决了,可以说基本上是无从下手.现将自己学习过 ...

  4. RA4M2开发(2)----基于IIC驱动OLED

    概述 在e2studio中创建新的工程并导入必要的文件,包括I2C驱动代码和SSD1306 OLED显示驱动代码. 配置RA4M2的I2C接口,使其作为I2C master进行通信. 初始化SSD13 ...

  5. linux mpc8313启动流程,基于MPC8313E和FPGA的双口RAM驱动开发

    摘要 以MPC8313E芯片为平台,介绍了一个基于嵌入式Linux探作系统的双口RAM设备驱动.通过该设备驱动搭建Linux服务器,利用缓存技术实时读取FPGA双口RAM数据,最终实现将海量图像数据高 ...

  6. 【嵌入式基础】基于IIC和SPI协议的温湿度采集与OLED显示

    本文主要介绍IIC总线通信协议和SPI协议,并使用STM32系列芯片基于IIC协议实现AHT20温湿度传感器上位机数据采集,基于SPI协议实现OLED显示. 目录 一.IIC总线通信协议 1.IIC协 ...

  7. 基于IIC的温度传感器实验

    基于IIC的温度传感器实验 一.IIC简介 二.硬件IIC与软件IIC的区别 三.实现I2CAHT20温湿度传感器的温度采集 1.AHT20简介 2.配置函数库,编写函数 1:下载驱动函数 2:修改相 ...

  8. 图像-摄像头驱动流程

    驱动架构 在Kernel层用camera的驱动将其驱动起来以后,将硬件驱动接口交给Hal: 上层的camera应用程序在andriod实时系统的虚拟机中,加载留给camera公用的库文 件,调用Hal ...

  9. MSP430杂谈--AD7745硬件IIC驱动与模拟IIC驱动

    和上一篇AD7793类似,项目中也涉及到利用AD7745读取电容值,来测环境湿度.编写了基于MSP430的AD7745的硬件IIC驱动和模拟IIC驱动,分享给大家. AD7745硬件IIC驱动完整版下 ...

最新文章

  1. leetcode 347. Top K Frequent Elements | 347. 前 K 个高频元素(大根堆)
  2. 不同路径 IIPython解法
  3. 双链表的基本操作---插入,删除,交,并,相邻元素的交换,不相邻元素的交换...
  4. 后端:Java中的BigDecimal类你了解多少?
  5. android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈
  6. java 外卖订餐系统_java外卖订餐系统小项目
  7. 吴恩达机器学习之逻辑回归理论部分
  8. spring配置数据源错误记录
  9. 一图看完双11阿里云原生技术亮点
  10. windows C++多线程(四):_beginthread的使用
  11. 喝酒必备神器微信小程序源码下载免服务器和域名带流量主收益
  12. 【运筹学】线性规划 单纯形法原理 ( 构造初始可行基 | 基变换 | 最优性检验 | 解的判别 | 检验数 | ( 唯一 / 无穷多 ) 最优解判别定理 | 无界解判别定理 )
  13. MySQL frm、MYD、MYI数据文件恢复
  14. 桌面IE图标删不掉解决方案
  15. 通过wvdial完成4G自动拨号上网
  16. windows能装linux系统盘,用U盘安装linux系统(Windows环境下制作启动盘)
  17. 用PHP查看微信撤回的消息,[笔记]使用itchat监听微信撤回消息
  18. 浅谈网站建设方案主要内容
  19. WEB页面登陆管理 H3C设备
  20. ubuntu软件包降级命令_如何在Ubuntu上降级软件包

热门文章

  1. LeetCode 面试题62. 圆圈中最后剩下的数字 详细题解
  2. 全球与中国胶原蛋白敷料市场深度研究分析报告
  3. 使用IDEA生成DOC文档
  4. Python技能树及 CSDN MarkDown编辑器测评
  5. 网格布局(固定单元格间隔,单元格、容器大小不定)布局使用
  6. 情人节程序员用HTML网页表白【在一起计时】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  7. 分享Visual Studio 2019专业版、企业版密匙
  8. 主语从句、宾语从句、表语从句、同位语从句
  9. python word 表格 框线_python-docx 操作word文档给表格加边框
  10. 二叉树 | 二叉树的镜像(翻转)