fix bmi160 driver logic
bosch_bmi160_bmm150.c
1. using fifo_enabled to control int1 enable/disable
2. fix minor ODR calculation and some other issues
bug: 26760550
Change-Id: Id84124bdfee0c016af70878dd0f948ced86e9296
diff --git a/firmware/src/drivers/bosch_bmi160_bmm150/bosch_bmi160_bmm150.c b/firmware/src/drivers/bosch_bmi160_bmm150/bosch_bmi160_bmm150.c
index e3c725f..2d7f453 100644
--- a/firmware/src/drivers/bosch_bmi160_bmm150/bosch_bmi160_bmm150.c
+++ b/firmware/src/drivers/bosch_bmi160_bmm150/bosch_bmi160_bmm150.c
@@ -185,13 +185,17 @@
#define GYR_MIN_RATE 6
#define ACC_MAX_RATE 12
#define GYR_MAX_RATE 13
-#define SENSOR_OSR 3
+#define MAG_MAX_RATE 11
+#define ACC_MAX_OSR 3
+#define GYR_MAX_OSR 4
#define OSR_THRESHOULD 8
#define RETRY_CNT_CALIBRATION 10
#define RETRY_CNT_ID 5
#define RETRY_CNT_MAG 30
+#define SPI_PACKET_SIZE 30
+
enum SensorIndex {
ACC = 0,
GYR,
@@ -289,6 +293,7 @@
uint8_t flush;
};
+// FIXME: alignment
struct BMI160Task {
uint32_t tid;
struct SpiMode mode;
@@ -299,7 +304,7 @@
uint8_t pmuBuffer[2];
uint8_t errBuffer[2];
uint8_t stateBuffer[2];
- struct SpiPacket packets[30];
+ struct SpiPacket packets[SPI_PACKET_SIZE];
int xferCnt;
struct Gpio *Int1;
struct Gpio *Int2;
@@ -330,7 +335,6 @@
uint8_t interrupt_enable_2;
uint8_t active_oneshot_sensor_cnt;
- uint8_t active_data_sensor_cnt;
uint8_t acc_downsample;
uint8_t gyr_downsample;
@@ -464,6 +468,10 @@
static void spiBatchTxRx(struct SpiMode *mode,
SpiCbkF callback, void *cookie)
{
+ if (mRegCnt > SPI_PACKET_SIZE) {
+ osLog(LOG_ERROR, "spiBatchTxRx too many packets!\n");
+ }
+
spiMasterRxTx(mTask.spiDev, mTask.cs,
mTask.packets, mRegCnt, mode, callback, cookie);
mRegCnt = 0;
@@ -704,7 +712,7 @@
mTask.Int1_EN = true;
} else if (!on && mTask.Int1_EN == true) {
for (i = ACC; i <= MAG; i++) {
- if (mTask.sensors[i].powered)
+ if (mTask.fifo_enabled[i])
return;
}
disableInterrupt(mTask.Int1, &mTask.Isr1);
@@ -783,7 +791,7 @@
return (mTask.fifo_enabled[ACC] || mTask.fifo_enabled[GYR] || mTask.fifo_enabled[MAG]);
}
-static void configFifo(bool on)
+static void configFifo(void)
{
uint8_t val = 0x12;
bool prev_fifo_state = anyFifoEnabled();
@@ -812,15 +820,19 @@
}
if (!prev_fifo_state && anyFifoEnabled()) {
- // if this is the first data sensor fifo to enable, we need to
+ // if this is the first data sensor enabled in the fifo, we need to
// sync the sensor time and rtc time
invalidate_sensortime_to_rtc_time();
osEnqueuePrivateEvt(EVT_TIME_SYNC, NULL, NULL, mTask.tid);
}
- // clear all fifo data;
- mTask.xferCnt = 1024;
- SPI_READ(BMI160_REG_FIFO_DATA, mTask.xferCnt, mTask.rxBuffer);
+ // FIXME: should be if (prev_fifo_state), but SENSOR_CONFIG_CHANGING always dispatchData()...
+ // This inceases time-to-first sample latency?
+ {
+ // flush the FIFO
+ mTask.xferCnt = 1028;
+ SPI_READ(BMI160_REG_FIFO_DATA, mTask.xferCnt, mTask.rxBuffer);
+ }
// calculate the new water mark level
SPI_WRITE(BMI160_REG_FIFO_CONFIG_0, calcWaterMark());
// write the composed byte to fifo_config reg.
@@ -843,6 +855,7 @@
// set ACC power mode to SUSPEND
SPI_WRITE(BMI160_REG_CMD, 0x10, 5000);
mTask.sensors[ACC].configed = false;
+ mTask.fifo_enabled[ACC] = false;
}
mTask.sensors[ACC].powered = on;
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC]);
@@ -869,6 +882,7 @@
// set GYR power mode to SUSPEND
SPI_WRITE(BMI160_REG_CMD, 0x14, 1000);
mTask.sensors[GYR].configed = false;
+ mTask.fifo_enabled[GYR] = false;
}
mTask.sensors[GYR].powered = on;
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR]);
@@ -895,6 +909,7 @@
// set MAG power mode to SUSPEND
SPI_WRITE(BMI160_REG_CMD, 0x18, 1000);
mTask.sensors[MAG].configed = false;
+ mTask.fifo_enabled[MAG] = false;
}
mTask.sensors[MAG].powered = on;
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[MAG]);
@@ -1093,8 +1108,10 @@
mTask.state = SENSOR_CONFIG_CHANGING;
odr = computeOdr(rate);
- if (odr == -1)
+ if (!odr) {
+ osLog(LOG_ERROR, "invalid acc rate\n");
return false;
+ }
updateTimeDelta(ACC, odr);
@@ -1108,7 +1125,7 @@
// for high odrs, oversample to reduce hw latency and downsample
// to get desired odr
if (odr > OSR_THRESHOULD) {
- osr = (SENSOR_OSR + odr) > ACC_MAX_RATE ? (ACC_MAX_RATE - odr) : SENSOR_OSR;
+ osr = (ACC_MAX_OSR + odr) > ACC_MAX_RATE ? (ACC_MAX_RATE - odr) : ACC_MAX_OSR;
odr += osr;
}
@@ -1126,7 +1143,7 @@
SPI_WRITE(BMI160_REG_FIFO_DOWNS, (mTask.acc_downsample << 4) | mTask.gyr_downsample | 0x88);
// flush the data and configure the fifo
- configFifo(true);
+ configFifo();
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[ACC]);
} else {
@@ -1148,8 +1165,10 @@
mTask.state = SENSOR_CONFIG_CHANGING;
odr = computeOdr(rate);
- if (odr == -1)
+ if (!odr) {
+ osLog(LOG_ERROR, "invalid gyr rate\n");
return false;
+ }
updateTimeDelta(GYR, odr);
@@ -1163,7 +1182,7 @@
// for high odrs, oversample to reduce hw latency and downsample
// to get desired odr
if (odr > OSR_THRESHOULD) {
- osr = (SENSOR_OSR + odr) > GYR_MAX_RATE ? (GYR_MAX_RATE - odr) : SENSOR_OSR;
+ osr = (GYR_MAX_OSR + odr) > GYR_MAX_RATE ? (GYR_MAX_RATE - odr) : GYR_MAX_OSR;
odr += osr;
}
@@ -1181,7 +1200,7 @@
SPI_WRITE(BMI160_REG_FIFO_DOWNS, (mTask.acc_downsample << 4) | mTask.gyr_downsample | 0x88);
// flush the data and configure the fifo
- configFifo(true);
+ configFifo();
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[GYR]);
} else {
@@ -1210,14 +1229,18 @@
mTask.sensors[MAG].configed = true;
odr = computeOdr(rate);
- if (odr == -1)
+ if (!odr) {
+ osLog(LOG_ERROR, "invalid mag rate\n");
return false;
+ }
updateTimeDelta(MAG, odr);
+ odr = odr > MAG_MAX_RATE ? MAG_MAX_RATE : odr;
+
// set the rate for MAG
SPI_WRITE(BMI160_REG_MAG_CONF, odr);
- configFifo(true);
+ configFifo();
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask.sensors[MAG]);
} else {
@@ -1470,7 +1493,7 @@
mSensor->data_evt = slabAllocatorAlloc(mDataSlab);
if (mSensor->data_evt == NULL) {
// slab allocation failed
- osLog(LOG_ERROR, "bmi160: IMU: Slab allocation failed\n");
+ osLog(LOG_ERROR, "Slab allocation failed\n");
return false;
}
@@ -1787,7 +1810,6 @@
mTask.xferCnt = 1028;
// read out fifo.
SPI_READ(BMI160_REG_FIFO_DATA, mTask.xferCnt, mTask.rxBuffer);
- // record the time.
spiBatchTxRx(&mTask.mode, sensorSpiCallback, &mTask);
break;
default:
@@ -2056,7 +2078,7 @@
{
int i;
- for (i=0; &mTask.sensors[i] != mSensor; i++) ;
+ for (i = 0; &mTask.sensors[i] != mSensor; i++) ;
if (ConfigData->enable == 0 && mSensor->powered)
mSensorOps[i].sensorPower(false, (void *)i);
@@ -2101,11 +2123,10 @@
timeSyncEvt();
return;
}
-
for (i = ACC; i < NUM_OF_SENSOR; i++) {
if (mTask.pending_config[i]) {
- osLog(LOG_INFO, "Process pending config event for %s\n", mSensorInfo[i].sensorName);
mTask.pending_config[i] = false;
+ osLog(LOG_INFO, "Process pending config event for %s\n", mSensorInfo[i].sensorName);
configEvent(&mTask.sensors[i], &mTask.sensors[i].pConfig);
return;
}
@@ -2119,12 +2140,10 @@
saveCalibration();
return;
}
-
}
static void sensorInit(void)
{
-
// read ERR reg value and Power state reg value for debug purpose.
SPI_READ(BMI160_REG_ERR, 1, mTask.errBuffer);
SPI_READ(BMI160_REG_PMU_STATUS, 1, mTask.pmuBuffer);
@@ -2200,7 +2219,7 @@
} else if (mTask.mag_state < MAG_SET_DATA && mTask.stateBuffer[1] & 0x04) {
SPI_READ(BMI160_REG_STATUS, 1, mTask.stateBuffer, 1000);
if (--mRetryLeft == 0) {
- osLog(LOG_ERROR, "bmi160: Enable MAG failed. Go back to IDLE\n");
+ osLog(LOG_ERROR, "Enable MAG failed. Go back to IDLE\n");
mTask.state = SENSOR_IDLE;
processPendingEvt();
break;
@@ -2278,7 +2297,7 @@
case SENSOR_VERIFY_ID:
if (mTask.rxBuffer[3] != BMI160_ID) {
mRetryLeft --;
- osLog(LOG_ERROR, " BMI160 failed id match: %02x\n", mTask.rxBuffer[1]);
+ osLog(LOG_ERROR, "failed id match: %02x\n", mTask.rxBuffer[1]);
if (mRetryLeft == 0)
break;
// For some reason the first ID read will fail to get the
@@ -2293,7 +2312,6 @@
break;
}
case SENSOR_INITIALIZING:
-
if (mTask.init_state == INIT_DONE) {
osLog(LOG_INFO, "Done initialzing, system IDLE\n");
for (i=0; i<NUM_OF_SENSOR; i++)
@@ -2309,7 +2327,7 @@
case SENSOR_POWERING_UP:
mSensor = (struct BMI160Sensor *)evtData;
if (mSensor->idx <= MAG) {
- mTask.active_data_sensor_cnt++;
+ // wait till FIFO is configed to enable interrupt
if (mSensor->idx == GYR && anyFifoEnabled()) {
minimize_sensortime_history();
}
@@ -2341,8 +2359,8 @@
mTask.state = SENSOR_POWERING_DOWN_DONE;
if (mSensor->idx <= MAG) {
configInt1(false);
- configFifo(false);
- if (--mTask.active_data_sensor_cnt == 0) {
+ configFifo();
+ if (!anyFifoEnabled()) {
// if this is the last data sensor to disable, we need to flush
// the fifo and invalidate time
mTask.frame_sensortime = ULONG_LONG_MAX;
@@ -2374,9 +2392,8 @@
osLog(LOG_INFO, "Done powering down for %s\n", mSensorInfo[mSensor->idx].sensorName);
osLog(LOG_INFO, " NEW POWER STATUS: %02x, ERROR: %02x\n", mTask.pmuBuffer[1], mTask.errBuffer[1]);
- if (mTask.active_data_sensor_cnt > 0)
+ if (anyFifoEnabled())
dispatchData();
-
processPendingEvt();
break;
case SENSOR_INT_1_HANDLING:
@@ -2522,7 +2539,6 @@
mTask.Int2_EN = false;
mTask.pending_int[0] = false;
mTask.pending_int[1] = false;
- mTask.active_data_sensor_cnt = 0;
mTask.mode.speed = BMI160_SPI_SPEED_HZ;
mTask.mode.bitsPerWord = 8;