From 30366769587d89ac9d7e2b45effeed8e6ee6078f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Tue, 26 Dec 2017 19:56:32 +0100 Subject: [PATCH] Check used GPIOs via locks --- code/espurna/config/hardware.h | 8 ++++-- code/espurna/config/prototypes.h | 7 ++++++ code/espurna/gpio.ino | 37 ++++++++++++++++++++++++++++ code/espurna/sensors/BaseSensor.h | 8 +----- code/espurna/sensors/DHTSensor.h | 23 +++++++++++++++++ code/espurna/sensors/DallasSensor.h | 17 +++++++++++++ code/espurna/sensors/ECH1560Sensor.h | 4 +-- code/espurna/sensors/EventSensor.h | 4 +-- code/espurna/sensors/HLW8012Sensor.h | 4 +-- 9 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 code/espurna/gpio.ino diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 832e139b..d9682a45 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -219,8 +219,12 @@ #define LED1_PIN_INVERSE 1 // Jack is connected to GPIO14 (and with a small hack to GPIO4) - #define I2C_SDA_PIN 4 - #define I2C_SCL_PIN 14 + #define DALLAS_SUPPORT 1 + #define DALLAS_PIN 14 + #define DHT_SUPPORT 1 + #define DHT_PIN 14 + //#define I2C_SDA_PIN 4 + //#define I2C_SCL_PIN 14 #elif defined(ITEAD_SONOFF_SV) diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index dc004ded..0e081647 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -56,6 +56,13 @@ unsigned char i2cFindAndLock(size_t size, unsigned char * addresses); bool i2cGetLock(unsigned char address); bool i2cReleaseLock(unsigned char address); +// ----------------------------------------------------------------------------- +// GPIO +// ----------------------------------------------------------------------------- +bool gpioValid(unsigned char gpio); +bool gpioGetLock(unsigned char gpio); +bool gpioReleaseLock(unsigned char gpio); + // ----------------------------------------------------------------------------- // Debug // ----------------------------------------------------------------------------- diff --git a/code/espurna/gpio.ino b/code/espurna/gpio.ino new file mode 100644 index 00000000..b9bfae8b --- /dev/null +++ b/code/espurna/gpio.ino @@ -0,0 +1,37 @@ +/* + +GPIO MODULE + +Copyright (C) 2017 by Xose PĂ©rez + +*/ + +bool _gpio_locked[16] = {false}; + +bool gpioValid(unsigned char gpio) { + if (0 <= gpio && gpio <= 5) return true; + if (12 <= gpio && gpio <= 15) return true; + return false; +} + +bool gpioGetLock(unsigned char gpio) { + if (gpioValid(gpio)) { + if (!_gpio_locked[gpio]) { + _gpio_locked[gpio] = true; + DEBUG_MSG_P(PSTR("[GPIO] GPIO%d locked\n"), gpio); + return true; + } + } + DEBUG_MSG_P(PSTR("[GPIO] Failed getting lock for GPIO%d\n"), gpio); + return false; +} + +bool gpioReleaseLock(unsigned char gpio) { + if (gpioValid(gpio)) { + _gpio_locked[gpio] = false; + DEBUG_MSG_P(PSTR("[GPIO] GPIO%d lock released\n"), gpio); + return true; + } + DEBUG_MSG_P(PSTR("[GPIO] Failed releasing lock for GPIO%d\n"), gpio); + return false; +} diff --git a/code/espurna/sensors/BaseSensor.h b/code/espurna/sensors/BaseSensor.h index b9ea6d46..e032024e 100644 --- a/code/espurna/sensors/BaseSensor.h +++ b/code/espurna/sensors/BaseSensor.h @@ -48,6 +48,7 @@ typedef enum magnitude_t { #define SENSOR_ERROR_UNKNOWN_ID 4 // Sensor did not report a known ID #define SENSOR_ERROR_CRC 5 // Sensor data corrupted #define SENSOR_ERROR_I2C 6 // Wrong or locked I2C address +#define SENSOR_ERROR_GPIO_USED 7 // The GPIO is already in use class BaseSensor { @@ -106,13 +107,6 @@ class BaseSensor { protected: - // Check if valid GPIO - bool _validGPIO(unsigned char gpio) { - if (0 <= gpio && gpio <= 5) return true; - if (12 <= gpio && gpio <= 15) return true; - return false; - } - unsigned char _sensor_id = 0x00; int _error = 0; bool _dirty = true; diff --git a/code/espurna/sensors/DHTSensor.h b/code/espurna/sensors/DHTSensor.h index b2486a00..d2c7e8cd 100644 --- a/code/espurna/sensors/DHTSensor.h +++ b/code/espurna/sensors/DHTSensor.h @@ -30,6 +30,10 @@ class DHTSensor : public BaseSensor { _sensor_id = SENSOR_DHTXX_ID; } + ~DHTSensor() { + if (_previous != 0xFF) gpioReleaseLock(_previous); + } + // --------------------------------------------------------------------- void setGPIO(unsigned char gpio) { @@ -54,6 +58,24 @@ class DHTSensor : public BaseSensor { // Sensor API // --------------------------------------------------------------------- + // Initialization method, must be idempotent + void begin() { + + _count = 0; + + // Manage GPIO lock + if (_previous != 0xFF) gpioReleaseLock(_previous); + _previous = 0xFF; + if (!gpioGetLock(_gpio)) { + _error = SENSOR_ERROR_GPIO_USED; + return; + } + _previous = _gpio; + + _count = 2; + + } + // Pre-read hook (usually to populate registers with up-to-date data) void pre() { _read(); @@ -194,6 +216,7 @@ class DHTSensor : public BaseSensor { } unsigned char _gpio; + unsigned char _previous = 0xFF; unsigned char _type; unsigned long _last_ok = 0; diff --git a/code/espurna/sensors/DallasSensor.h b/code/espurna/sensors/DallasSensor.h index 25faa50d..e01a86cf 100644 --- a/code/espurna/sensors/DallasSensor.h +++ b/code/espurna/sensors/DallasSensor.h @@ -39,6 +39,7 @@ class DallasSensor : public BaseSensor { ~DallasSensor() { if (_wire) delete _wire; + if (_previous != 0xFF) gpioReleaseLock(_previous); } // --------------------------------------------------------------------- @@ -65,6 +66,14 @@ class DallasSensor : public BaseSensor { if (!_dirty) return; _dirty = false; + // Manage GPIO lock + if (_previous != 0xFF) gpioReleaseLock(_previous); + _previous = 0xFF; + if (!gpioGetLock(_gpio)) { + _error = SENSOR_ERROR_GPIO_USED; + return; + } + // OneWire if (_wire) delete _wire; _wire = new OneWire(_gpio); @@ -78,6 +87,13 @@ class DallasSensor : public BaseSensor { loadDevices(); } + // Check connection + if (_count == 0) { + gpioReleaseLock(_gpio); + } else { + _previous = _gpio; + } + } // Loop-like method, call it in your main loop @@ -281,6 +297,7 @@ class DallasSensor : public BaseSensor { std::vector _devices; unsigned char _gpio; + unsigned char _previous = 0xFF; OneWire * _wire = NULL; }; diff --git a/code/espurna/sensors/ECH1560Sensor.h b/code/espurna/sensors/ECH1560Sensor.h index 63403069..cf95d550 100644 --- a/code/espurna/sensors/ECH1560Sensor.h +++ b/code/espurna/sensors/ECH1560Sensor.h @@ -303,7 +303,7 @@ static void (*_ech1560_sensor_isr_list[10])() = { }; void ECH1560Sensor::_attach(ECH1560Sensor * instance, unsigned char gpio, unsigned char mode) { - if (!_validGPIO(gpio)) return; + if (!gpioValid(gpio)) return; _detach(gpio); unsigned char index = gpio > 5 ? gpio-6 : gpio; _ech1560_sensor_instance[index] = instance; @@ -314,7 +314,7 @@ void ECH1560Sensor::_attach(ECH1560Sensor * instance, unsigned char gpio, unsign } void ECH1560Sensor::_detach(unsigned char gpio) { - if (!_validGPIO(gpio)) return; + if (!gpioValid(gpio)) return; unsigned char index = gpio > 5 ? gpio-6 : gpio; if (_ech1560_sensor_instance[index]) { detachInterrupt(gpio); diff --git a/code/espurna/sensors/EventSensor.h b/code/espurna/sensors/EventSensor.h index c14f92f9..985d07e3 100644 --- a/code/espurna/sensors/EventSensor.h +++ b/code/espurna/sensors/EventSensor.h @@ -177,7 +177,7 @@ static void (*_event_sensor_isr_list[10])() = { }; void EventSensor::_attach(EventSensor * instance, unsigned char gpio, unsigned char mode) { - if (!_validGPIO(gpio)) return; + if (!gpioValid(gpio)) return; _detach(gpio); unsigned char index = gpio > 5 ? gpio-6 : gpio; _event_sensor_instance[index] = instance; @@ -188,7 +188,7 @@ void EventSensor::_attach(EventSensor * instance, unsigned char gpio, unsigned c } void EventSensor::_detach(unsigned char gpio) { - if (!_validGPIO(gpio)) return; + if (!gpioValid(gpio)) return; unsigned char index = gpio > 5 ? gpio-6 : gpio; if (_event_sensor_instance[index]) { detachInterrupt(gpio); diff --git a/code/espurna/sensors/HLW8012Sensor.h b/code/espurna/sensors/HLW8012Sensor.h index 8a813b44..34729bd8 100644 --- a/code/espurna/sensors/HLW8012Sensor.h +++ b/code/espurna/sensors/HLW8012Sensor.h @@ -287,7 +287,7 @@ static void (*_hlw8012_sensor_isr_list[10])() = { }; void HLW8012Sensor::_attach(HLW8012Sensor * instance, unsigned char gpio, unsigned char mode) { - if (!_validGPIO(gpio)) return; + if (!gpioValid(gpio)) return; _detach(gpio); unsigned char index = gpio > 5 ? gpio-6 : gpio; _hlw8012_sensor_instance[index] = instance; @@ -298,7 +298,7 @@ void HLW8012Sensor::_attach(HLW8012Sensor * instance, unsigned char gpio, unsign } void HLW8012Sensor::_detach(unsigned char gpio) { - if (!_validGPIO(gpio)) return; + if (!gpioValid(gpio)) return; unsigned char index = gpio > 5 ? gpio-6 : gpio; if (_hlw8012_sensor_instance[index]) { detachInterrupt(gpio);