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 kAckValue = I2C_MASTER_ACK;
19constexpr uint8_t kNackValue = I2C_MASTER_NACK;
20constexpr uint8_t kCheckAck = 1U;
21constexpr uint8_t kNoCheckAck = 0U;
23uint64_t ToTimeoutUs(uint32_t timeout_ms)
25 return (timeout_ms == UINT32_MAX) ? UINT64_MAX
26 :
static_cast<uint64_t
>(timeout_ms) * 1000ULL;
35 return static_cast<uint64_t
>(esp_timer_get_time());
38inline void SetBusClockAtomic(i2c_port_t port,
bool enable)
41#pragma GCC diagnostic push
42#pragma GCC diagnostic ignored "-Wunused-variable"
44 PERIPH_RCC_ATOMIC() { i2c_ll_enable_bus_clock(port, enable); }
46#pragma GCC diagnostic pop
50inline void ResetBusRegisterAtomic(i2c_port_t port)
53#pragma GCC diagnostic push
54#pragma GCC diagnostic ignored "-Wunused-variable"
56 PERIPH_RCC_ATOMIC() { i2c_ll_reset_register(port); }
58#pragma GCC diagnostic pop
62void WriteCommand(i2c_dev_t* dev,
int cmd_idx, uint8_t op_code, uint8_t ack_val,
63 uint8_t ack_exp, uint8_t ack_en, uint8_t byte_num)
65 i2c_ll_hw_cmd_t cmd = {};
66 cmd.op_code = op_code;
67 cmd.ack_val = ack_val;
68 cmd.ack_exp = ack_exp;
70 cmd.byte_num = byte_num;
71 i2c_ll_master_write_cmd_reg(dev, cmd, cmd_idx);
74ErrorCode WaitSegmentDone(i2c_hal_context_t& hal,
int done_cmd_idx, uint64_t timeout_us)
76 const uint64_t start_us = GetNowUs();
78 auto recover_after_error = [&]()
80 i2c_ll_clear_intr_mask(hal.dev, I2C_LL_INTR_MASK);
81 i2c_hal_master_fsm_rst(&hal);
82 i2c_ll_update(hal.dev);
87 const uint32_t intr = hal.dev->int_raw.val;
89 if ((intr & I2C_LL_INTR_NACK) != 0U)
91 recover_after_error();
94 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
96 recover_after_error();
99 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
101 recover_after_error();
105 if (i2c_ll_master_is_cmd_done(hal.dev, done_cmd_idx) ||
106 ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) != 0U))
111 if ((timeout_us != UINT64_MAX) && ((GetNowUs() - start_us) > timeout_us))
113 recover_after_error();
119ErrorCode StartAndWaitSegment(i2c_hal_context_t& hal,
int done_cmd_idx,
122 i2c_ll_clear_intr_mask(hal.dev, I2C_LL_INTR_MASK);
123 i2c_hal_master_trans_start(&hal);
124 return WaitSegmentDone(hal, done_cmd_idx, timeout_us);
127template <
typename OperationType>
131 if (op.type != OperationType::OperationType::BLOCK)
133 op.UpdateStatus(in_isr, result);
140ESP32I2C::ESP32I2C(i2c_port_t port_num,
int scl_pin,
int sda_pin, uint32_t clock_speed,
141 bool enable_internal_pullup, uint32_t timeout_ms,
142 uint32_t isr_enable_min_size)
143 : port_num_(port_num),
146 enable_internal_pullup_(enable_internal_pullup),
147 timeout_ms_(timeout_ms),
148 isr_enable_min_size_(isr_enable_min_size),
151 ASSERT(port_num_ >= 0);
152 ASSERT(port_num_ < SOC_I2C_NUM);
153 ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(scl_pin_)));
154 ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(sda_pin_)));
155 ASSERT(config_.clock_speed > 0U);
156 ASSERT(kFifoLen > 2U);
158 if (InitHardware() != ErrorCode::OK)
165bool ESP32I2C::Acquire() {
return !busy_.TestAndSet(); }
167void ESP32I2C::Release() { busy_.Clear(); }
169bool ESP32I2C::IsValid7BitAddr(uint16_t addr) {
return addr <= 0x7FU; }
171ErrorCode ESP32I2C::EnsureInitialized(
bool in_isr)
175 return ErrorCode::OK;
179 return ErrorCode::INIT_ERR;
181 return InitHardware();
184size_t ESP32I2C::MemAddrBytes(MemAddrLength mem_addr_size)
186 return (mem_addr_size == MemAddrLength::BYTE_16) ? 2U : 1U;
189void ESP32I2C::EncodeMemAddr(uint16_t mem_addr,
size_t mem_len, uint8_t* out)
191 ASSERT(out !=
nullptr);
194 out[0] =
static_cast<uint8_t
>((mem_addr >> 8) & 0xFFU);
195 out[1] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
199 out[0] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
202ErrorCode ESP32I2C::ResolveClockSource(uint32_t& source_hz)
205 const esp_err_t err =
206 esp_clk_tree_src_get_freq_hz(
static_cast<soc_module_clk_t
>(I2C_CLK_SRC_DEFAULT),
207 ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &source_hz);
208 if ((err != ESP_OK) || (source_hz == 0U))
210 return ErrorCode::INIT_ERR;
212 return ErrorCode::OK;
217 if ((hal_.dev ==
nullptr) || (config_.clock_speed == 0U))
219 return ErrorCode::ARG_ERR;
222 i2c_ll_set_source_clk(hal_.dev, I2C_CLK_SRC_DEFAULT);
223 if (ResolveClockSource(source_clock_hz_) != ErrorCode::OK)
225 return ErrorCode::INIT_ERR;
228 if (config_.clock_speed > (source_clock_hz_ / 20U))
230 return ErrorCode::ARG_ERR;
233 _i2c_hal_set_bus_timing(&hal_,
static_cast<int>(config_.clock_speed),
234 I2C_CLK_SRC_DEFAULT,
static_cast<int>(source_clock_hz_));
235 i2c_ll_master_set_filter(hal_.dev, 7U);
236 i2c_ll_update(hal_.dev);
238 return ErrorCode::OK;
245 return ErrorCode::OK;
248 if ((port_num_ < 0) || (port_num_ >= SOC_I2C_NUM) ||
249 (
static_cast<size_t>(port_num_) >= SOC_I2C_NUM))
251 return ErrorCode::OUT_OF_RANGE;
254 if (!GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(scl_pin_)) ||
255 !GPIO_IS_VALID_OUTPUT_GPIO(
static_cast<gpio_num_t
>(sda_pin_)))
257 return ErrorCode::ARG_ERR;
260 SetBusClockAtomic(port_num_,
true);
261 ResetBusRegisterAtomic(port_num_);
263 _i2c_hal_init(&hal_,
static_cast<int>(port_num_));
264 if (hal_.dev ==
nullptr)
267 return ErrorCode::INIT_ERR;
270 i2c_hal_master_init(&hal_);
271 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
272 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
275 if (err != ErrorCode::OK)
281 err = InstallInterrupt();
282 if (err != ErrorCode::OK)
289 if (err != ErrorCode::OK)
296 return ErrorCode::OK;
301 if (hal_.dev ==
nullptr)
303 return ErrorCode::STATE_ERR;
306 const auto& sig = i2c_periph_signal[port_num_];
307 const gpio_num_t sda_gpio =
static_cast<gpio_num_t
>(sda_pin_);
308 const gpio_num_t scl_gpio =
static_cast<gpio_num_t
>(scl_pin_);
310 gpio_set_level(sda_gpio, 1);
311 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(sda_pin_));
312 gpio_set_direction(sda_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
313 gpio_set_pull_mode(sda_gpio,
314 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
315 esp_rom_gpio_connect_out_signal(sda_pin_, sig.sda_out_sig,
false,
false);
316 esp_rom_gpio_connect_in_signal(sda_pin_, sig.sda_in_sig,
false);
318 gpio_set_level(scl_gpio, 1);
319 esp_rom_gpio_pad_select_gpio(
static_cast<uint32_t
>(scl_pin_));
320 gpio_set_direction(scl_gpio, GPIO_MODE_INPUT_OUTPUT_OD);
321 gpio_set_pull_mode(scl_gpio,
322 enable_internal_pullup_ ? GPIO_PULLUP_ONLY : GPIO_FLOATING);
323 esp_rom_gpio_connect_out_signal(scl_pin_, sig.scl_out_sig,
false,
false);
324 esp_rom_gpio_connect_in_signal(scl_pin_, sig.scl_in_sig,
false);
326 return ErrorCode::OK;
331 if (hal_.dev ==
nullptr)
333 return ErrorCode::INIT_ERR;
336#if SOC_I2C_SUPPORT_HW_FSM_RST
337 i2c_hal_master_fsm_rst(&hal_);
338 i2c_ll_update(hal_.dev);
339 return ErrorCode::OK;
342 ResetBusRegisterAtomic(port_num_);
343 i2c_hal_master_init(&hal_);
344 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
345 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
347 const ErrorCode pin_ec = ConfigurePins();
348 if (pin_ec != ErrorCode::OK)
352 return ApplyConfig();
356bool ESP32I2C::ShouldUseInterruptAsync(
size_t total_size)
const
358 if (!intr_installed_)
362 return (isr_enable_min_size_ > 0U) &&
363 (total_size >=
static_cast<size_t>(isr_enable_min_size_));
366ErrorCode ESP32I2C::StartAsyncTransaction(uint16_t slave_addr,
367 const uint8_t* write_prefix_payload,
368 size_t write_prefix_size,
369 const uint8_t* write_payload,
size_t write_size,
370 uint8_t* read_payload,
size_t read_size,
373 if (!initialized_ || (hal_.dev ==
nullptr))
375 return ErrorCode::INIT_ERR;
377 if (!IsValid7BitAddr(slave_addr))
379 return ErrorCode::ARG_ERR;
381 if ((write_prefix_size > 0U) && (write_prefix_payload ==
nullptr))
383 return ErrorCode::PTR_NULL;
385 if (write_prefix_size > async_write_prefix_.size())
387 return ErrorCode::SIZE_ERR;
389 if ((write_size > 0U) && (write_payload ==
nullptr))
391 return ErrorCode::PTR_NULL;
393 if ((read_size > 0U) && (read_payload ==
nullptr))
395 return ErrorCode::PTR_NULL;
399 return ErrorCode::BUSY;
402 if (i2c_ll_is_bus_busy(hal_.dev))
404 const ErrorCode ec = RecoverController();
405 if (ec != ErrorCode::OK)
411 i2c_ll_txfifo_rst(hal_.dev);
412 i2c_ll_rxfifo_rst(hal_.dev);
413 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
414 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
418 async_running_ =
true;
419 async_slave_addr_ = slave_addr;
420 async_write_prefix_size_ = write_prefix_size;
421 async_write_prefix_offset_ = 0U;
422 if (write_prefix_size > 0U)
424 Memory::FastCopy(async_write_prefix_.data(), write_prefix_payload, write_prefix_size);
426 async_write_payload_ = write_payload;
427 async_write_size_ = write_size;
428 async_write_offset_ = 0U;
429 async_read_payload_ = read_payload;
430 async_read_size_ = read_size;
431 async_read_offset_ = 0U;
432 async_pending_read_chunk_ = 0U;
433 async_write_phase_done_ =
434 !((write_prefix_size > 0U) || (write_size > 0U) || (read_size == 0U));
435 async_write_addr_sent_ =
false;
436 async_write_stop_sent_ =
false;
437 async_read_addr_sent_ =
false;
439 const ErrorCode kick = KickAsyncTransaction();
440 if ((kick == ErrorCode::PENDING) || (kick == ErrorCode::OK))
442 if (kick == ErrorCode::OK)
444 FinishAsync(
false, ErrorCode::OK);
446 return ErrorCode::OK;
449 async_running_ =
false;
450 async_write_prefix_size_ = 0U;
451 async_write_prefix_offset_ = 0U;
452 async_write_payload_ =
nullptr;
453 async_write_size_ = 0U;
454 async_write_offset_ = 0U;
455 async_read_payload_ =
nullptr;
456 async_read_size_ = 0U;
457 async_read_offset_ = 0U;
458 async_pending_read_chunk_ = 0U;
459 async_write_phase_done_ =
true;
460 async_write_addr_sent_ =
false;
461 async_write_stop_sent_ =
false;
462 async_read_addr_sent_ =
false;
466ErrorCode ESP32I2C::KickAsyncTransaction()
468 if (!async_running_ || (hal_.dev ==
nullptr))
470 return ErrorCode::STATE_ERR;
473 const uint8_t write_addr =
474 static_cast<uint8_t
>((async_slave_addr_ << 1U) | I2C_MASTER_WRITE);
475 const uint8_t read_addr =
476 static_cast<uint8_t
>((async_slave_addr_ << 1U) | I2C_MASTER_READ);
477 const size_t fifo_len = kFifoLen;
478 const size_t write_chunk_cap = (fifo_len > 1U) ? (fifo_len - 1U) : 0U;
479 ASSERT(write_chunk_cap > 0U);
483 if (async_pending_read_chunk_ > 0U)
485 i2c_ll_read_rxfifo(hal_.dev, async_read_payload_ + async_read_offset_,
486 static_cast<uint8_t
>(async_pending_read_chunk_));
487 async_read_offset_ += async_pending_read_chunk_;
488 async_pending_read_chunk_ = 0U;
493 if (!async_write_phase_done_)
495 if (!async_write_addr_sent_)
497 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
499 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
500 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue,
502 async_write_addr_sent_ =
true;
505 if (async_write_prefix_offset_ < async_write_prefix_size_)
507 const size_t chunk = std::min(
508 async_write_prefix_size_ - async_write_prefix_offset_, write_chunk_cap);
509 i2c_ll_write_txfifo(hal_.dev,
510 async_write_prefix_.data() + async_write_prefix_offset_,
511 static_cast<uint8_t
>(chunk));
512 async_write_prefix_offset_ += chunk;
514 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue,
515 kCheckAck,
static_cast<uint8_t
>(chunk));
516 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
519 else if (async_write_offset_ < async_write_size_)
522 std::min(async_write_size_ - async_write_offset_, write_chunk_cap);
523 i2c_ll_write_txfifo(hal_.dev, async_write_payload_ + async_write_offset_,
524 static_cast<uint8_t
>(chunk));
525 async_write_offset_ += chunk;
527 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue,
528 kCheckAck,
static_cast<uint8_t
>(chunk));
529 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
532 else if (async_read_size_ == 0U)
534 if (!async_write_stop_sent_)
536 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
538#if SOC_I2C_STOP_INDEPENDENT
539 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
542 async_write_stop_sent_ =
true;
544 async_write_phase_done_ = async_write_stop_sent_;
548 async_write_phase_done_ =
true;
553 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
554 i2c_ll_enable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
555 i2c_hal_master_trans_start(&hal_);
556 return ErrorCode::PENDING;
562 if (async_read_size_ > 0U)
564 if (!async_read_addr_sent_)
566 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
568 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
569 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue,
571 async_read_addr_sent_ =
true;
574 if (async_read_offset_ < async_read_size_)
576 const size_t chunk = std::min(async_read_size_ - async_read_offset_, fifo_len);
577 const bool is_last = (async_read_offset_ + chunk) >= async_read_size_;
581 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kAckValue, kAckValue,
582 kNoCheckAck,
static_cast<uint8_t
>(chunk));
583 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
586 else if (chunk == 1U)
588 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kNackValue, kAckValue,
593 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kAckValue, kAckValue,
594 kNoCheckAck,
static_cast<uint8_t
>(chunk - 1U));
595 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kNackValue, kAckValue,
601 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
603#if SOC_I2C_STOP_INDEPENDENT
604 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
609 async_pending_read_chunk_ = chunk;
614 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
615 i2c_ll_enable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
616 i2c_hal_master_trans_start(&hal_);
617 return ErrorCode::PENDING;
621 return ErrorCode::OK;
625void ESP32I2C::FinishAsync(
bool in_isr, ErrorCode ec)
632 if (hal_.dev !=
nullptr)
634 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
635 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
640 async_running_ =
false;
641 async_write_prefix_size_ = 0U;
642 async_write_prefix_offset_ = 0U;
643 async_write_payload_ =
nullptr;
644 async_write_size_ = 0U;
645 async_write_offset_ = 0U;
646 async_read_payload_ =
nullptr;
647 async_read_size_ = 0U;
648 async_read_offset_ = 0U;
649 async_pending_read_chunk_ = 0U;
650 async_write_phase_done_ =
true;
651 async_write_addr_sent_ =
false;
652 async_write_stop_sent_ =
false;
653 async_read_addr_sent_ =
false;
656 if (op.type == ReadOperation::OperationType::BLOCK)
658 (void)block_wait_.TryPost(in_isr, ec);
662 op.UpdateStatus(in_isr, ec);
670 return ErrorCode::OK;
673 const int irq = i2c_periph_signal[port_num_].irq;
676 return ErrorCode::NOT_SUPPORT;
679 if (esp_intr_alloc(irq, 0, I2cIsrEntry,
this, &intr_handle_) != ESP_OK)
681 intr_handle_ =
nullptr;
682 return ErrorCode::INIT_ERR;
685 intr_installed_ =
true;
686 return ErrorCode::OK;
689void ESP32I2C::I2cIsrEntry(
void* arg)
691 auto* self =
static_cast<ESP32I2C*
>(arg);
694 self->HandleInterrupt();
698void ESP32I2C::HandleInterrupt()
700 if (hal_.dev ==
nullptr)
705 const uint32_t intr = hal_.dev->int_raw.val;
706 if ((intr & I2C_LL_MASTER_EVENT_INTR) == 0U)
713 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
714 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
718 i2c_ll_disable_intr_mask(hal_.dev, I2C_LL_MASTER_EVENT_INTR);
719 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
721 if ((intr & I2C_LL_INTR_NACK) != 0U)
723 i2c_hal_master_fsm_rst(&hal_);
724 i2c_ll_update(hal_.dev);
725 FinishAsync(
true, ErrorCode::NO_RESPONSE);
728 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
730 i2c_hal_master_fsm_rst(&hal_);
731 i2c_ll_update(hal_.dev);
732 FinishAsync(
true, ErrorCode::TIMEOUT);
735 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
737 i2c_hal_master_fsm_rst(&hal_);
738 i2c_ll_update(hal_.dev);
739 FinishAsync(
true, ErrorCode::FAILED);
743 if ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) == 0U)
748 const ErrorCode kick = KickAsyncTransaction();
749 if (kick == ErrorCode::PENDING)
754 FinishAsync(
true, kick);
757ErrorCode ESP32I2C::ExecuteTransaction(uint16_t slave_addr,
const uint8_t* write_payload,
758 size_t write_size, uint8_t* read_payload,
761 if (!initialized_ || (hal_.dev ==
nullptr))
763 return ErrorCode::INIT_ERR;
765 if (!IsValid7BitAddr(slave_addr))
767 return ErrorCode::ARG_ERR;
769 if ((write_size > 0U) && (write_payload ==
nullptr))
771 return ErrorCode::PTR_NULL;
773 if ((read_size > 0U) && (read_payload ==
nullptr))
775 return ErrorCode::PTR_NULL;
778 if (i2c_ll_is_bus_busy(hal_.dev))
780 const ErrorCode ec = RecoverController();
781 if (ec != ErrorCode::OK)
787 i2c_ll_txfifo_rst(hal_.dev);
788 i2c_ll_rxfifo_rst(hal_.dev);
789 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
791 const uint64_t timeout_us = ToTimeoutUs(timeout_ms_);
792 const uint8_t write_addr =
static_cast<uint8_t
>((slave_addr << 1U) | I2C_MASTER_WRITE);
793 const uint8_t read_addr =
static_cast<uint8_t
>((slave_addr << 1U) | I2C_MASTER_READ);
794 const size_t fifo_len = kFifoLen;
795 const size_t write_chunk_cap = (fifo_len > 1U) ? (fifo_len - 1U) : 0U;
796 ASSERT(write_chunk_cap > 0U);
800 auto start_and_wait = [&](
int done_cmd) -> ErrorCode
801 {
return StartAndWaitSegment(hal_, done_cmd, timeout_us); };
803 if ((write_size > 0U) || (read_size == 0U))
805 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
808 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
809 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue, kCheckAck,
812 size_t write_offset = 0U;
813 while (write_offset < write_size)
815 const size_t chunk = std::min(write_size - write_offset, write_chunk_cap);
816 i2c_ll_write_txfifo(hal_.dev,
817 static_cast<const uint8_t*
>(write_payload) + write_offset,
818 static_cast<uint8_t
>(chunk));
819 write_offset += chunk;
821 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue, kCheckAck,
822 static_cast<uint8_t
>(chunk));
823 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue, kNoCheckAck,
826 const ErrorCode ec = start_and_wait(cmd_idx - 1);
827 if (ec != ErrorCode::OK)
829 (void)RecoverController();
835 if (write_size == 0U)
839 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
841#if SOC_I2C_STOP_INDEPENDENT
842 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
846 const ErrorCode ec = start_and_wait(cmd_idx - 1);
847 if (ec != ErrorCode::OK)
849 (void)RecoverController();
854 else if (read_size == 0U)
856 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
858#if SOC_I2C_STOP_INDEPENDENT
859 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue, kNoCheckAck,
862 const ErrorCode ec = start_and_wait(cmd_idx - 1);
863 if (ec != ErrorCode::OK)
865 (void)RecoverController();
874 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
876 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
877 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue, kCheckAck,
880 size_t read_offset = 0U;
881 while (read_offset < read_size)
883 const size_t chunk = std::min(read_size - read_offset, fifo_len);
884 const bool is_last = (read_offset + chunk) >= read_size;
888 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kAckValue, kAckValue,
889 kNoCheckAck,
static_cast<uint8_t
>(chunk));
890 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
893 else if (chunk == 1U)
895 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kNackValue, kAckValue,
900 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kAckValue, kAckValue,
901 kNoCheckAck,
static_cast<uint8_t
>(chunk - 1U));
902 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kNackValue, kAckValue,
908 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
910#if SOC_I2C_STOP_INDEPENDENT
911 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
916 const ErrorCode ec = start_and_wait(cmd_idx - 1);
917 if (ec != ErrorCode::OK)
919 (void)RecoverController();
923 i2c_ll_read_rxfifo(hal_.dev, read_payload + read_offset,
924 static_cast<uint8_t
>(chunk));
925 read_offset += chunk;
930 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
931 return ErrorCode::OK;
938 return ErrorCode::ARG_ERR;
943 const ErrorCode init_err = InitHardware();
944 if (init_err != ErrorCode::OK)
952 return ErrorCode::BUSY;
964 const ErrorCode init_ec = EnsureInitialized(in_isr);
965 if (init_ec != ErrorCode::OK)
967 return Complete(op, in_isr, init_ec);
970 if (!IsValid7BitAddr(slave_addr))
972 return Complete(op, in_isr, ErrorCode::ARG_ERR);
975 if ((write_data.
size_ > 0U) && (write_data.
addr_ ==
nullptr))
977 return Complete(op, in_isr, ErrorCode::PTR_NULL);
982 return Complete(op, in_isr, ErrorCode::BUSY);
985 const size_t total_size = write_data.
size_;
986 if (ShouldUseInterruptAsync(total_size))
988 if (op.
type == WriteOperation::OperationType::BLOCK)
990 block_wait_.Start(*op.
data.sem_info.sem);
992 const ErrorCode ans = StartAsyncTransaction(
993 slave_addr,
nullptr, 0U,
static_cast<const uint8_t*
>(write_data.
addr_),
994 write_data.
size_,
nullptr, 0U, op);
995 if (ans != ErrorCode::OK)
997 if (op.
type == WriteOperation::OperationType::BLOCK)
999 block_wait_.Cancel();
1002 return Complete(op, in_isr, ans);
1004 if (op.
type == WriteOperation::OperationType::BLOCK)
1007 return block_wait_.Wait(op.
data.sem_info.timeout);
1009 return ErrorCode::OK;
1013 ExecuteTransaction(slave_addr,
static_cast<const uint8_t*
>(write_data.
addr_),
1014 write_data.
size_,
nullptr, 0U);
1016 return Complete(op, in_isr, ans);
1022 const ErrorCode init_ec = EnsureInitialized(in_isr);
1023 if (init_ec != ErrorCode::OK)
1025 return Complete(op, in_isr, init_ec);
1028 if (!IsValid7BitAddr(slave_addr))
1030 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1033 if ((read_data.
size_ > 0U) && (read_data.
addr_ ==
nullptr))
1035 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1040 return Complete(op, in_isr, ErrorCode::BUSY);
1043 const size_t total_size = read_data.
size_;
1044 if (ShouldUseInterruptAsync(total_size))
1046 if (op.
type == ReadOperation::OperationType::BLOCK)
1048 block_wait_.Start(*op.
data.sem_info.sem);
1050 const ErrorCode ans = StartAsyncTransaction(slave_addr,
nullptr, 0U,
nullptr, 0U,
1051 static_cast<uint8_t*
>(read_data.
addr_),
1052 read_data.
size_, op);
1053 if (ans != ErrorCode::OK)
1055 if (op.
type == ReadOperation::OperationType::BLOCK)
1057 block_wait_.Cancel();
1060 return Complete(op, in_isr, ans);
1062 if (op.
type == ReadOperation::OperationType::BLOCK)
1065 return block_wait_.Wait(op.
data.sem_info.timeout);
1067 return ErrorCode::OK;
1070 const ErrorCode ans = ExecuteTransaction(
1071 slave_addr,
nullptr, 0U,
static_cast<uint8_t*
>(read_data.
addr_), read_data.
size_);
1073 return Complete(op, in_isr, ans);
1076ErrorCode ESP32I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
1078 MemAddrLength mem_addr_size,
bool in_isr)
1080 const ErrorCode init_ec = EnsureInitialized(in_isr);
1081 if (init_ec != ErrorCode::OK)
1083 return Complete(op, in_isr, init_ec);
1086 if (!IsValid7BitAddr(slave_addr))
1088 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1091 if ((write_data.
size_ > 0U) && (write_data.
addr_ ==
nullptr))
1093 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1096 const size_t mem_len = MemAddrBytes(mem_addr_size);
1097 if (mem_len > kMaxWritePayload)
1099 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1104 return Complete(op, in_isr, ErrorCode::BUSY);
1107 std::array<uint8_t, 2> mem_raw = {};
1108 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1110 const size_t total_size = mem_len + write_data.
size_;
1111 if (ShouldUseInterruptAsync(total_size))
1113 if (op.
type == WriteOperation::OperationType::BLOCK)
1115 block_wait_.Start(*op.
data.sem_info.sem);
1117 const ErrorCode ans = StartAsyncTransaction(
1118 slave_addr, mem_raw.data(), mem_len,
1119 static_cast<const uint8_t*
>(write_data.
addr_), write_data.
size_,
nullptr, 0U, op);
1120 if (ans != ErrorCode::OK)
1122 if (op.
type == WriteOperation::OperationType::BLOCK)
1124 block_wait_.Cancel();
1127 return Complete(op, in_isr, ans);
1129 if (op.
type == WriteOperation::OperationType::BLOCK)
1132 return block_wait_.Wait(op.
data.sem_info.timeout);
1134 return ErrorCode::OK;
1137 std::array<uint8_t, kFifoLen> staging = {};
1138 const size_t max_chunk = kMaxWritePayload - mem_len;
1139 auto* src =
static_cast<const uint8_t*
>(write_data.
addr_);
1143 if (write_data.
size_ == 0U)
1145 EncodeMemAddr(mem_addr, mem_len, staging.data());
1146 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len,
nullptr, 0U);
1150 while (offset < write_data.
size_)
1152 const size_t chunk = std::min(write_data.
size_ - offset, max_chunk);
1153 const uint16_t cur_mem =
static_cast<uint16_t
>(mem_addr + offset);
1154 EncodeMemAddr(cur_mem, mem_len, staging.data());
1155 Memory::FastCopy(staging.data() + mem_len, src + offset, chunk);
1156 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len + chunk,
nullptr, 0U);
1157 if (ans != ErrorCode::OK)
1166 return Complete(op, in_isr, ans);
1170 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
1172 const ErrorCode init_ec = EnsureInitialized(in_isr);
1173 if (init_ec != ErrorCode::OK)
1175 return Complete(op, in_isr, init_ec);
1178 if (!IsValid7BitAddr(slave_addr))
1180 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1183 if ((read_data.
size_ > 0U) && (read_data.
addr_ ==
nullptr))
1185 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1188 const size_t mem_len = MemAddrBytes(mem_addr_size);
1189 if (mem_len > kMaxWriteReadPrefix)
1191 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1196 return Complete(op, in_isr, ErrorCode::BUSY);
1199 std::array<uint8_t, 2> mem_raw = {};
1200 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1202 auto* dst =
static_cast<uint8_t*
>(read_data.
addr_);
1203 const size_t total_size = mem_len + read_data.
size_;
1204 if ((read_data.
size_ > 0U) && ShouldUseInterruptAsync(total_size))
1206 if (op.
type == ReadOperation::OperationType::BLOCK)
1208 block_wait_.Start(*op.
data.sem_info.sem);
1210 const ErrorCode ans = StartAsyncTransaction(slave_addr, mem_raw.data(), mem_len,
1211 nullptr, 0U, dst, read_data.
size_, op);
1212 if (ans != ErrorCode::OK)
1214 if (op.
type == ReadOperation::OperationType::BLOCK)
1216 block_wait_.Cancel();
1219 return Complete(op, in_isr, ans);
1221 if (op.
type == ReadOperation::OperationType::BLOCK)
1224 return block_wait_.Wait(op.
data.sem_info.timeout);
1226 return ErrorCode::OK;
1232 while (offset < read_data.
size_)
1234 const size_t chunk = std::min(read_data.
size_ - offset, kMaxReadPayload);
1235 const uint16_t cur_mem =
static_cast<uint16_t
>(mem_addr + offset);
1236 EncodeMemAddr(cur_mem, mem_len, mem_raw.data());
1238 ans = ExecuteTransaction(slave_addr, mem_raw.data(), mem_len, dst + offset, chunk);
1239 if (ans != ErrorCode::OK)
1247 return Complete(op, in_isr, ans);
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
union LibXR::Operation::@5 data
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
static Timebase * timebase
静态指针,用于存储全局时间基对象。 Static pointer storing the global timebase instance.
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).