9#include "freertos/FreeRTOS.h"
10#include "freertos/task.h"
13static const char*
TAG =
"I2cBus";
34 I2cBusImpl(i2c_port_t port, gpio_num_t sda, gpio_num_t scl,
const char*
name)
35 : port_(port), sda_(sda), scl_(scl), name_(
name) {}
42 const char*
getName()
const override {
return name_; }
47 const uint8_t* data,
size_t len)
override;
49 uint8_t* data,
size_t len)
override;
50 esp_err_t
writeRaw(uint8_t addr,
const uint8_t* data,
size_t len)
override;
51 esp_err_t
readRaw(uint8_t addr, uint8_t* data,
size_t len)
override;
52 esp_err_t
writeReadRaw(uint8_t addr,
const uint8_t* wr,
size_t wr_len,
53 uint8_t* rd,
size_t rd_len)
override;
54 bool probe(uint8_t addr)
override;
55 esp_err_t
eepromRead(uint8_t addr, uint16_t offset, uint8_t* buf,
size_t len)
override;
56 esp_err_t
eepromWrite(uint8_t addr, uint16_t offset,
const uint8_t* buf,
size_t len)
override;
66 static constexpr size_t MAX_DEVICES = 4;
68 size_t deviceCount_ = 0;
80 i2c_config_t conf = {};
81 conf.mode = I2C_MODE_MASTER;
82 conf.sda_io_num = sda_;
83 conf.scl_io_num = scl_;
84 conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
85 conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
89 esp_err_t err = i2c_param_config(port_, &conf);
91 LOG_E(
TAG,
"%s: i2c_param_config failed: %d", name_, err);
96 err = i2c_driver_install(port_, I2C_MODE_MASTER, 0, 0, 0);
98 LOG_E(
TAG,
"%s: i2c_driver_install failed: %d", name_, err);
104 LOG_I(
TAG,
"%s initialized (SDA=%d, SCL=%d)", name_, sda_, scl_);
115 if (deviceCount_ >= MAX_DEVICES) {
116 LOG_E(
TAG,
"%s: device pool full", name_);
117 return ESP_ERR_NO_MEM;
120 I2cDevice* dev = &devices_[deviceCount_++];
125 LOG_I(
TAG,
"%s: added device at 0x%02X", name_, addr);
138 const uint8_t* data,
size_t len) {
139 auto* dev =
static_cast<I2cDevice*
>(handle);
140 if (!dev)
return ESP_ERR_INVALID_ARG;
142 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
143 i2c_master_start(cmd);
144 i2c_master_write_byte(cmd, (dev->addr << 1) | I2C_MASTER_WRITE,
true);
145 i2c_master_write_byte(cmd, reg,
true);
146 if (data && len > 0) {
147 i2c_master_write(cmd, data, len,
true);
149 i2c_master_stop(cmd);
151 esp_err_t err = i2c_master_cmd_begin(dev->port, cmd, pdMS_TO_TICKS(
I2C_TIMEOUT_MS));
152 i2c_cmd_link_delete(cmd);
166 uint8_t* data,
size_t len) {
167 auto* dev =
static_cast<I2cDevice*
>(handle);
168 if (!dev || !data || len == 0)
return ESP_ERR_INVALID_ARG;
171 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
172 i2c_master_start(cmd);
173 i2c_master_write_byte(cmd, (dev->addr << 1) | I2C_MASTER_WRITE,
true);
174 i2c_master_write_byte(cmd, reg,
true);
177 i2c_master_start(cmd);
178 i2c_master_write_byte(cmd, (dev->addr << 1) | I2C_MASTER_READ,
true);
180 i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK);
182 i2c_master_read_byte(cmd, data + len - 1, I2C_MASTER_NACK);
183 i2c_master_stop(cmd);
185 esp_err_t err = i2c_master_cmd_begin(dev->port, cmd, pdMS_TO_TICKS(
I2C_TIMEOUT_MS));
186 i2c_cmd_link_delete(cmd);
192 if (!data && len > 0)
return ESP_ERR_INVALID_ARG;
193 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
194 i2c_master_start(cmd);
195 i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE,
true);
196 if (len > 0) i2c_master_write(cmd, data, len,
true);
197 i2c_master_stop(cmd);
198 esp_err_t err = i2c_master_cmd_begin(port_, cmd, pdMS_TO_TICKS(
I2C_TIMEOUT_MS));
199 i2c_cmd_link_delete(cmd);
204 if (!data || len == 0)
return ESP_ERR_INVALID_ARG;
205 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
206 i2c_master_start(cmd);
207 i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ,
true);
208 i2c_master_read(cmd, data, len, I2C_MASTER_LAST_NACK);
209 i2c_master_stop(cmd);
210 esp_err_t err = i2c_master_cmd_begin(port_, cmd, pdMS_TO_TICKS(
I2C_TIMEOUT_MS));
211 i2c_cmd_link_delete(cmd);
216 uint8_t* rd,
size_t rd_len) {
217 if ((!wr && wr_len > 0) || !rd || rd_len == 0)
return ESP_ERR_INVALID_ARG;
218 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
219 i2c_master_start(cmd);
220 i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE,
true);
221 if (wr_len > 0) i2c_master_write(cmd, wr, wr_len,
true);
222 i2c_master_start(cmd);
223 i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ,
true);
224 i2c_master_read(cmd, rd, rd_len, I2C_MASTER_LAST_NACK);
225 i2c_master_stop(cmd);
226 esp_err_t err = i2c_master_cmd_begin(port_, cmd, pdMS_TO_TICKS(
I2C_TIMEOUT_MS));
227 i2c_cmd_link_delete(cmd);
232 i2c_cmd_handle_t cmd = i2c_cmd_link_create();
233 i2c_master_start(cmd);
234 i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE,
true);
235 i2c_master_stop(cmd);
236 esp_err_t err = i2c_master_cmd_begin(port_, cmd, pdMS_TO_TICKS(20));
237 i2c_cmd_link_delete(cmd);
238 return err == ESP_OK;
242 if (!buf || len == 0)
return ESP_ERR_INVALID_ARG;
243 uint8_t reg[2] = {
static_cast<uint8_t
>(offset >> 8),
static_cast<uint8_t
>(offset & 0xff) };
248 if (!buf || len == 0)
return ESP_ERR_INVALID_ARG;
249 constexpr size_t PAGE = 16;
251 while (written < len) {
252 uint16_t cur =
static_cast<uint16_t
>(offset + written);
253 size_t room = PAGE - (cur % PAGE);
254 size_t chunk = (len - written < room) ? (len - written) : room;
255 uint8_t frame[2 + PAGE];
256 frame[0] =
static_cast<uint8_t
>(cur >> 8);
257 frame[1] =
static_cast<uint8_t
>(cur & 0xff);
258 for (
size_t i = 0; i < chunk; ++i) frame[2 + i] = buf[written + i];
259 esp_err_t err =
writeRaw(addr, frame, 2 + chunk);
260 if (err != ESP_OK)
return err;
261 vTaskDelay(pdMS_TO_TICKS(5));
char name[cdc::hal::ISecureElement::RMEM_NAME_LEN]
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_I(tag, fmt,...)
#define LOG_E(tag, fmt,...)
core::ServiceState getState() const override
esp_err_t writeReadRaw(uint8_t addr, const uint8_t *wr, size_t wr_len, uint8_t *rd, size_t rd_len) override
bool init() override
Initializes hardware I2C controller and driver.
esp_err_t readRaw(uint8_t addr, uint8_t *data, size_t len) override
bool probe(uint8_t addr) override
esp_err_t addDevice(uint8_t addr, I2cDeviceHandle *out_dev) override
Registers an I2C target device in static device pool.
const char * getName() const override
esp_err_t eepromRead(uint8_t addr, uint16_t offset, uint8_t *buf, size_t len) override
esp_err_t writeRaw(uint8_t addr, const uint8_t *data, size_t len) override
I2cBusImpl(i2c_port_t port, gpio_num_t sda, gpio_num_t scl, const char *name)
esp_err_t eepromWrite(uint8_t addr, uint16_t offset, const uint8_t *buf, size_t len) override
esp_err_t writeReg(I2cDeviceHandle dev, uint8_t reg, const uint8_t *data, size_t len) override
Writes bytes to a register of an I2C device.
esp_err_t readReg(I2cDeviceHandle dev, uint8_t reg, uint8_t *data, size_t len) override
Reads bytes from a register of an I2C device.
II2cBus * getI2cBus1()
Returns singleton instance of I2C bus 1.
II2cBus * getI2cBus0()
Returns singleton instance of I2C bus 0.
static constexpr uint32_t I2C_TIMEOUT_MS
static I2cBusImpl g_i2c0(I2C_NUM_0, I2C0_SDA_PIN, I2C0_SCL_PIN, "i2c0")
Singleton instances for both hardware I2C ports.
static constexpr uint32_t I2C_FREQ_HZ
I2C bus timing configuration constants.
static I2cBusImpl g_i2c1(I2C_NUM_1, I2C1_SDA_PIN, I2C1_SCL_PIN, "i2c1")