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 kFifoLen = SOC_I2C_FIFO_LEN
 
static constexpr size_t kMaxWritePayload = (kFifoLen > 4U) ? (kFifoLen - 4U) : 0U
 
static constexpr size_t kMaxWriteReadPrefix
 
static constexpr size_t kMaxReadPayload = (kFifoLen > 4U) ? (kFifoLen - 4U) : kFifoLen
 

Additional Inherited Members

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

Detailed Description

Definition at line 20 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 140 of file esp_i2c.cpp.

143 : port_num_(port_num),
144 scl_pin_(scl_pin),
145 sda_pin_(sda_pin),
146 enable_internal_pullup_(enable_internal_pullup),
147 timeout_ms_(timeout_ms),
148 isr_enable_min_size_(isr_enable_min_size),
149 config_{clock_speed}
150{
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);
157
158 if (InitHardware() != ErrorCode::OK)
159 {
160 ASSERT(false);
161 return;
162 }
163}
@ 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 165 of file esp_i2c.cpp.

165{ 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 215 of file esp_i2c.cpp.

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

◆ ConfigurePins()

ErrorCode LibXR::ESP32I2C::ConfigurePins ( )
private

Definition at line 299 of file esp_i2c.cpp.

300{
301 if (hal_.dev == nullptr)
302 {
304 }
305
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_);
309
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);
317
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);
325
326 return ErrorCode::OK;
327}
@ STATE_ERR
状态错误 | State error

◆ EncodeMemAddr()

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

Definition at line 189 of file esp_i2c.cpp.

190{
191 ASSERT(out != nullptr);
192 if (mem_len == 2U)
193 {
194 out[0] = static_cast<uint8_t>((mem_addr >> 8) & 0xFFU);
195 out[1] = static_cast<uint8_t>(mem_addr & 0xFFU);
196 return;
197 }
198
199 out[0] = static_cast<uint8_t>(mem_addr & 0xFFU);
200}

◆ EnsureInitialized()

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

Definition at line 171 of file esp_i2c.cpp.

172{
173 if (initialized_)
174 {
175 return ErrorCode::OK;
176 }
177 if (in_isr)
178 {
179 return ErrorCode::INIT_ERR;
180 }
181 return InitHardware();
182}

◆ 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 757 of file esp_i2c.cpp.

760{
761 if (!initialized_ || (hal_.dev == nullptr))
762 {
763 return ErrorCode::INIT_ERR;
764 }
765 if (!IsValid7BitAddr(slave_addr))
766 {
767 return ErrorCode::ARG_ERR;
768 }
769 if ((write_size > 0U) && (write_payload == nullptr))
770 {
771 return ErrorCode::PTR_NULL;
772 }
773 if ((read_size > 0U) && (read_payload == nullptr))
774 {
775 return ErrorCode::PTR_NULL;
776 }
777
778 if (i2c_ll_is_bus_busy(hal_.dev))
779 {
780 const ErrorCode ec = RecoverController();
781 if (ec != ErrorCode::OK)
782 {
783 return ec;
784 }
785 }
786
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);
790
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);
797
798 int cmd_idx = 0;
799
800 auto start_and_wait = [&](int done_cmd) -> ErrorCode
801 { return StartAndWaitSegment(hal_, done_cmd, timeout_us); };
802
803 if ((write_size > 0U) || (read_size == 0U))
804 {
805 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
806 kNoCheckAck, 0U);
807
808 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
809 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue, kCheckAck,
810 1U);
811
812 size_t write_offset = 0U;
813 while (write_offset < write_size)
814 {
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;
820
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,
824 0U);
825
826 const ErrorCode ec = start_and_wait(cmd_idx - 1);
827 if (ec != ErrorCode::OK)
828 {
829 (void)RecoverController();
830 return ec;
831 }
832 cmd_idx = 0;
833 }
834
835 if (write_size == 0U)
836 {
837 if (read_size == 0U)
838 {
839 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
840 kNoCheckAck, 0U);
841#if SOC_I2C_STOP_INDEPENDENT
842 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
843 kNoCheckAck, 0U);
844#endif
845 }
846 const ErrorCode ec = start_and_wait(cmd_idx - 1);
847 if (ec != ErrorCode::OK)
848 {
849 (void)RecoverController();
850 return ec;
851 }
852 cmd_idx = 0;
853 }
854 else if (read_size == 0U)
855 {
856 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
857 kNoCheckAck, 0U);
858#if SOC_I2C_STOP_INDEPENDENT
859 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue, kNoCheckAck,
860 0U);
861#endif
862 const ErrorCode ec = start_and_wait(cmd_idx - 1);
863 if (ec != ErrorCode::OK)
864 {
865 (void)RecoverController();
866 return ec;
867 }
868 cmd_idx = 0;
869 }
870 }
871
872 if (read_size > 0U)
873 {
874 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
875 kNoCheckAck, 0U);
876 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
877 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue, kCheckAck,
878 1U);
879
880 size_t read_offset = 0U;
881 while (read_offset < read_size)
882 {
883 const size_t chunk = std::min(read_size - read_offset, fifo_len);
884 const bool is_last = (read_offset + chunk) >= read_size;
885
886 if (!is_last)
887 {
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,
891 kNoCheckAck, 0U);
892 }
893 else if (chunk == 1U)
894 {
895 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kNackValue, kAckValue,
896 kNoCheckAck, 1U);
897 }
898 else
899 {
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,
903 kNoCheckAck, 1U);
904 }
905
906 if (is_last)
907 {
908 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
909 kNoCheckAck, 0U);
910#if SOC_I2C_STOP_INDEPENDENT
911 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
912 kNoCheckAck, 0U);
913#endif
914 }
915
916 const ErrorCode ec = start_and_wait(cmd_idx - 1);
917 if (ec != ErrorCode::OK)
918 {
919 (void)RecoverController();
920 return ec;
921 }
922
923 i2c_ll_read_rxfifo(hal_.dev, read_payload + read_offset,
924 static_cast<uint8_t>(chunk));
925 read_offset += chunk;
926 cmd_idx = 0;
927 }
928 }
929
930 i2c_ll_clear_intr_mask(hal_.dev, I2C_LL_INTR_MASK);
931 return ErrorCode::OK;
932}
ErrorCode
定义错误码枚举
Definition libxr_def.hpp:64
@ PTR_NULL
空指针 | Null pointer

◆ FinishAsync()

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

Definition at line 625 of file esp_i2c.cpp.

626{
627 if (!async_running_)
628 {
629 return;
630 }
631
632 if (hal_.dev != nullptr)
633 {
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);
636 }
637
638 ReadOperation op = async_op_;
639 async_op_ = {};
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;
654
655 Release();
656 if (op.type == ReadOperation::OperationType::BLOCK)
657 {
658 (void)block_wait_.TryPost(in_isr, ec);
659 }
660 else
661 {
662 op.UpdateStatus(in_isr, ec);
663 }
664}
Operation< ErrorCode > ReadOperation
Read operation type.
Definition libxr_rw.hpp:344

◆ HandleInterrupt()

void LibXR::ESP32I2C::HandleInterrupt ( )
private

Definition at line 698 of file esp_i2c.cpp.

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

◆ I2cIsrEntry()

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

Definition at line 689 of file esp_i2c.cpp.

690{
691 auto* self = static_cast<ESP32I2C*>(arg);
692 if (self != nullptr)
693 {
694 self->HandleInterrupt();
695 }
696}

◆ InitHardware()

ErrorCode LibXR::ESP32I2C::InitHardware ( )
private

Definition at line 241 of file esp_i2c.cpp.

242{
243 if (initialized_)
244 {
245 return ErrorCode::OK;
246 }
247
248 if ((port_num_ < 0) || (port_num_ >= SOC_I2C_NUM) ||
249 (static_cast<size_t>(port_num_) >= SOC_I2C_NUM))
250 {
252 }
253
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_)))
256 {
257 return ErrorCode::ARG_ERR;
258 }
259
260 SetBusClockAtomic(port_num_, true);
261 ResetBusRegisterAtomic(port_num_);
262
263 _i2c_hal_init(&hal_, static_cast<int>(port_num_));
264 if (hal_.dev == nullptr)
265 {
266 ASSERT(false);
267 return ErrorCode::INIT_ERR;
268 }
269
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);
273
274 ErrorCode err = ConfigurePins();
275 if (err != ErrorCode::OK)
276 {
277 ASSERT(false);
278 return err;
279 }
280
281 err = InstallInterrupt();
282 if (err != ErrorCode::OK)
283 {
284 ASSERT(false);
285 return err;
286 }
287
288 err = ApplyConfig();
289 if (err != ErrorCode::OK)
290 {
291 ASSERT(false);
292 return err;
293 }
294
295 initialized_ = true;
296 return ErrorCode::OK;
297}
@ OUT_OF_RANGE
超出范围 | Out of range

◆ InstallInterrupt()

ErrorCode LibXR::ESP32I2C::InstallInterrupt ( )
private

Definition at line 666 of file esp_i2c.cpp.

667{
668 if (intr_installed_)
669 {
670 return ErrorCode::OK;
671 }
672
673 const int irq = i2c_periph_signal[port_num_].irq;
674 if (irq <= 0)
675 {
677 }
678
679 if (esp_intr_alloc(irq, 0, I2cIsrEntry, this, &intr_handle_) != ESP_OK)
680 {
681 intr_handle_ = nullptr;
682 return ErrorCode::INIT_ERR;
683 }
684
685 intr_installed_ = true;
686 return ErrorCode::OK;
687}
@ NOT_SUPPORT
不支持 | Not supported

◆ IsValid7BitAddr()

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

Definition at line 169 of file esp_i2c.cpp.

169{ return addr <= 0x7FU; }

◆ KickAsyncTransaction()

ErrorCode LibXR::ESP32I2C::KickAsyncTransaction ( )
private

Definition at line 466 of file esp_i2c.cpp.

467{
468 if (!async_running_ || (hal_.dev == nullptr))
469 {
471 }
472
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);
480
481 while (true)
482 {
483 if (async_pending_read_chunk_ > 0U)
484 {
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;
489 }
490
491 int cmd_idx = 0;
492
493 if (!async_write_phase_done_)
494 {
495 if (!async_write_addr_sent_)
496 {
497 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
498 kNoCheckAck, 0U);
499 i2c_ll_write_txfifo(hal_.dev, &write_addr, 1U);
500 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue,
501 kCheckAck, 1U);
502 async_write_addr_sent_ = true;
503 }
504
505 if (async_write_prefix_offset_ < async_write_prefix_size_)
506 {
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;
513
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,
517 kNoCheckAck, 0U);
518 }
519 else if (async_write_offset_ < async_write_size_)
520 {
521 const size_t chunk =
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;
526
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,
530 kNoCheckAck, 0U);
531 }
532 else if (async_read_size_ == 0U)
533 {
534 if (!async_write_stop_sent_)
535 {
536 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
537 kNoCheckAck, 0U);
538#if SOC_I2C_STOP_INDEPENDENT
539 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
540 kNoCheckAck, 0U);
541#endif
542 async_write_stop_sent_ = true;
543 }
544 async_write_phase_done_ = async_write_stop_sent_;
545 }
546 else
547 {
548 async_write_phase_done_ = true;
549 }
550
551 if (cmd_idx > 0)
552 {
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;
557 }
558
559 continue;
560 }
561
562 if (async_read_size_ > 0U)
563 {
564 if (!async_read_addr_sent_)
565 {
566 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_RESTART, kAckValue, kAckValue,
567 kNoCheckAck, 0U);
568 i2c_ll_write_txfifo(hal_.dev, &read_addr, 1U);
569 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_WRITE, kAckValue, kAckValue,
570 kCheckAck, 1U);
571 async_read_addr_sent_ = true;
572 }
573
574 if (async_read_offset_ < async_read_size_)
575 {
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_;
578
579 if (!is_last)
580 {
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,
584 kNoCheckAck, 0U);
585 }
586 else if (chunk == 1U)
587 {
588 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_READ, kNackValue, kAckValue,
589 kNoCheckAck, 1U);
590 }
591 else
592 {
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,
596 kNoCheckAck, 1U);
597 }
598
599 if (is_last)
600 {
601 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_STOP, kAckValue, kAckValue,
602 kNoCheckAck, 0U);
603#if SOC_I2C_STOP_INDEPENDENT
604 WriteCommand(hal_.dev, cmd_idx++, I2C_LL_CMD_END, kAckValue, kAckValue,
605 kNoCheckAck, 0U);
606#endif
607 }
608
609 async_pending_read_chunk_ = chunk;
610 }
611
612 if (cmd_idx > 0)
613 {
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;
618 }
619 }
620
621 return ErrorCode::OK;
622 }
623}

◆ MemAddrBytes()

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

Definition at line 184 of file esp_i2c.cpp.

185{
186 return (mem_addr_size == MemAddrLength::BYTE_16) ? 2U : 1U;
187}

◆ 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 1169 of file esp_i2c.cpp.

1171{
1172 const ErrorCode init_ec = EnsureInitialized(in_isr);
1173 if (init_ec != ErrorCode::OK)
1174 {
1175 return Complete(op, in_isr, init_ec);
1176 }
1177
1178 if (!IsValid7BitAddr(slave_addr))
1179 {
1180 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1181 }
1182
1183 if ((read_data.size_ > 0U) && (read_data.addr_ == nullptr))
1184 {
1185 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1186 }
1187
1188 const size_t mem_len = MemAddrBytes(mem_addr_size);
1189 if (mem_len > kMaxWriteReadPrefix)
1190 {
1191 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1192 }
1193
1194 if (!Acquire())
1195 {
1196 return Complete(op, in_isr, ErrorCode::BUSY);
1197 }
1198
1199 std::array<uint8_t, 2> mem_raw = {};
1200 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1201
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))
1205 {
1206 if (op.type == ReadOperation::OperationType::BLOCK)
1207 {
1208 block_wait_.Start(*op.data.sem_info.sem);
1209 }
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)
1213 {
1214 if (op.type == ReadOperation::OperationType::BLOCK)
1215 {
1216 block_wait_.Cancel();
1217 }
1218 Release();
1219 return Complete(op, in_isr, ans);
1220 }
1221 if (op.type == ReadOperation::OperationType::BLOCK)
1222 {
1223 ASSERT(!in_isr);
1224 return block_wait_.Wait(op.data.sem_info.timeout);
1225 }
1226 return ErrorCode::OK;
1227 }
1228
1229 size_t offset = 0U;
1231
1232 while (offset < read_data.size_)
1233 {
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());
1237
1238 ans = ExecuteTransaction(slave_addr, mem_raw.data(), mem_len, dst + offset, chunk);
1239 if (ans != ErrorCode::OK)
1240 {
1241 break;
1242 }
1243 offset += chunk;
1244 }
1245
1246 Release();
1247 return Complete(op, in_isr, ans);
1248}
@ 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 1076 of file esp_i2c.cpp.

1079{
1080 const ErrorCode init_ec = EnsureInitialized(in_isr);
1081 if (init_ec != ErrorCode::OK)
1082 {
1083 return Complete(op, in_isr, init_ec);
1084 }
1085
1086 if (!IsValid7BitAddr(slave_addr))
1087 {
1088 return Complete(op, in_isr, ErrorCode::ARG_ERR);
1089 }
1090
1091 if ((write_data.size_ > 0U) && (write_data.addr_ == nullptr))
1092 {
1093 return Complete(op, in_isr, ErrorCode::PTR_NULL);
1094 }
1095
1096 const size_t mem_len = MemAddrBytes(mem_addr_size);
1097 if (mem_len > kMaxWritePayload)
1098 {
1099 return Complete(op, in_isr, ErrorCode::SIZE_ERR);
1100 }
1101
1102 if (!Acquire())
1103 {
1104 return Complete(op, in_isr, ErrorCode::BUSY);
1105 }
1106
1107 std::array<uint8_t, 2> mem_raw = {};
1108 EncodeMemAddr(mem_addr, mem_len, mem_raw.data());
1109
1110 const size_t total_size = mem_len + write_data.size_;
1111 if (ShouldUseInterruptAsync(total_size))
1112 {
1113 if (op.type == WriteOperation::OperationType::BLOCK)
1114 {
1115 block_wait_.Start(*op.data.sem_info.sem);
1116 }
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)
1121 {
1122 if (op.type == WriteOperation::OperationType::BLOCK)
1123 {
1124 block_wait_.Cancel();
1125 }
1126 Release();
1127 return Complete(op, in_isr, ans);
1128 }
1129 if (op.type == WriteOperation::OperationType::BLOCK)
1130 {
1131 ASSERT(!in_isr);
1132 return block_wait_.Wait(op.data.sem_info.timeout);
1133 }
1134 return ErrorCode::OK;
1135 }
1136
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_);
1140 size_t offset = 0U;
1142
1143 if (write_data.size_ == 0U)
1144 {
1145 EncodeMemAddr(mem_addr, mem_len, staging.data());
1146 ans = ExecuteTransaction(slave_addr, staging.data(), mem_len, nullptr, 0U);
1147 }
1148 else
1149 {
1150 while (offset < write_data.size_)
1151 {
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)
1158 {
1159 break;
1160 }
1161 offset += chunk;
1162 }
1163 }
1164
1165 Release();
1166 return Complete(op, in_isr, ans);
1167}
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:5

◆ Port()

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

Definition at line 49 of file esp_i2c.hpp.

49{ 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 1019 of file esp_i2c.cpp.

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

◆ RecoverController()

ErrorCode LibXR::ESP32I2C::RecoverController ( )
private

Definition at line 329 of file esp_i2c.cpp.

330{
331 if (hal_.dev == nullptr)
332 {
333 return ErrorCode::INIT_ERR;
334 }
335
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;
340#else
341 // ESP32-class targets without HW FSM reset require full register reset.
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);
346
347 const ErrorCode pin_ec = ConfigurePins();
348 if (pin_ec != ErrorCode::OK)
349 {
350 return pin_ec;
351 }
352 return ApplyConfig();
353#endif
354}

◆ Release()

void LibXR::ESP32I2C::Release ( )
private

Definition at line 167 of file esp_i2c.cpp.

167{ 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 202 of file esp_i2c.cpp.

203{
204 source_hz = 0U;
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))
209 {
210 return ErrorCode::INIT_ERR;
211 }
212 return ErrorCode::OK;
213}

◆ 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 934 of file esp_i2c.cpp.

935{
936 if (config.clock_speed == 0U)
937 {
938 return ErrorCode::ARG_ERR;
939 }
940
941 if (!initialized_)
942 {
943 const ErrorCode init_err = InitHardware();
944 if (init_err != ErrorCode::OK)
945 {
946 return init_err;
947 }
948 }
949
950 if (!Acquire())
951 {
952 return ErrorCode::BUSY;
953 }
954
955 config_ = config;
956 const ErrorCode ans = ApplyConfig();
957 Release();
958 return ans;
959}

◆ ShouldUseInterruptAsync()

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

Definition at line 356 of file esp_i2c.cpp.

357{
358 if (!intr_installed_)
359 {
360 return false;
361 }
362 return (isr_enable_min_size_ > 0U) &&
363 (total_size >= static_cast<size_t>(isr_enable_min_size_));
364}

◆ 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 366 of file esp_i2c.cpp.

372{
373 if (!initialized_ || (hal_.dev == nullptr))
374 {
375 return ErrorCode::INIT_ERR;
376 }
377 if (!IsValid7BitAddr(slave_addr))
378 {
379 return ErrorCode::ARG_ERR;
380 }
381 if ((write_prefix_size > 0U) && (write_prefix_payload == nullptr))
382 {
383 return ErrorCode::PTR_NULL;
384 }
385 if (write_prefix_size > async_write_prefix_.size())
386 {
387 return ErrorCode::SIZE_ERR;
388 }
389 if ((write_size > 0U) && (write_payload == nullptr))
390 {
391 return ErrorCode::PTR_NULL;
392 }
393 if ((read_size > 0U) && (read_payload == nullptr))
394 {
395 return ErrorCode::PTR_NULL;
396 }
397 if (async_running_)
398 {
399 return ErrorCode::BUSY;
400 }
401
402 if (i2c_ll_is_bus_busy(hal_.dev))
403 {
404 const ErrorCode ec = RecoverController();
405 if (ec != ErrorCode::OK)
406 {
407 return ec;
408 }
409 }
410
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);
415
416 async_op_ = op;
417 op.MarkAsRunning();
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)
423 {
424 Memory::FastCopy(async_write_prefix_.data(), write_prefix_payload, write_prefix_size);
425 }
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;
438
439 const ErrorCode kick = KickAsyncTransaction();
440 if ((kick == ErrorCode::PENDING) || (kick == ErrorCode::OK))
441 {
442 if (kick == ErrorCode::OK)
443 {
444 FinishAsync(false, ErrorCode::OK);
445 }
446 return ErrorCode::OK;
447 }
448
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;
463 return kick;
464}
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:213

◆ 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 961 of file esp_i2c.cpp.

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

Field Documentation

◆ async_op_

ReadOperation LibXR::ESP32I2C::async_op_ {}
private

Definition at line 101 of file esp_i2c.hpp.

101{};

◆ async_pending_read_chunk_

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

Definition at line 112 of file esp_i2c.hpp.

◆ async_read_addr_sent_

bool LibXR::ESP32I2C::async_read_addr_sent_ = false
private

Definition at line 116 of file esp_i2c.hpp.

◆ async_read_offset_

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

Definition at line 111 of file esp_i2c.hpp.

◆ async_read_payload_

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

Definition at line 109 of file esp_i2c.hpp.

◆ async_read_size_

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

Definition at line 110 of file esp_i2c.hpp.

◆ async_running_

bool LibXR::ESP32I2C::async_running_ = false
private

Definition at line 100 of file esp_i2c.hpp.

◆ async_slave_addr_

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

Definition at line 102 of file esp_i2c.hpp.

◆ async_write_addr_sent_

bool LibXR::ESP32I2C::async_write_addr_sent_ = false
private

Definition at line 114 of file esp_i2c.hpp.

◆ async_write_offset_

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

Definition at line 108 of file esp_i2c.hpp.

◆ async_write_payload_

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

Definition at line 106 of file esp_i2c.hpp.

◆ async_write_phase_done_

bool LibXR::ESP32I2C::async_write_phase_done_ = true
private

Definition at line 113 of file esp_i2c.hpp.

◆ async_write_prefix_

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

Definition at line 103 of file esp_i2c.hpp.

103{};

◆ async_write_prefix_offset_

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

Definition at line 105 of file esp_i2c.hpp.

◆ async_write_prefix_size_

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

Definition at line 104 of file esp_i2c.hpp.

◆ async_write_size_

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

Definition at line 107 of file esp_i2c.hpp.

◆ async_write_stop_sent_

bool LibXR::ESP32I2C::async_write_stop_sent_ = false
private

Definition at line 115 of file esp_i2c.hpp.

◆ block_wait_

AsyncBlockWait LibXR::ESP32I2C::block_wait_ {}
private

Definition at line 117 of file esp_i2c.hpp.

117{};

◆ busy_

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

Definition at line 96 of file esp_i2c.hpp.

◆ config_

Configuration LibXR::ESP32I2C::config_ {}
private

Definition at line 93 of file esp_i2c.hpp.

93{};

◆ enable_internal_pullup_

bool LibXR::ESP32I2C::enable_internal_pullup_
private

Definition at line 89 of file esp_i2c.hpp.

◆ hal_

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

Definition at line 94 of file esp_i2c.hpp.

94{};

◆ initialized_

bool LibXR::ESP32I2C::initialized_ = false
private

Definition at line 92 of file esp_i2c.hpp.

◆ intr_handle_

intr_handle_t LibXR::ESP32I2C::intr_handle_ = nullptr
private

Definition at line 97 of file esp_i2c.hpp.

◆ intr_installed_

bool LibXR::ESP32I2C::intr_installed_ = false
private

Definition at line 98 of file esp_i2c.hpp.

◆ isr_enable_min_size_

uint32_t LibXR::ESP32I2C::isr_enable_min_size_
private

Definition at line 91 of file esp_i2c.hpp.

◆ kFifoLen

size_t LibXR::ESP32I2C::kFifoLen = SOC_I2C_FIFO_LEN
staticconstexprprivate

Definition at line 52 of file esp_i2c.hpp.

◆ kMaxReadPayload

size_t LibXR::ESP32I2C::kMaxReadPayload = (kFifoLen > 4U) ? (kFifoLen - 4U) : kFifoLen
staticconstexprprivate

Definition at line 56 of file esp_i2c.hpp.

◆ kMaxWritePayload

size_t LibXR::ESP32I2C::kMaxWritePayload = (kFifoLen > 4U) ? (kFifoLen - 4U) : 0U
staticconstexprprivate

Definition at line 53 of file esp_i2c.hpp.

◆ kMaxWriteReadPrefix

size_t LibXR::ESP32I2C::kMaxWriteReadPrefix
staticconstexprprivate
Initial value:
=
(kFifoLen > 5U) ? (kFifoLen - 5U) : 0U

Definition at line 54 of file esp_i2c.hpp.

◆ PIN_NO_CHANGE

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

Definition at line 23 of file esp_i2c.hpp.

◆ port_num_

i2c_port_t LibXR::ESP32I2C::port_num_
private

Definition at line 86 of file esp_i2c.hpp.

◆ scl_pin_

int LibXR::ESP32I2C::scl_pin_
private

Definition at line 87 of file esp_i2c.hpp.

◆ sda_pin_

int LibXR::ESP32I2C::sda_pin_
private

Definition at line 88 of file esp_i2c.hpp.

◆ source_clock_hz_

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

Definition at line 95 of file esp_i2c.hpp.

◆ timeout_ms_

uint32_t LibXR::ESP32I2C::timeout_ms_
private

Definition at line 90 of file esp_i2c.hpp.


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