STMemsAndroidHAL分析

原创 2017年01月02日 21:21:35
一   代码结构图




二  代码分析

open_sensors

//创建 sensors_poll_context_t 实例
// sensors_poll_context_t 继承Android 定义的struct sensors_poll_device_t, 
//实现了Android hal 定义的必要的接口
//也是对sensor 实例操作的核心结构体
/** Open a new instance of a sensor device using name */
static int open_sensors(const struct hw_module_t* module,
            const char __attribute__((unused))*id,
            struct hw_device_t** device)
{
    int status = -EINVAL;

    //实例化两个结构体   SensorBase* mSensors[numSensorDrivers], struct pollfd mPollFds[numFds];
    //主要通过这两个结构体对hal sensor进行操作
    sensors_poll_context_t *dev = new sensors_poll_context_t();

    //以下是对hal 规定的比较的方法和变量进行初始化
    memset(&dev->device, 0, sizeof(SENSOR_POLL_DEVICE));

    dev->device.common.tag        = HARDWARE_DEVICE_TAG;
     ...
    dev->device.common.module    = const_cast<hw_module_t*>(module);
    dev->device.common.close    = poll__close;
    dev->device.activate        = poll__activate;
    dev->device.setDelay        = poll__setDelay;
    dev->device.poll            = poll__poll;


    *device = &dev->device.common;
    status = 0;

    return status;
}

//根据配置,实例华对应的sensor
//mSensors 是一个SensorBase的实例
//mPollFds 是一个pollfd结构,用来监听sensor
sensors_poll_context_t::sensors_poll_context_t()
{
#if (SENSORS_MAGNETIC_FIELD_ENABLE == 1)
    mSensors[magn] = new MagnSensor();
    mPollFds[magn].fd = mSensors[magn]->getFd();
    mPollFds[magn].events = POLLIN;
    mPollFds[magn].revents = 0;
#endif

#if (SENSORS_GYROSCOPE_ENABLE == 1)
    mSensors[gyro] = new GyroSensor();
    mPollFds[gyro].fd = mSensors[gyro]->getFd();
    mPollFds[gyro].events = POLLIN;
    mPollFds[gyro].revents = 0;
#endif
   ...... 
}

以gyro为例
//首先初始化SensorBase, SensorBase 主要是打开gyro 对应的文件,返回一个文件句柄data_fd,
GyroSensor::GyroSensor()
    : SensorBase(NULL, SENSOR_DATANAME_GYROSCOPE),
    mInputReader(6),文件句柄
    mHasPendingEvent(false)
{
    pthread_mutex_init(&dataMutex, NULL);

//首先初始化mPendingEvent, mPendingEvent 是sensors_event_t结构体,表示的是传感器的数据
#if (GYROSCOPE_GBIAS_ESTIMATION_FUSION == 0)
    mPendingEvent[Gyro].version = sizeof(sensors_event_t);
    mPendingEvent[Gyro].sensor = ID_GYROSCOPE;
    mPendingEvent[Gyro].type = SENSOR_TYPE_GYROSCOPE;
    mPendingEvent[Gyro].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
//好像是对gyro数据进行校准的
  #if ((SENSORS_UNCALIB_GYROSCOPE_ENABLE == 1) && (GYROSCOPE_GBIAS_ESTIMATION_STANDALONE == 1))
    mPendingEvent[GyroUncalib].version = sizeof(sensors_event_t);
    mPendingEvent[GyroUncalib].sensor = ID_UNCALIB_GYROSCOPE;
    mPendingEvent[GyroUncalib].type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED;
    mPendingEvent[GyroUncalib].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
  #endif
#endif

#if defined(STORE_CALIB_GYRO_ENABLED)
    pStoreCalibration = StoreCalibration::getInstance();
#endif

//判断sensor的节点文件是否存在
    if (data_fd) {的节点文件是否存在
        STLOGI("GyroSensor::GyroSensor gyro_device_sysfs_path:(%s)", sysfs_device_path);
    } else {
        STLOGE("GyroSensor::GyroSensor gyro_device_sysfs_path:(%s) not found", sysfs_device_path);
    }
//从driver获取到的原始数据
    memset(data_raw, 0, sizeof(data_raw));

//好像是对gyro数据进行校准的,会用到了iNemoEngine 和 AccelSensor对gyro进行校准
#if (GYROSCOPE_GBIAS_ESTIMATION_STANDALONE == 1)
    iNemoEngine_API_gbias_Initialization(NULL);
  #if (SENSORS_ACCELEROMETER_ENABLE == 1)
    acc = new AccelSensor();
  #endif
#endif
}

poll__activate

GyroSensor::enable
调用sensor的接口 writeEnable,writeDelay进行设置,这两个是linux input设备的概念。只有将enable节点设成1,才能从input event获取到数据。

3 poll


int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
    int nbEvents = 0;
    int n = 0;

    do {
        if (count) {
            n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
            if (n < 0) {
                STLOGE("poll() failed (%s)", strerror(errno));
                return -errno;
            }
        }
        for (int i=0 ; count && i<numSensorDrivers ; i++) {
            SensorBase* const sensor(mSensors[i]);
            if((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents()))
            {
                //通过readEvents去获取event数据
                int nb = sensor->readEvents(data, count);
                if (nb < count) {
                    mPollFds[i].revents = 0;
                }
                count -= nb;
                nbEvents += nb;
                data += nb;
            }
        }
#if (ANDROID_VERSION >= ANDROID_JBMR2)
        if(mPollFds[flushFD].revents & POLLIN && count) {
            if (read(mPollFds[flushFD].fd, data, sizeof(struct sensors_event_t)) > 0) {
                count--;
                nbEvents++;
                data++;
            }
            mPollFds[flushFD].revents = 0;
        }
#endif
    } while (n && count);

    return nbEvents;
}

主要看GyroSensor::readEvents(
int GyroSensor::readEvents(sensors_event_t* data, int count)
{
    if (count < 1)
        return -EINVAL;

    if (mHasPendingEvent) {
        mHasPendingEvent = false;
    }

    ssize_t n = mInputReader.fill(data_fd);
    if (n < 0)
        return n;

    int numEventReceived = 0;
    input_event const* event;

#if (FETCH_FULL_EVENT_BEFORE_RETURN)
    again:
#endif

    while (count && mInputReader.readEvent(&event)) {
        
        if (event->type == EVENT_TYPE_GYRO) {
           //每次循环,分别读取event里面的  x, y, z 和timestamp数据
#if (DEBUG_GYROSCOPE == 1)
    STLOGD("GyroSensor::readEvents (event_code=%d)", event->code);
#endif

            float value = (float) event->value;
            if (event->code == EVENT_TYPE_GYRO_X) {
                data_raw[0] = value * CONVERT_GYRO_X;
            }
            else if (event->code == EVENT_TYPE_GYRO_Y) {
                data_raw[1] = value * CONVERT_GYRO_Y;
            }
            else if (event->code == EVENT_TYPE_GYRO_Z) {
                data_raw[2] = value * CONVERT_GYRO_Z;
            }
#if defined(GYRO_EVENT_HAS_TIMESTAMP)
            else if (event->code == EVENT_TYPE_TIME_MSB) {
                timestamp = ((int64_t)(event->value)) << 32;
            }
            else if (event->code == EVENT_TYPE_TIME_LSB) {
                timestamp |= (uint32_t)(event->value);
            }
#endif
            else {
                STLOGE("GyroSensor: unknown event code (type = %d, code = %d)", event->type, event->code);
            }
        } else if (event->type == EV_SYN) {
            //当收到EV_SYN,表示一次对sensor的数据已经读取完,接下来会对sensor数据进行处理,gyro数据处理将另外介绍
           ...
            //最后会将数据返回到data
            *data++ = mPendingEvent[Gyro];
        }
          


DUMP文件分析2:一个最简单的DUMP分析示例

本节开始,我将在示例中给大家讲述基本的DUMP文件分析方法。读者应该对Windows系统比较了解,同时比较熟悉Windbg。 本节的示例非常简单,也非常经典,就是常常会遇到的访问空指针。Window...
  • hustd10
  • hustd10
  • 2016年07月30日 21:53
  • 8687

浅谈Core文件分析

由于计算机程序问题的发生是随机的,为了给定位问题提供一个接口,一些人发明了在发生问题后将内存中的进程相关信息格式化地保存在一个文件中的手段,以便于在发生问题而中断了进程的执行后,通过内存信息转储文件得...
  • fan9511
  • fan9511
  • 2014年07月23日 14:05
  • 1369

如何进行堆栈分析

1.平常会遇到程序卡的时间很久,不知道shenm
  • hekang1011
  • hekang1011
  • 2014年09月24日 23:09
  • 897

针对Oracle大表执行表分析

报表数据库相当于一个数据仓库,数据量一般来说都比较大,这个时候性能就要特别注意。为了促使Oracle选择最优的执行计划,最好定期进行表分析,以使oracle得到正确的统计信息。一般如果数据分布和表结构...
  • anttu
  • anttu
  • 2017年05月21日 17:23
  • 2879

指南:分析类

分析类分析类代表“系统中具备职责和行为的事物”的初期概念模型。这些概念模型最终将演进为设计模型中的类和子系统。主题分析类的构造型 边界类 控制类 实体类 关联关系限制 边界类限制 控制类限制 实体类限...
  • luckisok
  • luckisok
  • 2005年10月14日 21:33
  • 2509

陶哲轩实分析-第3章-集合论-4-6

陶哲轩实分析笔记与习题答案
  • buck84
  • buck84
  • 2016年05月08日 20:48
  • 1038

Oracle-表分析和索引分析解读

概述当表没有做分析的时候,Oracle 会使用动态采样来收集统计信息。 获取准确的段对象(表,表分区,索引等)的分析数据,是CBO存在的基石,CBO的机制就是收集尽可能多的对象信息和系统信息,通过对这...
  • yangshangwei
  • yangshangwei
  • 2016年12月01日 23:16
  • 7188

深入分析JVM逃逸分析对性能的影响

逃逸分析(Escape Analysis)逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,称为方法逃逸。甚至还有可能被外部线程访问到,譬如赋值给类变量或可...
  • jijianshuai
  • jijianshuai
  • 2017年06月26日 14:53
  • 437

敏感性分析

敏感性分析是投资项目的经济评价中常用的一种研究不确定性的方法。它在确定性分析的基础上,进一步分析不确定性因素对投资项目的最终经济效果指标的影响及影响程度。...
  • u013083076
  • u013083076
  • 2014年04月24日 21:38
  • 1515

独立成分分析及Demo

独立成分分析
  • hit1524468
  • hit1524468
  • 2017年03月05日 12:03
  • 953
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STMemsAndroidHAL分析
举报原因:
原因补充:

(最多只允许输入30个字)