libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::ESP32I2C Class Reference
Inheritance diagram for LibXR::ESP32I2C:
[legend]
Collaboration diagram for LibXR::ESP32I2C:
[legend]

Public Member Functions

 ESP32I2C (i2c_port_t port_num, int scl_pin, int sda_pin, uint32_t clock_speed=400000U, bool enable_internal_pullup=true, uint32_t timeout_ms=100U, uint32_t isr_enable_min_size=32U)
 
ErrorCode Read (uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr=false) override
 读取 I2C 设备的数据。 Reads data from an I2C device.
 
ErrorCode Write (uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) override
 I2C 设备写入数据。 Writes data to an I2C device.
 
ErrorCode SetConfig (Configuration config) override
 配置 I2C 设备参数。 Configures the I2C device settings.
 
ErrorCode MemRead (uint16_t slave_addr, uint16_t mem_addr, RawData read_data, ReadOperation &op, MemAddrLength mem_addr_size=MemAddrLength::BYTE_8, bool in_isr=false) override
 I2C 设备指定寄存器读取数据。 Reads data from a specific register of an I2C device.
 
ErrorCode MemWrite (uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data, WriteOperation &op, MemAddrLength mem_addr_size=MemAddrLength::BYTE_8, bool in_isr=false) override
 I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.
 
i2c_port_t Port () const
 
- Public Member Functions inherited from LibXR::I2C
 I2C ()
 默认构造函数。 Default constructor.
 

Static Public Attributes

static constexpr int PIN_NO_CHANGE = -1
 

Private Member Functions

bool Acquire ()
 
void Release ()
 
ErrorCode InitHardware ()
 
ErrorCode ConfigurePins ()
 
ErrorCode ApplyConfig ()
 
ErrorCode ResolveClockSource (uint32_t &source_hz)
 
ErrorCode RecoverController ()
 
ErrorCode EnsureInitialized (bool in_isr)
 
bool ShouldUseInterruptAsync (size_t total_size) const
 
ErrorCode ExecuteTransaction (uint16_t slave_addr, const uint8_t *write_payload, size_t write_size, uint8_t *read_payload, size_t read_size)
 
ErrorCode StartAsyncTransaction (uint16_t slave_addr, const uint8_t *write_prefix_payload, size_t write_prefix_size, const uint8_t *write_payload, size_t write_size, uint8_t *read_payload, size_t read_size, ReadOperation &op)
 
ErrorCode KickAsyncTransaction ()
 
void FinishAsync (bool in_isr, ErrorCode ec)
 
ErrorCode InstallInterrupt ()
 
void HandleInterrupt ()
 

Static Private Member Functions

static size_t MemAddrBytes (MemAddrLength mem_addr_size)
 
static void EncodeMemAddr (uint16_t mem_addr, size_t mem_len, uint8_t *out)
 
static bool IsValid7BitAddr (uint16_t addr)
 
static void I2cIsrEntry (void *arg)
 

Private Attributes

i2c_port_t port_num_
 
int scl_pin_
 
int sda_pin_
 
bool enable_internal_pullup_
 
uint32_t timeout_ms_
 
uint32_t isr_enable_min_size_
 
bool initialized_ = false
 
Configuration config_ {}
 
i2c_hal_context_t hal_ = {}
 
uint32_t source_clock_hz_ = 0U
 
Flag::Plain busy_
 
intr_handle_t intr_handle_ = nullptr
 
bool intr_installed_ = false
 
bool async_running_ = false
 
ReadOperation async_op_ {}
 
uint16_t async_slave_addr_ = 0U
 
std::array< uint8_t, 2 > async_write_prefix_ = {}
 
size_t async_write_prefix_size_ = 0U
 
size_t async_write_prefix_offset_ = 0U
 
const uint8_t * async_write_payload_ = nullptr
 
size_t async_write_size_ = 0U
 
size_t async_write_offset_ = 0U
 
uint8_t * async_read_payload_ = nullptr
 
size_t async_read_size_ = 0U
 
size_t async_read_offset_ = 0U
 
size_t async_pending_read_chunk_ = 0U
 
bool async_write_phase_done_ = true
 
bool async_write_addr_sent_ = false
 
bool async_write_stop_sent_ = false
 
bool async_read_addr_sent_ = false
 
AsyncBlockWait block_wait_ {}
 

Static Private Attributes

static constexpr size_t FIFO_LEN = SOC_I2C_FIFO_LEN
 
static constexpr size_t MAX_WRITE_PAYLOAD = (FIFO_LEN > 4U) ? (FIFO_LEN - 4U) : 0U
 
static constexpr size_t MAX_WRITE_READ_PREFIX = (FIFO_LEN > 5U) ? (FIFO_LEN - 5U) : 0U
 
static constexpr size_t MAX_READ_PAYLOAD = (FIFO_LEN > 4U) ? (FIFO_LEN - 4U) : FIFO_LEN
 

Additional Inherited Members

- Public Types inherited from LibXR::I2C
enum class  MemAddrLength : uint8_t { BYTE_8 , BYTE_16 }
 

Detailed Description

Definition at line 19 of file esp_i2c.hpp.

Constructor & Destructor Documentation

◆ ESP32I2C()

LibXR::ESP32I2C::ESP32I2C ( i2c_port_t port_num,
int scl_pin,
int sda_pin,
uint32_t clock_speed = 400000U,
bool enable_internal_pullup = true,
uint32_t timeout_ms = 100U,
uint32_t isr_enable_min_size = 32U )

Definition at line 134 of file esp_i2c.cpp.

137 : port_num_(port_num),
138 scl_pin_(scl_pin),
139 sda_pin_(sda_pin),
140 enable_internal_pullup_(enable_internal_pullup),
141 timeout_ms_(timeout_ms),
142 isr_enable_min_size_(isr_enable_min_size),
143 config_{clock_speed}
144{
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);
151
152 if (InitHardware() != ErrorCode::OK)
153 {
154 ASSERT(false);
155 return;
156 }
157}
@ OK
操作成功 | Operation successful
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz)。 The I2C clock speed (in Hz).
Definition i2c.hpp:26

Member Function Documentation

◆ Acquire()

bool LibXR::ESP32I2C::Acquire ( )
private

Definition at line 159 of file esp_i2c.cpp.

159{ return !busy_.TestAndSet(); }
bool TestAndSet() noexcept
测试并置位:置位并返回旧状态 / Test-and-set: set and return previous state
Definition flag.hpp:146

◆ ApplyConfig()

ErrorCode LibXR::ESP32I2C::ApplyConfig ( )
private

Definition at line 209 of file esp_i2c.cpp.

210{
211 if ((hal_.dev == nullptr) || (config_.clock_speed == 0U))
212 {
213 return ErrorCode::ARG_ERR;
214 }
215
216 i2c_ll_set_source_clk(hal_.dev, I2C_CLK_SRC_DEFAULT);
217 if (ResolveClockSource(source_clock_hz_) != ErrorCode::OK)
218 {
219 return ErrorCode::INIT_ERR;
220 }
221
222 if (config_.clock_speed > (source_clock_hz_ / 20U))
223 {
224 return ErrorCode::ARG_ERR;
225 }
226
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);
231
232 return ErrorCode::OK;
233}
@ INIT_ERR
初始化错误 | Initialization error
@ ARG_ERR
参数错误 | Argument error

◆ ConfigurePins()

ErrorCode LibXR::ESP32I2C::ConfigurePins ( )
private

Definition at line 293 of file esp_i2c.cpp.

294{
295 if (hal_.dev == nullptr)
296 {
298 }
299
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_);
303
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);
311
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);
319
320 return ErrorCode::OK;
321}
@ STATE_ERR
状态错误 | State error

◆ EncodeMemAddr()

void LibXR::ESP32I2C::EncodeMemAddr ( uint16_t mem_addr,
size_t mem_len,
uint8_t * out )
staticprivate

Definition at line 183 of file esp_i2c.cpp.

184{
185 ASSERT(out != nullptr);
186 if (mem_len == 2U)
187 {
188 out[0] = static_cast<uint8_t>((mem_addr >> 8) & 0xFFU);
189 out[1] = static_cast<uint8_t>(mem_addr & 0xFFU);
190 return;
191 }
192
193 out[0] = static_cast<uint8_t>(mem_addr & 0xFFU);
194}

◆ EnsureInitialized()

ErrorCode LibXR::ESP32I2C::EnsureInitialized ( bool in_isr)
private

Definition at line 165 of file esp_i2c.cpp.

166{
167 if (initialized_)
168 {
169 return ErrorCode::OK;
170 }
171 if (in_isr)
172 {
173 return ErrorCode::INIT_ERR;
174 }
175 return InitHardware();
176}

◆ ExecuteTransaction()

ErrorCode LibXR::ESP32I2C::ExecuteTransaction ( uint16_t slave_addr,
const uint8_t * write_payload,
size_t write_size,
uint8_t * read_payload,
size_t read_size )
private

Definition at line 751 of file esp_i2c.cpp.

754{
755 if (!initialized_ || (hal_.dev == nullptr))
756 {
757 return ErrorCode::INIT_ERR;
758 }
759 if (!IsValid7BitAddr(slave_addr))
760 {
761 return ErrorCode::ARG_ERR;
762 }
763 if ((write_size > 0U) && (write_payload == nullptr))
764 {
765 return ErrorCode::PTR_NULL;
766 }
767 if ((read_size > 0U) && (read_payload == nullptr))
768 {
769 return ErrorCode::PTR_NULL;
770 }
771
772 if (i2c_ll_is_bus_busy(hal_.dev))
773 {
774 const ErrorCode ec = RecoverController();
775 if (ec != ErrorCode::OK)
776 {
777 return ec;
778 }
779 }
780
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);
784
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);
791
792 int cmd_idx = 0;
793
794 auto start_and_wait = [&](int done_cmd) -> ErrorCode
795 { return StartAndWaitSegment(hal_, done_cmd, timeout_us); };
796
797 if ((write_size > 0U) || (read_size == 0U))
798 {
799 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
800 NO_CHECK_ACK, 0U);
801
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,
804 1U);
805
806 size_t write_offset = 0U;
807 while (write_offset < write_size)
808 {
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;
814
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,
818 NO_CHECK_ACK, 0U);
819
820 const ErrorCode ec = start_and_wait(cmd_idx - 1);
821 if (ec != ErrorCode::OK)
822 {
823 (void)RecoverController();
824 return ec;
825 }
826 cmd_idx = 0;
827 }
828
829 if (write_size == 0U)
830 {
831 if (read_size == 0U)
832 {
833 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
834 NO_CHECK_ACK, 0U);
835#if SOC_I2C_STOP_INDEPENDENT
836 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
837 NO_CHECK_ACK, 0U);
838#endif
839 }
840 const ErrorCode ec = start_and_wait(cmd_idx - 1);
841 if (ec != ErrorCode::OK)
842 {
843 (void)RecoverController();
844 return ec;
845 }
846 cmd_idx = 0;
847 }
848 else if (read_size == 0U)
849 {
850 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
851 NO_CHECK_ACK, 0U);
852#if SOC_I2C_STOP_INDEPENDENT
853 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
854 NO_CHECK_ACK, 0U);
855#endif
856 const ErrorCode ec = start_and_wait(cmd_idx - 1);
857 if (ec != ErrorCode::OK)
858 {
859 (void)RecoverController();
860 return ec;
861 }
862 cmd_idx = 0;
863 }
864 }
865
866 if (read_size > 0U)
867 {
868 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
869 NO_CHECK_ACK, 0U);
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,
872 1U);
873
874 size_t read_offset = 0U;
875 while (read_offset < read_size)
876 {
877 const size_t chunk = std::min(read_size - read_offset, fifo_len);
878 const bool is_last = (read_offset + chunk) >= read_size;
879
880 if (!is_last)
881 {
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,
885 NO_CHECK_ACK, 0U);
886 }
887 else if (chunk == 1U)
888 {
889 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
890 NO_CHECK_ACK, 1U);
891 }
892 else
893 {
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,
897 NO_CHECK_ACK, 1U);
898 }
899
900 if (is_last)
901 {
902 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
903 NO_CHECK_ACK, 0U);
904#if SOC_I2C_STOP_INDEPENDENT
905 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
906 NO_CHECK_ACK, 0U);
907#endif
908 }
909
910 const ErrorCode ec = start_and_wait(cmd_idx - 1);
911 if (ec != ErrorCode::OK)
912 {
913 (void)RecoverController();
914 return ec;
915 }
916
917 i2c_ll_read_rxfifo(hal_.dev, read_payload + read_offset,
918 static_cast<uint8_t>(chunk));
919 read_offset += chunk;
920 cmd_idx = 0;
921 }
922 }
923
924 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
925 return ErrorCode::OK;
926}
ErrorCode
定义错误码枚举
@ PTR_NULL
空指针 | Null pointer

◆ FinishAsync()

void LibXR::ESP32I2C::FinishAsync ( bool in_isr,
ErrorCode ec )
private

Definition at line 619 of file esp_i2c.cpp.

620{
621 if (!async_running_)
622 {
623 return;
624 }
625
626 if (hal_.dev != nullptr)
627 {
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);
630 }
631
632 ReadOperation op = async_op_;
633 async_op_ = {};
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;
648
649 Release();
650 if (op.type == ReadOperation::OperationType::BLOCK)
651 {
652 (void)block_wait_.TryPost(in_isr, ec);
653 }
654 else
655 {
656 op.UpdateStatus(in_isr, ec);
657 }
658}
Operation< ErrorCode > ReadOperation
Read operation type.

◆ HandleInterrupt()

void LibXR::ESP32I2C::HandleInterrupt ( )
private

Definition at line 692 of file esp_i2c.cpp.

693{
694 if (hal_.dev == nullptr)
695 {
696 return;
697 }
698
699 const uint32_t intr = hal_.dev->int_raw.val;
700 if ((intr & I2C_LL_MASTER_EVENT_INTR) == 0U)
701 {
702 return;
703 }
704
705 if (!async_running_)
706 {
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);
709 return;
710 }
711
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);
714
715 if ((intr & I2C_LL_INTR_NACK) != 0U)
716 {
717 i2c_hal_master_fsm_rst(&hal_);
718 i2c_ll_update(hal_.dev);
719 FinishAsync(true, ErrorCode::NO_RESPONSE);
720 return;
721 }
722 if ((intr & I2C_LL_INTR_TIMEOUT) != 0U)
723 {
724 i2c_hal_master_fsm_rst(&hal_);
725 i2c_ll_update(hal_.dev);
726 FinishAsync(true, ErrorCode::TIMEOUT);
727 return;
728 }
729 if ((intr & I2C_LL_INTR_ARBITRATION) != 0U)
730 {
731 i2c_hal_master_fsm_rst(&hal_);
732 i2c_ll_update(hal_.dev);
733 FinishAsync(true, ErrorCode::FAILED);
734 return;
735 }
736
737 if ((intr & (I2C_LL_INTR_MST_COMPLETE | I2C_LL_INTR_END_DETECT)) == 0U)
738 {
739 return;
740 }
741
742 const ErrorCode kick = KickAsyncTransaction();
743 if (kick == ErrorCode::PENDING)
744 {
745 return;
746 }
747
748 FinishAsync(true, kick);
749}
@ TIMEOUT
超时 | Timeout
@ NO_RESPONSE
无响应 | No response
@ FAILED
操作失败 | Operation failed
@ PENDING
等待中 | Pending

◆ I2cIsrEntry()

void LibXR::ESP32I2C::I2cIsrEntry ( void * arg)
staticprivate

Definition at line 683 of file esp_i2c.cpp.

684{
685 auto* self = static_cast<ESP32I2C*>(arg);
686 if (self != nullptr)
687 {
688 self->HandleInterrupt();
689 }
690}

◆ InitHardware()

ErrorCode LibXR::ESP32I2C::InitHardware ( )
private

Definition at line 235 of file esp_i2c.cpp.

236{
237 if (initialized_)
238 {
239 return ErrorCode::OK;
240 }
241
242 if ((port_num_ < 0) || (port_num_ >= SOC_I2C_NUM) ||
243 (static_cast<size_t>(port_num_) >= SOC_I2C_NUM))
244 {
246 }
247
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_)))
250 {
251 return ErrorCode::ARG_ERR;
252 }
253
254 SetBusClockAtomic(port_num_, true);
255 ResetBusRegisterAtomic(port_num_);
256
257 _i2c_hal_init(&hal_, static_cast<int>(port_num_));
258 if (hal_.dev == nullptr)
259 {
260 ASSERT(false);
261 return ErrorCode::INIT_ERR;
262 }
263
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);
267
268 ErrorCode err = ConfigurePins();
269 if (err != ErrorCode::OK)
270 {
271 ASSERT(false);
272 return err;
273 }
274
275 err = InstallInterrupt();
276 if (err != ErrorCode::OK)
277 {
278 ASSERT(false);
279 return err;
280 }
281
282 err = ApplyConfig();
283 if (err != ErrorCode::OK)
284 {
285 ASSERT(false);
286 return err;
287 }
288
289 initialized_ = true;
290 return ErrorCode::OK;
291}
@ OUT_OF_RANGE
超出范围 | Out of range

◆ InstallInterrupt()

ErrorCode LibXR::ESP32I2C::InstallInterrupt ( )
private

Definition at line 660 of file esp_i2c.cpp.

661{
662 if (intr_installed_)
663 {
664 return ErrorCode::OK;
665 }
666
667 const int irq = i2c_periph_signal[port_num_].irq;
668 if (irq <= 0)
669 {
671 }
672
673 if (esp_intr_alloc(irq, 0, I2cIsrEntry, this, &intr_handle_) != ESP_OK)
674 {
675 intr_handle_ = nullptr;
676 return ErrorCode::INIT_ERR;
677 }
678
679 intr_installed_ = true;
680 return ErrorCode::OK;
681}
@ NOT_SUPPORT
不支持 | Not supported

◆ IsValid7BitAddr()

bool LibXR::ESP32I2C::IsValid7BitAddr ( uint16_t addr)
staticprivate

Definition at line 163 of file esp_i2c.cpp.

163{ return addr <= 0x7FU; }

◆ KickAsyncTransaction()

ErrorCode LibXR::ESP32I2C::KickAsyncTransaction ( )
private

Definition at line 460 of file esp_i2c.cpp.

461{
462 if (!async_running_ || (hal_.dev == nullptr))
463 {
465 }
466
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);
474
475 while (true)
476 {
477 if (async_pending_read_chunk_ > 0U)
478 {
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;
483 }
484
485 int cmd_idx = 0;
486
487 if (!async_write_phase_done_)
488 {
489 if (!async_write_addr_sent_)
490 {
491 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
492 NO_CHECK_ACK, 0U);
493 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
494 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
495 CHECK_ACK, 1U);
496 async_write_addr_sent_ = true;
497 }
498
499 if (async_write_prefix_offset_ < async_write_prefix_size_)
500 {
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;
507
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,
511 NO_CHECK_ACK, 0U);
512 }
513 else if (async_write_offset_ < async_write_size_)
514 {
515 const size_t chunk =
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;
520
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,
524 NO_CHECK_ACK, 0U);
525 }
526 else if (async_read_size_ == 0U)
527 {
528 if (!async_write_stop_sent_)
529 {
530 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
531 NO_CHECK_ACK, 0U);
532#if SOC_I2C_STOP_INDEPENDENT
533 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
534 NO_CHECK_ACK, 0U);
535#endif
536 async_write_stop_sent_ = true;
537 }
538 async_write_phase_done_ = async_write_stop_sent_;
539 }
540 else
541 {
542 async_write_phase_done_ = true;
543 }
544
545 if (cmd_idx > 0)
546 {
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;
551 }
552
553 continue;
554 }
555
556 if (async_read_size_ > 0U)
557 {
558 if (!async_read_addr_sent_)
559 {
560 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, ACK_VALUE, ACK_VALUE,
561 NO_CHECK_ACK, 0U);
562 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
563 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, ACK_VALUE, ACK_VALUE,
564 CHECK_ACK, 1U);
565 async_read_addr_sent_ = true;
566 }
567
568 if (async_read_offset_ < async_read_size_)
569 {
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_;
572
573 if (!is_last)
574 {
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,
578 NO_CHECK_ACK, 0U);
579 }
580 else if (chunk == 1U)
581 {
582 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, NACK_VALUE, ACK_VALUE,
583 NO_CHECK_ACK, 1U);
584 }
585 else
586 {
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,
590 NO_CHECK_ACK, 1U);
591 }
592
593 if (is_last)
594 {
595 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, ACK_VALUE, ACK_VALUE,
596 NO_CHECK_ACK, 0U);
597#if SOC_I2C_STOP_INDEPENDENT
598 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, ACK_VALUE, ACK_VALUE,
599 NO_CHECK_ACK, 0U);
600#endif
601 }
602
603 async_pending_read_chunk_ = chunk;
604 }
605
606 if (cmd_idx > 0)
607 {
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;
612 }
613 }
614
615 return ErrorCode::OK;
616 }
617}

◆ MemAddrBytes()

size_t LibXR::ESP32I2C::MemAddrBytes ( MemAddrLength mem_addr_size)
staticprivate

Definition at line 178 of file esp_i2c.cpp.

179{
180 return (mem_addr_size == MemAddrLength::BYTE_16) ? 2U : 1U;
181}

◆ MemRead()

ErrorCode LibXR::ESP32I2C::MemRead ( uint16_t slave_addr,
uint16_t mem_addr,
RawData read_data,
ReadOperation & op,
MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
bool in_isr = false )
overridevirtual

I2C 设备指定寄存器读取数据。 Reads data from a specific register of an I2C device.

该函数从指定 I2C 从设备的寄存器地址读取数据,并存储到 read_data 中。 This function reads data from the specified register of the I2C slave and stores it in read_data.

Parameters
slave_addr目标 I2C 从设备地址,不带 R/W 位。 Target I2C slave address, no R/W bit included.
mem_addr寄存器地址(通常为 8 位或 16 位)。 Register address (typically 8-bit or 16-bit).
read_data用于存储读取数据的 RawData 对象。 RawData object to store read data.
op异步或同步的读取操作对象。 Read operation object (sync or async).
mem_addr_size寄存器地址长度。 Size of register address in bytes.
in_isr是否在中断中进行操作。Whether the operation is performed in an ISR.
Returns
返回 ErrorCode,表示是否读取成功。 Returns ErrorCode indicating success or failure.

Implements LibXR::I2C.

Definition at line 1163 of file esp_i2c.cpp.

1165{
1166 const ErrorCode init_ec = EnsureInitialized(in_isr);
1167 if (init_ec != ErrorCode::OK)
1168 {
1169 return Complete(op, in_isr, init_ec);
1170 }
1171
1172 if (!IsValid7BitAddr(slave_addr))
1173 {
1174 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1175 }
1176
1177 if ((read_data.size_ > 0U) && (read_data.addr_ == nullptr))
1178 {
1179 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1180 }
1181
1182 const size_t mem_len = MemAddrBytes(mem_addr_size);
1183 if (mem_len > MAX_WRITE_READ_PREFIX)
1184 {
1185 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1186 }
1187
1188 if (!Acquire())
1189 {
1190 return Complete(op, in_isr, ErrorCode::BUSY);
1191 }
1192
1193 std::array<uint8_t, 2> mem_raw = {};
1194 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1195
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))
1199 {
1200 if (op.type == ReadOperation::OperationType::BLOCK)
1201 {
1202 block_wait_.Start(*op.data.sem_info.sem);
1203 }
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)
1207 {
1208 if (op.type == ReadOperation::OperationType::BLOCK)
1209 {
1210 block_wait_.Cancel();
1211 }
1212 Release();
1213 return Complete(op, in_isr, ans);
1214 }
1215 if (op.type == ReadOperation::OperationType::BLOCK)
1216 {
1217 ASSERT(!in_isr);
1218 return block_wait_.Wait(op.data.sem_info.timeout);
1219 }
1220 return ErrorCode::OK;
1221 }
1222
1223 size_t offset = 0U;
1225
1226 while (offset < read_data.size_)
1227 {
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());
1231
1232 ans = ExecuteTransaction(slave_addr, mem_raw.data(), mem_len, dst + offset, chunk);
1233 if (ans != ErrorCode::OK)
1234 {
1235 break;
1236 }
1237 offset += chunk;
1238 }
1239
1240 Release();
1241 return Complete(op, in_isr, ans);
1242}
@ SIZE_ERR
尺寸错误 | Size error
@ BUSY
忙碌 | Busy

◆ MemWrite()

ErrorCode LibXR::ESP32I2C::MemWrite ( uint16_t slave_addr,
uint16_t mem_addr,
ConstRawData write_data,
WriteOperation & op,
MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
bool in_isr = false )
overridevirtual

I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.

该函数将 write_data 写入指定 I2C 从设备的寄存器地址。 This function writes write_data to the specified register of the I2C slave.

Parameters
slave_addr目标 I2C 从设备地址,不带 R/W 位。 Target I2C slave address, no R/W bit included.
mem_addr寄存器地址(通常为 8 位或 16 位)。 Register address (typically 8-bit or 16-bit).
write_data要写入的数据,ConstRawData 类型。 Data to be written, of type ConstRawData.
op异步或同步的写入操作对象。 Write operation object (sync or async).
mem_addr_size寄存器地址长度。 Size of register address in bytes.
in_isr是否在中断中进行操作。Whether the operation is performed in an ISR.
Returns
返回 ErrorCode,表示是否写入成功。 Returns ErrorCode indicating success or failure.

Implements LibXR::I2C.

Definition at line 1070 of file esp_i2c.cpp.

1073{
1074 const ErrorCode init_ec = EnsureInitialized(in_isr);
1075 if (init_ec != ErrorCode::OK)
1076 {
1077 return Complete(op, in_isr, init_ec);
1078 }
1079
1080 if (!IsValid7BitAddr(slave_addr))
1081 {
1082 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1083 }
1084
1085 if ((write_data.size_ > 0U) && (write_data.addr_ == nullptr))
1086 {
1087 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1088 }
1089
1090 const size_t mem_len = MemAddrBytes(mem_addr_size);
1091 if (mem_len > MAX_WRITE_PAYLOAD)
1092 {
1093 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1094 }
1095
1096 if (!Acquire())
1097 {
1098 return Complete(op, in_isr, ErrorCode::BUSY);
1099 }
1100
1101 std::array<uint8_t, 2> mem_raw = {};
1102 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1103
1104 const size_t total_size = mem_len + write_data.size_;
1105 if (ShouldUseInterruptAsync(total_size))
1106 {
1107 if (op.type == WriteOperation::OperationType::BLOCK)
1108 {
1109 block_wait_.Start(*op.data.sem_info.sem);
1110 }
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)
1115 {
1116 if (op.type == WriteOperation::OperationType::BLOCK)
1117 {
1118 block_wait_.Cancel();
1119 }
1120 Release();
1121 return Complete(op, in_isr, ans);
1122 }
1123 if (op.type == WriteOperation::OperationType::BLOCK)
1124 {
1125 ASSERT(!in_isr);
1126 return block_wait_.Wait(op.data.sem_info.timeout);
1127 }
1128 return ErrorCode::OK;
1129 }
1130
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_);
1134 size_t offset = 0U;
1136
1137 if (write_data.size_ == 0U)
1138 {
1139 EncodeMemAddr(mem_addr, mem_len, staging.data());
1140 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len, nullptr, 0U);
1141 }
1142 else
1143 {
1144 while (offset < write_data.size_)
1145 {
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)
1152 {
1153 break;
1154 }
1155 offset += chunk;
1156 }
1157 }
1158
1159 Release();
1160 return Complete(op, in_isr, ans);
1161}
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy

◆ Port()

i2c_port_t LibXR::ESP32I2C::Port ( ) const
inline

Definition at line 46 of file esp_i2c.hpp.

46{ return port_num_; }

◆ Read()

ErrorCode LibXR::ESP32I2C::Read ( uint16_t slave_addr,
RawData read_data,
ReadOperation & op,
bool in_isr = false )
overridevirtual

读取 I2C 设备的数据。 Reads data from an I2C device.

该函数从指定的 I2C 从设备地址读取数据,并存储到 read_data 中。 This function reads data from the specified I2C slave address and stores it in read_data.

Parameters
slave_addr目标 I2C 从设备地址,不带 R/W 位。 Target I2C slave address, no R/W bit included.
read_data存储读取数据的 RawData 对象。 A RawData object to store the read data.
op读取操作对象,包含同步或异步操作模式。 Read operation object containing synchronous or asynchronous operation mode.
in_isr是否在中断中进行操作。Whether the operation is performed in an ISR.
Returns
返回 ErrorCode,指示操作是否成功。 Returns an ErrorCode indicating whether the operation was successful.

Implements LibXR::I2C.

Definition at line 1013 of file esp_i2c.cpp.

1015{
1016 const ErrorCode init_ec = EnsureInitialized(in_isr);
1017 if (init_ec != ErrorCode::OK)
1018 {
1019 return Complete(op, in_isr, init_ec);
1020 }
1021
1022 if (!IsValid7BitAddr(slave_addr))
1023 {
1024 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1025 }
1026
1027 if ((read_data.size_ > 0U) && (read_data.addr_ == nullptr))
1028 {
1029 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1030 }
1031
1032 if (!Acquire())
1033 {
1034 return Complete(op, in_isr, ErrorCode::BUSY);
1035 }
1036
1037 const size_t total_size = read_data.size_;
1038 if (ShouldUseInterruptAsync(total_size))
1039 {
1040 if (op.type == ReadOperation::OperationType::BLOCK)
1041 {
1042 block_wait_.Start(*op.data.sem_info.sem);
1043 }
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)
1048 {
1049 if (op.type == ReadOperation::OperationType::BLOCK)
1050 {
1051 block_wait_.Cancel();
1052 }
1053 Release();
1054 return Complete(op, in_isr, ans);
1055 }
1056 if (op.type == ReadOperation::OperationType::BLOCK)
1057 {
1058 ASSERT(!in_isr);
1059 return block_wait_.Wait(op.data.sem_info.timeout);
1060 }
1061 return ErrorCode::OK;
1062 }
1063
1064 const ErrorCode ans = ExecuteTransaction(
1065 slave_addr, nullptr, 0U, static_cast<uint8_t*>(read_data.addr_), read_data.size_);
1066 Release();
1067 return Complete(op, in_isr, ans);
1068}

◆ RecoverController()

ErrorCode LibXR::ESP32I2C::RecoverController ( )
private

Definition at line 323 of file esp_i2c.cpp.

324{
325 if (hal_.dev == nullptr)
326 {
327 return ErrorCode::INIT_ERR;
328 }
329
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;
334#else
335 // ESP32-class targets without HW FSM reset require full register reset.
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);
340
341 const ErrorCode pin_ec = ConfigurePins();
342 if (pin_ec != ErrorCode::OK)
343 {
344 return pin_ec;
345 }
346 return ApplyConfig();
347#endif
348}

◆ Release()

void LibXR::ESP32I2C::Release ( )
private

Definition at line 161 of file esp_i2c.cpp.

161{ busy_.Clear(); }
void Clear() noexcept
清除标志 / Clear the flag
Definition flag.hpp:130

◆ ResolveClockSource()

ErrorCode LibXR::ESP32I2C::ResolveClockSource ( uint32_t & source_hz)
private

Definition at line 196 of file esp_i2c.cpp.

197{
198 source_hz = 0U;
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))
203 {
204 return ErrorCode::INIT_ERR;
205 }
206 return ErrorCode::OK;
207}

◆ SetConfig()

ErrorCode LibXR::ESP32I2C::SetConfig ( Configuration config)
overridevirtual

配置 I2C 设备参数。 Configures the I2C device settings.

该函数用于设置 I2C 设备的参数,例如通信速率等。 This function sets the parameters of the I2C device, such as the communication speed.

Parameters
config包含 I2C 设置信息的 Configuration 结构体。 A Configuration structure containing I2C settings.
Returns
返回 ErrorCode,指示配置是否成功。 Returns an ErrorCode indicating whether the configuration was successful.

Implements LibXR::I2C.

Definition at line 928 of file esp_i2c.cpp.

929{
930 if (config.clock_speed == 0U)
931 {
932 return ErrorCode::ARG_ERR;
933 }
934
935 if (!initialized_)
936 {
937 const ErrorCode init_err = InitHardware();
938 if (init_err != ErrorCode::OK)
939 {
940 return init_err;
941 }
942 }
943
944 if (!Acquire())
945 {
946 return ErrorCode::BUSY;
947 }
948
949 config_ = config;
950 const ErrorCode ans = ApplyConfig();
951 Release();
952 return ans;
953}

◆ ShouldUseInterruptAsync()

bool LibXR::ESP32I2C::ShouldUseInterruptAsync ( size_t total_size) const
private

Definition at line 350 of file esp_i2c.cpp.

351{
352 if (!intr_installed_)
353 {
354 return false;
355 }
356 return (isr_enable_min_size_ > 0U) &&
357 (total_size >= static_cast<size_t>(isr_enable_min_size_));
358}

◆ StartAsyncTransaction()

ErrorCode LibXR::ESP32I2C::StartAsyncTransaction ( uint16_t slave_addr,
const uint8_t * write_prefix_payload,
size_t write_prefix_size,
const uint8_t * write_payload,
size_t write_size,
uint8_t * read_payload,
size_t read_size,
ReadOperation & op )
private

Definition at line 360 of file esp_i2c.cpp.

366{
367 if (!initialized_ || (hal_.dev == nullptr))
368 {
369 return ErrorCode::INIT_ERR;
370 }
371 if (!IsValid7BitAddr(slave_addr))
372 {
373 return ErrorCode::ARG_ERR;
374 }
375 if ((write_prefix_size > 0U) && (write_prefix_payload == nullptr))
376 {
377 return ErrorCode::PTR_NULL;
378 }
379 if (write_prefix_size > async_write_prefix_.size())
380 {
381 return ErrorCode::SIZE_ERR;
382 }
383 if ((write_size > 0U) && (write_payload == nullptr))
384 {
385 return ErrorCode::PTR_NULL;
386 }
387 if ((read_size > 0U) && (read_payload == nullptr))
388 {
389 return ErrorCode::PTR_NULL;
390 }
391 if (async_running_)
392 {
393 return ErrorCode::BUSY;
394 }
395
396 if (i2c_ll_is_bus_busy(hal_.dev))
397 {
398 const ErrorCode ec = RecoverController();
399 if (ec != ErrorCode::OK)
400 {
401 return ec;
402 }
403 }
404
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);
409
410 async_op_ = op;
411 op.MarkAsRunning();
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)
417 {
418 Memory::FastCopy(async_write_prefix_.data(), write_prefix_payload, write_prefix_size);
419 }
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;
432
433 const ErrorCode kick = KickAsyncTransaction();
434 if ((kick == ErrorCode::PENDING) || (kick == ErrorCode::OK))
435 {
436 if (kick == ErrorCode::OK)
437 {
438 FinishAsync(false, ErrorCode::OK);
439 }
440 return ErrorCode::OK;
441 }
442
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;
457 return kick;
458}
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.

◆ Write()

ErrorCode LibXR::ESP32I2C::Write ( uint16_t slave_addr,
ConstRawData write_data,
WriteOperation & op,
bool in_isr = false )
overridevirtual

I2C 设备写入数据。 Writes data to an I2C device.

该函数将 write_data 写入指定的 I2C 从设备地址。 This function writes write_data to the specified I2C slave address.

Parameters
slave_addr目标 I2C 从设备地址,不带 R/W 位。 Target I2C slave address, no R/W bit included.
write_data需要写入的数据,ConstRawData 类型。 The data to be written, of type ConstRawData.
op写入操作对象,包含同步或异步操作模式。 Write operation object containing synchronous or asynchronous operation mode.
in_isr是否在中断中进行操作。Whether the operation is performed in an ISR.
Returns
返回 ErrorCode,指示操作是否成功。 Returns an ErrorCode indicating whether the operation was successful.

Implements LibXR::I2C.

Definition at line 955 of file esp_i2c.cpp.

957{
958 const ErrorCode init_ec = EnsureInitialized(in_isr);
959 if (init_ec != ErrorCode::OK)
960 {
961 return Complete(op, in_isr, init_ec);
962 }
963
964 if (!IsValid7BitAddr(slave_addr))
965 {
966 return Complete(op, in_isr, ErrorCode::ARG_ERR);
967 }
968
969 if ((write_data.size_ > 0U) && (write_data.addr_ == nullptr))
970 {
971 return Complete(op, in_isr, ErrorCode::PTR_NULL);
972 }
973
974 if (!Acquire())
975 {
976 return Complete(op, in_isr, ErrorCode::BUSY);
977 }
978
979 const size_t total_size = write_data.size_;
980 if (ShouldUseInterruptAsync(total_size))
981 {
982 if (op.type == WriteOperation::OperationType::BLOCK)
983 {
984 block_wait_.Start(*op.data.sem_info.sem);
985 }
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)
990 {
991 if (op.type == WriteOperation::OperationType::BLOCK)
992 {
993 block_wait_.Cancel();
994 }
995 Release();
996 return Complete(op, in_isr, ans);
997 }
998 if (op.type == WriteOperation::OperationType::BLOCK)
999 {
1000 ASSERT(!in_isr);
1001 return block_wait_.Wait(op.data.sem_info.timeout);
1002 }
1003 return ErrorCode::OK;
1004 }
1005
1006 const ErrorCode ans =
1007 ExecuteTransaction(slave_addr, static_cast<const uint8_t*>(write_data.addr_),
1008 write_data.size_, nullptr, 0U);
1009 Release();
1010 return Complete(op, in_isr, ans);
1011}

Field Documentation

◆ async_op_

ReadOperation LibXR::ESP32I2C::async_op_ {}
private

Definition at line 96 of file esp_i2c.hpp.

96{};

◆ async_pending_read_chunk_

size_t LibXR::ESP32I2C::async_pending_read_chunk_ = 0U
private

Definition at line 107 of file esp_i2c.hpp.

◆ async_read_addr_sent_

bool LibXR::ESP32I2C::async_read_addr_sent_ = false
private

Definition at line 111 of file esp_i2c.hpp.

◆ async_read_offset_

size_t LibXR::ESP32I2C::async_read_offset_ = 0U
private

Definition at line 106 of file esp_i2c.hpp.

◆ async_read_payload_

uint8_t* LibXR::ESP32I2C::async_read_payload_ = nullptr
private

Definition at line 104 of file esp_i2c.hpp.

◆ async_read_size_

size_t LibXR::ESP32I2C::async_read_size_ = 0U
private

Definition at line 105 of file esp_i2c.hpp.

◆ async_running_

bool LibXR::ESP32I2C::async_running_ = false
private

Definition at line 95 of file esp_i2c.hpp.

◆ async_slave_addr_

uint16_t LibXR::ESP32I2C::async_slave_addr_ = 0U
private

Definition at line 97 of file esp_i2c.hpp.

◆ async_write_addr_sent_

bool LibXR::ESP32I2C::async_write_addr_sent_ = false
private

Definition at line 109 of file esp_i2c.hpp.

◆ async_write_offset_

size_t LibXR::ESP32I2C::async_write_offset_ = 0U
private

Definition at line 103 of file esp_i2c.hpp.

◆ async_write_payload_

const uint8_t* LibXR::ESP32I2C::async_write_payload_ = nullptr
private

Definition at line 101 of file esp_i2c.hpp.

◆ async_write_phase_done_

bool LibXR::ESP32I2C::async_write_phase_done_ = true
private

Definition at line 108 of file esp_i2c.hpp.

◆ async_write_prefix_

std::array<uint8_t, 2> LibXR::ESP32I2C::async_write_prefix_ = {}
private

Definition at line 98 of file esp_i2c.hpp.

98{};

◆ async_write_prefix_offset_

size_t LibXR::ESP32I2C::async_write_prefix_offset_ = 0U
private

Definition at line 100 of file esp_i2c.hpp.

◆ async_write_prefix_size_

size_t LibXR::ESP32I2C::async_write_prefix_size_ = 0U
private

Definition at line 99 of file esp_i2c.hpp.

◆ async_write_size_

size_t LibXR::ESP32I2C::async_write_size_ = 0U
private

Definition at line 102 of file esp_i2c.hpp.

◆ async_write_stop_sent_

bool LibXR::ESP32I2C::async_write_stop_sent_ = false
private

Definition at line 110 of file esp_i2c.hpp.

◆ block_wait_

AsyncBlockWait LibXR::ESP32I2C::block_wait_ {}
private

Definition at line 112 of file esp_i2c.hpp.

112{};

◆ busy_

Flag::Plain LibXR::ESP32I2C::busy_
private

Definition at line 91 of file esp_i2c.hpp.

◆ config_

Configuration LibXR::ESP32I2C::config_ {}
private

Definition at line 88 of file esp_i2c.hpp.

88{};

◆ enable_internal_pullup_

bool LibXR::ESP32I2C::enable_internal_pullup_
private

Definition at line 84 of file esp_i2c.hpp.

◆ FIFO_LEN

size_t LibXR::ESP32I2C::FIFO_LEN = SOC_I2C_FIFO_LEN
staticconstexprprivate

Definition at line 49 of file esp_i2c.hpp.

◆ hal_

i2c_hal_context_t LibXR::ESP32I2C::hal_ = {}
private

Definition at line 89 of file esp_i2c.hpp.

89{};

◆ initialized_

bool LibXR::ESP32I2C::initialized_ = false
private

Definition at line 87 of file esp_i2c.hpp.

◆ intr_handle_

intr_handle_t LibXR::ESP32I2C::intr_handle_ = nullptr
private

Definition at line 92 of file esp_i2c.hpp.

◆ intr_installed_

bool LibXR::ESP32I2C::intr_installed_ = false
private

Definition at line 93 of file esp_i2c.hpp.

◆ isr_enable_min_size_

uint32_t LibXR::ESP32I2C::isr_enable_min_size_
private

Definition at line 86 of file esp_i2c.hpp.

◆ MAX_READ_PAYLOAD

size_t LibXR::ESP32I2C::MAX_READ_PAYLOAD = (FIFO_LEN > 4U) ? (FIFO_LEN - 4U) : FIFO_LEN
staticconstexprprivate

Definition at line 52 of file esp_i2c.hpp.

◆ MAX_WRITE_PAYLOAD

size_t LibXR::ESP32I2C::MAX_WRITE_PAYLOAD = (FIFO_LEN > 4U) ? (FIFO_LEN - 4U) : 0U
staticconstexprprivate

Definition at line 50 of file esp_i2c.hpp.

◆ MAX_WRITE_READ_PREFIX

size_t LibXR::ESP32I2C::MAX_WRITE_READ_PREFIX = (FIFO_LEN > 5U) ? (FIFO_LEN - 5U) : 0U
staticconstexprprivate

Definition at line 51 of file esp_i2c.hpp.

◆ PIN_NO_CHANGE

int LibXR::ESP32I2C::PIN_NO_CHANGE = -1
staticconstexpr

Definition at line 22 of file esp_i2c.hpp.

◆ port_num_

i2c_port_t LibXR::ESP32I2C::port_num_
private

Definition at line 81 of file esp_i2c.hpp.

◆ scl_pin_

int LibXR::ESP32I2C::scl_pin_
private

Definition at line 82 of file esp_i2c.hpp.

◆ sda_pin_

int LibXR::ESP32I2C::sda_pin_
private

Definition at line 83 of file esp_i2c.hpp.

◆ source_clock_hz_

uint32_t LibXR::ESP32I2C::source_clock_hz_ = 0U
private

Definition at line 90 of file esp_i2c.hpp.

◆ timeout_ms_

uint32_t LibXR::ESP32I2C::timeout_ms_
private

Definition at line 85 of file esp_i2c.hpp.


The documentation for this class was generated from the following files: