From 23b4a9ed8be7ad25197acc4557dfe1c530b49e67 Mon Sep 17 00:00:00 2001 From: Rahix <rahix@rahix.de> Date: Sun, 29 Dec 2019 11:41:19 +0100 Subject: [PATCH] fix(bhi160): Disable driver on critical error If initialization fails, bhi160 API calls should not infinitely block waiting for it to complete; they should fail immediately with an error stating that something went wrong. Add a flag that indicates the driver to not accept API requests because initialization was not finished properly. Signed-off-by: Rahix <rahix@rahix.de> --- epicardium/FreeRTOSConfig.h | 1 + epicardium/modules/bhi.c | 40 +++++++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/epicardium/FreeRTOSConfig.h b/epicardium/FreeRTOSConfig.h index 22c6dfb0..8ff4a4b4 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 3ef515b8..c767a8cc 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); /* -- GitLab