Fix #471
This commit is contained in:
		
							parent
							
								
									7cd1afc52d
								
							
						
					
					
						commit
						1d3ca574f1
					
				
					 6 changed files with 54 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue