bosch_bmi160: add debug logging for hanging SPI transactions

Bug: 29625330
Change-Id: I5a8d70f85e02ff2f32bc63dee190b8c3de725b07
diff --git a/firmware/src/drivers/bosch_bmi160/bosch_bmi160.c b/firmware/src/drivers/bosch_bmi160/bosch_bmi160.c
index a694187..6e21cb5 100644
--- a/firmware/src/drivers/bosch_bmi160/bosch_bmi160.c
+++ b/firmware/src/drivers/bosch_bmi160/bosch_bmi160.c
@@ -458,6 +458,7 @@
     uint8_t *sensorTimeBuffer;
     uint8_t *temperatureBuffer;
     uint8_t txrxBuffer[SPI_BUF_SIZE];
+    uint32_t spiTimeoutTimerHandle;
 
     // states
     volatile uint8_t state;  //task state, type enum SensorState, do NOT change this directly
@@ -487,9 +488,11 @@
     // spi rw
     struct SlabAllocator *mDataSlab;
     uint16_t mWbufCnt;
-    uint8_t mRegCnt;
+    uint8_t mRegCnt, mLastRegCnt;
     uint8_t mRetryLeft;
     bool spiInUse;
+    int spiBatches, spiCallbacks;
+    const char * spiSrc;
 };
 
 static uint32_t AccRates[] = {
@@ -741,6 +744,37 @@
     T(mRegCnt)++;
 }
 
+static void printDebug()
+{
+    int i;
+    int wbufCnt = 0;
+    // TODO (trevorbunker)
+    INFO_PRINT("stepPower\n");
+    INFO_PRINT("DEBUG: state = %" PRI_STATE "\n", getStateName(atomicReadByte(&(mTask.state))));
+    INFO_PRINT("DEBUG: interrupt_enable_0 = 0x%02x\n", mTask.interrupt_enable_0);
+    INFO_PRINT("DEBUG: interrupt_enable_2 = 0x%02x\n", mTask.interrupt_enable_2);
+    INFO_PRINT("DEBUG: spiInUse = %d\n", mTask.spiInUse);
+    INFO_PRINT("DEBUG: Int1 = %d\n", gpioGet(mTask.Int1));
+    INFO_PRINT("DEBUG: Int2 = %d\n", gpioGet(mTask.Int2));
+    INFO_PRINT("DEBUG: pending_int[0] = %d\n", mTask.pending_int[0]);
+    INFO_PRINT("DEBUG: pending_int[1] = %d\n", mTask.pending_int[1]);
+    INFO_PRINT("DEBUG: spiBatches = %d\n", mTask.spiBatches);
+    INFO_PRINT("DEBUG: spiCallbacks = %d\n", mTask.spiCallbacks);
+    INFO_PRINT("DEBUG: spiSrc = %s\n", mTask.spiSrc);
+    for (i = 0; i < mTask.mLastRegCnt; i++) {
+        INFO_PRINT("Request %d, reg addr 0x%02x, size %d, txBuf 0x%08x, rxBuf 0x%08x, delay %d\n",
+                   i, (unsigned int)mTask.txrxBuffer[wbufCnt], (int)mTask.packets[i].size, (unsigned int)mTask.packets[i].txBuf,
+                   (unsigned int)mTask.packets[i].rxBuf, (int)mTask.packets[i].delay);
+        wbufCnt += mTask.packets[i].size;
+    }
+}
+
+static void spiTimeoutCallback(uint32_t timerId, void *data)
+{
+    ERROR_PRINT("SPI transaction never returned\n");
+    printDebug();
+}
+
 static void spiBatchTxRx(struct SpiMode *mode,
         SpiCbkF callback, void *cookie, const char * src)
 {
@@ -753,9 +787,24 @@
         ERROR_PRINT("spiBatchTxRx too many packets!\n");
         return;
     }
+    if (T(spiInUse)) {
+        ERROR_PRINT("cannot call spiBatchTxRx when spi is already in use!\n");
+        return;
+    }
 
+    T(spiBatches)++;
     T(spiInUse) = true;
-    spiMasterRxTx(T(spiDev), T(cs), T(packets), T(mRegCnt), mode, callback, cookie);
+
+    mTask.spiTimeoutTimerHandle = timTimerSet(1000000000ull, 0, 50, spiTimeoutCallback, NULL, true);
+    if (!mTask.spiTimeoutTimerHandle)
+        ERROR_PRINT("Couldn't get a timer for the SPI timeout timer\n");
+
+    T(spiSrc) = src;
+    if (spiMasterRxTx(T(spiDev), T(cs), T(packets), T(mRegCnt), mode, callback, cookie) < 0) {
+        ERROR_PRINT("spiMasterRxTx failed!\n");
+    }
+
+    T(mLastRegCnt) = T(mRegCnt);
     T(mRegCnt) = 0;
     T(mWbufCnt) = 0;
 }
@@ -792,6 +841,13 @@
 static void sensorSpiCallback(void *cookie, int err)
 {
     mTask.spiInUse = false;
+    mTask.spiCallbacks++;
+
+    if (mTask.spiTimeoutTimerHandle) {
+        timTimerCancel(mTask.spiTimeoutTimerHandle);
+        mTask.spiTimeoutTimerHandle = 0;
+    }
+
     if (!osEnqueuePrivateEvt(EVT_SPI_DONE, cookie, NULL, mTask.tid))
         ERROR_PRINT("sensorSpiCallback: osEnqueuePrivateEvt() failed\n");
 }
@@ -1191,6 +1247,8 @@
 
 static bool stepPower(bool on, void *cookie)
 {
+    printDebug();
+
     TDECL();
     if (trySwitchState(on ? SENSOR_POWERING_UP : SENSOR_POWERING_DOWN)) {
         // if step counter is powered, no need to change actual config of step
@@ -1615,6 +1673,9 @@
         }
         mTask.stepCntSamplingTimerHandle = timTimerSet(sensorTimerLookupCommon(StepCntRates, stepCntRateTimerVals, rate),
                                                        0, 50, stepCntSamplingCallback, NULL, false);
+        if (!mTask.stepCntSamplingTimerHandle)
+            ERROR_PRINT("Couldn't get a timer for the step counter timer\n");
+
     }
 
     sensorSignalInternalEvt(mTask.sensors[STEPCNT].handle,
@@ -2296,7 +2357,7 @@
 #endif
         } else {
             size = 0; // drop this batch
-            ERROR_PRINT("Invalid fh_mode\n");
+            ERROR_PRINT("Invalid fh_mode %d\n", fh_mode);
         }
     }
 
@@ -3177,7 +3238,8 @@
             // For some reason the first ID read will fail to get the
             // correct value. need to retry a few times.
             SET_STATE(SENSOR_BOOT);
-            timTimerSet(100000000, 100, 100, sensorTimerCallback, NULL, true);
+            if (timTimerSet(100000000, 100, 100, sensorTimerCallback, NULL, true) == 0)
+                ERROR_PRINT("Couldn't get a timer to verify ID\n");
             break;
         } else {
             SET_STATE(SENSOR_INITIALIZING);
@@ -3303,8 +3365,9 @@
 
         if (mTask.active_poll_generation == mTask.poll_generation) {
             // attach the generation number to event
-            timTimerSet(kTimeSyncPeriodNs, 100, 100, timeSyncCallback,
-                    (void *)mTask.poll_generation, true);
+            if (timTimerSet(kTimeSyncPeriodNs, 100, 100, timeSyncCallback,
+                    (void *)mTask.poll_generation, true) == 0)
+                ERROR_PRINT("Couldn't get a timer for time sync\n");
         }
 
         returnIdle = true;
@@ -3340,7 +3403,8 @@
         // wait 100ms for sensor to boot
         currTime = timGetTime();
         if (currTime < 100000000ULL) {
-            timTimerSet(100000000 - currTime, 100, 100, sensorTimerCallback, NULL, true);
+            if (timTimerSet(100000000 - currTime, 100, 100, sensorTimerCallback, NULL, true) == 0)
+                ERROR_PRINT("Couldn't get a timer for boot delay\n");
             break;
         }
         /* We have already been powered on long enough - fall through */
@@ -3420,6 +3484,7 @@
     T(cs) = GPIO_PB(12);
 
     T(watermark) = 0;
+    T(spiSrc) = "xxx";
 
     spiMasterRequest(BMI160_SPI_BUS_ID, &T(spiDev));
 
@@ -3656,12 +3721,19 @@
 static void chunkedReadSpiCallback(void *cookie, int err) {
     TASK = (_Task*) cookie;
 
+    if (T(spiTimeoutTimerHandle)) {
+        timTimerCancel(T(spiTimeoutTimerHandle));
+        T(spiTimeoutTimerHandle) = 0;
+    }
+
+    T(spiCallbacks)++;
     T(spiInUse) = false;
     DEBUG_PRINT_IF(err !=0 || GET_STATE() != SENSOR_INT_1_HANDLING,
             "crcb,e:%d,s:%d", err, (int)GET_STATE());
     bool int1 = gpioGet(T(Int1));
     if (err != 0) {
-        DEBUG_PRINT_IF(DBG_CHUNKED, "crd retry");
+        //DEBUG_PRINT_IF(DBG_CHUNKED, "crd retry");
+        INFO_PRINT("crd retry");
         // read full fifo length to be safe
         chunkedReadInit(0, FIFO_READ_SIZE);
         return;
@@ -3679,6 +3751,7 @@
         // real frame parse works properly
         T(dataBuffer) = T(txrxBuffer);
         T(xferCnt) = FIFO_READ_SIZE;
+        T(spiCallbacks)--;
         sensorSpiCallback(cookie, err);
     } else {
         DEBUG_PRINT_IF(DBG_CHUNKED, "crd cont");