From 1d3ca574f14374a5261319e0ce8c3a2625883b91 Mon Sep 17 00:00:00 2001 From: rus Date: Wed, 25 Oct 2017 12:58:00 +0500 Subject: [PATCH] Fix #471 --- examples/ds3231_test/ds3231_test.c | 2 +- extras/bmp180/bmp180.c | 4 +-- extras/bmp280/README.md | 3 +- extras/i2c/i2c.c | 55 ++++++++++++++++++------------ extras/i2c/i2c.h | 19 ++++++++--- extras/sht3x/README.md | 2 +- 6 files changed, 54 insertions(+), 31 deletions(-) diff --git a/examples/ds3231_test/ds3231_test.c b/examples/ds3231_test/ds3231_test.c index b6f41bb..aeef939 100644 --- a/examples/ds3231_test/ds3231_test.c +++ b/examples/ds3231_test/ds3231_test.c @@ -41,7 +41,7 @@ void user_init(void) printf("SDK version : %s\n", sdk_system_get_sdk_version()); printf("GIT version : %s\n", GITSHORTREV); - i2c_init(0,scl,sda,I2C_FREQ_400K); + i2c_init(0, scl, sda, I2C_FREQ_400K); xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL); } diff --git a/extras/bmp180/bmp180.c b/extras/bmp180/bmp180.c index 947772b..e1627a1 100644 --- a/extras/bmp180/bmp180.c +++ b/extras/bmp180/bmp180.c @@ -216,8 +216,8 @@ typedef struct } bmp180_command_t; // Just works due to the fact that QueueHandle_t is a "void *" -static QueueHandle_t bmp180_rx_queue[MAX_I2C_BUS] = { NULL }; -static TaskHandle_t bmp180_task_handle[MAX_I2C_BUS] = { NULL }; +static QueueHandle_t bmp180_rx_queue[I2C_MAX_BUS] = { NULL }; +static TaskHandle_t bmp180_task_handle[I2C_MAX_BUS] = { NULL }; // // Forward declarations diff --git a/extras/bmp280/README.md b/extras/bmp280/README.md index 09e0115..29d14f0 100644 --- a/extras/bmp280/README.md +++ b/extras/bmp280/README.md @@ -21,9 +21,10 @@ from it. Connect BMP280 or BME280 module to you ESP8266 module and initialize the I2C SCL and SDA pins: ``` +const uint8_t bus = 0; const uint8_t scl_pin = 0; const uint8_t sda_pin = 2; -i2c_init(scl_pin, sda_pin); +i2c_init(bus, scl_pin, sda_pin, I2C_FREQ_100K); ``` diff --git a/extras/i2c/i2c.c b/extras/i2c/i2c.c index 3ba0caf..6379736 100644 --- a/extras/i2c/i2c.c +++ b/extras/i2c/i2c.c @@ -38,7 +38,7 @@ #define debug(fmt, ...) #endif -#define CLK_STRETCH (10) +//#define CLK_STRETCH (10) // Following array contain delay values for different frequencies // Warning: 1 is minimal, that mean at 80MHz clock, frequency max is 320kHz @@ -60,22 +60,29 @@ typedef struct i2c_bus_description bool started; bool flag; bool force; + uint32_t clk_stretch; } i2c_bus_description_t; -static i2c_bus_description_t i2c_bus[MAX_I2C_BUS]; +static i2c_bus_description_t i2c_bus[I2C_MAX_BUS]; inline bool i2c_status(uint8_t bus) { return i2c_bus[bus].started; } -void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq) +int i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq) { + if (bus >= I2C_MAX_BUS) { + debug("Invalid bus"); + return -EINVAL; + } + i2c_bus[bus].started = false; i2c_bus[bus].flag = false; i2c_bus[bus].g_scl_pin = scl_pin; i2c_bus[bus].g_sda_pin = sda_pin; i2c_bus[bus].frequency = freq; + i2c_bus[bus].clk_stretch = I2C_DEFAULT_CLK_STRETCH; // Just to prevent these pins floating too much if not connected. gpio_set_pullup(i2c_bus[bus].g_scl_pin, 1, 1); @@ -90,16 +97,24 @@ void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq) // Prevent user, if frequency is high if (sdk_system_get_cpu_freq() == SYS_CPU_80MHZ) - if (i2c_freq_array[i2c_bus[bus].frequency][1] == 1) + if (i2c_freq_array[i2c_bus[bus].frequency][1] == 1) { debug("Max frequency is 320Khz at 80MHz"); + return -ENOTSUP; + } + return 0; } -void i2c_frequency(uint8_t bus, i2c_freq_t freq) +void i2c_set_frequency(uint8_t bus, i2c_freq_t freq) { i2c_bus[bus].frequency = freq; } +void i2c_set_clock_stretch(uint8_t bus, uint32_t clk_stretch) +{ + i2c_bus[bus].clk_stretch = clk_stretch; +} + static inline void i2c_delay(uint8_t bus) { uint32_t delay; @@ -159,7 +174,7 @@ void i2c_start(uint8_t bus) // Set SDA to 1 (void) read_sda(bus); i2c_delay(bus); - uint32_t clk_stretch = CLK_STRETCH; + uint32_t clk_stretch = i2c_bus[bus].clk_stretch; while (read_scl(bus) == 0 && clk_stretch--) ; // Repeated start setup time, minimum 4.7us @@ -178,7 +193,7 @@ void i2c_start(uint8_t bus) // Output stop condition bool i2c_stop(uint8_t bus) { - uint32_t clk_stretch = CLK_STRETCH; + uint32_t clk_stretch = i2c_bus[bus].clk_stretch; // Set SDA to 0 clear_sda(bus); i2c_delay(bus); @@ -203,7 +218,7 @@ bool i2c_stop(uint8_t bus) // Write a bit to I2C bus static void i2c_write_bit(uint8_t bus, bool bit) { - uint32_t clk_stretch = CLK_STRETCH; + uint32_t clk_stretch = i2c_bus[bus].clk_stretch; if (bit) { (void) read_sda(bus); } else { @@ -225,7 +240,7 @@ static void i2c_write_bit(uint8_t bus, bool bit) // Read a bit from I2C bus static bool i2c_read_bit(uint8_t bus) { - uint32_t clk_stretch = CLK_STRETCH; + uint32_t clk_stretch = i2c_bus[bus].clk_stretch; bool bit; // Let the slave drive data (void) read_sda(bus); @@ -272,24 +287,20 @@ static int i2c_bus_test(uint8_t bus) { taskENTER_CRITICAL(); // To prevent task swaping after checking flag and before set it! bool status = i2c_bus[bus].flag; // get current status - if(i2c_bus[bus].force) - { + if (i2c_bus[bus].force) { i2c_bus[bus].flag = true; // force bus on taskEXIT_CRITICAL(); - if(status) + if (status) i2c_stop(bus); //Bus was busy, stop it. } - else - { - if (status) - { + else { + if (status) { taskEXIT_CRITICAL(); debug("busy"); taskYIELD(); // If bus busy, change task to try finish last com. return -EBUSY; // If bus busy, inform user } - else - { + else { i2c_bus[bus].flag = true; // Set Bus busy taskEXIT_CRITICAL(); } @@ -299,12 +310,12 @@ static int i2c_bus_test(uint8_t bus) int i2c_slave_write(uint8_t bus, uint8_t slave_addr, const uint8_t *data, const uint8_t *buf, uint32_t len) { - if(i2c_bus_test(bus)) + if (i2c_bus_test(bus)) return -EBUSY; i2c_start(bus); if (!i2c_write(bus, slave_addr << 1)) goto error; - if(data != NULL) + if (data != NULL) if (!i2c_write(bus, *data)) goto error; while (len--) { @@ -325,9 +336,9 @@ error: int i2c_slave_read(uint8_t bus, uint8_t slave_addr, const uint8_t *data, uint8_t *buf, uint32_t len) { - if(i2c_bus_test(bus)) + if (i2c_bus_test(bus)) return -EBUSY; - if(data != NULL) { + if (data != NULL) { i2c_start(bus); if (!i2c_write(bus, slave_addr << 1)) goto error; diff --git a/extras/i2c/i2c.h b/extras/i2c/i2c.h index 80015a6..26e3926 100644 --- a/extras/i2c/i2c.h +++ b/extras/i2c/i2c.h @@ -40,10 +40,12 @@ extern "C" { /** * Define i2c bus max number */ -#ifndef MAX_I2C_BUS - #define MAX_I2C_BUS 2 +#ifndef I2C_MAX_BUS + #define I2C_MAX_BUS 2 #endif +#define I2C_DEFAULT_CLK_STRETCH (10) + typedef enum { I2C_FREQ_80K = 0,//!< I2C_FREQ_80K @@ -69,15 +71,24 @@ typedef struct i2c_dev * @param scl_pin SCL pin for I2C * @param sda_pin SDA pin for I2C * @param freq frequency of bus (ex : I2C_FREQ_400K) + * @param clk_stretch I2C clock stretch. I2C_DEFAULT_CLK_STRETCH would be good in most cases + * @return Non-zero if error occured */ -void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq); +int i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq); /** * Change bus frequency * @param bus Bus i2c selection * @param freq frequency of bus (ex : I2C_FREQ_400K) */ -void i2c_frequency(uint8_t bus, i2c_freq_t freq); +void i2c_set_frequency(uint8_t bus, i2c_freq_t freq); + +/** + * Change clock stretch + * @param bus I2C bus + * @param clk_stretch I2C clock stretch. I2C_DEFAULT_CLK_STRETCH by default + */ +void i2c_set_clock_stretch(uint8_t bus, uint32_t clk_stretch); /** * Write a byte to I2C bus. diff --git a/extras/sht3x/README.md b/extras/sht3x/README.md index c8cd13c..e303c67 100644 --- a/extras/sht3x/README.md +++ b/extras/sht3x/README.md @@ -83,7 +83,7 @@ Before using the SHT3x driver, function ```i2c_init``` needs to be called for ea #define I2C_SDA_PIN GPIO_ID_PIN((4)) ... -i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K)) +i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_100K) ... ```