6#include "esp_clk_tree.h"
7#include "esp_private/periph_ctrl.h"
8#include "esp_rom_gpio.h"
9#include "esp_rom_sys.h"
11#include "libxr_def.hpp"
12#include "timebase.hpp"
19constexpr uint8_t ACK_VALUE = I2C_MASTER_ACK;
20constexpr uint8_t NACK_VALUE = I2C_MASTER_NACK;
21constexpr uint8_t CHECK_ACK = 1U;
22constexpr uint8_t NO_CHECK_ACK = 0U;
24uint64_t ToTimeoutUs(uint32_t timeout_ms)
26 return (timeout_ms == UINT32_MAX) ? UINT64_MAX
27 :
static_cast<uint64_t
>(timeout_ms) * 1000ULL;
32inline void SetBusClockAtomic(i2c_port_t port,
bool enable)
35#pragma GCC diagnostic push
36#pragma GCC diagnostic ignored "-Wunused-variable"
38 PERIPH_RCC_ATOMIC() { i2c_ll_enable_bus_clock(port, enable); }
40#pragma GCC diagnostic pop
44inline void ResetBusRegisterAtomic(i2c_port_t port)
47#pragma GCC diagnostic push
48#pragma GCC diagnostic ignored "-Wunused-variable"
50 PERIPH_RCC_ATOMIC() { i2c_ll_reset_register(port); }
52#pragma GCC diagnostic pop
56void WriteCommand(i2c_dev_t* dev,
int cmd_idx, uint8_t op_code, uint8_t ack_val,
57 uint8_t ack_exp, uint8_t ack_en, uint8_t byte_num)
59 i2c_ll_hw_cmd_t cmd = {};
60 cmd.op_code = op_code;
61 cmd.ack_val = ack_val;
62 cmd.ack_exp = ack_exp;
64 cmd.byte_num = byte_num;
65 i2c_ll_master_write_cmd_reg(dev, cmd, cmd_idx);
68ErrorCode WaitSegmentDone(i2c_hal_context_t& hal,
int done_cmd_idx, uint64_t timeout_us)
70 const uint64_t start_us = GetNowUs();
72 auto recover_after_error = [&]()
74 i2c_ll_clear_intr_mask(hal.dev, I2C_LL_INTR_MASK);
75 i2c_hal_master_fsm_rst(&hal);
76 i2c_ll_update(hal.dev);
81 const uint32_t intr = hal.dev->int_raw.val;
83 if ((intr & I2C_LL_INTR_NACK) != 0U)
85 recover_after_error();
88 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
90 recover_after_error();
93 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
95 recover_after_error();
99 if (i2c_ll_master_is_cmd_done(hal.dev, done_cmd_idx) ||
100 ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) != 0U))
105 if ((timeout_us != UINT64_MAX) && ((GetNowUs() - start_us) > timeout_us))
107 recover_after_error();
113ErrorCode StartAndWaitSegment(i2c_hal_context_t& hal,
int done_cmd_idx,
116 i2c_ll_clear_intr_mask(hal.dev, I2C_LL_INTR_MASK);
117 i2c_hal_master_trans_start(&hal);
118 return WaitSegmentDone(hal, done_cmd_idx, timeout_us);
121template <
typename OperationType>
126 if (op.type != OperationType::OperationType::BLOCK)
128 op.UpdateStatus(in_isr, result);
135ESP32I2C::ESP32I2C(i2c_port_t port_num,
int scl_pin,
int sda_pin, uint32_t clock_speed,
136 bool enable_internal_pullup, uint32_t timeout_ms,
137 uint32_t isr_enable_min_size)
138 : port_num_(port_num),
141 enable_internal_pullup_(enable_internal_pullup),
142 timeout_ms_(timeout_ms),
143 isr_enable_min_size_(isr_enable_min_size),
146 ASSERT(port_num_ >= 0);
147 ASSERT(port_num_ < SOC_I2C_NUM);
148 ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(scl_pin_)));
149 ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(sda_pin_)));
150 ASSERT(config_.clock_speed > 0U);
151 static_assert(FIFO_LEN > 2U);
153 if (InitHardware() != ErrorCode::OK)
160bool ESP32I2C::Acquire() {
return !busy_.TestAndSet(); }
162void ESP32I2C::Release() { busy_.Clear(); }
164bool ESP32I2C::IsValid7BitAddr(uint16_t addr) {
return addr <= 0x7FU; }
166ErrorCode ESP32I2C::EnsureInitialized(
bool in_isr)
170 return ErrorCode::OK;
174 return ErrorCode::INIT_ERR;
176 return InitHardware();
179size_t ESP32I2C::MemAddrBytes(MemAddrLength mem_addr_size)
181 return (mem_addr_size == MemAddrLength::BYTE_16) ? 2U : 1U;
184void ESP32I2C::EncodeMemAddr(uint16_t mem_addr,
size_t mem_len, uint8_t* out)
186 DEV_ASSERT(out !=
nullptr);
189 out[0] =
static_cast<uint8_t
>((mem_addr >> 8) & 0xFFU);
190 out[1] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
194 out[0] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
197ErrorCode ESP32I2C::ResolveClockSource(uint32_t& source_hz)
200 const esp_err_t err =
201 esp_clk_tree_src_get_freq_hz(
static_cast<soc_module_clk_t
>(I2C_CLK_SRC_DEFAULT),
202 ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &source_hz);
203 if ((err != ESP_OK) || (source_hz == 0U))
205 return ErrorCode::INIT_ERR;
207 return ErrorCode::OK;
212 if ((hal_.dev ==
nullptr) || (config_.clock_speed == 0U))
214 return ErrorCode::ARG_ERR;
217 uint32_t source_clock_hz = 0U;
218 if (ResolveClockSource(source_clock_hz) != ErrorCode::OK)
220 return ErrorCode::INIT_ERR;
225 if (config_.clock_speed > 400000U || config_.clock_speed > source_clock_hz / 28U)
227 return ErrorCode::NOT_SUPPORT;
229#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
231 if (source_clock_hz / config_.clock_speed / 2U > I2C_SCL_START_HOLD_TIME_V)
233 return ErrorCode::NOT_SUPPORT;
237 if (source_clock_hz / (config_.clock_speed * 1024U) + 1U > 256U)
239 return ErrorCode::NOT_SUPPORT;
243 source_clock_hz_ = source_clock_hz;
244 PERIPH_RCC_ATOMIC() { i2c_ll_set_source_clk(hal_.dev, I2C_CLK_SRC_DEFAULT); }
246 i2c_ll_master_set_filter(hal_.dev, 7U);
247 _i2c_hal_set_bus_timing(&hal_,
static_cast<int>(config_.clock_speed),
248 I2C_CLK_SRC_DEFAULT,
static_cast<int>(source_clock_hz_));
249 i2c_ll_update(hal_.dev);
251 return ErrorCode::OK;
258 return ErrorCode::OK;
261 if ((port_num_ < 0) || (port_num_ >= SOC_I2C_NUM) ||
262 (
static_cast<size_t>(port_num_) >= SOC_I2C_NUM))
264 return ErrorCode::OUT_OF_RANGE;
267 if (!GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(scl_pin_)) ||
268 !GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(sda_pin_)))
270 return ErrorCode::ARG_ERR;
273 SetBusClockAtomic(port_num_,
true);
274 ResetBusRegisterAtomic(port_num_);
276 _i2c_hal_init(&hal_,
static_cast<int>(port_num_));
277 if (hal_.dev ==
nullptr)
279 return ErrorCode::INIT_ERR;
282 i2c_hal_master_init(&hal_);
283 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
284 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
287 if (err != ErrorCode::OK)
292 err = InstallInterrupt();
293 if (err != ErrorCode::OK)
299 if (err != ErrorCode::OK)
305 return ErrorCode::OK;
310 if (hal_.dev ==
nullptr)
312 return ErrorCode::STATE_ERR;
315 const auto& sig = i2c_periph_signal[port_num_];
316 const gpio_num_t sda_gpio =
static_cast<gpio_num_t
>(sda_pin_);
317 const gpio_num_t scl_gpio =
static_cast<gpio_num_t
>(scl_pin_);
319 gpio_set_level(sda_gpio, 1);
320 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(sda_pin_));
321 gpio_set_direction(sda_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
322 gpio_set_pull_mode(sda_gpio,
323 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
324 esp_rom_gpio_connect_out_signal(sda_pin_, sig.sda_out_sig,
false,
false);
325 esp_rom_gpio_connect_in_signal(sda_pin_, sig.sda_in_sig,
false);
327 gpio_set_level(scl_gpio, 1);
328 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(scl_pin_));
329 gpio_set_direction(scl_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
330 gpio_set_pull_mode(scl_gpio,
331 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
332 esp_rom_gpio_connect_out_signal(scl_pin_, sig.scl_out_sig,
false,
false);
333 esp_rom_gpio_connect_in_signal(scl_pin_, sig.scl_in_sig,
false);
335 return ErrorCode::OK;
340 if (hal_.dev ==
nullptr)
342 return ErrorCode::INIT_ERR;
345#if SOC_I2C_SUPPORT_HW_FSM_RST
346 i2c_hal_master_fsm_rst(&hal_);
347 i2c_ll_update(hal_.dev);
352 ResetBusRegisterAtomic(port_num_);
353 i2c_hal_master_init(&hal_);
354 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
355 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
356 const ErrorCode config_ec = ApplyConfig();
357 if (config_ec != ErrorCode::OK)
363#if SOC_I2C_SUPPORT_HW_CLR_BUS
364 constexpr uint64_t BUS_CLEAR_TIMEOUT_US = 50000ULL;
365 const uint64_t start_us = GetNowUs();
366 i2c_ll_master_clr_bus(hal_.dev, I2C_LL_RESET_SLV_SCL_PULSE_NUM_DEFAULT,
true);
367 while (i2c_ll_master_is_bus_clear_done(hal_.dev))
369 if ((GetNowUs() - start_us) > BUS_CLEAR_TIMEOUT_US)
371 i2c_ll_master_clr_bus(hal_.dev, 0,
false);
372 i2c_ll_update(hal_.dev);
373 return ErrorCode::TIMEOUT;
376 i2c_ll_update(hal_.dev);
381 constexpr int BUS_CLEAR_SCL_PULSES = 9;
382 constexpr uint32_t BUS_CLEAR_HALF_PERIOD_US = 5U;
384 const gpio_num_t scl_gpio =
static_cast<gpio_num_t
>(scl_pin_);
385 const gpio_num_t sda_gpio =
static_cast<gpio_num_t
>(sda_pin_);
386 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(scl_pin_));
387 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(sda_pin_));
388 gpio_set_level(scl_gpio, 0);
389 gpio_set_level(sda_gpio, 1);
390 gpio_set_direction(scl_gpio, GPIO_MODE_OUTPUT_OD);
391 gpio_set_direction(sda_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
392 gpio_set_pull_mode(scl_gpio,
393 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
394 gpio_set_pull_mode(sda_gpio,
395 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
396 esp_rom_delay_us(BUS_CLEAR_HALF_PERIOD_US);
399 while ((gpio_get_level(sda_gpio) == 0) && (pulse_count++ < BUS_CLEAR_SCL_PULSES))
401 gpio_set_level(scl_gpio, 1);
402 esp_rom_delay_us(BUS_CLEAR_HALF_PERIOD_US);
403 gpio_set_level(scl_gpio, 0);
404 esp_rom_delay_us(BUS_CLEAR_HALF_PERIOD_US);
408 gpio_set_level(sda_gpio, 0);
409 gpio_set_level(scl_gpio, 1);
410 esp_rom_delay_us(BUS_CLEAR_HALF_PERIOD_US);
411 gpio_set_level(sda_gpio, 1);
412 esp_rom_delay_us(BUS_CLEAR_HALF_PERIOD_US);
417 const ErrorCode pin_ec = ConfigurePins();
418 if (pin_ec != ErrorCode::OK)
423 return ErrorCode::OK;
426bool ESP32I2C::ShouldUseInterruptAsync(
size_t total_size)
const
428 if (!intr_installed_)
432 return (isr_enable_min_size_ > 0U) &&
433 (total_size >=
static_cast<size_t>(isr_enable_min_size_));
436ErrorCode ESP32I2C::StartAsyncTransaction(uint16_t slave_addr,
437 const uint8_t* write_prefix_payload,
438 size_t write_prefix_size,
439 const uint8_t* write_payload,
size_t write_size,
440 uint8_t* read_payload,
size_t read_size,
441 ReadOperation& op,
bool in_isr)
443 if (!initialized_ || (hal_.dev ==
nullptr))
445 return ErrorCode::INIT_ERR;
447 if (!IsValid7BitAddr(slave_addr))
449 return ErrorCode::ARG_ERR;
451 if ((write_prefix_size > 0U) && (write_prefix_payload ==
nullptr))
453 return ErrorCode::PTR_NULL;
455 if (write_prefix_size > async_write_prefix_.size())
457 return ErrorCode::SIZE_ERR;
459 if ((write_size > 0U) && (write_payload ==
nullptr))
461 return ErrorCode::PTR_NULL;
463 if ((read_size > 0U) && (read_payload ==
nullptr))
465 return ErrorCode::PTR_NULL;
469 return ErrorCode::BUSY;
472 if (i2c_ll_is_bus_busy(hal_.dev))
476 return ErrorCode::BUSY;
478 const ErrorCode ec = RecoverController();
479 if (ec != ErrorCode::OK)
485 i2c_ll_txfifo_rst(hal_.dev);
486 i2c_ll_rxfifo_rst(hal_.dev);
487 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
488 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
492 async_running_ =
true;
493 async_slave_addr_ = slave_addr;
494 async_write_prefix_size_ = write_prefix_size;
495 async_write_prefix_offset_ = 0U;
496 if (write_prefix_size > 0U)
498 Memory::FastCopy(async_write_prefix_.data(), write_prefix_payload, write_prefix_size);
500 async_write_payload_ = write_payload;
501 async_write_size_ = write_size;
502 async_write_offset_ = 0U;
503 async_read_payload_ = read_payload;
504 async_read_size_ = read_size;
505 async_read_offset_ = 0U;
506 async_pending_read_chunk_ = 0U;
507 async_write_phase_done_ =
508 !((write_prefix_size > 0U) || (write_size > 0U) || (read_size == 0U));
509 async_write_addr_sent_ =
false;
510 async_write_stop_sent_ =
false;
511 async_read_addr_sent_ =
false;
513 const ErrorCode kick = KickAsyncTransaction();
514 if ((kick == ErrorCode::PENDING) || (kick == ErrorCode::OK))
516 if (kick == ErrorCode::OK)
518 FinishAsync(
false, ErrorCode::OK);
520 return ErrorCode::OK;
523 async_running_ =
false;
524 async_write_prefix_size_ = 0U;
525 async_write_prefix_offset_ = 0U;
526 async_write_payload_ =
nullptr;
527 async_write_size_ = 0U;
528 async_write_offset_ = 0U;
529 async_read_payload_ =
nullptr;
530 async_read_size_ = 0U;
531 async_read_offset_ = 0U;
532 async_pending_read_chunk_ = 0U;
533 async_write_phase_done_ =
true;
534 async_write_addr_sent_ =
false;
535 async_write_stop_sent_ =
false;
536 async_read_addr_sent_ =
false;
540ErrorCode ESP32I2C::KickAsyncTransaction()
542 if (!async_running_ || (hal_.dev ==
nullptr))
544 return ErrorCode::STATE_ERR;
547 const uint8_t write_addr =
548 static_cast<uint8_t
>((async_slave_addr_ << 1U) | I2C_MASTER_WRITE);
549 const uint8_t read_addr =
550 static_cast<uint8_t
>((async_slave_addr_ << 1U) | I2C_MASTER_READ);
551 const size_t fifo_len = FIFO_LEN;
552 const size_t write_chunk_cap = (fifo_len > 1U) ? (fifo_len - 1U) : 0U;
553 static_assert(write_chunk_cap > 0U);
557 if (async_pending_read_chunk_ > 0U)
559 i2c_ll_read_rxfifo(hal_.dev, async_read_payload_ + async_read_offset_,
560 static_cast<uint8_t
>(async_pending_read_chunk_));
561 async_read_offset_ += async_pending_read_chunk_;
562 async_pending_read_chunk_ = 0U;
567 if (!async_write_phase_done_)
569 if (!async_write_addr_sent_)
571 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
573 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
574 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
576 async_write_addr_sent_ =
true;
579 if (async_write_prefix_offset_ < async_write_prefix_size_)
581 const size_t chunk = std::min(
582 async_write_prefix_size_ - async_write_prefix_offset_, write_chunk_cap);
583 i2c_ll_write_txfifo(hal_.dev,
584 async_write_prefix_.data() + async_write_prefix_offset_,
585 static_cast<uint8_t
>(chunk));
586 async_write_prefix_offset_ += chunk;
588 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
589 CHECK_ACK,
static_cast<uint8_t
>(chunk));
590 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
593 else if (async_write_offset_ < async_write_size_)
596 std::min(async_write_size_ - async_write_offset_, write_chunk_cap);
597 i2c_ll_write_txfifo(hal_.dev, async_write_payload_ + async_write_offset_,
598 static_cast<uint8_t
>(chunk));
599 async_write_offset_ += chunk;
601 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
602 CHECK_ACK,
static_cast<uint8_t
>(chunk));
603 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
606 else if (async_read_size_ == 0U)
608 if (!async_write_stop_sent_)
610 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
612#if SOC_I2C_STOP_INDEPENDENT
613 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
616 async_write_stop_sent_ =
true;
618 async_write_phase_done_ = async_write_stop_sent_;
622 async_write_phase_done_ =
true;
627 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
628 i2c_ll_enable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
629 i2c_hal_master_trans_start(&hal_);
630 return ErrorCode::PENDING;
636 if (async_read_size_ > 0U)
638 if (!async_read_addr_sent_)
640 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
642 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
643 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
645 async_read_addr_sent_ =
true;
648 if (async_read_offset_ < async_read_size_)
650 const size_t chunk = std::min(async_read_size_ - async_read_offset_, fifo_len);
651 const bool is_last = (async_read_offset_ + chunk) >= async_read_size_;
655 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
656 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk));
657 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
660 else if (chunk == 1U)
662 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
667 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
668 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk - 1U));
669 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
675 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
677#if SOC_I2C_STOP_INDEPENDENT
678 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
683 async_pending_read_chunk_ = chunk;
688 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
689 i2c_ll_enable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
690 i2c_hal_master_trans_start(&hal_);
691 return ErrorCode::PENDING;
695 return ErrorCode::OK;
699void ESP32I2C::FinishAsync(
bool in_isr, ErrorCode ec)
706 if (hal_.dev !=
nullptr)
708 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
709 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
714 async_running_ =
false;
715 async_write_prefix_size_ = 0U;
716 async_write_prefix_offset_ = 0U;
717 async_write_payload_ =
nullptr;
718 async_write_size_ = 0U;
719 async_write_offset_ = 0U;
720 async_read_payload_ =
nullptr;
721 async_read_size_ = 0U;
722 async_read_offset_ = 0U;
723 async_pending_read_chunk_ = 0U;
724 async_write_phase_done_ =
true;
725 async_write_addr_sent_ =
false;
726 async_write_stop_sent_ =
false;
727 async_read_addr_sent_ =
false;
730 if (op.type == ReadOperation::OperationType::BLOCK)
732 (void)block_wait_.TryPost(in_isr, ec);
736 op.UpdateStatus(in_isr, ec);
744 return ErrorCode::OK;
747 const int irq = i2c_periph_signal[port_num_].irq;
750 return ErrorCode::NOT_SUPPORT;
753 if (esp_intr_alloc(irq, 0, I2cIsrEntry,
this, &intr_handle_) != ESP_OK)
755 intr_handle_ =
nullptr;
756 return ErrorCode::INIT_ERR;
759 intr_installed_ =
true;
760 return ErrorCode::OK;
763void ESP32I2C::I2cIsrEntry(
void* arg)
765 auto* self =
static_cast<ESP32I2C*
>(arg);
768 self->HandleInterrupt();
772void ESP32I2C::HandleInterrupt()
774 if (hal_.dev ==
nullptr)
779 const uint32_t intr = hal_.dev->int_raw.val;
780 if ((intr & I2C_LL_MASTER_EVENT_INTR) == 0U)
787 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
788 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
792 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
793 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
795 if ((intr & I2C_LL_INTR_NACK) != 0U)
797 i2c_hal_master_fsm_rst(&hal_);
798 i2c_ll_update(hal_.dev);
799 FinishAsync(
true, ErrorCode::NO_RESPONSE);
802 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
804 i2c_hal_master_fsm_rst(&hal_);
805 i2c_ll_update(hal_.dev);
806 FinishAsync(
true, ErrorCode::TIMEOUT);
809 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
811 i2c_hal_master_fsm_rst(&hal_);
812 i2c_ll_update(hal_.dev);
813 FinishAsync(
true, ErrorCode::FAILED);
817 if ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) == 0U)
822 const ErrorCode kick = KickAsyncTransaction();
823 if (kick == ErrorCode::PENDING)
828 FinishAsync(
true, kick);
831ErrorCode ESP32I2C::ExecuteTransaction(uint16_t slave_addr,
const uint8_t* write_payload,
832 size_t write_size, uint8_t* read_payload,
833 size_t read_size,
bool in_isr)
835 if (!initialized_ || (hal_.dev ==
nullptr))
837 return ErrorCode::INIT_ERR;
839 if (!IsValid7BitAddr(slave_addr))
841 return ErrorCode::ARG_ERR;
843 if ((write_size > 0U) && (write_payload ==
nullptr))
845 return ErrorCode::PTR_NULL;
847 if ((read_size > 0U) && (read_payload ==
nullptr))
849 return ErrorCode::PTR_NULL;
852 if (i2c_ll_is_bus_busy(hal_.dev))
856 return ErrorCode::BUSY;
858 const ErrorCode ec = RecoverController();
859 if (ec != ErrorCode::OK)
865 i2c_ll_txfifo_rst(hal_.dev);
866 i2c_ll_rxfifo_rst(hal_.dev);
867 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
869 const uint64_t timeout_us = ToTimeoutUs(timeout_ms_);
870 const uint8_t write_addr =
static_cast<uint8_t
>((slave_addr << 1U) | I2C_MASTER_WRITE);
871 const uint8_t read_addr =
static_cast<uint8_t
>((slave_addr << 1U) | I2C_MASTER_READ);
872 const size_t fifo_len = FIFO_LEN;
873 const size_t write_chunk_cap = (fifo_len > 1U) ? (fifo_len - 1U) : 0U;
874 static_assert(write_chunk_cap > 0U);
878 auto start_and_wait = [&](
int done_cmd) -> ErrorCode
879 {
return StartAndWaitSegment(hal_, done_cmd, timeout_us); };
881 if ((write_size > 0U) || (read_size == 0U))
883 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
886 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
887 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE, CHECK_ACK,
890 size_t write_offset = 0U;
891 while (write_offset < write_size)
893 const size_t chunk = std::min(write_size - write_offset, write_chunk_cap);
894 i2c_ll_write_txfifo(hal_.dev,
895 static_cast<const uint8_t*
>(write_payload) + write_offset,
896 static_cast<uint8_t
>(chunk));
897 write_offset += chunk;
899 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE, CHECK_ACK,
900 static_cast<uint8_t
>(chunk));
901 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
904 const ErrorCode ec = start_and_wait(cmd_idx - 1);
905 if (ec != ErrorCode::OK)
909 (void)RecoverController();
916 if (write_size == 0U)
920 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
922#if SOC_I2C_STOP_INDEPENDENT
923 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
927 const ErrorCode ec = start_and_wait(cmd_idx - 1);
928 if (ec != ErrorCode::OK)
932 (void)RecoverController();
938 else if (read_size == 0U)
940 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
942#if SOC_I2C_STOP_INDEPENDENT
943 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
946 const ErrorCode ec = start_and_wait(cmd_idx - 1);
947 if (ec != ErrorCode::OK)
951 (void)RecoverController();
961 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
963 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
964 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE, CHECK_ACK,
967 size_t read_offset = 0U;
968 while (read_offset < read_size)
970 const size_t chunk = std::min(read_size - read_offset, fifo_len);
971 const bool is_last = (read_offset + chunk) >= read_size;
975 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
976 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk));
977 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
980 else if (chunk == 1U)
982 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
987 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
988 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk - 1U));
989 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
995 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
997#if SOC_I2C_STOP_INDEPENDENT
998 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
1003 const ErrorCode ec = start_and_wait(cmd_idx - 1);
1004 if (ec != ErrorCode::OK)
1008 (void)RecoverController();
1013 i2c_ll_read_rxfifo(hal_.dev, read_payload + read_offset,
1014 static_cast<uint8_t
>(chunk));
1015 read_offset += chunk;
1020 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
1021 return ErrorCode::OK;
1028 return ErrorCode::ARG_ERR;
1033 const ErrorCode init_err = InitHardware();
1034 if (init_err != ErrorCode::OK)
1042 return ErrorCode::BUSY;
1045 if (i2c_ll_is_bus_busy(hal_.dev))
1048 return ErrorCode::BUSY;
1054 if (ans != ErrorCode::OK)
1056 config_ = previous_config;
1065 const ErrorCode init_ec = EnsureInitialized(in_isr);
1066 if (init_ec != ErrorCode::OK)
1068 return Complete(op, in_isr, init_ec);
1071 if (!IsValid7BitAddr(slave_addr))
1073 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1076 if ((write_data.
size_ > 0U) && (write_data.
addr_ ==
nullptr))
1078 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1083 return Complete(op, in_isr, ErrorCode::BUSY);
1086 const size_t total_size = write_data.
size_;
1087 if (ShouldUseInterruptAsync(total_size))
1089 if (op.
type == WriteOperation::OperationType::BLOCK)
1091 block_wait_.Start(*op.
data.sem_info.
sem);
1093 const ErrorCode ans = StartAsyncTransaction(
1094 slave_addr,
nullptr, 0U,
static_cast<const uint8_t*
>(write_data.
addr_),
1095 write_data.
size_,
nullptr, 0U, op, in_isr);
1096 if (ans != ErrorCode::OK)
1098 if (op.
type == WriteOperation::OperationType::BLOCK)
1100 block_wait_.Cancel();
1103 return Complete(op, in_isr, ans);
1105 if (op.
type == WriteOperation::OperationType::BLOCK)
1108 return block_wait_.Wait(op.
data.sem_info.
timeout);
1110 return ErrorCode::OK;
1114 ExecuteTransaction(slave_addr,
static_cast<const uint8_t*
>(write_data.
addr_),
1115 write_data.
size_,
nullptr, 0U, in_isr);
1117 return Complete(op, in_isr, ans);
1123 const ErrorCode init_ec = EnsureInitialized(in_isr);
1124 if (init_ec != ErrorCode::OK)
1126 return Complete(op, in_isr, init_ec);
1129 if (!IsValid7BitAddr(slave_addr))
1131 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1134 if ((read_data.
size_ > 0U) && (read_data.
addr_ ==
nullptr))
1136 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1141 return Complete(op, in_isr, ErrorCode::BUSY);
1144 const size_t total_size = read_data.
size_;
1145 if (ShouldUseInterruptAsync(total_size))
1147 if (op.
type == ReadOperation::OperationType::BLOCK)
1149 block_wait_.Start(*op.
data.sem_info.
sem);
1151 const ErrorCode ans = StartAsyncTransaction(slave_addr,
nullptr, 0U,
nullptr, 0U,
1152 static_cast<uint8_t*
>(read_data.
addr_),
1153 read_data.
size_, op, in_isr);
1154 if (ans != ErrorCode::OK)
1156 if (op.
type == ReadOperation::OperationType::BLOCK)
1158 block_wait_.Cancel();
1161 return Complete(op, in_isr, ans);
1163 if (op.
type == ReadOperation::OperationType::BLOCK)
1166 return block_wait_.Wait(op.
data.sem_info.
timeout);
1168 return ErrorCode::OK;
1172 ExecuteTransaction(slave_addr,
nullptr, 0U,
static_cast<uint8_t*
>(read_data.
addr_),
1173 read_data.
size_, in_isr);
1175 return Complete(op, in_isr, ans);
1178ErrorCode ESP32I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
1180 MemAddrLength mem_addr_size,
bool in_isr)
1182 const ErrorCode init_ec = EnsureInitialized(in_isr);
1183 if (init_ec != ErrorCode::OK)
1185 return Complete(op, in_isr, init_ec);
1188 if (!IsValid7BitAddr(slave_addr))
1190 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1193 if ((write_data.
size_ > 0U) && (write_data.
addr_ ==
nullptr))
1195 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1198 const size_t mem_len = MemAddrBytes(mem_addr_size);
1199 if (mem_len > MAX_WRITE_PAYLOAD)
1201 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1206 return Complete(op, in_isr, ErrorCode::BUSY);
1209 std::array<uint8_t, 2> mem_raw = {};
1210 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1212 const size_t total_size = mem_len + write_data.
size_;
1213 if (ShouldUseInterruptAsync(total_size))
1215 if (op.
type == WriteOperation::OperationType::BLOCK)
1217 block_wait_.Start(*op.
data.sem_info.
sem);
1220 StartAsyncTransaction(slave_addr, mem_raw.data(), mem_len,
1221 static_cast<const uint8_t*
>(write_data.
addr_),
1222 write_data.
size_,
nullptr, 0U, op, in_isr);
1223 if (ans != ErrorCode::OK)
1225 if (op.
type == WriteOperation::OperationType::BLOCK)
1227 block_wait_.Cancel();
1230 return Complete(op, in_isr, ans);
1232 if (op.
type == WriteOperation::OperationType::BLOCK)
1235 return block_wait_.Wait(op.
data.sem_info.
timeout);
1237 return ErrorCode::OK;
1240 std::array<uint8_t, FIFO_LEN> staging = {};
1241 const size_t max_chunk = MAX_WRITE_PAYLOAD - mem_len;
1242 auto* src =
static_cast<const uint8_t*
>(write_data.
addr_);
1246 if (write_data.
size_ == 0U)
1248 EncodeMemAddr(mem_addr, mem_len, staging.data());
1249 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len,
nullptr, 0U, in_isr);
1253 while (offset < write_data.
size_)
1255 const size_t chunk = std::min(write_data.
size_ - offset, max_chunk);
1256 const uint16_t cur_mem =
static_cast<uint16_t
>(mem_addr + offset);
1257 EncodeMemAddr(cur_mem, mem_len, staging.data());
1258 Memory::FastCopy(staging.data() + mem_len, src + offset, chunk);
1259 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len + chunk,
nullptr, 0U,
1261 if (ans != ErrorCode::OK)
1270 return Complete(op, in_isr, ans);
1274 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
1276 const ErrorCode init_ec = EnsureInitialized(in_isr);
1277 if (init_ec != ErrorCode::OK)
1279 return Complete(op, in_isr, init_ec);
1282 if (!IsValid7BitAddr(slave_addr))
1284 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1287 if ((read_data.
size_ > 0U) && (read_data.
addr_ ==
nullptr))
1289 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1292 const size_t mem_len = MemAddrBytes(mem_addr_size);
1293 if (mem_len > MAX_WRITE_READ_PREFIX)
1295 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1300 return Complete(op, in_isr, ErrorCode::BUSY);
1303 std::array<uint8_t, 2> mem_raw = {};
1304 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1306 auto* dst =
static_cast<uint8_t*
>(read_data.
addr_);
1307 const size_t total_size = mem_len + read_data.
size_;
1308 if ((read_data.
size_ > 0U) && ShouldUseInterruptAsync(total_size))
1310 if (op.
type == ReadOperation::OperationType::BLOCK)
1312 block_wait_.Start(*op.
data.sem_info.
sem);
1315 StartAsyncTransaction(slave_addr, mem_raw.data(), mem_len,
nullptr, 0U, dst,
1316 read_data.
size_, op, in_isr);
1317 if (ans != ErrorCode::OK)
1319 if (op.
type == ReadOperation::OperationType::BLOCK)
1321 block_wait_.Cancel();
1324 return Complete(op, in_isr, ans);
1326 if (op.
type == ReadOperation::OperationType::BLOCK)
1329 return block_wait_.Wait(op.
data.sem_info.
timeout);
1331 return ErrorCode::OK;
1337 while (offset < read_data.
size_)
1339 const size_t chunk = std::min(read_data.
size_ - offset, MAX_READ_PAYLOAD);
1340 const uint16_t cur_mem =
static_cast<uint16_t
>(mem_addr + offset);
1341 EncodeMemAddr(cur_mem, mem_len, mem_raw.data());
1343 ans = ExecuteTransaction(slave_addr, mem_raw.data(), mem_len, dst + offset, chunk,
1345 if (ans != ErrorCode::OK)
1353 return Complete(op, in_isr, ans);
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
uint32_t timeout
等待超时值 / Wait timeout.
union LibXR::Operation::@6 data
完成通知对象,由 type 选择有效成员 / Notification target selected by type.
Semaphore * sem
借用的信号量 / Borrowed semaphore.
OperationType type
当前通知方式 / Current notification mode.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ NO_RESPONSE
无响应 / No response
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
Operation< ErrorCode > ReadOperation
读操作的完成通知描述符 / Read completion descriptor.
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz) / The I2C clock speed (in Hz).