diff --git a/cores/esp32/esp32-hal-i2c-slave.c b/cores/esp32/esp32-hal-i2c-slave.c index 9b54cce9b1d..7e64b4d817d 100644 --- a/cores/esp32/esp32-hal-i2c-slave.c +++ b/cores/esp32/esp32-hal-i2c-slave.c @@ -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 @@ -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 ------------------------------------------------------------- @@ -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]; @@ -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)); + ret = ESP_FAIL; + } I2C_SLAVE_MUTEX_UNLOCK(); return ret; @@ -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; } @@ -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; +} diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index c3f98e517bb..cd1ac0cdadd 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -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; @@ -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 = { }; @@ -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 @@ -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