From a1b7960d739be5369661038adf6429f26bf9821d Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Fri, 5 Jan 2018 13:48:28 +0100 Subject: [PATCH 1/5] inline function moved to .c file to avoid multiple definition --- extras/bme680/bme680_platform.c | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 extras/bme680/bme680_platform.c diff --git a/extras/bme680/bme680_platform.c b/extras/bme680/bme680_platform.c new file mode 100644 index 0000000..00cb8cf --- /dev/null +++ b/extras/bme680/bme680_platform.c @@ -0,0 +1,82 @@ +/* + * Driver for Bosch Sensortec BME680 digital temperature, humidity, pressure + * and gas sensor connected to I2C or SPI + * + * This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos) + * [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32 + * and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux + * based systems using a wrapper library for ESP8266 functions. + * + * --------------------------------------------------------------------------- + * + * The BSD License (3-clause license) + * + * Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Platform file: platform specific definitions, includes and functions + */ + +#include "bme680_platform.h" + +// platform specific SPI functions + +static const spi_settings_t bus_settings = { + .mode = SPI_MODE0, + .freq_divider = SPI_FREQ_DIV_1M, + .msb = true, + .minimal_pins = false, + .endianness = SPI_LITTLE_ENDIAN +}; + +bool spi_device_init (uint8_t bus, uint8_t cs) +{ + gpio_enable(cs, GPIO_OUTPUT); + gpio_write (cs, true); + return true; +} + +size_t spi_transfer_pf(uint8_t bus, uint8_t cs, const uint8_t *mosi, uint8_t *miso, uint16_t len) +{ + spi_settings_t old_settings; + + spi_get_settings(bus, &old_settings); + spi_set_settings(bus, &bus_settings); + gpio_write(cs, false); + + size_t transfered = spi_transfer (bus, (const void*)mosi, (void*)miso, len, SPI_8BIT); + + gpio_write(cs, true); + spi_set_settings(bus, &old_settings); + + return transfered; +} + From 5b36ada7296f03b6ab6705ad73b474bd224f32ad Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Fri, 5 Jan 2018 13:48:39 +0100 Subject: [PATCH 2/5] inline function moved to .c file to avoid multiple definition --- extras/bme680/bme680_platform.h | 34 ++++----------------------------- 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/extras/bme680/bme680_platform.h b/extras/bme680/bme680_platform.h index 31fa0a5..465b5ea 100644 --- a/extras/bme680/bme680_platform.h +++ b/extras/bme680/bme680_platform.h @@ -76,36 +76,10 @@ #define spi_bus_init(bus,sck,miso,mosi) // not needed on ESP8266 -static const spi_settings_t bus_settings = { - .mode = SPI_MODE0, - .freq_divider = SPI_FREQ_DIV_1M, - .msb = true, - .minimal_pins = false, - .endianness = SPI_LITTLE_ENDIAN -}; - -inline static bool spi_device_init (uint8_t bus, uint8_t cs) -{ - gpio_enable(cs, GPIO_OUTPUT); - gpio_write (cs, true); - return true; -} - -inline static size_t spi_transfer_pf(uint8_t bus, uint8_t cs, const uint8_t *mosi, uint8_t *miso, uint16_t len) -{ - spi_settings_t old_settings; - - spi_get_settings(bus, &old_settings); - spi_set_settings(bus, &bus_settings); - gpio_write(cs, false); - - size_t transfered = spi_transfer (bus, (const void*)mosi, (void*)miso, len, SPI_8BIT); - - gpio_write(cs, true); - spi_set_settings(bus, &old_settings); - - return transfered; -} +extern bool spi_device_init (uint8_t bus, uint8_t cs); +extern size_t spi_transfer_pf (uint8_t bus, uint8_t cs, + const uint8_t *mosi, uint8_t *miso, + uint16_t len); #endif // ESP_OPEN_RTOS From e2c7f3be541b50ff4f93001e522581752cfaa751 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Fri, 5 Jan 2018 13:48:28 +0100 Subject: [PATCH 3/5] inline function moved to .c file to avoid multiple definition --- extras/bme680/bme680_platform.c | 82 +++++++++++++++++++++++++++++++++ extras/bme680/bme680_platform.h | 34 ++------------ 2 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 extras/bme680/bme680_platform.c diff --git a/extras/bme680/bme680_platform.c b/extras/bme680/bme680_platform.c new file mode 100644 index 0000000..00cb8cf --- /dev/null +++ b/extras/bme680/bme680_platform.c @@ -0,0 +1,82 @@ +/* + * Driver for Bosch Sensortec BME680 digital temperature, humidity, pressure + * and gas sensor connected to I2C or SPI + * + * This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos) + * [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32 + * and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux + * based systems using a wrapper library for ESP8266 functions. + * + * --------------------------------------------------------------------------- + * + * The BSD License (3-clause license) + * + * Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Platform file: platform specific definitions, includes and functions + */ + +#include "bme680_platform.h" + +// platform specific SPI functions + +static const spi_settings_t bus_settings = { + .mode = SPI_MODE0, + .freq_divider = SPI_FREQ_DIV_1M, + .msb = true, + .minimal_pins = false, + .endianness = SPI_LITTLE_ENDIAN +}; + +bool spi_device_init (uint8_t bus, uint8_t cs) +{ + gpio_enable(cs, GPIO_OUTPUT); + gpio_write (cs, true); + return true; +} + +size_t spi_transfer_pf(uint8_t bus, uint8_t cs, const uint8_t *mosi, uint8_t *miso, uint16_t len) +{ + spi_settings_t old_settings; + + spi_get_settings(bus, &old_settings); + spi_set_settings(bus, &bus_settings); + gpio_write(cs, false); + + size_t transfered = spi_transfer (bus, (const void*)mosi, (void*)miso, len, SPI_8BIT); + + gpio_write(cs, true); + spi_set_settings(bus, &old_settings); + + return transfered; +} + diff --git a/extras/bme680/bme680_platform.h b/extras/bme680/bme680_platform.h index 31fa0a5..465b5ea 100644 --- a/extras/bme680/bme680_platform.h +++ b/extras/bme680/bme680_platform.h @@ -76,36 +76,10 @@ #define spi_bus_init(bus,sck,miso,mosi) // not needed on ESP8266 -static const spi_settings_t bus_settings = { - .mode = SPI_MODE0, - .freq_divider = SPI_FREQ_DIV_1M, - .msb = true, - .minimal_pins = false, - .endianness = SPI_LITTLE_ENDIAN -}; - -inline static bool spi_device_init (uint8_t bus, uint8_t cs) -{ - gpio_enable(cs, GPIO_OUTPUT); - gpio_write (cs, true); - return true; -} - -inline static size_t spi_transfer_pf(uint8_t bus, uint8_t cs, const uint8_t *mosi, uint8_t *miso, uint16_t len) -{ - spi_settings_t old_settings; - - spi_get_settings(bus, &old_settings); - spi_set_settings(bus, &bus_settings); - gpio_write(cs, false); - - size_t transfered = spi_transfer (bus, (const void*)mosi, (void*)miso, len, SPI_8BIT); - - gpio_write(cs, true); - spi_set_settings(bus, &old_settings); - - return transfered; -} +extern bool spi_device_init (uint8_t bus, uint8_t cs); +extern size_t spi_transfer_pf (uint8_t bus, uint8_t cs, + const uint8_t *mosi, uint8_t *miso, + uint16_t len); #endif // ESP_OPEN_RTOS From df0190026b35b1886253b5f68fefab4995c014a9 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Fri, 5 Jan 2018 18:31:24 +0100 Subject: [PATCH 4/5] minor change --- extras/bme680/bme680.c | 23 +++++++++++++---------- extras/bme680/bme680_platform.h | 6 +++--- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/extras/bme680/bme680.c b/extras/bme680/bme680.c index 60b10e5..81e4856 100644 --- a/extras/bme680/bme680.c +++ b/extras/bme680/bme680.c @@ -306,7 +306,7 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs) return NULL; } if (!addr) - spi_semaphore_init(); + spi_semaphore_init(dev); // reset the sensor if (!bme680_reset(dev)) @@ -1278,14 +1278,14 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui return false; } - spi_semaphore_take (); + spi_semaphore_take (dev); // set mem page first if (!bme680_spi_set_mem_page (dev, reg)) { + spi_semaphore_give (dev); error_dev ("Error on read from SPI slave on bus 1. Could not set mem page.", __FUNCTION__, dev); - spi_semaphore_give (); return false; } @@ -1302,17 +1302,17 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui if (!spi_transfer_pf (dev->bus, dev->cs, mosi, miso, len+1)) { + spi_semaphore_give (dev); error_dev ("Could not read data from SPI", __FUNCTION__, dev); dev->error_code |= BME680_SPI_READ_FAILED; - spi_semaphore_give (); return false; } - spi_semaphore_give (); - // shift data one by left, first byte received while sending register address is invalid for (int i=0; i < len; i++) data[i] = miso[i+1]; + spi_semaphore_give (dev); + #ifdef BME680_DEBUG_LEVEL_2 printf("BME680 %s: read the following bytes: ", __FUNCTION__); printf("%0x ", reg); @@ -1340,14 +1340,15 @@ static bool bme680_spi_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u return false; } - spi_semaphore_take (); + if (reg != BME680_REG_STATUS) + spi_semaphore_take (dev); // set mem page first if not mem page register is used if (reg != BME680_REG_STATUS && !bme680_spi_set_mem_page (dev, reg)) { error_dev ("Error on write from SPI slave on bus 1. Could not set mem page.", __FUNCTION__, dev); - spi_semaphore_give (); + spi_semaphore_give (dev); return false; } @@ -1369,12 +1370,14 @@ static bool bme680_spi_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u if (!spi_transfer_pf (dev->bus, dev->cs, mosi, NULL, len+1)) { + if (reg != BME680_REG_STATUS) + spi_semaphore_give (dev); error_dev ("Could not write data to SPI.", __FUNCTION__, dev); dev->error_code |= BME680_SPI_WRITE_FAILED; - spi_semaphore_give (); return false; } - spi_semaphore_give (); + if (reg != BME680_REG_STATUS) + spi_semaphore_give (dev); return true; } diff --git a/extras/bme680/bme680_platform.h b/extras/bme680/bme680_platform.h index 465b5ea..4765b02 100644 --- a/extras/bme680/bme680_platform.h +++ b/extras/bme680/bme680_platform.h @@ -68,9 +68,9 @@ // platform specific definitions -#define spi_semaphore_init() -#define spi_semaphore_take() -#define spi_semaphore_give() +#define spi_semaphore_init(d) +#define spi_semaphore_take(d) +#define spi_semaphore_give(d) // platform specific SPI functions From f8f7cf8158acc5cea07e2abd25062ccd768a6252 Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Sat, 6 Jan 2018 15:31:03 +0100 Subject: [PATCH 5/5] semaphore for SPI bus access removed from the driver, the user has to deal with concurrency --- .../bme680_one_sensor/bme680_one_sensor.c | 15 ++++++--- extras/bme680/README.md | 32 +++++++++++++------ extras/bme680/bme680.c | 16 ---------- extras/bme680/bme680_platform.h | 6 ---- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/examples/bme680/bme680_one_sensor/bme680_one_sensor.c b/examples/bme680/bme680_one_sensor/bme680_one_sensor.c index b1dde38..2ead95d 100644 --- a/examples/bme680/bme680_one_sensor/bme680_one_sensor.c +++ b/examples/bme680/bme680_one_sensor/bme680_one_sensor.c @@ -138,10 +138,7 @@ void user_init(void) if (sensor) { - // Create a task that uses the sensor - xTaskCreate(user_task, "user_task", TASK_STACK_DEPTH, NULL, 2, NULL); - - /** -- OPTIONAL PART -- */ + /** -- SENSOR CONFIGURATION PART (optional) --- */ // Changes the oversampling rates to 4x oversampling for temperature // and 2x oversampling for humidity. Pressure measurement is skipped. @@ -156,5 +153,15 @@ void user_init(void) // Set ambient temperature to 10 degree Celsius bme680_set_ambient_temperature (sensor, 10); + + /** -- TASK CREATION PART --- */ + + // must be done last to avoid concurrency situations with the sensor + // configuration part + + // Create a task that uses the sensor + xTaskCreate(user_task, "user_task", TASK_STACK_DEPTH, NULL, 2, NULL); } + else + printf("Could not initialize BME680 sensor\n"); } diff --git a/extras/bme680/README.md b/extras/bme680/README.md index 8b8853f..56eab72 100644 --- a/extras/bme680/README.md +++ b/extras/bme680/README.md @@ -378,10 +378,7 @@ Optionally, you could wish to set some measurement parameters. For details see t ``` if (sensor) { - // Create a task that uses the sensor - xTaskCreate(user_task, "user_task", 256, NULL, 2, NULL); - - /** -- OPTIONAL PART -- */ + /** -- SENSOR CONFIGURATION PART (optional) --- */ // Changes the oversampling rates to 4x oversampling for temperature // and 2x oversampling for humidity. Pressure measurement is skipped. @@ -394,11 +391,21 @@ if (sensor) bme680_set_heater_profile (sensor, 0, 200, 100); bme680_use_heater_profile (sensor, 0); + /** -- TASK CREATION PART --- */ + + // must be done last to avoid concurrency situations with the sensor + // configuration part + + // Create a task that uses the sensor + xTaskCreate(user_task, "user_task", TASK_STACK_DEPTH, NULL, 2, NULL); + ... } ``` -Last, the user task that uses the sensor has to be created. +Finally, a user task that uses the sensor has to be created. + +**Please note:** To avoid concurrency situations when driver functions are used to access the sensor, for example to read data, the user task must not be created until the sensor configuration is completed. ### User task @@ -566,10 +573,7 @@ void user_init(void) if (sensor) { - // Create a task that uses the sensor - xTaskCreate(user_task, "user_task", TASK_STACK_DEPTH, NULL, 2, NULL); - - /** -- OPTIONAL PART -- */ + /** -- SENSOR CONFIGURATION PART (optional) --- */ // Changes the oversampling rates to 4x oversampling for temperature // and 2x oversampling for humidity. Pressure measurement is skipped. @@ -584,7 +588,17 @@ void user_init(void) // Set ambient temperature to 10 degree Celsius bme680_set_ambient_temperature (sensor, 10); + + /** -- TASK CREATION PART --- */ + + // must be done last to avoid concurrency situations with the sensor + // configuration part + + // Create a task that uses the sensor + xTaskCreate(user_task, "user_task", TASK_STACK_DEPTH, NULL, 2, NULL); } + else + printf("Could not initialize BME680 sensor\n"); } ``` diff --git a/extras/bme680/bme680.c b/extras/bme680/bme680.c index 81e4856..0255d94 100644 --- a/extras/bme680/bme680.c +++ b/extras/bme680/bme680.c @@ -305,8 +305,6 @@ bme680_sensor_t* bme680_init_sensor(uint8_t bus, uint8_t addr, uint8_t cs) free (dev); return NULL; } - if (!addr) - spi_semaphore_init(dev); // reset the sensor if (!bme680_reset(dev)) @@ -1278,12 +1276,9 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui return false; } - spi_semaphore_take (dev); - // set mem page first if (!bme680_spi_set_mem_page (dev, reg)) { - spi_semaphore_give (dev); error_dev ("Error on read from SPI slave on bus 1. Could not set mem page.", __FUNCTION__, dev); return false; @@ -1302,7 +1297,6 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui if (!spi_transfer_pf (dev->bus, dev->cs, mosi, miso, len+1)) { - spi_semaphore_give (dev); error_dev ("Could not read data from SPI", __FUNCTION__, dev); dev->error_code |= BME680_SPI_READ_FAILED; return false; @@ -1311,8 +1305,6 @@ static bool bme680_spi_read(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, ui for (int i=0; i < len; i++) data[i] = miso[i+1]; - spi_semaphore_give (dev); - #ifdef BME680_DEBUG_LEVEL_2 printf("BME680 %s: read the following bytes: ", __FUNCTION__); printf("%0x ", reg); @@ -1340,15 +1332,11 @@ static bool bme680_spi_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u return false; } - if (reg != BME680_REG_STATUS) - spi_semaphore_take (dev); - // set mem page first if not mem page register is used if (reg != BME680_REG_STATUS && !bme680_spi_set_mem_page (dev, reg)) { error_dev ("Error on write from SPI slave on bus 1. Could not set mem page.", __FUNCTION__, dev); - spi_semaphore_give (dev); return false; } @@ -1370,14 +1358,10 @@ static bool bme680_spi_write(bme680_sensor_t* dev, uint8_t reg, uint8_t *data, u if (!spi_transfer_pf (dev->bus, dev->cs, mosi, NULL, len+1)) { - if (reg != BME680_REG_STATUS) - spi_semaphore_give (dev); error_dev ("Could not write data to SPI.", __FUNCTION__, dev); dev->error_code |= BME680_SPI_WRITE_FAILED; return false; } - if (reg != BME680_REG_STATUS) - spi_semaphore_give (dev); return true; } diff --git a/extras/bme680/bme680_platform.h b/extras/bme680/bme680_platform.h index 4765b02..9f47c2e 100644 --- a/extras/bme680/bme680_platform.h +++ b/extras/bme680/bme680_platform.h @@ -66,12 +66,6 @@ #include "esp/spi.h" #include "i2c/i2c.h" -// platform specific definitions - -#define spi_semaphore_init(d) -#define spi_semaphore_take(d) -#define spi_semaphore_give(d) - // platform specific SPI functions #define spi_bus_init(bus,sck,miso,mosi) // not needed on ESP8266