diff --git a/epicardium/FreeRTOSConfig.h b/epicardium/FreeRTOSConfig.h index 22c6dfb0f050c38c2d33b7f1d64b1e7940d8ea97..8ff4a4b468f9ea938e92491aa41eafb9f5dad1e3 100644 --- a/epicardium/FreeRTOSConfig.h +++ b/epicardium/FreeRTOSConfig.h @@ -50,6 +50,7 @@ #define INCLUDE_vTaskSuspend 1 #define INCLUDE_vTaskDelay 1 +#define INCLUDE_vTaskDelete 1 #define INCLUDE_uxTaskGetStackHighWaterMark 1 #define INCLUDE_xTimerPendFunctionCall 1 #define INCLUDE_xSemaphoreGetMutexHolder 1 diff --git a/epicardium/modules/bhi.c b/epicardium/modules/bhi.c index 3ef515b84f2f2c843e4c5ce3b49d1d4f0fe225db..c767a8cc24979bb661e6421d90161e7c95151151 100644 --- a/epicardium/modules/bhi.c +++ b/epicardium/modules/bhi.c @@ -61,6 +61,13 @@ static struct stream_info bhi160_streams[10]; /* Active */ static bool bhi160_sensor_active[10] = { 0 }; +/* + * Driver State: A flag that is set when an unrecoverable error occurred. + * Effectively, this means the sensor will be disabled until next reboot and any + * API calls will fail immediately. + */ +static bool bhi160_driver_b0rked = false; + /* -- Utilities -------------------------------------------------------- {{{ */ /* * Retrieve the data size for a sensor. This value is needed for the creation @@ -133,6 +140,11 @@ int epic_bhi160_enable_sensor( mutex_lock(&bhi160_mutex); hwlock_acquire(HWLOCK_I2C); + if (bhi160_driver_b0rked) { + result = -ENODEV; + goto out_free; + } + struct stream_info *stream = &bhi160_streams[sensor_type]; stream->item_size = bhi160_lookup_data_size(sensor_type); /* TODO: Sanity check length */ @@ -183,6 +195,11 @@ int epic_bhi160_disable_sensor(enum bhi160_sensor_type sensor_type) mutex_lock(&bhi160_mutex); hwlock_acquire(HWLOCK_I2C); + if (bhi160_driver_b0rked) { + result = -ENODEV; + goto out_free; + } + struct stream_info *stream = &bhi160_streams[sensor_type]; result = stream_deregister(bhi160_lookup_sd(sensor_type), stream); if (result < 0) { @@ -384,7 +401,7 @@ static void bhi160_interrupt_callback(void *_) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (bhi160_task_id != NULL) { + if (bhi160_task_id != NULL && !bhi160_driver_b0rked) { vTaskNotifyGiveFromISR( bhi160_task_id, &xHigherPriorityTaskWoken ); @@ -428,13 +445,28 @@ void vBhi160Task(void *pvParameters) /* Upload firmware */ ret = bhy_driver_init(bhy1_fw); if (ret) { - LOG_CRIT("bhi160", "BHy1 init failed!"); - vTaskDelay(portMAX_DELAY); + LOG_CRIT("bhi160", "BHy1 init failed! Disabling."); + + /* Disable BHI160 until next reboot */ + bhi160_driver_b0rked = true; + hwlock_release(HWLOCK_I2C); + mutex_unlock(&bhi160_mutex); + vTaskDelete(NULL); } /* Wait for first interrupt, a falling edge */ hwlock_release(HWLOCK_I2C); - ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100)); + if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(2000)) == 0) { + LOG_CRIT( + "bhi160", + "Sensor firmware was not loaded correctly. Disabling." + ); + + /* Disable BHI160 until next reboot */ + bhi160_driver_b0rked = true; + mutex_unlock(&bhi160_mutex); + vTaskDelete(NULL); + } hwlock_acquire(HWLOCK_I2C); /*