Android驱动开发之陀螺仪(三)

news/2025/1/11 14:29:56/

Android驱动开发之陀螺仪(二)

 

五、安卓hal层驱动数据读取

使能陀螺仪后,由于我配置的是原始数据准备中断,所以陀螺仪数据一旦准备好,就会发送中断信号,之前在第二章已经分析过中断的注册流程,这里就直接上代码了。

irqreturn_t inv_read_fifo(int irq, void *dev_id)
{struct inv_mpu_state *st = (struct inv_mpu_state *)dev_id;struct iio_dev *indio_dev = iio_priv_to_dev(st);int result, bpm,i;u8 Adata[BYTES_PER_SENSOR],Gdata[BYTES_PER_SENSOR],Mdata[BYTES_PER_SENSOR],data[1];u16 fifo_count;struct inv_reg_map_s *reg;u64 pts1;if (!(iio_buffer_enabled(indio_dev)) || (!st->chip_config.enable)){if (!(iio_buffer_enabled(indio_dev))){PRINT_ERR("++++++iio_buffer_enabled end_session : %d+++++\n",st->chip_config.enable);goto end_session;}reg = &st->reg;if (st->sensor[SENSOR_ACCEL].on) {result = inv_i2c_read(st, reg->raw_accel,BYTES_PER_SENSOR, Adata);if (result)goto end_session;}if (st->sensor[SENSOR_GYRO].on) {result = inv_i2c_read(st, reg->raw_gyro,BYTES_PER_SENSOR, Gdata);if (result)goto end_session;}if (st->sensor[SENSOR_COMPASS].on) {result = inv_secondary_read(0x02, 1 , data);if (result){goto end_session;}if(!(data && 0x01))goto end_session;result = inv_secondary_read(0x03,BYTES_PER_SENSOR, Mdata);if (result)goto end_session;result = inv_secondary_read(0x09, 1 , data);if (result)goto end_session;inv_report_gyro_accel(indio_dev, Adata, Gdata, Mdata, get_time_ns());goto end_session;end_session:inv_process_motion(st);return IRQ_HANDLED;
}

Android 安卓层陀螺仪流程分析这里是中断函数的实现,一开始先判断标志位是否使能,然后根据开启的模块读取相应的数据,最后调用inv_report_gyro_accel这个函数。

static int inv_report_gyro_accel(struct iio_dev *indio_dev,u8 *adata,u8 *gdata,u8 *mdata, s64 t)
{struct inv_mpu_state *st = iio_priv(indio_dev);short s[THREE_AXIS];int ind;int i;ind = 0;if (st->sensor[SENSOR_ACCEL].on) {for (i = 0; i < 3; i++)s[i] = be16_to_cpup((__be16 *)(&adata[ind + i * 2]));inv_push_8bytes_buffer(st, ACCEL_HDR, t, s);}if (st->sensor[SENSOR_GYRO].on) {for (i = 0; i < 3; i++)s[i] = be16_to_cpup((__be16 *)(&gdata[ind + i * 2]));inv_push_8bytes_buffer(st, GYRO_HDR, t, s);}if (st->sensor[SENSOR_COMPASS].on) {for (i = 0; i < 3; i++)s[i] = mdata[i*2] | (mdata[i*2+1] << 8);inv_push_8bytes_buffer(st, COMPASS_HDR, t, s);}return 0;
}
static int inv_push_8bytes_buffer(struct inv_mpu_state *st, u16 hdr,u64 t, s16 *d)
{struct iio_dev *indio_dev = iio_priv_to_dev(st);u8 buf[IIO_BUFFER_BYTES];int i;memcpy(buf, &hdr, sizeof(hdr));for (i = 0; i < 3; i++)memcpy(&buf[2 + i * 2], &d[i], sizeof(d[i]));iio_push_to_buffers(indio_dev, buf);memcpy(buf, &t, sizeof(t));iio_push_to_buffers(indio_dev, buf);return 0;
}

接着调用iio_push_to_buffers()这个将buf里的数据写到设备节点。

han层又是如果接收这个数据的呢

这就要回到之前第四章所要关注的第二个接口-----poll__poll()

static int poll__poll(struct sensors_poll_device_t *dev,sensors_event_t* data, int count)
{sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;return ctx->pollEvents(data, count);
}
int sensors_poll_context_t::pollEvents(sensors_event_t *data, int count)
{VHANDLER_LOG;int nbEvents = 0;int nb, polltime = -1;polltime = ((MPLSensor*) mSensor)->getStepCountPollTime();nb = poll(mPollFds, numSensorDrivers, polltime);if (nb > 0) {LOGI("poll nb=%d, count=%d, pt=%d\n", nb, count, polltime);for (int i = 0; count && i < numSensorDrivers; i++) {if (mPollFds[i].revents & (POLLIN | POLLPRI)) {nb = 0;if (i == mpl) {LOGI("HAL: buildMpuEvent start\n");((MPLSensor*) mSensor)->buildMpuEvent();mPollFds[i].revents = 0;} else if (i == compass) {LOGI("HAL: buildCompassEvent\n");((MPLSensor*) mSensor)->buildCompassEvent();mPollFds[i].revents = 0;}#if 1if(nb == 0) {nb = ((MPLSensor*) mSensor)->readEvents(data, count);LOGI("sensors_mpl:readEvents() - ""i=%d, nb=%d, count=%d, nbEvents=%d, ""data->timestamp=%lld, data->data[0]=%f,",i, nb, count, nbEvents, data->timestamp, data->data[0]);if (nb > 0) {count -= nb;nbEvents += nb;data += nb;}}#endif}}/* to see if any step counter events */if(((MPLSensor*) mSensor)->hasStepCountPendingEvents() == true) {nb = 0;nb = ((MPLSensor*) mSensor)->readDmpPedometerEvents(data, count, ID_SC, SENSOR_TYPE_STEP_COUNTER, 0);LOGI("sensors_mpl:readStepCount() - ""nb=%d, count=%d, nbEvents=%d, data->timestamp=%lld, ""data->data[0]=%f,",nb, count, nbEvents, data->timestamp, data->data[0]);if (nb > 0) {count -= nb;nbEvents += nb;data += nb;}}} else if(nb == 0) {/* to see if any step counter events */if(((MPLSensor*) mSensor)->hasStepCountPendingEvents() == true) {nb = 0;nb = ((MPLSensor*) mSensor)->readDmpPedometerEvents(data, count, ID_SC, SENSOR_TYPE_STEP_COUNTER, 0);LOGI("sensors_mpl:readStepCount() - ""nb=%d, count=%d, nbEvents=%d, data->timestamp=%lld, ""data->data[0]=%f,",nb, count, nbEvents, data->timestamp, data->data[0]);if (nb > 0) {count -= nb;nbEvents += nb;data += nb;}}if (mPollFds[numSensorDrivers].revents & POLLIN) {char msg;int result = read(mPollFds[numSensorDrivers].fd, &msg, 1);LOGE("error reading from wake pipe (%s)", strerror(errno));mPollFds[numSensorDrivers].revents = 0;}}return nbEvents;
}

app开启陀螺仪功能之后,就通过这个接口轮询sensor事件,一旦设备节点有数据传递过来,会被poll()捕获。

nb = poll(mPollFds, numSensorDrivers, polltime);
                if (i == mpl) {LOGI("HAL: buildMpuEvent start\n");((MPLSensor*) mSensor)->buildMpuEvent();mPollFds[i].revents = 0;} else if (i == compass) {LOGI("HAL: buildCompassEvent\n");((MPLSensor*) mSensor)->buildCompassEvent();mPollFds[i].revents = 0;}

捕获到数据后,若是加速度和角加速度,则调用buildMpuEvent(),若是磁场,则调用buildCompassEvent()。

这里就举例分析加速度吧,都一样的原理。

void MPLSensor::buildMpuEvent(void)
{VHANDLER_LOG;LOGI("HAL:enter buildMpuEvent:%d\n",mLeftOverBufferSize);mSkipReadEvents = 0;int64_t mGyroSensorTimestamp=0, mAccelSensorTimestamp=0, latestTimestamp=0;int lp_quaternion_on = 0, sixAxis_quaternion_on = 0,ped_quaternion_on = 0, ped_standalone_on = 0;size_t nbyte;unsigned short data_format = 0;int i, nb, mask = 0,sensors = 3;char *rdata = mIIOBuffer;ssize_t rsize = 0;size_t readCounter = 0;char *rdataP = NULL;/* 2 Bytes header + 6 Bytes x,y,z data | 8 bytes timestamp */nbyte= (BYTES_PER_SENSOR + 8) * sensors * 1;/* special case for 6 Axis or LPQ *//* 2 Bytes header + 4 Bytes x data + 2 Bytes n/a *//* 4 Bytes y data | 4 Bytes z data *//* 8 Bytes timestamp */if (mLeftOverBufferSize > 0) {LOGI("append old buffer size=%d", mLeftOverBufferSize);memcpy(rdata, mLeftOverBuffer, mLeftOverBufferSize);LOGI("HAL:input retrieve rdata=:%d, %d, %d, %d,%d, %d, %d, %d,%d, %d, ""%d, %d,%d, %d, %d, %d\n",rdata[0], rdata[1], rdata[2], rdata[3],rdata[4], rdata[5], rdata[6], rdata[7],rdata[8], rdata[9], rdata[10], rdata[11],rdata[12], rdata[13], rdata[14], rdata[15]);}rdataP = rdata + mLeftOverBufferSize;/* read expected number of bytes */rsize = read(iio_fd, rdataP, nbyte);LOGV("HAL:input data read iio_fd = %d", rsize);if(rsize < 0) {/* IIO buffer might have old data.Need to flush it if no sensor is on, to avoid infiniteread loop.*/LOGE("HAL:input data file descriptor not available - (%s)",strerror(errno));if (sensors == 0) {rsize = read(iio_fd, rdata, MAX_SUSPEND_BATCH_PACKET_SIZE);}return;}
#if 1if((rsize + mLeftOverBufferSize) == 8) {/* store packet then return */memcpy(mLeftOverBuffer, rdataP, rsize);mLeftOverBufferSize += rsize;LOGV_IF(1, "HAL:input data has partial packet");LOGV("HAL:input catch up retrieve rdata=:%d, %d, %d, %d, %d, %d, %d, %d",mLeftOverBuffer[0], mLeftOverBuffer[1], mLeftOverBuffer[2], mLeftOverBuffer[3],mLeftOverBuffer[4], mLeftOverBuffer[5], mLeftOverBuffer[6], mLeftOverBuffer[7]);mSkipReadEvents = 1;return;}LOGV("HAL:input data mLeftOverBufferSize=%d", mLeftOverBufferSize);
#endif/* reset data and count pointer */rdataP = rdata;readCounter = rsize + mLeftOverBufferSize;while (readCounter > 0) {// since copied buffer is already accounted for, reset left over sizemLeftOverBufferSize = 0;// clear data format mask for parsing the next set of datamask = 0;data_format = *((short *)(rdata));LOGV("HAL:input data_format = %d", data_format);LOGV("HAL:input readCounter = %d", readCounter);LOGV_IF(INPUT_DATA && ENG_VERBOSE,"HAL:input data_format=%x", data_format);if ((data_format & ~DATA_FORMAT_MASK) || (data_format == 0)) {LOGE("HAL:input invalid data_format 0x%02X", data_format);return;}if (data_format & DATA_FORMAT_STEP) {if (data_format == DATA_FORMAT_STEP) {rdata += BYTES_PER_SENSOR;latestTimestamp = *((long long*) (rdata));LOGV_IF(ENG_VERBOSE, "STEP DETECTED:0x%x - ts: %lld", data_format, latestTimestamp);// readCounter is decrement by 24 because DATA_FORMAT_STEP only applies in batch  modereadCounter -= BYTES_PER_SENSOR_PACKET;} else {LOGV_IF(0, "STEP DETECTED:0x%x", data_format);}mPedUpdate |= data_format;mask |= DATA_FORMAT_STEP;// cancels step bitdata_format &= (~DATA_FORMAT_STEP);}if (data_format & DATA_FORMAT_MARKER) {LOGV_IF(ENG_VERBOSE, "MARKER DETECTED:0x%x", data_format);// cancels marker bitdata_format &= (~DATA_FORMAT_MARKER);mFlushBatchSet = 1;}if (data_format == DATA_FORMAT_QUAT) {mCachedQuaternionData[0] = *((int *) (rdata + 4));mCachedQuaternionData[1] = *((int *) (rdata + 8));mCachedQuaternionData[2] = *((int *) (rdata + 12));rdata += QUAT_ONLY_LAST_PACKET_OFFSET;mQuatSensorTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_QUAT;readCounter -= BYTES_QUAT_DATA;}else if (data_format == DATA_FORMAT_6_AXIS) {mCached6AxisQuaternionData[0] = *((int *) (rdata + 4));mCached6AxisQuaternionData[1] = *((int *) (rdata + 8));mCached6AxisQuaternionData[2] = *((int *) (rdata + 12));rdata += QUAT_ONLY_LAST_PACKET_OFFSET;mQuatSensorTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_6_AXIS;readCounter -= BYTES_QUAT_DATA;}else if (data_format == DATA_FORMAT_PED_QUAT) {mCachedPedQuaternionData[0] = *((short *) (rdata + 2));mCachedPedQuaternionData[1] = *((short *) (rdata + 4));mCachedPedQuaternionData[2] = *((short *) (rdata + 6));rdata += BYTES_PER_SENSOR;mQuatSensorTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_PED_QUAT;readCounter -= BYTES_PER_SENSOR_PACKET;}else if (data_format == DATA_FORMAT_PED_STANDALONE) {LOGV_IF(ENG_VERBOSE, "STEP DETECTED:0x%x", data_format);rdata += BYTES_PER_SENSOR;mStepSensorTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_PED_STANDALONE;readCounter -= BYTES_PER_SENSOR_PACKET;mPedUpdate |= data_format;}else if (data_format == DATA_FORMAT_GYRO) {mCachedGyroData[0] = *((short *) (rdata + 2));mCachedGyroData[1] = *((short *) (rdata + 4));mCachedGyroData[2] = *((short *) (rdata + 6));rdata += BYTES_PER_SENSOR;mGyroSensorTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_GYRO;readCounter -= BYTES_PER_SENSOR_PACKET;}else if (data_format == DATA_FORMAT_ACCEL) {mCachedAccelData[0] = *((short *) (rdata + 2));mCachedAccelData[1] = *((short *) (rdata + 4));mCachedAccelData[2] = *((short *) (rdata + 6));rdata += BYTES_PER_SENSOR;mAccelSensorTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_ACCEL;readCounter -= BYTES_PER_SENSOR_PACKET;}else  if (data_format == DATA_FORMAT_COMPASS) {if (mCompassSensor->isIntegrated()) {mCachedCompassData[0] = *((short *) (rdata + 2));mCachedCompassData[1] = *((short *) (rdata + 4));mCachedCompassData[2] = *((short *) (rdata + 6));rdata += BYTES_PER_SENSOR;mCompassTimestamp = *((long long*) (rdata));mask |= DATA_FORMAT_COMPASS;readCounter -= BYTES_PER_SENSOR_PACKET;}}rdata += BYTES_PER_SENSOR;/* handle data read */if (mask & DATA_FORMAT_GYRO) {/* batch mode does not batch temperature *//* disable temperature read */if (!(mFeatureActiveMask & INV_DMP_BATCH_MODE)) {// send down temperature every 0.5 seconds// with timestamp measured in "driver" layerif(mGyroSensorTimestamp - mTempCurrentTime >= 500000000LL) {mTempCurrentTime = mGyroSensorTimestamp;long long temperature[2];if(inv_read_temperature(temperature) == 0) {LOGV_IF(INPUT_DATA,"HAL:input inv_read_temperature = %lld, timestamp= %lld",temperature[0], temperature[1]);inv_build_temp(temperature[0], temperature[1]);}}}mPendingMask |= 1 << Gyro;mPendingMask |= 1 << RawGyro;if (mLocalSensorMask & INV_THREE_AXIS_GYRO) {inv_build_gyro(mCachedGyroData, mGyroSensorTimestamp);LOGV_IF(INPUT_DATA,"HAL:input inv_build_gyro: %+8d %+8d %+8d - %lld",mCachedGyroData[0], mCachedGyroData[1],mCachedGyroData[2], mGyroSensorTimestamp);}latestTimestamp = mGyroSensorTimestamp;}if (mask & DATA_FORMAT_ACCEL) {mPendingMask |= 1 << Accelerometer;if (mLocalSensorMask & INV_THREE_AXIS_ACCEL) {inv_build_accel(mCachedAccelData, 0, mAccelSensorTimestamp);LOGV_IF(INPUT_DATA,"HAL:input inv_build_accel: %+8ld %+8ld %+8ld - %lld",mCachedAccelData[0], mCachedAccelData[1],mCachedAccelData[2], mAccelSensorTimestamp);/* remember inital 6 axis quaternion */inv_time_t tempTimestamp;inv_get_6axis_quaternion(mInitial6QuatValue, &tempTimestamp);if (mInitial6QuatValue[0] != 0 || mInitial6QuatValue[1] != 0 ||mInitial6QuatValue[2] != 0 || mInitial6QuatValue[3] != 0) {mInitial6QuatValueAvailable = 1;LOGV_IF(INPUT_DATA && ENG_VERBOSE,"HAL:input build 6q init: %+8ld %+8ld %+8ld %+8ld",mInitial6QuatValue[0], mInitial6QuatValue[1],mInitial6QuatValue[2], mInitial6QuatValue[3]);}}latestTimestamp = mAccelSensorTimestamp;}if ((mask & DATA_FORMAT_COMPASS)) {int status = 0;if (mCompassSensor->providesCalibration()) {status = mCompassSensor->getAccuracy();status |= INV_CALIBRATED;}if (mLocalSensorMask & INV_THREE_AXIS_COMPASS) {inv_build_compass(mCachedCompassData, status,mCompassTimestamp);LOGV_IF(INPUT_DATA,"HAL:input inv_build_compass: %+8ld %+8ld %+8ld - %lld",mCachedCompassData[0], mCachedCompassData[1],mCachedCompassData[2], mCompassTimestamp);}latestTimestamp = mCompassTimestamp;}if (isLowPowerQuatEnabled() && lp_quaternion_on == 1&& (mask & DATA_FORMAT_QUAT)) {/* if bias was applied to DMP bias,set status bits to disable gyro bias cal */int status = 0;if (mGyroBiasApplied == true) {LOGV_IF(INPUT_DATA && ENG_VERBOSE, "HAL:input dmp bias is used");status |= INV_BIAS_APPLIED;}status |= 32 | INV_QUAT_3AXIS; /* default 32 (16/32bits) */inv_build_quat(mCachedQuaternionData,status,mQuatSensorTimestamp);LOGV_IF(INPUT_DATA,"HAL:input inv_build_quat-3x: %+8ld %+8ld %+8ld - %lld",mCachedQuaternionData[0], mCachedQuaternionData[1],mCachedQuaternionData[2],mQuatSensorTimestamp);latestTimestamp = mQuatSensorTimestamp;}if ((mask & DATA_FORMAT_6_AXIS) && check6AxisQuatEnabled()&& (sixAxis_quaternion_on == 1)) {/* if bias was applied to DMP bias,set status bits to disable gyro bias cal */int status = 0;if (mGyroBiasApplied == true) {LOGV_IF(INPUT_DATA && ENG_VERBOSE, "HAL:input dmp bias is used");status |= INV_QUAT_6AXIS;}status |= 32 | INV_QUAT_3AXIS; /* default 32 (16/32bits) */inv_build_quat(mCached6AxisQuaternionData,status,mQuatSensorTimestamp);LOGV_IF(INPUT_DATA,"HAL:input inv_build_quat-6x: %+8ld %+8ld %+8ld - %lld",mCached6AxisQuaternionData[0], mCached6AxisQuaternionData[1],mCached6AxisQuaternionData[2], mQuatSensorTimestamp);latestTimestamp = mQuatSensorTimestamp;}if ((mask & DATA_FORMAT_PED_QUAT) && checkPedQuatEnabled()&& (ped_quaternion_on == 1)) {/* if bias was applied to DMP bias,set status bits to disable gyro bias cal */int status = 0;if (mGyroBiasApplied == true) {LOGV_IF(INPUT_DATA && ENG_VERBOSE,"HAL:input dmp bias is used");status |= INV_QUAT_6AXIS;}status |= 32 | INV_QUAT_3AXIS; /* default 32 (16/32bits) */mCachedPedQuaternionData[0] = mCachedPedQuaternionData[0] << 16;mCachedPedQuaternionData[1] = mCachedPedQuaternionData[1] << 16;mCachedPedQuaternionData[2] = mCachedPedQuaternionData[2] << 16;inv_build_quat(mCachedPedQuaternionData,status,mQuatSensorTimestamp);LOGV_IF(INPUT_DATA,"HAL:HAL:input inv_build_quat-ped_6x: %+8ld %+8ld %+8ld - %lld",mCachedPedQuaternionData[0], mCachedPedQuaternionData[1],mCachedPedQuaternionData[2], mQuatSensorTimestamp);latestTimestamp = mQuatSensorTimestamp;}/* take the latest timestamp */if (mask & DATA_FORMAT_STEP) {/* work around driver output duplicate step detector bit */if (latestTimestamp > mStepSensorTimestamp) {mStepSensorTimestamp = latestTimestamp;LOGV_IF(INPUT_DATA,"HAL:input build step: 1 - %lld", mStepSensorTimestamp);} else {mPedUpdate = 0;}}}    //while end
} 

从代码中可以看到从设备节点读取数据。

rsize = read(iio_fd, rdataP, nbyte);

然后进行在下面这段代码中,将读取到的数据赋予sensors.accel这个对象

inv_error_t inv_build_accel(const long *accel, int status, inv_time_t timestamp)
{if ((status & INV_CALIBRATED) == 0) {sensors.accel.raw[0] = (short)accel[0];sensors.accel.raw[1] = (short)accel[1];sensors.accel.raw[2] = (short)accel[2];sensors.accel.status |= INV_RAW_DATA;inv_apply_calibration(&sensors.accel, inv_data_builder.save_accel_mpl.accel_bias);} else {sensors.accel.calibrated[0] = accel[0];sensors.accel.calibrated[1] = accel[1];sensors.accel.calibrated[2] = accel[2];sensors.accel.status |= INV_CALIBRATED;sensors.accel.accuracy = status & 3;inv_data_builder.save.accel_accuracy = status & 3;}sensors.accel.status |= INV_NEW_DATA | INV_SENSOR_ON;sensors.accel.timestamp_prev = sensors.accel.timestamp;sensors.accel.timestamp = timestamp;return INV_SUCCESS;
}

运行完buildMpuEvent()接着就是readEvents();

int MPLSensor::readEvents(sensors_event_t* data, int count)
{VHANDLER_LOG;inv_execute_on_data();int numEventReceived = 0;long msg;msg = inv_get_message_level_0(1);LOGI("\nHAL:enter readEvents:%x\n",msg);// handle partial packet readif (mSkipReadEvents)return numEventReceived;for (int i = 0; i < NumSensors; i++) {int update = 0;// load up virtual sensorsif (mEnabled & (1 << i)) {update = CALL_MEMBER_FN(this, mHandlers[i])(mPendingEvents + i);mPendingMask |= (1 << i);if (update && (count > 0)) {*data++ = mPendingEvents[i];count--;numEventReceived++;}}}LOGV("\nHAL:readEvents end\n");return numEventReceived;
}

重点是这一段代码

if (mEnabled & (1 << i)) {update = CALL_MEMBER_FN(this, mHandlers[i])(mPendingEvents + i);mPendingMask |= (1 << i);if (update && (count > 0)) {*data++ = mPendingEvents[i];count--;numEventReceived++;}}

在构造函数里有这么一句代码

mHandlers[Accelerometer] = &MPLSensor::accelHandler;

那么下面这句也就不难看懂,就是运行accelHandler

#define CALL_MEMBER_FN(pobject, ptrToMember) ((pobject)->*(ptrToMember))
update = CALL_MEMBER_FN(this, mHandlers[i])(mPendingEvents + i);
int MPLSensor::accelHandler(sensors_event_t* s)
{VHANDLER_LOG;int update;LOGI("\nHAL:enter accelHandler\n");update = inv_get_sensor_type_accelerometer(s->acceleration.v, &s->acceleration.status, &s->timestamp);LOGV_IF(HANDLER_DATA, "HAL:accel data : %+f %+f %+f -- %lld - %d",s->acceleration.v[0], s->acceleration.v[1], s->acceleration.v[2],s->timestamp, update);mAccelAccuracy = s->acceleration.status;return update;
}
int inv_get_sensor_type_accelerometer(float *values, int8_t *accuracy,inv_time_t * timestamp)
{int status;/* Converts fixed point to m/s^2. Fixed point has 1g = 2^16.* So this 9.80665 / 2^16 */
#define ACCEL_CONVERSION 0.000149637603759766flong accel[3];inv_get_accel_set(accel, accuracy, timestamp);values[0] = accel[0] * ACCEL_CONVERSION;values[1] = accel[1] * ACCEL_CONVERSION;values[2] = accel[2] * ACCEL_CONVERSION;if (hal_out.accel_status & INV_NEW_DATA)status = 1;elsestatus = 0;MPL_LOGV("accel values:%f %f %f -%d -%lld", values[0], values[1],values[2], status, *timestamp);return status;
}

    这里将raw accel数据转换成accel数据后传递给mPendingEvents这个对象,mPendingEvents这个对象又赋值给data这个对象,而data这个对象就是frameworks层通过poll传递下来的参数,frameworks层再将这个参数一层层传递到app的onSensorChanged();

至此,android陀螺仪的驱动开发梳理完毕。

 

六、总结

    据说君正是有调试过MPU9250的,但是实际上很多地方都对不上,代码也是残缺的,我估计调试的并不是我们买的newton2_plus的这个开发板,所以很多地方都是自己做了修改,本文只是提供下大致的思路,可能对伸手党不太友好。

hal层和kernel层的代码分析完了 ,顺便把安卓层分析了一遍,做了UML模型,下面是传送门:

https://blog.csdn.net/u014078917/article/details/82259640

    

 


http://www.ppmy.cn/news/183479.html

相关文章

无线鼠标 桌面服务器,你可能不知道 桌面总是乱糟糟的很可能是因为你没买对鼠标...

原标题&#xff1a;你可能不知道 桌面总是乱糟糟的很可能是因为你没买对鼠标 [PC鲤选清单]无线耳机、无线充电、甚至显示器都能无线化了&#xff0c;都9102年了&#xff0c;为什么还要忍受一堆凌乱的数据线、耳机线、充电线&#xff1f;如果你和我一样已经受够了乱糟糟的桌面&a…

python 中控考勤机实时接收打卡数据(QThread)

中控考勤机demo中提供有C#的示例代码&#xff0c;尝试使用python来实现实时考勤数据的现实&#xff0c;由于刚接触python&#xff0c;很多问题还不明白是为什么&#xff0c;先记录下来。编程工具使用的是vs2017。 在连接考勤机时&#xff0c;比较耗时&#xff0c;界面会有卡顿…

记录--让URL地址都变成了ooooooooo

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 发现一个很有创意的小工具网站&#xff0c;如封面图所示功能很简单&#xff0c;就是将一个URL地址转换为都是 ooooooooo 的样子&#xff0c;通过转换后的地址访问可以转换回到原始地址&#xff0c;简单…

「C++」Qt可视化交互封装「遗传算法求解最佳路径问题(一日游规划,商旅问题)」

「C」Qt可视化交互封装「遗传算法求解最佳路径问题&#xff08;一日游规划&#xff0c;商旅问题&#xff09;」 1 效果与要求效果要求 2 代码2.1 算法代码2.2 Qt代码2.2.1 Qt类2.2.2 自定义类 参考 1 效果与要求 效果 「C」遗传算法求解最佳路径问题&#xff08;一日游规划&am…

day10 -- 视图

brief 在 MySQL 中&#xff0c;视图&#xff08;View&#xff09;是一种虚拟的表格&#xff0c;它是由一个 SQL 查询语句所定义的。视图通常基于一个或多个实际存在的表格&#xff0c;并且可以与这些表格进行交互操作&#xff0c;就像真实的表格一样。 MySQL 视图是一个存储在…

uniapp如何实现最新发布apk版本检查和更新

前言: 我们要实现的用户进入apk首页之后,将安卓本机的apk版本和最新的apk版本对比,如果有更高级别的版本(版本号迭代的时候要逐渐增加,比如:本地100版本号(v1.0.0),最新的是102版本号(v1.0.2),那么就提示更新)要提示用户更新,去点击更新按钮下载最新的apk并且安装体…

深度学习-RepVGGNet

文章目录 前言一、RepVgg简介二、为什么训练时采用多分支结构三、为什么推理时使用单分支结构四、结构重参数化1、融合Conv2d和BN 前言 看yolonas代码&#xff0c;发现有QARepVgg网络&#xff0c;完全不懂&#xff0c;所以来补课&#xff0c;先看了RepVGG 这篇文章主要来自于霹…

五年制专转本能给你带来的仅仅是一纸本科文凭吗?

五年制专转本能给你带来的仅仅是一纸本科文凭吗&#xff1f; 经历过五年制专转本的人才会懂&#xff0c;专转本获得的不仅仅只是本科学历&#xff0c;还带给了自己更多宝贵的东西&#xff0c;对以后的发展起着不可磨灭的作用。 一、提升了平台&#xff0c;营造更好的环境 当…