From 6daed46eccb919b18d9bba83036030e976751a17 Mon Sep 17 00:00:00 2001 From: lilvinz Date: Fri, 7 Dec 2012 00:29:51 +0100 Subject: [PATCH] pios_i2c: fixed a race condition with wrong bus locking when using FreeRTOS When more than one task is concurrently trying to access the same i2c bus and a timeout occurs on bus lock the transfer would just continue and blow up the pios_i2c driver. This has been fixed. --- flight/PiOS/STM32F10x/pios_i2c.c | 3 ++- flight/PiOS/STM32F4xx/pios_i2c.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/flight/PiOS/STM32F10x/pios_i2c.c b/flight/PiOS/STM32F10x/pios_i2c.c index d7252916c..9fb8c529f 100644 --- a/flight/PiOS/STM32F10x/pios_i2c.c +++ b/flight/PiOS/STM32F10x/pios_i2c.c @@ -933,7 +933,8 @@ int32_t PIOS_I2C_Transfer(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], /* Lock the bus */ portTickType timeout; timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS; - semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdTRUE); + if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) + return -2; #else uint32_t timeout = 0xfff; while(i2c_adapter->busy && --timeout); diff --git a/flight/PiOS/STM32F4xx/pios_i2c.c b/flight/PiOS/STM32F4xx/pios_i2c.c index 562774bcd..bb2a1bfc1 100644 --- a/flight/PiOS/STM32F4xx/pios_i2c.c +++ b/flight/PiOS/STM32F4xx/pios_i2c.c @@ -970,7 +970,8 @@ int32_t PIOS_I2C_Transfer(uint32_t i2c_id, const struct pios_i2c_txn txn_list[], /* Lock the bus */ portTickType timeout; timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS; - semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdTRUE); + if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) + return -2; #else PIOS_IRQ_Disable(); if(i2c_adapter->busy) { @@ -1046,7 +1047,8 @@ int32_t PIOS_I2C_Transfer_Callback(uint32_t i2c_id, const struct pios_i2c_txn tx /* Lock the bus */ portTickType timeout; timeout = i2c_adapter->cfg->transfer_timeout_ms / portTICK_RATE_MS; - semaphore_success &= (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdTRUE); + if (xSemaphoreTake(i2c_adapter->sem_busy, timeout) == pdFALSE) + return -2; #else if(i2c_adapter->busy) { PIOS_IRQ_Enable();