6#include "esp_clk_tree.h"
7#include "esp_private/periph_ctrl.h"
8#include "esp_rom_gpio.h"
10#include "libxr_def.hpp"
11#include "timebase.hpp"
18constexpr uint8_t ACK_VALUE = I2C_MASTER_ACK;
19constexpr uint8_t NACK_VALUE = I2C_MASTER_NACK;
20constexpr uint8_t CHECK_ACK = 1U;
21constexpr uint8_t NO_CHECK_ACK = 0U;
23uint64_t ToTimeoutUs(uint32_t timeout_ms)
25 return (timeout_ms == UINT32_MAX) ? UINT64_MAX
26 :
static_cast<uint64_t
>(timeout_ms) * 1000ULL;
31inline void SetBusClockAtomic(i2c_port_t port,
bool enable)
34#pragma GCC diagnostic push
35#pragma GCC diagnostic ignored "-Wunused-variable"
37 PERIPH_RCC_ATOMIC() { i2c_ll_enable_bus_clock(port, enable); }
39#pragma GCC diagnostic pop
43inline void ResetBusRegisterAtomic(i2c_port_t port)
46#pragma GCC diagnostic push
47#pragma GCC diagnostic ignored "-Wunused-variable"
49 PERIPH_RCC_ATOMIC() { i2c_ll_reset_register(port); }
51#pragma GCC diagnostic pop
55void WriteCommand(i2c_dev_t* dev,
int cmd_idx, uint8_t op_code, uint8_t ack_val,
56 uint8_t ack_exp, uint8_t ack_en, uint8_t byte_num)
58 i2c_ll_hw_cmd_t cmd = {};
59 cmd.op_code = op_code;
60 cmd.ack_val = ack_val;
61 cmd.ack_exp = ack_exp;
63 cmd.byte_num = byte_num;
64 i2c_ll_master_write_cmd_reg(dev, cmd, cmd_idx);
67ErrorCode WaitSegmentDone(i2c_hal_context_t& hal,
int done_cmd_idx, uint64_t timeout_us)
69 const uint64_t start_us = GetNowUs();
71 auto recover_after_error = [&]()
73 i2c_ll_clear_intr_mask(hal.dev, I2C_LL_INTR_MASK);
74 i2c_hal_master_fsm_rst(&hal);
75 i2c_ll_update(hal.dev);
80 const uint32_t intr = hal.dev->int_raw.val;
82 if ((intr & I2C_LL_INTR_NACK) != 0U)
84 recover_after_error();
87 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
89 recover_after_error();
92 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
94 recover_after_error();
98 if (i2c_ll_master_is_cmd_done(hal.dev, done_cmd_idx) ||
99 ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) != 0U))
104 if ((timeout_us != UINT64_MAX) && ((GetNowUs() - start_us) > timeout_us))
106 recover_after_error();
112ErrorCode StartAndWaitSegment(i2c_hal_context_t& hal,
int done_cmd_idx,
115 i2c_ll_clear_intr_mask(hal.dev, I2C_LL_INTR_MASK);
116 i2c_hal_master_trans_start(&hal);
117 return WaitSegmentDone(hal, done_cmd_idx, timeout_us);
120template <
typename OperationType>
125 if (op.type != OperationType::OperationType::BLOCK)
127 op.UpdateStatus(in_isr, result);
134ESP32I2C::ESP32I2C(i2c_port_t port_num,
int scl_pin,
int sda_pin, uint32_t clock_speed,
135 bool enable_internal_pullup, uint32_t timeout_ms,
136 uint32_t isr_enable_min_size)
137 : port_num_(port_num),
140 enable_internal_pullup_(enable_internal_pullup),
141 timeout_ms_(timeout_ms),
142 isr_enable_min_size_(isr_enable_min_size),
145 ASSERT(port_num_ >= 0);
146 ASSERT(port_num_ < SOC_I2C_NUM);
147 ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(scl_pin_)));
148 ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(sda_pin_)));
149 ASSERT(config_.clock_speed > 0U);
150 ASSERT(FIFO_LEN > 2U);
152 if (InitHardware() != ErrorCode::OK)
159bool ESP32I2C::Acquire() {
return !busy_.TestAndSet(); }
161void ESP32I2C::Release() { busy_.Clear(); }
163bool ESP32I2C::IsValid7BitAddr(uint16_t addr) {
return addr <= 0x7FU; }
165ErrorCode ESP32I2C::EnsureInitialized(
bool in_isr)
169 return ErrorCode::OK;
173 return ErrorCode::INIT_ERR;
175 return InitHardware();
178size_t ESP32I2C::MemAddrBytes(MemAddrLength mem_addr_size)
180 return (mem_addr_size == MemAddrLength::BYTE_16) ? 2U : 1U;
183void ESP32I2C::EncodeMemAddr(uint16_t mem_addr,
size_t mem_len, uint8_t* out)
185 ASSERT(out !=
nullptr);
188 out[0] =
static_cast<uint8_t
>((mem_addr >> 8) & 0xFFU);
189 out[1] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
193 out[0] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
196ErrorCode ESP32I2C::ResolveClockSource(uint32_t& source_hz)
199 const esp_err_t err =
200 esp_clk_tree_src_get_freq_hz(
static_cast<soc_module_clk_t
>(I2C_CLK_SRC_DEFAULT),
201 ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &source_hz);
202 if ((err != ESP_OK) || (source_hz == 0U))
204 return ErrorCode::INIT_ERR;
206 return ErrorCode::OK;
211 if ((hal_.dev ==
nullptr) || (config_.clock_speed == 0U))
213 return ErrorCode::ARG_ERR;
216 i2c_ll_set_source_clk(hal_.dev, I2C_CLK_SRC_DEFAULT);
217 if (ResolveClockSource(source_clock_hz_) != ErrorCode::OK)
219 return ErrorCode::INIT_ERR;
222 if (config_.clock_speed > (source_clock_hz_ / 20U))
224 return ErrorCode::ARG_ERR;
227 _i2c_hal_set_bus_timing(&hal_,
static_cast<int>(config_.clock_speed),
228 I2C_CLK_SRC_DEFAULT,
static_cast<int>(source_clock_hz_));
229 i2c_ll_master_set_filter(hal_.dev, 7U);
230 i2c_ll_update(hal_.dev);
232 return ErrorCode::OK;
239 return ErrorCode::OK;
242 if ((port_num_ < 0) || (port_num_ >= SOC_I2C_NUM) ||
243 (
static_cast<size_t>(port_num_) >= SOC_I2C_NUM))
245 return ErrorCode::OUT_OF_RANGE;
248 if (!GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(scl_pin_)) ||
249 !GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(sda_pin_)))
251 return ErrorCode::ARG_ERR;
254 SetBusClockAtomic(port_num_,
true);
255 ResetBusRegisterAtomic(port_num_);
257 _i2c_hal_init(&hal_,
static_cast<int>(port_num_));
258 if (hal_.dev ==
nullptr)
261 return ErrorCode::INIT_ERR;
264 i2c_hal_master_init(&hal_);
265 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
266 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
269 if (err != ErrorCode::OK)
275 err = InstallInterrupt();
276 if (err != ErrorCode::OK)
283 if (err != ErrorCode::OK)
290 return ErrorCode::OK;
295 if (hal_.dev ==
nullptr)
297 return ErrorCode::STATE_ERR;
300 const auto& sig = i2c_periph_signal[port_num_];
301 const gpio_num_t sda_gpio =
static_cast<gpio_num_t
>(sda_pin_);
302 const gpio_num_t scl_gpio =
static_cast<gpio_num_t
>(scl_pin_);
304 gpio_set_level(sda_gpio, 1);
305 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(sda_pin_));
306 gpio_set_direction(sda_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
307 gpio_set_pull_mode(sda_gpio,
308 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
309 esp_rom_gpio_connect_out_signal(sda_pin_, sig.sda_out_sig,
false,
false);
310 esp_rom_gpio_connect_in_signal(sda_pin_, sig.sda_in_sig,
false);
312 gpio_set_level(scl_gpio, 1);
313 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(scl_pin_));
314 gpio_set_direction(scl_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
315 gpio_set_pull_mode(scl_gpio,
316 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
317 esp_rom_gpio_connect_out_signal(scl_pin_, sig.scl_out_sig,
false,
false);
318 esp_rom_gpio_connect_in_signal(scl_pin_, sig.scl_in_sig,
false);
320 return ErrorCode::OK;
325 if (hal_.dev ==
nullptr)
327 return ErrorCode::INIT_ERR;
330#if SOC_I2C_SUPPORT_HW_FSM_RST
331 i2c_hal_master_fsm_rst(&hal_);
332 i2c_ll_update(hal_.dev);
333 return ErrorCode::OK;
336 ResetBusRegisterAtomic(port_num_);
337 i2c_hal_master_init(&hal_);
338 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
339 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
341 const ErrorCode pin_ec = ConfigurePins();
342 if (pin_ec != ErrorCode::OK)
346 return ApplyConfig();
350bool ESP32I2C::ShouldUseInterruptAsync(
size_t total_size)
const
352 if (!intr_installed_)
356 return (isr_enable_min_size_ > 0U) &&
357 (total_size >=
static_cast<size_t>(isr_enable_min_size_));
360ErrorCode ESP32I2C::StartAsyncTransaction(uint16_t slave_addr,
361 const uint8_t* write_prefix_payload,
362 size_t write_prefix_size,
363 const uint8_t* write_payload,
size_t write_size,
364 uint8_t* read_payload,
size_t read_size,
367 if (!initialized_ || (hal_.dev ==
nullptr))
369 return ErrorCode::INIT_ERR;
371 if (!IsValid7BitAddr(slave_addr))
373 return ErrorCode::ARG_ERR;
375 if ((write_prefix_size > 0U) && (write_prefix_payload ==
nullptr))
377 return ErrorCode::PTR_NULL;
379 if (write_prefix_size > async_write_prefix_.size())
381 return ErrorCode::SIZE_ERR;
383 if ((write_size > 0U) && (write_payload ==
nullptr))
385 return ErrorCode::PTR_NULL;
387 if ((read_size > 0U) && (read_payload ==
nullptr))
389 return ErrorCode::PTR_NULL;
393 return ErrorCode::BUSY;
396 if (i2c_ll_is_bus_busy(hal_.dev))
398 const ErrorCode ec = RecoverController();
399 if (ec != ErrorCode::OK)
405 i2c_ll_txfifo_rst(hal_.dev);
406 i2c_ll_rxfifo_rst(hal_.dev);
407 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
408 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
412 async_running_ =
true;
413 async_slave_addr_ = slave_addr;
414 async_write_prefix_size_ = write_prefix_size;
415 async_write_prefix_offset_ = 0U;
416 if (write_prefix_size > 0U)
418 Memory::FastCopy(async_write_prefix_.data(), write_prefix_payload, write_prefix_size);
420 async_write_payload_ = write_payload;
421 async_write_size_ = write_size;
422 async_write_offset_ = 0U;
423 async_read_payload_ = read_payload;
424 async_read_size_ = read_size;
425 async_read_offset_ = 0U;
426 async_pending_read_chunk_ = 0U;
427 async_write_phase_done_ =
428 !((write_prefix_size > 0U) || (write_size > 0U) || (read_size == 0U));
429 async_write_addr_sent_ =
false;
430 async_write_stop_sent_ =
false;
431 async_read_addr_sent_ =
false;
433 const ErrorCode kick = KickAsyncTransaction();
434 if ((kick == ErrorCode::PENDING) || (kick == ErrorCode::OK))
436 if (kick == ErrorCode::OK)
438 FinishAsync(
false, ErrorCode::OK);
440 return ErrorCode::OK;
443 async_running_ =
false;
444 async_write_prefix_size_ = 0U;
445 async_write_prefix_offset_ = 0U;
446 async_write_payload_ =
nullptr;
447 async_write_size_ = 0U;
448 async_write_offset_ = 0U;
449 async_read_payload_ =
nullptr;
450 async_read_size_ = 0U;
451 async_read_offset_ = 0U;
452 async_pending_read_chunk_ = 0U;
453 async_write_phase_done_ =
true;
454 async_write_addr_sent_ =
false;
455 async_write_stop_sent_ =
false;
456 async_read_addr_sent_ =
false;
460ErrorCode ESP32I2C::KickAsyncTransaction()
462 if (!async_running_ || (hal_.dev ==
nullptr))
464 return ErrorCode::STATE_ERR;
467 const uint8_t write_addr =
468 static_cast<uint8_t
>((async_slave_addr_ << 1U) | I2C_MASTER_WRITE);
469 const uint8_t read_addr =
470 static_cast<uint8_t
>((async_slave_addr_ << 1U) | I2C_MASTER_READ);
471 const size_t fifo_len = FIFO_LEN;
472 const size_t write_chunk_cap = (fifo_len > 1U) ? (fifo_len - 1U) : 0U;
473 ASSERT(write_chunk_cap > 0U);
477 if (async_pending_read_chunk_ > 0U)
479 i2c_ll_read_rxfifo(hal_.dev, async_read_payload_ + async_read_offset_,
480 static_cast<uint8_t
>(async_pending_read_chunk_));
481 async_read_offset_ += async_pending_read_chunk_;
482 async_pending_read_chunk_ = 0U;
487 if (!async_write_phase_done_)
489 if (!async_write_addr_sent_)
491 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
493 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
494 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
496 async_write_addr_sent_ =
true;
499 if (async_write_prefix_offset_ < async_write_prefix_size_)
501 const size_t chunk = std::min(
502 async_write_prefix_size_ - async_write_prefix_offset_, write_chunk_cap);
503 i2c_ll_write_txfifo(hal_.dev,
504 async_write_prefix_.data() + async_write_prefix_offset_,
505 static_cast<uint8_t
>(chunk));
506 async_write_prefix_offset_ += chunk;
508 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
509 CHECK_ACK,
static_cast<uint8_t
>(chunk));
510 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
513 else if (async_write_offset_ < async_write_size_)
516 std::min(async_write_size_ - async_write_offset_, write_chunk_cap);
517 i2c_ll_write_txfifo(hal_.dev, async_write_payload_ + async_write_offset_,
518 static_cast<uint8_t
>(chunk));
519 async_write_offset_ += chunk;
521 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
522 CHECK_ACK,
static_cast<uint8_t
>(chunk));
523 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
526 else if (async_read_size_ == 0U)
528 if (!async_write_stop_sent_)
530 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
532#if SOC_I2C_STOP_INDEPENDENT
533 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
536 async_write_stop_sent_ =
true;
538 async_write_phase_done_ = async_write_stop_sent_;
542 async_write_phase_done_ =
true;
547 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
548 i2c_ll_enable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
549 i2c_hal_master_trans_start(&hal_);
550 return ErrorCode::PENDING;
556 if (async_read_size_ > 0U)
558 if (!async_read_addr_sent_)
560 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
562 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
563 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
565 async_read_addr_sent_ =
true;
568 if (async_read_offset_ < async_read_size_)
570 const size_t chunk = std::min(async_read_size_ - async_read_offset_, fifo_len);
571 const bool is_last = (async_read_offset_ + chunk) >= async_read_size_;
575 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
576 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk));
577 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
580 else if (chunk == 1U)
582 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
587 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
588 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk - 1U));
589 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
595 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
597#if SOC_I2C_STOP_INDEPENDENT
598 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
603 async_pending_read_chunk_ = chunk;
608 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
609 i2c_ll_enable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
610 i2c_hal_master_trans_start(&hal_);
611 return ErrorCode::PENDING;
615 return ErrorCode::OK;
619void ESP32I2C::FinishAsync(
bool in_isr, ErrorCode ec)
626 if (hal_.dev !=
nullptr)
628 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
629 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
634 async_running_ =
false;
635 async_write_prefix_size_ = 0U;
636 async_write_prefix_offset_ = 0U;
637 async_write_payload_ =
nullptr;
638 async_write_size_ = 0U;
639 async_write_offset_ = 0U;
640 async_read_payload_ =
nullptr;
641 async_read_size_ = 0U;
642 async_read_offset_ = 0U;
643 async_pending_read_chunk_ = 0U;
644 async_write_phase_done_ =
true;
645 async_write_addr_sent_ =
false;
646 async_write_stop_sent_ =
false;
647 async_read_addr_sent_ =
false;
650 if (op.type == ReadOperation::OperationType::BLOCK)
652 (void)block_wait_.TryPost(in_isr, ec);
656 op.UpdateStatus(in_isr, ec);
664 return ErrorCode::OK;
667 const int irq = i2c_periph_signal[port_num_].irq;
670 return ErrorCode::NOT_SUPPORT;
673 if (esp_intr_alloc(irq, 0, I2cIsrEntry,
this, &intr_handle_) != ESP_OK)
675 intr_handle_ =
nullptr;
676 return ErrorCode::INIT_ERR;
679 intr_installed_ =
true;
680 return ErrorCode::OK;
683void ESP32I2C::I2cIsrEntry(
void* arg)
685 auto* self =
static_cast<ESP32I2C*
>(arg);
688 self->HandleInterrupt();
692void ESP32I2C::HandleInterrupt()
694 if (hal_.dev ==
nullptr)
699 const uint32_t intr = hal_.dev->int_raw.val;
700 if ((intr & I2C_LL_MASTER_EVENT_INTR) == 0U)
707 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
708 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
712 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
713 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
715 if ((intr & I2C_LL_INTR_NACK) != 0U)
717 i2c_hal_master_fsm_rst(&hal_);
718 i2c_ll_update(hal_.dev);
719 FinishAsync(
true, ErrorCode::NO_RESPONSE);
722 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
724 i2c_hal_master_fsm_rst(&hal_);
725 i2c_ll_update(hal_.dev);
726 FinishAsync(
true, ErrorCode::TIMEOUT);
729 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
731 i2c_hal_master_fsm_rst(&hal_);
732 i2c_ll_update(hal_.dev);
733 FinishAsync(
true, ErrorCode::FAILED);
737 if ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) == 0U)
742 const ErrorCode kick = KickAsyncTransaction();
743 if (kick == ErrorCode::PENDING)
748 FinishAsync(
true, kick);
751ErrorCode ESP32I2C::ExecuteTransaction(uint16_t slave_addr,
const uint8_t* write_payload,
752 size_t write_size, uint8_t* read_payload,
755 if (!initialized_ || (hal_.dev ==
nullptr))
757 return ErrorCode::INIT_ERR;
759 if (!IsValid7BitAddr(slave_addr))
761 return ErrorCode::ARG_ERR;
763 if ((write_size > 0U) && (write_payload ==
nullptr))
765 return ErrorCode::PTR_NULL;
767 if ((read_size > 0U) && (read_payload ==
nullptr))
769 return ErrorCode::PTR_NULL;
772 if (i2c_ll_is_bus_busy(hal_.dev))
774 const ErrorCode ec = RecoverController();
775 if (ec != ErrorCode::OK)
781 i2c_ll_txfifo_rst(hal_.dev);
782 i2c_ll_rxfifo_rst(hal_.dev);
783 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
785 const uint64_t timeout_us = ToTimeoutUs(timeout_ms_);
786 const uint8_t write_addr =
static_cast<uint8_t
>((slave_addr << 1U) | I2C_MASTER_WRITE);
787 const uint8_t read_addr =
static_cast<uint8_t
>((slave_addr << 1U) | I2C_MASTER_READ);
788 const size_t fifo_len = FIFO_LEN;
789 const size_t write_chunk_cap = (fifo_len > 1U) ? (fifo_len - 1U) : 0U;
790 ASSERT(write_chunk_cap > 0U);
794 auto start_and_wait = [&](
int done_cmd) -> ErrorCode
795 {
return StartAndWaitSegment(hal_, done_cmd, timeout_us); };
797 if ((write_size > 0U) || (read_size == 0U))
799 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
802 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
803 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE, CHECK_ACK,
806 size_t write_offset = 0U;
807 while (write_offset < write_size)
809 const size_t chunk = std::min(write_size - write_offset, write_chunk_cap);
810 i2c_ll_write_txfifo(hal_.dev,
811 static_cast<const uint8_t*
>(write_payload) + write_offset,
812 static_cast<uint8_t
>(chunk));
813 write_offset += chunk;
815 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE, CHECK_ACK,
816 static_cast<uint8_t
>(chunk));
817 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
820 const ErrorCode ec = start_and_wait(cmd_idx - 1);
821 if (ec != ErrorCode::OK)
823 (void)RecoverController();
829 if (write_size == 0U)
833 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
835#if SOC_I2C_STOP_INDEPENDENT
836 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
840 const ErrorCode ec = start_and_wait(cmd_idx - 1);
841 if (ec != ErrorCode::OK)
843 (void)RecoverController();
848 else if (read_size == 0U)
850 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
852#if SOC_I2C_STOP_INDEPENDENT
853 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
856 const ErrorCode ec = start_and_wait(cmd_idx - 1);
857 if (ec != ErrorCode::OK)
859 (void)RecoverController();
868 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
870 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
871 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE, CHECK_ACK,
874 size_t read_offset = 0U;
875 while (read_offset < read_size)
877 const size_t chunk = std::min(read_size - read_offset, fifo_len);
878 const bool is_last = (read_offset + chunk) >= read_size;
882 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
883 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk));
884 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
887 else if (chunk == 1U)
889 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
894 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, ACK_VALUE, ACK_VALUE,
895 NO_CHECK_ACK,
static_cast<uint8_t
>(chunk - 1U));
896 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
902 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
904#if SOC_I2C_STOP_INDEPENDENT
905 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
910 const ErrorCode ec = start_and_wait(cmd_idx - 1);
911 if (ec != ErrorCode::OK)
913 (void)RecoverController();
917 i2c_ll_read_rxfifo(hal_.dev, read_payload + read_offset,
918 static_cast<uint8_t
>(chunk));
919 read_offset += chunk;
924 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
925 return ErrorCode::OK;
932 return ErrorCode::ARG_ERR;
937 const ErrorCode init_err = InitHardware();
938 if (init_err != ErrorCode::OK)
946 return ErrorCode::BUSY;
958 const ErrorCode init_ec = EnsureInitialized(in_isr);
959 if (init_ec != ErrorCode::OK)
961 return Complete(op, in_isr, init_ec);
964 if (!IsValid7BitAddr(slave_addr))
966 return Complete(op, in_isr, ErrorCode::ARG_ERR);
969 if ((write_data.
size_ > 0U) && (write_data.
addr_ ==
nullptr))
971 return Complete(op, in_isr, ErrorCode::PTR_NULL);
976 return Complete(op, in_isr, ErrorCode::BUSY);
979 const size_t total_size = write_data.
size_;
980 if (ShouldUseInterruptAsync(total_size))
982 if (op.
type == WriteOperation::OperationType::BLOCK)
984 block_wait_.Start(*op.
data.sem_info.sem);
986 const ErrorCode ans = StartAsyncTransaction(
987 slave_addr,
nullptr, 0U,
static_cast<const uint8_t*
>(write_data.
addr_),
988 write_data.
size_,
nullptr, 0U, op);
989 if (ans != ErrorCode::OK)
991 if (op.
type == WriteOperation::OperationType::BLOCK)
993 block_wait_.Cancel();
996 return Complete(op, in_isr, ans);
998 if (op.
type == WriteOperation::OperationType::BLOCK)
1001 return block_wait_.Wait(op.
data.sem_info.timeout);
1003 return ErrorCode::OK;
1007 ExecuteTransaction(slave_addr,
static_cast<const uint8_t*
>(write_data.
addr_),
1008 write_data.
size_,
nullptr, 0U);
1010 return Complete(op, in_isr, ans);
1016 const ErrorCode init_ec = EnsureInitialized(in_isr);
1017 if (init_ec != ErrorCode::OK)
1019 return Complete(op, in_isr, init_ec);
1022 if (!IsValid7BitAddr(slave_addr))
1024 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1027 if ((read_data.
size_ > 0U) && (read_data.
addr_ ==
nullptr))
1029 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1034 return Complete(op, in_isr, ErrorCode::BUSY);
1037 const size_t total_size = read_data.
size_;
1038 if (ShouldUseInterruptAsync(total_size))
1040 if (op.
type == ReadOperation::OperationType::BLOCK)
1042 block_wait_.Start(*op.
data.sem_info.sem);
1044 const ErrorCode ans = StartAsyncTransaction(slave_addr,
nullptr, 0U,
nullptr, 0U,
1045 static_cast<uint8_t*
>(read_data.
addr_),
1046 read_data.
size_, op);
1047 if (ans != ErrorCode::OK)
1049 if (op.
type == ReadOperation::OperationType::BLOCK)
1051 block_wait_.Cancel();
1054 return Complete(op, in_isr, ans);
1056 if (op.
type == ReadOperation::OperationType::BLOCK)
1059 return block_wait_.Wait(op.
data.sem_info.timeout);
1061 return ErrorCode::OK;
1064 const ErrorCode ans = ExecuteTransaction(
1065 slave_addr,
nullptr, 0U,
static_cast<uint8_t*
>(read_data.
addr_), read_data.
size_);
1067 return Complete(op, in_isr, ans);
1070ErrorCode ESP32I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
1072 MemAddrLength mem_addr_size,
bool in_isr)
1074 const ErrorCode init_ec = EnsureInitialized(in_isr);
1075 if (init_ec != ErrorCode::OK)
1077 return Complete(op, in_isr, init_ec);
1080 if (!IsValid7BitAddr(slave_addr))
1082 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1085 if ((write_data.
size_ > 0U) && (write_data.
addr_ ==
nullptr))
1087 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1090 const size_t mem_len = MemAddrBytes(mem_addr_size);
1091 if (mem_len > MAX_WRITE_PAYLOAD)
1093 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1098 return Complete(op, in_isr, ErrorCode::BUSY);
1101 std::array<uint8_t, 2> mem_raw = {};
1102 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1104 const size_t total_size = mem_len + write_data.
size_;
1105 if (ShouldUseInterruptAsync(total_size))
1107 if (op.
type == WriteOperation::OperationType::BLOCK)
1109 block_wait_.Start(*op.
data.sem_info.sem);
1111 const ErrorCode ans = StartAsyncTransaction(
1112 slave_addr, mem_raw.data(), mem_len,
1113 static_cast<const uint8_t*
>(write_data.
addr_), write_data.
size_,
nullptr, 0U, op);
1114 if (ans != ErrorCode::OK)
1116 if (op.
type == WriteOperation::OperationType::BLOCK)
1118 block_wait_.Cancel();
1121 return Complete(op, in_isr, ans);
1123 if (op.
type == WriteOperation::OperationType::BLOCK)
1126 return block_wait_.Wait(op.
data.sem_info.timeout);
1128 return ErrorCode::OK;
1131 std::array<uint8_t, FIFO_LEN> staging = {};
1132 const size_t max_chunk = MAX_WRITE_PAYLOAD - mem_len;
1133 auto* src =
static_cast<const uint8_t*
>(write_data.
addr_);
1137 if (write_data.
size_ == 0U)
1139 EncodeMemAddr(mem_addr, mem_len, staging.data());
1140 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len,
nullptr, 0U);
1144 while (offset < write_data.
size_)
1146 const size_t chunk = std::min(write_data.
size_ - offset, max_chunk);
1147 const uint16_t cur_mem =
static_cast<uint16_t
>(mem_addr + offset);
1148 EncodeMemAddr(cur_mem, mem_len, staging.data());
1149 Memory::FastCopy(staging.data() + mem_len, src + offset, chunk);
1150 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len + chunk,
nullptr, 0U);
1151 if (ans != ErrorCode::OK)
1160 return Complete(op, in_isr, ans);
1164 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
1166 const ErrorCode init_ec = EnsureInitialized(in_isr);
1167 if (init_ec != ErrorCode::OK)
1169 return Complete(op, in_isr, init_ec);
1172 if (!IsValid7BitAddr(slave_addr))
1174 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1177 if ((read_data.
size_ > 0U) && (read_data.
addr_ ==
nullptr))
1179 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1182 const size_t mem_len = MemAddrBytes(mem_addr_size);
1183 if (mem_len > MAX_WRITE_READ_PREFIX)
1185 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1190 return Complete(op, in_isr, ErrorCode::BUSY);
1193 std::array<uint8_t, 2> mem_raw = {};
1194 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1196 auto* dst =
static_cast<uint8_t*
>(read_data.
addr_);
1197 const size_t total_size = mem_len + read_data.
size_;
1198 if ((read_data.
size_ > 0U) && ShouldUseInterruptAsync(total_size))
1200 if (op.
type == ReadOperation::OperationType::BLOCK)
1202 block_wait_.Start(*op.
data.sem_info.sem);
1204 const ErrorCode ans = StartAsyncTransaction(slave_addr, mem_raw.data(), mem_len,
1205 nullptr, 0U, dst, read_data.
size_, op);
1206 if (ans != ErrorCode::OK)
1208 if (op.
type == ReadOperation::OperationType::BLOCK)
1210 block_wait_.Cancel();
1213 return Complete(op, in_isr, ans);
1215 if (op.
type == ReadOperation::OperationType::BLOCK)
1218 return block_wait_.Wait(op.
data.sem_info.timeout);
1220 return ErrorCode::OK;
1226 while (offset < read_data.
size_)
1228 const size_t chunk = std::min(read_data.
size_ - offset, MAX_READ_PAYLOAD);
1229 const uint16_t cur_mem =
static_cast<uint16_t
>(mem_addr + offset);
1230 EncodeMemAddr(cur_mem, mem_len, mem_raw.data());
1232 ans = ExecuteTransaction(slave_addr, mem_raw.data(), mem_len, dst + offset, chunk);
1233 if (ans != ErrorCode::OK)
1241 return Complete(op, in_isr, ans);
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
union LibXR::Operation::@5 data
可写原始数据视图 / 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.
@ NO_RESPONSE
无响应 | No response
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
Operation< ErrorCode > ReadOperation
Read operation type.
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz)。 The I2C clock speed (in Hz).