本文转载自:http://blog.csdn.net/u012296694/article/details/48055491

本文主要描述了在android2.3平台G-sensor相关软硬件的体系架构和实现原理,按照Applications、Framework、HAL、Driver和Hardware五大层次分别介绍。

1.系统架构 (Architecture)

1.1 Android体系架构图

 

1.2 Sensor子系统架构图

· Application Framework

Sensor应用程序通过Sensor应用框架来获取sensor数据,应用框架层的Sensor Manager通过JNI与C++层进行通信。

· Sensor Libraries

Sensor中间层主要由Sensor Manager、Sensor service和Sensor硬件抽象层组成。

· Input Subsystem

通用的Linux输入框架专为与键盘、鼠标和触摸屏等输入设备而设计,并定义了一套标准事件集合。Sensor输入子系统采用采用了通用的Linux输入框架,它通过/sys/class/input节点和用户空间进行交互。

· Event Dev

Evdev提供了一种访问/dev/input/eventX输入设备事件的通用方法。

· AccelerometerDriver

此驱动通过SIRQ和I2C总线与MMA7660模组进行通信。SIRQ用来产生传感器事件中断。

2 应用 (Applications)

2.1 应用开发五步曲

(1)   获取传感器管理器对象;

mSensorManager =(SensorManager) getSystemService(SENSOR_SERVICE);

(2)   获取传感器对象;

mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

(3)  定义事件监听器;

mEventListener =new SensorEventListener() {

  1. @Override
  2. publicvoid onSensorChanged(SensorEvent event) {
  3. float[] values = event.values;
  4. mTextView.setText("Accelerometer:" + values[0] +", "
  5. + values[1] +", " + values[2]);
  6. }
  7. @Override
  8. publicvoidonAccuracyChanged(Sensor sensor,int accuracy) {
  9. }

(4)   注册事件监听器;

protectedvoid onResume() {

  1. super.onResume();
  2. mSensorManager.registerListener(mEventListener, mSensor,
  3. SensorManager.SENSOR_DELAY_NORMAL);

(5)   卸载事件监听器;

protectedvoid onPause() {

  1. super.onPause();
  2. mSensorManager.unregisterListener(mEventListener);
3 框架 (Framework)

3.1 工作模型

 

3.1.1 SensorManager的创建

 
nativeClassInit(): 初始化Native类信息;
sensors_module_init(): 创建Native SensorManager实例,从SensorService读取Sensor设备列表;
sensors_module_get_next_sensor(): 从SensorService读取下一个Sensor设备;
 

3.1.2 SensorThread数据接收处理

 
sensors_create_queue(): 创建和SensorService共享的消息队列;
sensors_data_poll(): 从消息队列中读取SensorService发过来的消息;
 

3.1.3 SensorService的工作原理

 
SensorDevice::poll(): 调用HAL接口读取数据;
SensorEventConnection::sendEvents(): 往消息队列中写入消息,SensorThread后续会读取该消息;
 

3.1.4 SensorDevice对HAL的访问

4 硬件抽象层 (HAL)

在linux操作系统中,应用同硬件之间的交互都是通过设备驱动来实现,Android系统为了降低应用开发人员开发难度,屏蔽硬件差异,定义出硬件抽象层,为开发人员提供获取各种设备相关的信息的接口。

4.1 Sensors HAL关键流程

4.1.1 打开Sensor设备

SensorBase ::openInput() : 打开input子系统的sensor消息文件句柄;
ioctl(EVIOCGABS(...)) : 获取ABS_X/ABS_Y/ABS_Z的加速度;
 

4.1.2 轮循Sensor事件

InputEventCircularReader::fill(): 调用read()从input子系统中读取事件放入环形缓冲区;
InputEventCircularReader::readEvent(): 从环形缓冲区中读取事件;
InputEventCircularReader::next(): 移动环形缓冲区当前指针;
 
5.2 Sensors HAL关键数据结构

5.2.1 sensors_module_t

  1. struct sensors_module_t {
  2. struct hw_module_t common;
  3. /**
  4. * Enumerate all available sensors. The list is returned in "list".
  5. * @return number of sensors in the list
  6. */
  7. int (*get_sensors_list)(struct sensors_module_t* module,
  8. struct sensor_t const** list);
  9. };

hw_get_module()会加载HAL模块,并返回HAL入口数据结构(hw_module_t)。HAL_MODULE_INFO_SYM默认是“HAL”,在hw_get_module中用dlsym获取。

  1. const struct sensors_module_t HAL_MODULE_INFO_SYM = {
  2. .common = {
  3. .tag = HARDWARE_MODULE_TAG,
  4. .version_major = 1,
  5. .version_minor = 0,
  6. .id = SENSORS_HARDWARE_MODULE_ID,
  7. .name = "MMA7660 Sensors Module",
  8. .author = "The Android Open Source Project",
  9. .methods = &sensors_module_methods,
  10. },
  11. .get_sensors_list = sensors__get_sensors_list
  12. };

5.2.2 hw_module_methods_t

 static struct hw_module_methods_t sensors_module_methods = {

  1. .open = open_sensors

5.2.3 sensors_poll_context_t

  1. struct sensors_poll_context_t {
  2. struct sensors_poll_device_t device; // must be first
  3. sensors_poll_context_t();
  4. ~sensors_poll_context_t();
  5. int activate(int handle, int enabled);
  6. int setDelay(int handle, int64_t ns);
  7. int pollEvents(sensors_event_t* data, int count);
  8. int handleToDriver(int handle);
  9. };

5.2.4 sensors_poll_device_t

 
  1. struct sensors_poll_device_t {
  2. struct hw_device_t common;
  3. int (*activate)(struct sensors_poll_device_t *dev,
  4. int handle, int enabled);
  5. int (*setDelay)(struct sensors_poll_device_t *dev,
  6. int handle, int64_t ns);
  7. int (*poll)(struct sensors_poll_device_t *dev,
  8. sensors_event_t* data, int count);
  9. };

5.2.5 sensor_t

定义传感器的基本参数。

  1. static const struct sensor_t sSensorList[] = {
  2. { "MMA7660 3-axis Accelerometer",
  3. "Freescale Semiconductor",
  4. 1, SENSORS_HANDLE_BASE+ID_A,
  5. SENSOR_TYPE_ACCELEROMETER, 3.0f*9.81f, (3.0f*9.81f)/64.0f, 0.35f, 0, { } },
  6. };
  1. struct sensor_t {
  2. const char*     name;
  3. const char*     vendor;
  4. int             version;
  5. int             handle;
  6. int             type;
  7. float           maxRange;
  8. float           resolution;
  9. float           power;
  10. int32_t         minDelay;
  11. void*           reserved[8];
  12. };

6 驱动 (driver)

6.1 mma7660驱动框架

mma7660与主机通信是通过I2C接口,因此mma7660驱动程序采用Linux系统的I2C子系统框架来实现,主要由3部分组成:
 
(1) I2C核心
I2C核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即“algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。这部分是与平台无关的。
此部分在Linux内核的I2C驱动中实现,mma7660驱动使用其提供的功能接口来注册设备驱动。

(2) I2C总线驱动
I2C总线驱动是对I2C硬件体系结构中适配器端的实现。I2C总线驱动主要包含了I2C适配器数据结构i2c_adapter、I2C适配器的algorithm数据结构i2c_algorithm和控制I2C适配器产生通信信号的函数。经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。不同的CPU平台对应着不同的I2C总线驱动。
此部分在Linux内核的I2C驱动中实现,mma7660驱动直接获取其提供的adapter,并调用I2C核心的接口来注册。

(3) I2C设备驱动
I2C设备驱动是对I2C硬件体系结构中设备端的实现。设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。I2C设备驱动主要包含了数据结构i2c_driver和i2c_client,mma7660驱动需要实现其中的成员函数。
在Linux内核源代码中的drivers目录下的i2c_dev.c文件,实现了I2C适配器设备文件的功能,应用程序通过“i2c-%d”文件名并使用文件操作接口open()、write()、read()、ioctl()和close()等来访问这个设备。应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器并控制I2C设备的工作方式。

6.2 mma7660操作流程

6.2.1 初始化

6.2.2 探测设备

 

6.2.3 移除设备

 

6.2.4 采集数据

 

6.2.5 睡眠和唤醒

Suspend处理:关闭mma7660模组;
Resume处理:使能mma7660模组;

  1. static int mma7660_suspend(struct i2c_client *client, pm_message_t mesg)
  2. {
  3. int result;
  4. result = i2c_smbus_write_byte_data(client, MMA7660_MODE,
  5. MK_MMA7660_MODE(0, 0, 0, 0, 0, 0, 0));
  6. assert(result==0);
  7. return result;
  8. }
  9. static int mma7660_resume(struct i2c_client *client)
  10. {
  11. int result;
  12. result = i2c_smbus_write_byte_data(client, MMA7660_MODE,
  13. MK_MMA7660_MODE(0, 1, 0, 0, 0, 0, 1));
  14. assert(result==0);
  15. return result;
  16. }
  17. static struct i2c_driver mma7660_driver = {
  18. .driver = {
  19. .name = MMA7660_DRV_NAME,
  20. .owner = THIS_MODULE,
  21. },
  22. .class = I2C_CLASS_HWMON,
  23. .suspend = mma7660_suspend,
  24. .resume = mma7660_resume,
  25. .probe = mma7660_probe,
  26. .detect = mma7660_detect,
  27. //  .address_data = &addr_data,
  28. .remove = __devexit_p(mma7660_remove),
  29. .id_table = mma7660_id,
  30. };

6.3 命令行调试

6.3.1 sysfs调试接口

(1) 定义sysfs attribute相关数据结构;

  1. static SENSOR_DEVICE_ATTR(all_axis_force, S_IRUGO, show_xyz_force, NULL, 0);
  2. static SENSOR_DEVICE_ATTR(x_axis_force, S_IRUGO, show_axis_force, NULL, 0);
  3. static SENSOR_DEVICE_ATTR(y_axis_force, S_IRUGO, show_axis_force, NULL, 1);
  4. static SENSOR_DEVICE_ATTR(z_axis_force, S_IRUGO, show_axis_force, NULL, 2);
  5. static SENSOR_DEVICE_ATTR(orientation, S_IRUGO, show_orientation, NULL, 0);
  6. static struct attribute* mma7660_attrs[] =
  7. {
  8. &sensor_dev_attr_all_axis_force.dev_attr.attr,
  9. &sensor_dev_attr_x_axis_force.dev_attr.attr,
  10. &sensor_dev_attr_y_axis_force.dev_attr.attr,
  11. &sensor_dev_attr_z_axis_force.dev_attr.attr,
  12. &sensor_dev_attr_orientation.dev_attr.attr,
  13. NULL
  14. };
  15. static const struct attribute_group mma7660_group =
  16. {
  17. .attrs = mma7660_attrs,
  18. };

(2) 在probe函数中创建sysfs文件系统;

  1. result = sysfs_create_group(&client->dev.kobj, &mma7660_group);
  2. if (result != 0) {
  3. ERR("sysfs_create_group err\n");
  4. goto exit_sysfs_creat_failed;
  5. }

(3) 实现sysfs属性相关的读写函数;

  1. ssize_t show_orientation(struct device *dev, struct device_attribute *attr, char *buf)
  2. {
  3. int result;
  4. u8 tilt, new_orientation;
  5. mma7660_read_tilt(&tilt);
  6. DBG("tilt [0x%x]\n", tilt);
  7. new_orientation = tilt & 0x1f;
  8. if (orientation!=new_orientation)
  9. orientation = new_orientation;
  10. switch ((orientation>>2)&0x07) {
  11. case 1:
  12. result = sprintf(buf, "Left\n");
  13. break;
  14. case 2:
  15. result = sprintf(buf, "Right\n");
  16. break;
  17. case 5:
  18. result = sprintf(buf, "Downward\n");
  19. break;
  20. case 6:
  21. result = sprintf(buf, "Upward\n");
  22. break;
  23. default:
  24. switch(orientation & 0x03) {
  25. case 1:
  26. result = sprintf(buf, "Front\n");
  27. break;
  28. case 2:
  29. result = sprintf(buf, "Back\n");
  30. break;
  31. default:
  32. result = sprintf(buf, "Unknown\n");
  33. }
  34. }
  35. return result;
  36. }
  1. ssize_t show_xyz_force(struct device *dev, struct device_attribute *attr, char *buf)
  2. {
  3. int i;
  4. s8 xyz[3];
  5. for (i=0; i<3; i++)
  6. mma7660_read_xyz(i, &xyz[i]);
  7. return sprintf(buf, "(%d,%d,%d)\n", xyz[0], xyz[1], xyz[2]);
  8. }
  9. ssize_t show_axis_force(struct device *dev, struct device_attribute *attr, char *buf)
  10. {
  11. s8 force;
  12. int n = to_sensor_dev_attr(attr)->index;
  13. mma7660_read_xyz(n, &force);
  14. return sprintf(buf, "%d\n", force);
  15. }

6.3.2 Gsensor调试实例

  1. /sys/devices/platform/gl5201-i2c.1/i2c-1/1-004c # ls
  2. uevent
  3. name
  4. modalias
  5. subsystem
  6. power
  7. driver
  8. all_axis_force
  9. x_axis_force
  10. y_axis_force
  11. z_axis_force
  12. orientation
  13. input
  14. /sys/devices/platform/gl5201-i2c.1/i2c-1/1-004c # cat all_axis_force
  15. (-1,0,22)
 

7 Hardware

7.1 mma7660模组

7.2 关键特性
  • Sampling Resolution: 6bit
  • Digital Output (I2C)
  • 3mm x 3mm x 0.9mm DFN Package
  • Low Power Current Consumption:

Off Mode: 0.4 μA,
    Standby Mode: 2 μA, 
    Active Mode: 47 μA at 1 ODR

  • Configurable Samples per Second from 1 to 120 samples
  • Low Voltage Operation:

Analog Voltage: 2.4 V - 3.6 V
    Digital Voltage: 1.71 V - 3.6 V

  • Auto-Wake/Sleep Feature for Low Power Consumption
  • Tilt Orientation Detection for Portrait/Landscape Capability
  • Gesture Detection Including Shake Detection and Tap Detection

7.2.1 功能模块图

7.2.2 硬件连接图

7.2.3 运动检测原理

mma7660是一种电容式3轴g-sensor,其技术原理是在wafer的表面做出梳状结构,当产生动作时,由侦测电容差来判断变形量,反推出加速度的值。
简单物理模型如下图:

7.2.4 I2C读写时序

7.2.5 工作状态机

7.2.6 寄存器定义

7.2.7 事件检测

  • 方向和摇动检测
  • 轻拍或倾斜检测

gsensor架构和原理分析【转】的更多相关文章

  1. Apache Flink:特性、概念、组件栈、架构及原理分析

     2016-04-30 22:24:39    Yanjun Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时(Flink Runtim ...

  2. CDN架构以及原理分析

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp61  在不同地域的用户访问网站的响应速度存在差异,为了提高用户访问的响应 ...

  3. NVIDIA GPU架构与原理分析(一)——GPU简介与主流Fermi、Kepler架构GPU概述

    1 GPU简介 图形处理单元GPU英文全称Graphic Processing Unit,GPU是相对于CPU的一个概念,NVIDIA公司在1999年发布GeForce256图形处理芯片时首先提出GP ...

  4. Ceph 架构以及原理分析

    一.架构 Ceph在一个统一的系统中独特地提供对象,块和文件存储. Ceph高度可靠,易于管理且免费. Ceph的强大功能可以改变您公司的IT基础架构以及管理大量数据的能力. Ceph提供了非凡的可扩 ...

  5. dubbo源码解析五 --- 集群容错架构设计与原理分析

    欢迎来我的 Star Followers 后期后继续更新Dubbo别的文章 Dubbo 源码分析系列之一环境搭建 博客园 Dubbo 入门之二 --- 项目结构解析 博客园 Dubbo 源码分析系列之 ...

  6. springMVC课程笔记(一)springMVC架构原理分析

    一.springMVC架构原理分析 1.先搞清楚什么是springMVC: 其实springMVC是spring框架中的一个模块,springMVC和spring无需通过中间整合层整合,SpringM ...

  7. 爱莲(iLinkIT)的架构与原理

    随着移动互联网时代的到来,手机正在逐步替代其他的设备,手机是电话.手机是即时通讯,手机是相机,手机是导航仪,手机是钱包,手机是音乐播放器……. 除此之外,手机还是一个大大的U盘,曾几何时,我们用一根长 ...

  8. memcache分布式部署的原理分析

    下面本文章来给各位同学介绍memcache分布式部署的原理分析,希望此文章对你理解memcache分布式部署会有所帮助哦.   今天在封装memcache操作类库过程中,意识到一直以来对memcach ...

  9. HTML5 移动应用开发环境搭建及原理分析

    开发环境搭建: 一.Android 开发平台搭建 安装java jdk:\\10.194.151.132\Mewfile\tmp\ADT 配置java jdk 1)  新建系统变量,JAVA_HOME ...

随机推荐

  1. C++ 类学习笔记 :: 作用域限定符

    类与封装的概念: 1.类: 类的实现.类的使用. 当使用类的时候,不需要关心实现的细节.当创建类的时候,才需要考虑到内部具体的实现细节. 2.类的封装: 成员变量,C++用于表示属性的变量. 成员函数 ...

  2. jquery判断 input type="file"上传文件是否为空

    要想获取type="file"的input内容,用var file = $("id").val();肯定是不行的,下面是代码: html上传按钮为: <i ...

  3. 深入理解java虚拟机(1)走进jvm

    1.JDK:java程序设计语言.java虚拟机.javaAPI 二.自动内存管理机制 ----------------------------------------------------- 1. ...

  4. element-ui 中 switch 开关绑定number 的解决方法

    虽然element-ui 的文档中说明 v-model的值可以是 boolean / string / number 三种类型 , (文档在此)https://element.eleme.cn/#/z ...

  5. drf三大认证解析

    目录 三大认证 认证模块: 权限模块 频率模块 RABC author组件 认证权限六表. Content_type 认证与权限工作原理+自定义认证类 自定义权限类 admin关联自定义用户表 前后台 ...

  6. js 动态生成表格案例

    <1>布局:一个table表格,表格分为两个部分,上面是thead表头,表头里面仅一行,有4列(th),   下面是tbody表格内容,要求tbody中的每一行都是用js动态创建的 < ...

  7. Python杂章

    IDLE常用的快捷键: Ctrl+]:缩进代码 Ctrl+[:取消缩进 Alt+3:注释代码 Alt+4:去掉注释 F5:运行代码 Ctrl+Z:撤销一步 print('你好,Python!')

  8. hdu 6205 card card card 最大子段和

    #include<iostream> #include<deque> #include<memory.h> #include<stdio.h> #inc ...

  9. 移动端适配 后篇(rem+vm)

    涉及到的一些名词, 详细解释可参考 移动端适配前篇--移动端适配 rem 名词解释 [英寸Inch]英寸表示屏幕斜对角线的长度 [像素Pixel]像素是图像的基本采样单位,它不是一个确定的物理量,因为 ...

  10. Codeforces Round #593 (Div. 2) C. Labs

    题目:https://codeforces.com/contest/1236/problem/C 思路:将 n ^ 2 个 lab 平分为 n 个 group group A 和 B 组成的 有序对 ...