Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I2C - Peripheral manager implementation #8220

Merged
merged 7 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion cores/esp32/esp32-hal-i2c-slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "hal/clk_gate_ll.h"
#include "esp32-hal-log.h"
#include "esp32-hal-i2c-slave.h"
#include "esp32-hal-periman.h"

#define I2C_SLAVE_USE_RX_QUEUE 0 // 1: Queue, 0: RingBuffer

Expand Down Expand Up @@ -194,7 +195,7 @@ static bool i2c_slave_handle_rx_fifo_full(i2c_slave_struct_t * i2c, uint32_t len
static size_t i2c_slave_read_rx(i2c_slave_struct_t * i2c, uint8_t * data, size_t len);
static void i2c_slave_isr_handler(void* arg);
static void i2c_slave_task(void *pv_args);

static bool i2cSlaveDetachBus(void * bus_i2c_num);

//=====================================================================================================================
//-------------------------------------- Public Functions -------------------------------------------------------------
Expand Down Expand Up @@ -231,6 +232,11 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t
frequency = 1000000;
}

perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_SLAVE, i2cSlaveDetachBus);
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_INIT, NULL) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}

log_i("Initialising I2C Slave: sda=%d scl=%d freq=%d, addr=0x%x", sda, scl, frequency, slaveID);

i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
Expand Down Expand Up @@ -344,6 +350,10 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t
i2c_ll_slave_enable_rx_it(i2c->dev);
i2c_ll_set_stretch(i2c->dev, 0x3FF);
i2c_ll_update(i2c->dev);
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE, (void *)(i2c->num+1)) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE, (void *)(i2c->num+1))){
i2cSlaveDetachBus((void *)(i2c->num+1));
P-R-O-C-H-Y marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
I2C_SLAVE_MUTEX_UNLOCK();
return ret;

Expand All @@ -367,7 +377,11 @@ esp_err_t i2cSlaveDeinit(uint8_t num){
}
#endif
I2C_SLAVE_MUTEX_LOCK();
int scl = i2c->scl;
int sda = i2c->sda;
i2c_slave_free_resources(i2c);
perimanSetPinBus(scl, ESP32_BUS_TYPE_INIT, NULL);
perimanSetPinBus(sda, ESP32_BUS_TYPE_INIT, NULL);
I2C_SLAVE_MUTEX_UNLOCK();
return ESP_OK;
}
Expand Down Expand Up @@ -846,3 +860,17 @@ static void i2c_slave_task(void *pv_args)
}
vTaskDelete(NULL);
}

static bool i2cSlaveDetachBus(void * bus_i2c_num){
uint8_t num = (int)bus_i2c_num - 1;
i2c_slave_struct_t * i2c = &_i2c_bus_array[num];
if (i2c->scl == -1 && i2c->sda == -1) {
return true;
}
esp_err_t err = i2cSlaveDeinit(num);
if(err != ESP_OK){
log_e("i2cSlaveDeinit failed with error: %d", err);
return false;
}
return true;
}
32 changes: 32 additions & 0 deletions cores/esp32/esp32-hal-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,33 @@
#include "hal/i2c_hal.h"
#include "hal/i2c_ll.h"
#include "driver/i2c.h"
#include "esp32-hal-periman.h"

typedef volatile struct {
bool initialized;
uint32_t frequency;
#if !CONFIG_DISABLE_HAL_LOCKS
SemaphoreHandle_t lock;
int8_t scl;
int8_t sda;
#endif
} i2c_bus_t;

static i2c_bus_t bus[SOC_I2C_NUM];

static bool i2cDetachBus(void * bus_i2c_num){
uint8_t i2c_num = (int)bus_i2c_num - 1;
if(!bus[i2c_num].initialized){
return true;
}
esp_err_t err = i2cDeinit(i2c_num);
if(err != ESP_OK){
log_e("i2cDeinit failed with error: %d", err);
return false;
}
return true;
}

bool i2cIsInit(uint8_t i2c_num){
if(i2c_num >= SOC_I2C_NUM){
return false;
Expand Down Expand Up @@ -72,6 +88,12 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency){
} else if(frequency > 1000000UL){
frequency = 1000000UL;
}

perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER, i2cDetachBus);
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_INIT, NULL) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}

log_i("Initialising I2C Master: sda=%d scl=%d freq=%d", sda, scl, frequency);

i2c_config_t conf = { };
Expand All @@ -93,8 +115,14 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency){
} else {
bus[i2c_num].initialized = true;
bus[i2c_num].frequency = frequency;
bus[i2c_num].scl = scl;
bus[i2c_num].sda = sda;
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER, (void *)(i2c_num+1)) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER, (void *)(i2c_num+1))){
i2cDetachBus((void *)(i2c_num+1));
return false;
}
}
}
#if !CONFIG_DISABLE_HAL_LOCKS
Expand Down Expand Up @@ -122,6 +150,10 @@ esp_err_t i2cDeinit(uint8_t i2c_num){
err = i2c_driver_delete((i2c_port_t)i2c_num);
if(err == ESP_OK){
bus[i2c_num].initialized = false;
perimanSetPinBus(bus[i2c_num].scl, ESP32_BUS_TYPE_INIT, NULL);
perimanSetPinBus(bus[i2c_num].sda, ESP32_BUS_TYPE_INIT, NULL);
bus[i2c_num].scl = -1;
bus[i2c_num].sda = -1;
}
}
#if !CONFIG_DISABLE_HAL_LOCKS
Expand Down