Skip to content

Instantly share code, notes, and snippets.

@ZeroSkill1
Created February 23, 2026 19:54
Show Gist options
  • Select an option

  • Save ZeroSkill1/cc150908cb713546b49f3d0874ae8b29 to your computer and use it in GitHub Desktop.

Select an option

Save ZeroSkill1/cc150908cb713546b49f3d0874ae8b29 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include "driver/i2c_slave.h"
#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "esp_event.h"
static i2c_slave_dev_handle_t handle = 0;
static QueueHandle_t event_queue = 0;
enum {
I2C_RECV = 0x1,
I2C_REQ = 0x2,
};
typedef struct {
enum {
i2c_txn_type_recv = 0,
i2c_txn_type_req = 1
} type;
union {
struct {
uint8_t buf[0x50];
uint8_t len;
} rx;
i2c_slave_request_event_data_t tx;
};
} i2c_txn_t;
bool i2c_slave_received(i2c_slave_dev_handle_t i2c_slave, const i2c_slave_rx_done_event_data_t *evt_data, void *arg) {
BaseType_t xTaskWoken = 0;
i2c_txn_t txn;
txn.type = i2c_txn_type_recv;
uint8_t maxsize = evt_data->length > sizeof(txn.rx.buf) ? sizeof(txn.rx.buf) : evt_data->length;
txn.rx.len = maxsize;
memcpy(txn.rx.buf, evt_data->buffer, maxsize);
xQueueSendFromISR(event_queue, &txn, &xTaskWoken);
return xTaskWoken;
}
bool i2c_slave_requested(i2c_slave_dev_handle_t i2c_slave, const i2c_slave_request_event_data_t *evt_data, void *arg) {
BaseType_t xTaskWoken = 0;
i2c_txn_t txn;
txn.type = i2c_txn_type_req;
xQueueSendFromISR(event_queue, &txn, &xTaskWoken);
return xTaskWoken;
}
static void i2c_slave_task(void *arg) {
while (1) {
i2c_txn_t txn;
if (xQueueReceive(event_queue, &txn, 10) == pdTRUE) {
if (txn.type == i2c_txn_type_recv) {
txn.rx.buf[txn.rx.len - 1] = 0;
printf("received data: %s\n", (char *)txn.rx.buf);
} else {
printf("received read request, sending back test\n");
uint32_t wlen = 0;
ESP_ERROR_CHECK(i2c_slave_write(handle, (const uint8_t *)"testing", sizeof("testing"), &wlen, 100));
}
}
}
vTaskDelete(NULL);
}
void app_main(void)
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
event_queue = xQueueCreate(16, sizeof(i2c_txn_t));
if (!event_queue) {
ESP_LOGE("i2cgdb", "failed to create queue");
return;
}
i2c_slave_config_t cfg = {
.i2c_port = 0,
.scl_io_num = GPIO_NUM_15,
.sda_io_num = GPIO_NUM_16,
.clk_source = I2C_CLK_SRC_DEFAULT,
.send_buf_depth = 100,
.receive_buf_depth = 100,
.slave_addr = 106,
.addr_bit_len = I2C_ADDR_BIT_LEN_7,
};
ESP_ERROR_CHECK(i2c_new_slave_device(&cfg, &handle));
i2c_slave_event_callbacks_t cbs = {
.on_receive = &i2c_slave_received,
.on_request = &i2c_slave_requested,
};
ESP_ERROR_CHECK(i2c_slave_register_event_callbacks(handle, &cbs, NULL));
xTaskCreate(i2c_slave_task, "i2c_slave_task", 1024 * 4, NULL, 10, NULL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment