10constexpr uint16_t kSharedMax7BitAddress = 0x7FU;
11constexpr uint16_t kSharedMax10BitAddress = 0x3FFU;
15 return mode == HPMI2C::AddressMode::ADDR_10BIT ? kSharedMax10BitAddress
16 : kSharedMax7BitAddress;
21 return (slave_addr <= ResolveHpmI2cMaxSlaveAddress(mode)) ? ErrorCode::OK
25ErrorCode ResolveHpmI2cMemAddressSize(I2C::MemAddrLength len, uint32_t& addr_size)
29 case I2C::MemAddrLength::BYTE_8:
32 case I2C::MemAddrLength::BYTE_16:
37 return ErrorCode::ARG_ERR;
41void FillHpmI2cMemAddress(uint16_t mem_addr, I2C::MemAddrLength len, uint8_t out[2])
43 if (len == I2C::MemAddrLength::BYTE_16)
45 out[0] =
static_cast<uint8_t
>((mem_addr >> 8) & 0xFFU);
46 out[1] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
50 out[0] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
58 return ResolveHpmI2cMaxSlaveAddress(mode);
68 return ResolveHpmI2cMemAddressSize(len, addr_size);
73 FillHpmI2cMemAddress(mem_addr, len, out);
78 if (policy.addr_hit_timeout_us == 0U || policy.stop_timeout_us == 0U ||
79 policy.bus_idle_timeout_us == 0U || policy.transfer_timeout_us == 0U)
84#if LIBXR_HPM_I2C_HAS_DMA_MGR
85 if (AsyncTransferActive())
95#if LIBXR_HPM_I2C_SUPPORTED
97#if __has_include("board.h")
101 void board_i2c_bus_clear(I2C_Type* ptr);
103#define LIBXR_HPM_I2C_HAS_BOARD_HELPER 1
105#define LIBXR_HPM_I2C_HAS_BOARD_HELPER 0
108#if __has_include("hpm_interrupt.h")
109#include "hpm_interrupt.h"
110#define LIBXR_HPM_I2C_HAS_INTERRUPT 1
112#define LIBXR_HPM_I2C_HAS_INTERRUPT 0
115#if __has_include("hpm_l1c_drv.h")
116#include "hpm_l1c_drv.h"
117#define LIBXR_HPM_I2C_HAS_L1C 1
119#define LIBXR_HPM_I2C_HAS_L1C 0
122#if defined(__GNUC__) || defined(__clang__)
128extern "C" void libxr_hpm_i2c_wait_relax_hook(
void) __attribute__((weak));
129#define LIBXR_HPM_I2C_HAS_WAIT_RELAX_HOOK 1
131#define LIBXR_HPM_I2C_HAS_WAIT_RELAX_HOOK 0
134#if LIBXR_HPM_I2C_HAS_DMA_MGR
142constexpr uint16_t kI2CFlagRead = I2C_RD;
143constexpr uint16_t kI2CFlagAddr10Bit = I2C_ADDR_10BIT;
144constexpr uint16_t kI2CFlagNoStart = I2C_NO_START;
145constexpr uint16_t kI2CFlagNoAddress = I2C_NO_ADDRESS;
146constexpr uint16_t kI2CFlagNoStop = I2C_NO_STOP;
147constexpr uint16_t kI2CFlagWriteCheckAck = I2C_WRITE_CHECK_ACK;
151#if LIBXR_HPM_I2C_HAS_DMA_MGR
152static_assert(
sizeof(uintptr_t) <=
sizeof(uint32_t),
153 "HPM I2C DMA helper assumes a 32-bit address space.");
155uint32_t ToHpmI2cDmaAddress(
const volatile void* addr)
157 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(addr));
161constexpr size_t kHpmI2cInstanceCount = 8U;
162#elif defined(HPM_I2C6)
163constexpr size_t kHpmI2cInstanceCount = 7U;
164#elif defined(HPM_I2C5)
165constexpr size_t kHpmI2cInstanceCount = 6U;
166#elif defined(HPM_I2C4)
167constexpr size_t kHpmI2cInstanceCount = 5U;
169constexpr size_t kHpmI2cInstanceCount = 4U;
171HPMI2C* g_hpm_i2c_instance_map[kHpmI2cInstanceCount] = {};
173using HPMI2CPlatform::kInvalidDmaSource;
174using HPMI2CPlatform::ResolveBoardI2cDmaSource;
175using HPMI2CPlatform::ResolveBoardI2cIrq;
176using HPMI2CPlatform::ResolveI2cIndex;
179#if LIBXR_HPM_I2C_HAS_DMA_MGR
180#if LIBXR_HPM_I2C_HAS_L1C
181static bool ResolveDCacheRange(
const void* addr, uint32_t size, uint32_t& start,
182 uint32_t& aligned_size)
184 if (addr ==
nullptr || size == 0U)
191 const uint64_t line_size = HPM_L1C_CACHELINE_SIZE;
192 const uint64_t address = ToHpmI2cDmaAddress(addr);
193 const uint64_t end = address +
static_cast<uint64_t
>(size);
194 constexpr uint64_t kAddressSpaceSize =
static_cast<uint64_t
>(UINT32_MAX) + 1ULL;
195 if (end > kAddressSpaceSize)
202 const uint64_t aligned_start = address - (address % line_size);
203 const uint64_t aligned_end = ((end + line_size - 1U) / line_size) * line_size;
204 const uint64_t range_size = aligned_end - aligned_start;
205 if (aligned_end > kAddressSpaceSize || range_size > UINT32_MAX)
212 start =
static_cast<uint32_t
>(aligned_start);
213 aligned_size =
static_cast<uint32_t
>(range_size);
214 return aligned_size > 0U;
218static void FlushDCacheIfNeeded(
const void* addr, uint32_t size)
220#if LIBXR_HPM_I2C_HAS_L1C
221 if (addr !=
nullptr && size > 0U && l1c_dc_is_enabled())
224 uint32_t aligned_size = 0U;
225 if (ResolveDCacheRange(addr, size, start, aligned_size))
227 l1c_dc_flush(start, aligned_size);
237#if LIBXR_HPM_I2C_HAS_DMA_MGR
238static void InvalidateDCacheIfNeeded(
const void* addr, uint32_t size)
240#if LIBXR_HPM_I2C_HAS_L1C
241 if (addr !=
nullptr && size > 0U && l1c_dc_is_enabled())
244 uint32_t aligned_size = 0U;
245 if (ResolveDCacheRange(addr, size, start, aligned_size))
247 l1c_dc_invalidate(start, aligned_size);
259#if LIBXR_HPM_I2C_HAS_WAIT_RELAX_HOOK
260 if (libxr_hpm_i2c_wait_relax_hook !=
nullptr)
262 libxr_hpm_i2c_wait_relax_hook();
266 __asm
volatile(
"nop");
269uint32_t GetI2cWaitTicksPerUs()
271 static uint32_t ticks_per_us = 0U;
272 if (ticks_per_us == 0U)
274 ticks_per_us = clock_get_core_clock_ticks_per_us();
279uint64_t GetI2cWaitTimeoutTicks(uint64_t timeout_us)
281 const uint64_t ticks_per_us = GetI2cWaitTicksPerUs();
282 if (ticks_per_us != 0U && timeout_us > (UINT64_MAX / ticks_per_us))
286 return ticks_per_us * timeout_us;
289uint64_t GetI2cWaitCycle() {
return hpm_csr_get_core_cycle(); }
291template <
typename Predicate>
292bool WaitUntil(
const Predicate& predicate, uint64_t timeout_us)
294 const uint64_t start = GetI2cWaitCycle();
295 const uint64_t timeout_ticks = GetI2cWaitTimeoutTicks(timeout_us);
298 if ((GetI2cWaitCycle() - start) > timeout_ticks)
307bool WaitForBusIdle(I2C_Type* i2c, uint64_t timeout_us)
309 return WaitUntil([i2c]()
310 {
return (i2c_get_status(i2c) & I2C_STATUS_BUSBUSY_MASK) == 0U; },
321 i2c_clear_status(i2c, I2C_STATUS_CMPL_MASK);
322 i2c->CTRL = I2C_CTRL_PHASE_STOP_MASK;
323 i2c_master_issue_data_transmission(i2c);
327 const uint32_t status = i2c_get_status(i2c);
328 return ((status & I2C_STATUS_CMPL_MASK) != 0U) ||
329 ((status & I2C_STATUS_BUSBUSY_MASK) == 0U);
331 policy.stop_timeout_us);
333 i2c, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_BYTETRANS_MASK);
337hpm_stat_t DoManualTransferWithFlagsImpl(I2C_Type* i2c, uint16_t slave_addr,
RawData data,
340 if (i2c ==
nullptr || data.
addr_ ==
nullptr || data.
size_ == 0U)
342 return status_invalid_argument;
345 i2c_enable_10bit_address_mode(i2c, (flags & I2C_ADDR_10BIT) != 0U);
347 i2c, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_BYTETRANS_MASK);
349 i2c_master_set_slave_address(i2c, slave_addr);
351 if ((flags & I2C_RD) != 0U)
353 i2c_set_direction(i2c, I2C_DIR_MASTER_READ);
357 i2c_set_direction(i2c, I2C_DIR_MASTER_WRITE);
360 if ((flags & I2C_NO_START) != 0U)
362 i2c_master_disable_start_phase(i2c);
366 i2c_master_enable_start_phase(i2c);
369 if ((flags & I2C_NO_ADDRESS) != 0U)
371 i2c_master_disable_addr_phase(i2c);
375 i2c_master_enable_addr_phase(i2c);
378 if ((flags & I2C_NO_STOP) != 0U)
380 i2c_master_disable_stop_phase(i2c);
384 i2c_master_enable_stop_phase(i2c);
387 i2c_master_enable_data_phase(i2c);
388 i2c_set_data_count(i2c,
static_cast<uint32_t
>(data.
size_));
389 const uint32_t saved_inten = i2c->INTEN;
390 i2c->INTEN = saved_inten | I2C_EVENT_BYTE_RECEIVED;
391 i2c_master_issue_data_transmission(i2c);
393 hpm_stat_t raw_status = status_success;
394 auto* bytes =
static_cast<uint8_t*
>(data.
addr_);
395 uint32_t left =
static_cast<uint32_t
>(data.
size_);
397 if ((flags & I2C_NO_ADDRESS) == 0U)
399 const bool addr_hit = WaitUntil(
400 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_ADDRHIT_MASK) != 0U; },
401 policy.addr_hit_timeout_us);
404 raw_status = status_i2c_no_addr_hit;
408 i2c_clear_status(i2c, I2C_STATUS_ADDRHIT_MASK);
412 if (raw_status == status_success && (flags & I2C_RD) != 0U)
416 const bool ready = WaitUntil(
417 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_FIFOEMPTY_MASK) == 0U; },
418 policy.transfer_timeout_us);
421 raw_status = status_timeout;
425 *(bytes++) = i2c_read_byte(i2c);
429 i2c_respond_Nack(i2c);
431 else if ((flags & I2C_NO_READ_ACK) == 0U)
433 i2c_respond_ack(i2c);
437 else if (raw_status == status_success)
441 if ((flags & I2C_WRITE_CHECK_ACK) != 0U)
443 i2c_write_byte(i2c, *(bytes++));
446 const bool ready = WaitUntil(
447 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_BYTETRANS_MASK) != 0U; },
448 policy.transfer_timeout_us);
451 raw_status = status_timeout;
455 const uint32_t status = i2c_get_status(i2c);
456 i2c_clear_status(i2c, I2C_STATUS_BYTETRANS_MASK);
457 if (!I2C_STATUS_ACK_GET(status))
459 raw_status = status_i2c_no_ack;
465 const bool ready = WaitUntil(
466 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_FIFOFULL_MASK) == 0U; },
467 policy.transfer_timeout_us);
470 raw_status = status_timeout;
474 i2c_write_byte(i2c, *(bytes++));
480 if (raw_status == status_success)
482 const bool complete =
483 WaitUntil([i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_CMPL_MASK) != 0U; },
484 policy.transfer_timeout_us);
487 raw_status = status_timeout;
491 i2c_clear_status(i2c, I2C_STATUS_CMPL_MASK);
492 if (i2c_get_data_count(i2c) != 0U)
494 raw_status = status_i2c_transmit_not_completed;
499 if (raw_status != status_success)
501 IssueStopAndWait(i2c, policy);
503 i2c, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_BYTETRANS_MASK);
504 i2c_master_disable_data_phase(i2c);
505 i2c_master_disable_addr_phase(i2c);
506 i2c_master_disable_start_phase(i2c);
507 i2c_master_disable_stop_phase(i2c);
510 i2c->INTEN = saved_inten;
516#if LIBXR_HPM_I2C_HAS_DMA_MGR && LIBXR_HPM_I2C_HAS_INTERRUPT
517extern "C" void libxr_hpm_i2c_process_interrupt(I2C_Type* ptr)
519 const int32_t index = ResolveI2cIndex(ptr);
520 if (index >= 0 &&
static_cast<size_t>(index) < kHpmI2cInstanceCount &&
521 g_hpm_i2c_instance_map[index] !=
nullptr)
523 g_hpm_i2c_instance_map[index]->HandleAsyncInterrupt(
true);
527#if defined(IRQn_I2C0) && defined(HPM_I2C0)
528SDK_DECLARE_EXT_ISR_M(IRQn_I2C0, libxr_hpm_i2c0_isr)
529void libxr_hpm_i2c0_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C0); }
531#if defined(IRQn_I2C1) && defined(HPM_I2C1)
532SDK_DECLARE_EXT_ISR_M(IRQn_I2C1, libxr_hpm_i2c1_isr)
533void libxr_hpm_i2c1_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C1); }
535#if defined(IRQn_I2C2) && defined(HPM_I2C2)
536SDK_DECLARE_EXT_ISR_M(IRQn_I2C2, libxr_hpm_i2c2_isr)
537void libxr_hpm_i2c2_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C2); }
539#if defined(IRQn_I2C3) && defined(HPM_I2C3)
540SDK_DECLARE_EXT_ISR_M(IRQn_I2C3, libxr_hpm_i2c3_isr)
541void libxr_hpm_i2c3_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C3); }
543#if defined(IRQn_I2C4) && defined(HPM_I2C4)
544SDK_DECLARE_EXT_ISR_M(IRQn_I2C4, libxr_hpm_i2c4_isr)
545void libxr_hpm_i2c4_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C4); }
547#if defined(IRQn_I2C5) && defined(HPM_I2C5)
548SDK_DECLARE_EXT_ISR_M(IRQn_I2C5, libxr_hpm_i2c5_isr)
549void libxr_hpm_i2c5_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C5); }
551#if defined(IRQn_I2C6) && defined(HPM_I2C6)
552SDK_DECLARE_EXT_ISR_M(IRQn_I2C6, libxr_hpm_i2c6_isr)
553void libxr_hpm_i2c6_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C6); }
555#if defined(IRQn_I2C7) && defined(HPM_I2C7)
556SDK_DECLARE_EXT_ISR_M(IRQn_I2C7, libxr_hpm_i2c7_isr)
557void libxr_hpm_i2c7_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C7); }
560extern "C" void libxr_hpm_i2c_process_interrupt(I2C_Type* ptr) { UNUSED(ptr); }
563HPMI2C::HPMI2C(I2C_Type* i2c, clock_name_t clock,
bool auto_board_init,
565 : i2c_(i2c), clock_(clock), current_config_(config), auto_board_init_(auto_board_init)
567 ASSERT(
i2c_ !=
nullptr);
569#if LIBXR_HPM_I2C_HAS_BOARD_HELPER
582 clock_add_to_group(
clock_, 0);
603#if LIBXR_HPM_I2C_HAS_DMA_MGR
604 if (AsyncTransferActive())
608 DisableAsyncI2cIrq();
637 case status_invalid_argument:
639 case status_i2c_bus_busy:
641 case status_i2c_not_supported:
643 case status_i2c_no_ack:
644 case status_i2c_no_addr_hit:
646 case status_i2c_invalid_data:
648 case status_i2c_transmit_not_completed:
655ErrorCode HPMI2C::ResolveMode(uint32_t clock_speed, i2c_mode_t& mode)
657 if (clock_speed == 100000UL)
659 mode = i2c_mode_normal;
661 else if (clock_speed == 400000UL)
663 mode = i2c_mode_fast;
665 else if (clock_speed == 1000000UL)
667 mode = i2c_mode_fast_plus;
669 else if (clock_speed == 0)
681#if LIBXR_HPM_I2C_HAS_DMA_MGR
682ErrorCode HPMI2C::ConvertDmaStatus(hpm_stat_t status)
688 case status_invalid_argument:
690 case status_dma_mgr_no_resource:
698i2c_seq_transfer_opt_t HPMI2C::ConvertSequenceFrame(SequenceFrame frame)
703 return i2c_frist_frame;
705 return i2c_next_frame;
708 return i2c_last_frame;
729 clock_add_to_group(
clock_, 0);
761 i2c_mode_t mode = i2c_mode_normal;
762 ErrorCode ans = ResolveMode(config.clock_speed, mode);
774 i2c_config_t i2c_config{};
775 i2c_config.i2c_mode = mode;
793 case status_i2c_bus_busy:
794 case status_i2c_no_ack:
795 case status_i2c_no_addr_hit:
827#if LIBXR_HPM_I2C_HAS_BOARD_HELPER
830 if (i2c_get_line_scl_status(
i2c_) && !i2c_get_line_sda_status(
i2c_))
832 board_i2c_bus_clear(
i2c_);
838#if defined(HPM_IP_FEATURE_I2C_SUPPORT_RESET) && (HPM_IP_FEATURE_I2C_SUPPORT_RESET == 1)
839 if (i2c_get_line_scl_status(
i2c_) && !i2c_get_line_sda_status(
i2c_))
841 i2c_gen_reset_signal(
i2c_, 9);
846#if LIBXR_HPM_I2C_HAS_DMA_MGR
847uint32_t HPMI2C::ToSystemAddress(
const void* addr)
849 return core_local_mem_to_sys_address(HPM_CORE0, ToHpmI2cDmaAddress(addr));
852ErrorCode HPMI2C::PrepareAsyncTransfer(uint16_t slave_addr, uint16_t flags, uint32_t size,
853 bool clear_fifo,
bool require_bus_idle)
860 if (require_bus_idle)
868 i2c_clear_status(
i2c_, I2C_STATUS_CMPL_MASK);
871 i2c_clear_fifo(
i2c_);
875 i2c_master_set_slave_address(
i2c_, slave_addr);
876 if ((final_flags & I2C_RD) != 0U)
878 i2c_set_direction(
i2c_, I2C_DIR_MASTER_READ);
882 i2c_set_direction(
i2c_, I2C_DIR_MASTER_WRITE);
885 if ((final_flags & I2C_NO_START) != 0U)
887 i2c_master_disable_start_phase(
i2c_);
891 i2c_master_enable_start_phase(
i2c_);
894 if ((final_flags & I2C_NO_ADDRESS) != 0U)
896 i2c_master_disable_addr_phase(
i2c_);
900 i2c_master_enable_addr_phase(
i2c_);
903 if ((final_flags & I2C_NO_STOP) != 0U)
905 i2c_master_disable_stop_phase(
i2c_);
909 i2c_master_enable_stop_phase(
i2c_);
914 i2c_master_enable_data_phase(
i2c_);
915 i2c_set_data_count(
i2c_, size);
919 i2c_master_disable_data_phase(
i2c_);
922 i2c_dma_disable(
i2c_);
923 i2c_master_issue_data_transmission(
i2c_);
925 if ((final_flags & I2C_NO_ADDRESS) == 0U)
927 const bool addr_hit = WaitUntil(
928 [
this]() {
return (i2c_get_status(
i2c_) & I2C_STATUS_ADDRHIT_MASK) != 0U; },
932 StopAndReleaseAsyncBus();
935 i2c_clear_status(
i2c_, I2C_STATUS_ADDRHIT_MASK);
941ErrorCode HPMI2C::StartAsyncReadDma(
void* dst, uint32_t size)
943 if (
i2c_ ==
nullptr || dst ==
nullptr || size == 0U)
953 FlushDCacheIfNeeded(dst, size);
956 dma_mgr_set_chn_dst_addr(&async_dma_resource_, ToSystemAddress(dst));
957 if (status != status_success)
959 return ConvertDmaStatus(status);
962 dma_mgr_set_chn_dst_work_mode(&async_dma_resource_, DMA_MGR_HANDSHAKE_MODE_NORMAL);
963 if (status != status_success)
965 return ConvertDmaStatus(status);
967 status = dma_mgr_set_chn_dst_addr_ctrl(&async_dma_resource_,
968 DMA_MGR_ADDRESS_CONTROL_INCREMENT);
969 if (status != status_success)
971 return ConvertDmaStatus(status);
974 dma_mgr_set_chn_src_addr(&async_dma_resource_, ToHpmI2cDmaAddress(&
i2c_->DATA));
975 if (status != status_success)
977 return ConvertDmaStatus(status);
979 status = dma_mgr_set_chn_src_work_mode(&async_dma_resource_,
980 DMA_MGR_HANDSHAKE_MODE_HANDSHAKE);
981 if (status != status_success)
983 return ConvertDmaStatus(status);
986 dma_mgr_set_chn_src_addr_ctrl(&async_dma_resource_, DMA_MGR_ADDRESS_CONTROL_FIXED);
987 if (status != status_success)
989 return ConvertDmaStatus(status);
991 status = dma_mgr_set_chn_src_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
992 if (status != status_success)
994 return ConvertDmaStatus(status);
996 status = dma_mgr_set_chn_dst_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
997 if (status != status_success)
999 return ConvertDmaStatus(status);
1001 status = dma_mgr_set_chn_transize(&async_dma_resource_, size);
1002 if (status != status_success)
1004 return ConvertDmaStatus(status);
1007 i2c_dma_enable(
i2c_);
1008 dma_clear_transfer_status(async_dma_resource_.base, async_dma_resource_.channel);
1009 status = dma_mgr_enable_channel(&async_dma_resource_);
1010 if (status != status_success)
1012 i2c_dma_disable(
i2c_);
1013 return ConvertDmaStatus(status);
1018ErrorCode HPMI2C::StartAsyncWriteDma(
const void* src, uint32_t size)
1020 if (
i2c_ ==
nullptr || src ==
nullptr || size == 0U)
1030 FlushDCacheIfNeeded(src, size);
1033 dma_mgr_set_chn_src_addr(&async_dma_resource_, ToSystemAddress(src));
1034 if (status != status_success)
1036 return ConvertDmaStatus(status);
1039 dma_mgr_set_chn_src_work_mode(&async_dma_resource_, DMA_MGR_HANDSHAKE_MODE_NORMAL);
1040 if (status != status_success)
1042 return ConvertDmaStatus(status);
1044 status = dma_mgr_set_chn_src_addr_ctrl(&async_dma_resource_,
1045 DMA_MGR_ADDRESS_CONTROL_INCREMENT);
1046 if (status != status_success)
1048 return ConvertDmaStatus(status);
1051 dma_mgr_set_chn_dst_addr(&async_dma_resource_, ToHpmI2cDmaAddress(&
i2c_->DATA));
1052 if (status != status_success)
1054 return ConvertDmaStatus(status);
1056 status = dma_mgr_set_chn_dst_work_mode(&async_dma_resource_,
1057 DMA_MGR_HANDSHAKE_MODE_HANDSHAKE);
1058 if (status != status_success)
1060 return ConvertDmaStatus(status);
1063 dma_mgr_set_chn_dst_addr_ctrl(&async_dma_resource_, DMA_MGR_ADDRESS_CONTROL_FIXED);
1064 if (status != status_success)
1066 return ConvertDmaStatus(status);
1068 status = dma_mgr_set_chn_src_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
1069 if (status != status_success)
1071 return ConvertDmaStatus(status);
1073 status = dma_mgr_set_chn_dst_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
1074 if (status != status_success)
1076 return ConvertDmaStatus(status);
1078 status = dma_mgr_set_chn_transize(&async_dma_resource_, size);
1079 if (status != status_success)
1081 return ConvertDmaStatus(status);
1084 i2c_dma_enable(
i2c_);
1085 dma_clear_transfer_status(async_dma_resource_.base, async_dma_resource_.channel);
1086 status = dma_mgr_enable_channel(&async_dma_resource_);
1087 if (status != status_success)
1089 i2c_dma_disable(
i2c_);
1090 return ConvertDmaStatus(status);
1095void HPMI2C::StopAsyncDma()
1097 if (async_dma_ready_)
1099 (void)dma_mgr_disable_channel(&async_dma_resource_);
1101 if (
i2c_ !=
nullptr)
1103 i2c_dma_disable(
i2c_);
1107void HPMI2C::StopAndReleaseAsyncBus()
1113void HPMI2C::AsyncCompletionStateMachine::Reset(AsyncTransferContext& ctx)
1115 ctx.final_status.store(status_success, std::memory_order_release);
1116 ctx.should_recover.store(
false, std::memory_order_release);
1117 ctx.dma_done.store(
false, std::memory_order_release);
1118 ctx.cmpl_done.store(
false, std::memory_order_release);
1121void HPMI2C::AsyncCompletionStateMachine::MarkDmaDone(AsyncTransferContext& ctx)
1123 ctx.dma_done.store(
true, std::memory_order_release);
1126void HPMI2C::AsyncCompletionStateMachine::MarkI2cDone(AsyncTransferContext& ctx,
1127 hpm_stat_t status,
bool recover)
1129 ctx.cmpl_done.store(
true, std::memory_order_release);
1130 ctx.final_status.store(status, std::memory_order_release);
1131 ctx.should_recover.store(recover, std::memory_order_release);
1134void HPMI2C::AsyncCompletionStateMachine::MarkFailure(AsyncTransferContext& ctx,
1135 hpm_stat_t status,
bool recover)
1137 ctx.final_status.store(status, std::memory_order_release);
1138 ctx.should_recover.store(recover, std::memory_order_release);
1141void HPMI2C::AsyncCompletionStateMachine::SetFinalStatus(AsyncTransferContext& ctx,
1144 ctx.final_status.store(status, std::memory_order_release);
1147bool HPMI2C::AsyncCompletionStateMachine::DmaDone(
const AsyncTransferContext& ctx)
1149 return ctx.dma_done.load(std::memory_order_acquire);
1152bool HPMI2C::AsyncCompletionStateMachine::Ready(
const AsyncTransferContext& ctx)
1154 return DmaDone(ctx) && ctx.cmpl_done.load(std::memory_order_acquire);
1157hpm_stat_t HPMI2C::AsyncCompletionStateMachine::FinalStatus(
1158 const AsyncTransferContext& ctx)
1160 return ctx.final_status.load(std::memory_order_acquire);
1163bool HPMI2C::AsyncCompletionStateMachine::ShouldRecover(
const AsyncTransferContext& ctx)
1165 return ctx.should_recover.load(std::memory_order_acquire);
1168void HPMI2C::ClearAsyncContext()
1170 async_ctx_.kind = AsyncTransferKind::NONE;
1171 async_ctx_.slave_addr = 0U;
1172 async_ctx_.mem_addr_size = MemAddrLength::BYTE_8;
1173 async_ctx_.mem_addr = 0U;
1174 async_ctx_.mem_addr_size_in_byte = 0U;
1175 async_ctx_.mem_addr_bytes[0] = 0U;
1176 async_ctx_.mem_addr_bytes[1] = 0U;
1177 async_ctx_.flags = 0U;
1178 async_ctx_.read_data = {
nullptr, 0};
1179 async_ctx_.write_data = {
nullptr, 0};
1180 async_ctx_.read_op = {};
1181 async_ctx_.write_op = {};
1182 AsyncCompletionStateMachine::Reset(async_ctx_);
1185void HPMI2C::ResetAsyncState()
1187 ClearAsyncContext();
1188 async_busy_.store(0U, std::memory_order_release);
1189 async_completion_claim_.store(0U, std::memory_order_release);
1192void HPMI2C::AbortAsyncStart(
bool stop_dma,
bool disable_irq,
bool recover_controller)
1200 DisableAsyncI2cIrq();
1203 if (recover_controller)
1215void HPMI2C::CompleteAsyncTransfer(
bool in_isr,
ErrorCode ans)
1217 if (!TryClaimAsyncCompletion())
1221 DisableAsyncI2cIrq();
1225 const bool should_recover = AsyncCompletionStateMachine::ShouldRecover(async_ctx_);
1234 async_ctx_.kind = AsyncTransferKind::NONE;
1237 if (kind == AsyncTransferKind::WRITE)
1239 CompleteAsyncOperation(write_op, in_isr, ans);
1243 CompleteAsyncOperation(read_op, in_isr, ans);
1250 if (AsyncTransferActive())
1261 async_busy_.store(1U, std::memory_order_release);
1262 ClearAsyncContext();
1263 async_ctx_.kind = AsyncTransferKind::WRITE;
1264 async_ctx_.slave_addr = slave_addr;
1265 async_ctx_.write_data = write_data;
1266 async_ctx_.write_op = op;
1268 async_completion_claim_.store(0U, std::memory_order_release);
1270 StartAsyncBlockWaitIfNeeded(op);
1272 ans = EnableAsyncI2cIrq();
1275 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1276 AbortAsyncStart(
false,
false,
false);
1277 CancelAsyncBlockWaitIfNeeded(op);
1281 i2c_clear_fifo(
i2c_);
1282 ans = StartAsyncWriteDma(write_data.
addr_,
static_cast<uint32_t
>(write_data.
size_));
1285 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1286 AbortAsyncStart(
false,
true,
false);
1287 CancelAsyncBlockWaitIfNeeded(op);
1291 hpm_stat_t start_status = i2c_master_start_dma_write(
1292 i2c_, slave_addr,
static_cast<uint32_t
>(write_data.
size_));
1296 AsyncCompletionStateMachine::MarkFailure(async_ctx_, start_status,
1299 CancelAsyncBlockWaitIfNeeded(op);
1304 if (op.
type == WriteOperation::OperationType::BLOCK)
1306 return WaitForAsyncBlockResult(op.
data.sem_info.timeout);
1314 if (AsyncTransferActive())
1325 async_busy_.store(1U, std::memory_order_release);
1326 ClearAsyncContext();
1327 async_ctx_.kind = AsyncTransferKind::READ;
1328 async_ctx_.slave_addr = slave_addr;
1329 async_ctx_.read_data = read_data;
1330 async_ctx_.read_op = op;
1331 async_ctx_.flags = kI2CFlagRead;
1332 async_completion_claim_.store(0U, std::memory_order_release);
1334 StartAsyncBlockWaitIfNeeded(op);
1336 ans = EnableAsyncI2cIrq();
1339 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1340 AbortAsyncStart(
false,
false,
false);
1341 CancelAsyncBlockWaitIfNeeded(op);
1345 i2c_clear_fifo(
i2c_);
1346 ans = StartAsyncReadDma(read_data.
addr_,
static_cast<uint32_t
>(read_data.
size_));
1349 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1350 AbortAsyncStart(
false,
true,
false);
1351 CancelAsyncBlockWaitIfNeeded(op);
1355 hpm_stat_t start_status =
1356 i2c_master_start_dma_read(
i2c_, slave_addr,
static_cast<uint32_t
>(read_data.
size_));
1360 AsyncCompletionStateMachine::MarkFailure(async_ctx_, start_status,
1363 CancelAsyncBlockWaitIfNeeded(op);
1368 if (op.
type == ReadOperation::OperationType::BLOCK)
1370 return WaitForAsyncBlockResult(op.
data.sem_info.timeout);
1375ErrorCode HPMI2C::StartMemReadAsync(uint16_t slave_addr, uint16_t mem_addr,
1377 MemAddrLength mem_addr_size)
1379 if (AsyncTransferActive())
1384 uint32_t addr_size = 0U;
1390 if (addr_size > I2C_SOC_TRANSFER_COUNT_MAX)
1401 async_busy_.store(1U, std::memory_order_release);
1402 ClearAsyncContext();
1403 async_ctx_.kind = AsyncTransferKind::MEM_READ;
1404 async_ctx_.slave_addr = slave_addr;
1405 async_ctx_.mem_addr = mem_addr;
1406 async_ctx_.mem_addr_size = mem_addr_size;
1407 async_ctx_.mem_addr_size_in_byte = addr_size;
1408 FillMemAddress(mem_addr, mem_addr_size, async_ctx_.mem_addr_bytes);
1409 async_ctx_.read_data = read_data;
1410 async_ctx_.read_op = op;
1411 async_ctx_.flags = kI2CFlagRead;
1412 async_completion_claim_.store(0U, std::memory_order_release);
1414 StartAsyncBlockWaitIfNeeded(op);
1416 ans = PrepareAsyncTransfer(slave_addr, kI2CFlagNoStop, async_ctx_.mem_addr_size_in_byte,
1421 CancelAsyncBlockWaitIfNeeded(op);
1425 for (uint32_t i = 0U; i < async_ctx_.mem_addr_size_in_byte; ++i)
1427 i2c_write_byte(
i2c_, async_ctx_.mem_addr_bytes[i]);
1430 const bool mem_addr_complete =
1431 WaitUntil([
this]() {
return (i2c_get_status(
i2c_) & I2C_STATUS_CMPL_MASK) != 0U; },
1433 if (!mem_addr_complete)
1435 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_timeout,
true);
1436 StopAndReleaseAsyncBus();
1438 CancelAsyncBlockWaitIfNeeded(op);
1441 i2c_clear_status(
i2c_, I2C_STATUS_CMPL_MASK);
1442 i2c_clear_fifo(
i2c_);
1445 i2c_master_set_slave_address(
i2c_, slave_addr);
1446 i2c_set_direction(
i2c_, I2C_DIR_MASTER_READ);
1447 i2c_master_enable_start_phase(
i2c_);
1448 i2c_master_enable_addr_phase(
i2c_);
1449 i2c_master_enable_stop_phase(
i2c_);
1450 i2c_master_enable_data_phase(
i2c_);
1451 i2c_set_data_count(
i2c_,
static_cast<uint32_t
>(read_data.
size_));
1452 i2c_dma_disable(
i2c_);
1453 if ((final_flags & kI2CFlagAddr10Bit) != 0U)
1455 i2c_enable_10bit_address_mode(
i2c_,
true);
1458 ans = EnableAsyncI2cIrq();
1461 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1462 StopAndReleaseAsyncBus();
1464 CancelAsyncBlockWaitIfNeeded(op);
1468 ans = StartAsyncReadDma(read_data.
addr_,
static_cast<uint32_t
>(read_data.
size_));
1471 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1472 DisableAsyncI2cIrq();
1473 StopAndReleaseAsyncBus();
1475 CancelAsyncBlockWaitIfNeeded(op);
1479 i2c_master_issue_data_transmission(
i2c_);
1480 const bool addr_hit = WaitUntil(
1481 [
this]() {
return (i2c_get_status(
i2c_) & I2C_STATUS_ADDRHIT_MASK) != 0U; },
1485 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_i2c_no_addr_hit,
true);
1486 AbortAsyncStart(
true,
true,
true);
1487 CancelAsyncBlockWaitIfNeeded(op);
1490 i2c_clear_status(
i2c_, I2C_STATUS_ADDRHIT_MASK);
1493 if (op.
type == ReadOperation::OperationType::BLOCK)
1495 return WaitForAsyncBlockResult(op.
data.sem_info.timeout);
1502 if (async_dma_ready_)
1507 if (
i2c_ ==
nullptr)
1512 async_dma_source_ = ResolveBoardI2cDmaSource(
i2c_);
1513 if (async_dma_source_ == kInvalidDmaSource)
1519#if defined(BOARD_APP_I2C_DMA)
1521 dma_mgr_request_specified_resource(&async_dma_resource_, BOARD_APP_I2C_DMA);
1523 hpm_stat_t status = status_fail;
1525 if (status != status_success)
1527 status = dma_mgr_request_resource(&async_dma_resource_);
1528 if (status != status_success)
1530 return ConvertDmaStatus(status);
1534 dma_mgr_chn_conf_t cfg{};
1535 dma_mgr_get_default_chn_config(&cfg);
1536 cfg.src_width = DMA_MGR_TRANSFER_WIDTH_BYTE;
1537 cfg.dst_width = DMA_MGR_TRANSFER_WIDTH_BYTE;
1538 cfg.en_dmamux =
true;
1539 cfg.dmamux_src = async_dma_source_;
1540 cfg.interrupt_mask = DMA_MGR_INTERRUPT_MASK_ALL;
1541 status = dma_mgr_setup_channel(&async_dma_resource_, &cfg);
1542 if (status != status_success)
1544 (void)dma_mgr_release_resource(&async_dma_resource_);
1545 async_dma_resource_ = {
nullptr, 0U, -1};
1546 return ConvertDmaStatus(status);
1549 status = dma_mgr_install_chn_tc_callback(&async_dma_resource_, &HPMI2C::OnDmaTcCallback,
1551 if (status != status_success)
1553 (void)dma_mgr_release_resource(&async_dma_resource_);
1554 async_dma_resource_ = {
nullptr, 0U, -1};
1555 return ConvertDmaStatus(status);
1557 status = dma_mgr_install_chn_error_callback(&async_dma_resource_,
1558 &HPMI2C::OnDmaErrorCallback,
this);
1559 if (status != status_success)
1561 (void)dma_mgr_release_resource(&async_dma_resource_);
1562 async_dma_resource_ = {
nullptr, 0U, -1};
1563 return ConvertDmaStatus(status);
1565 status = dma_mgr_install_chn_abort_callback(&async_dma_resource_,
1566 &HPMI2C::OnDmaAbortCallback,
this);
1567 if (status != status_success)
1569 (void)dma_mgr_release_resource(&async_dma_resource_);
1570 async_dma_resource_ = {
nullptr, 0U, -1};
1571 return ConvertDmaStatus(status);
1573 status = dma_mgr_enable_chn_irq(&async_dma_resource_, DMA_MGR_INTERRUPT_MASK_TC |
1574 DMA_MGR_INTERRUPT_MASK_ERROR |
1575 DMA_MGR_INTERRUPT_MASK_ABORT);
1576 if (status != status_success)
1578 (void)dma_mgr_release_resource(&async_dma_resource_);
1579 async_dma_resource_ = {
nullptr, 0U, -1};
1580 return ConvertDmaStatus(status);
1582 status = dma_mgr_enable_dma_irq_with_priority(&async_dma_resource_, 1U);
1583 if (status != status_success)
1585 (void)dma_mgr_release_resource(&async_dma_resource_);
1586 async_dma_resource_ = {
nullptr, 0U, -1};
1587 return ConvertDmaStatus(status);
1590 async_dma_ready_ =
true;
1594ErrorCode HPMI2C::WaitForAsyncBlockResult(uint32_t timeout)
1596 const ErrorCode ans = block_wait_.Wait(timeout);
1599 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_timeout,
true);
1605void HPMI2C::ReleaseAsyncBus()
1607 if (
i2c_ ==
nullptr)
1612 i2c_clear_status(
i2c_, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK);
1613 i2c_master_disable_data_phase(
i2c_);
1614 i2c_master_disable_addr_phase(
i2c_);
1615 i2c_master_disable_start_phase(
i2c_);
1616 i2c_master_disable_stop_phase(
i2c_);
1617 i2c_master_issue_data_transmission(
i2c_);
1622#if !LIBXR_HPM_I2C_HAS_INTERRUPT
1625 const int32_t irq = ResolveBoardI2cIrq(
i2c_);
1626 const int32_t index = ResolveI2cIndex(
i2c_);
1627 if (irq < 0 || index < 0 ||
static_cast<size_t>(index) >= kHpmI2cInstanceCount)
1631 if (g_hpm_i2c_instance_map[index] !=
nullptr && g_hpm_i2c_instance_map[index] !=
this)
1636 g_hpm_i2c_instance_map[index] =
this;
1638 i2c_, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_ARBLOSE_MASK);
1639 i2c_enable_irq(
i2c_, I2C_EVENT_TRANSACTION_COMPLETE | I2C_EVENT_LOSS_ARBITRATION);
1640 intc_m_enable_irq_with_priority(
static_cast<uint32_t
>(irq), 1U);
1645void HPMI2C::DisableAsyncI2cIrq()
1647#if LIBXR_HPM_I2C_HAS_INTERRUPT
1648 if (
i2c_ !=
nullptr)
1650 i2c_disable_irq(
i2c_, I2C_EVENT_TRANSACTION_COMPLETE | I2C_EVENT_LOSS_ARBITRATION);
1651 const int32_t irq = ResolveBoardI2cIrq(
i2c_);
1654 intc_m_disable_irq(
static_cast<uint32_t
>(irq));
1657 const int32_t index = ResolveI2cIndex(
i2c_);
1658 if (index >= 0 &&
static_cast<size_t>(index) < kHpmI2cInstanceCount &&
1659 g_hpm_i2c_instance_map[index] ==
this)
1661 g_hpm_i2c_instance_map[index] =
nullptr;
1666void HPMI2C::HandleAsyncInterrupt(
bool in_isr)
1668 if (!AsyncTransferActive() ||
i2c_ ==
nullptr)
1673 const uint32_t status = i2c_get_status(
i2c_);
1674 if ((status & I2C_STATUS_ARBLOSE_MASK) != 0U)
1676 i2c_clear_status(
i2c_, I2C_STATUS_ARBLOSE_MASK);
1677 AsyncCompletionStateMachine::MarkI2cDone(async_ctx_, status_timeout,
true);
1682 if ((status & I2C_STATUS_CMPL_MASK) != 0U)
1684 i2c_clear_status(
i2c_, I2C_STATUS_CMPL_MASK);
1685 if (async_ctx_.kind == AsyncTransferKind::WRITE &&
1686 (async_ctx_.flags & kI2CFlagWriteCheckAck) != 0U && !I2C_STATUS_ACK_GET(status))
1688 AsyncCompletionStateMachine::MarkI2cDone(async_ctx_, status_i2c_no_ack,
true);
1692 AsyncCompletionStateMachine::MarkI2cDone(async_ctx_, status_success,
false);
1696 MaybeCompleteAsyncTransfer(in_isr);
1699void HPMI2C::MaybeCompleteAsyncTransfer(
bool in_isr)
1701 if (!AsyncTransferActive() || !AsyncCompletionStateMachine::Ready(async_ctx_))
1706 if (async_ctx_.kind == AsyncTransferKind::READ ||
1707 async_ctx_.kind == AsyncTransferKind::MEM_READ)
1709 InvalidateDCacheIfNeeded(async_ctx_.read_data.addr_,
1710 static_cast<uint32_t
>(async_ctx_.read_data.size_));
1712 hpm_stat_t final_status = AsyncCompletionStateMachine::FinalStatus(async_ctx_);
1713 if (final_status == status_success && i2c_get_data_count(
i2c_) != 0U)
1715 final_status = status_i2c_transmit_not_completed;
1716 AsyncCompletionStateMachine::SetFinalStatus(async_ctx_, final_status);
1721bool HPMI2C::TryClaimAsyncCompletion()
1723 uint32_t expected = 0U;
1724 return async_completion_claim_.compare_exchange_strong(
1725 expected, 1U, std::memory_order_acq_rel, std::memory_order_acquire);
1728void HPMI2C::OnDmaTcCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr)
1732 auto* self =
static_cast<HPMI2C*
>(cb_data_ptr);
1733 if (self ==
nullptr || !self->AsyncTransferActive())
1738 AsyncCompletionStateMachine::MarkDmaDone(self->async_ctx_);
1739 self->MaybeCompleteAsyncTransfer(
true);
1742void HPMI2C::OnDmaErrorCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr)
1746 auto* self =
static_cast<HPMI2C*
>(cb_data_ptr);
1747 if (self ==
nullptr || !self->AsyncTransferActive())
1751 if (AsyncCompletionStateMachine::DmaDone(self->async_ctx_))
1755 AsyncCompletionStateMachine::MarkFailure(self->async_ctx_, status_fail,
true);
1759void HPMI2C::OnDmaAbortCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr)
1763 auto* self =
static_cast<HPMI2C*
>(cb_data_ptr);
1764 if (self ==
nullptr || !self->AsyncTransferActive())
1768 if (AsyncCompletionStateMachine::DmaDone(self->async_ctx_))
1772 AsyncCompletionStateMachine::MarkFailure(self->async_ctx_, status_fail,
true);
1778 bool allow_zero_size)
const
1780 if (data.
size_ == 0)
1784 if (data.
addr_ ==
nullptr)
1788 if (data.
size_ > I2C_SOC_TRANSFER_COUNT_MAX)
1796 bool allow_zero_size)
const
1798 if (data.
size_ == 0)
1802 if (data.
addr_ ==
nullptr)
1806 if (data.
size_ > I2C_SOC_TRANSFER_COUNT_MAX)
1814 MemAddrLength mem_addr_size,
1815 uint32_t& addr_size)
const
1817 if (write_data.
size_ > 0 && write_data.
addr_ ==
nullptr)
1827 if ((addr_size + write_data.
size_) > I2C_SOC_TRANSFER_COUNT_MAX)
1836 if (
i2c_ ==
nullptr)
1853#if LIBXR_HPM_I2C_HAS_DMA_MGR
1854 if (AsyncTransferActive())
1859 if (op.
type != ReadOperation::OperationType::BLOCK)
1861 const ErrorCode ans = StartReadAsync(slave_addr, read_data, op);
1877 i2c_master_read(
i2c_, slave_addr,
static_cast<uint8_t*
>(read_data.
addr_),
1878 static_cast<uint32_t
>(read_data.
size_));
1888 SequenceFrame frame,
bool check_ack)
1890#if LIBXR_HPM_I2C_HAS_DMA_MGR
1891 if (AsyncTransferActive())
1906 uint16_t flags = kI2CFlagWriteCheckAck;
1915 flags |= kI2CFlagAddr10Bit;
1916 flags |= kI2CFlagNoStop;
1919 flags |= kI2CFlagAddr10Bit | I2C_NO_START | I2C_NO_ADDRESS | kI2CFlagNoStop;
1923 flags |= kI2CFlagAddr10Bit | I2C_NO_START | I2C_NO_ADDRESS;
1929 status = raw_status;
1933 status = i2c_master_seq_transmit_check_ack(
1935 const_cast<uint8_t*
>(
static_cast<const uint8_t*
>(write_data.
addr_)),
1936 static_cast<uint32_t
>(write_data.
size_), ConvertSequenceFrame(frame), check_ack);
1948 SequenceFrame frame)
1950#if LIBXR_HPM_I2C_HAS_DMA_MGR
1951 if (AsyncTransferActive())
1966 uint16_t flags = kI2CFlagRead | kI2CFlagAddr10Bit;
1970 flags |= kI2CFlagNoStop;
1973 flags |= I2C_NO_START | I2C_NO_ADDRESS | kI2CFlagNoStop;
1977 flags |= I2C_NO_START | I2C_NO_ADDRESS;
1984 status = i2c_master_seq_receive(
1985 i2c_, slave_addr,
static_cast<uint8_t*
>(read_data.
addr_),
1986 static_cast<uint32_t
>(read_data.
size_), ConvertSequenceFrame(frame));
1999#if LIBXR_HPM_I2C_HAS_DMA_MGR
2000 if (AsyncTransferActive())
2025#if LIBXR_HPM_I2C_HAS_DMA_MGR
2026 if (AsyncTransferActive())
2028 return status_i2c_bus_busy;
2032 return DoManualTransferWithFlagsImpl(
i2c_, slave_addr, data, flags,
wait_policy_);
2044#if LIBXR_HPM_I2C_HAS_DMA_MGR
2045 if (AsyncTransferActive())
2062#if LIBXR_HPM_I2C_HAS_DMA_MGR
2063 if (AsyncTransferActive())
2079#if LIBXR_HPM_I2C_HAS_DMA_MGR
2080 if (AsyncTransferActive())
2096#if LIBXR_HPM_I2C_HAS_DMA_MGR
2097 if (AsyncTransferActive())
2105 static_cast<uint16_t
>(flags & ~kI2CFlagRead)));
2117#if LIBXR_HPM_I2C_HAS_DMA_MGR
2118 if (AsyncTransferActive())
2123 if (op.
type != WriteOperation::OperationType::BLOCK)
2125 const ErrorCode ans = StartWriteAsync(slave_addr, write_data, op);
2140 hpm_stat_t status = i2c_master_write(
2142 const_cast<uint8_t*
>(
static_cast<const uint8_t*
>(write_data.
addr_)),
2143 static_cast<uint32_t
>(write_data.
size_));
2153 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
2161#if LIBXR_HPM_I2C_HAS_DMA_MGR
2162 if (AsyncTransferActive())
2167 if (op.
type != ReadOperation::OperationType::BLOCK)
2170 StartMemReadAsync(slave_addr, mem_addr, read_data, op, mem_addr_size);
2179 uint32_t addr_size = 0;
2185 if (addr_size > I2C_SOC_TRANSFER_COUNT_MAX)
2196 uint8_t addr[2] = {};
2210 const hpm_stat_t status = i2c_master_address_read(
2211 i2c_, slave_addr, addr, addr_size,
static_cast<uint8_t*
>(read_data.
addr_),
2212 static_cast<uint32_t
>(read_data.
size_));
2224 MemAddrLength mem_addr_size,
bool in_isr)
2226 uint32_t addr_size = 0;
2233#if LIBXR_HPM_I2C_HAS_DMA_MGR
2234 if (AsyncTransferActive())
2246 uint8_t addr[2] = {};
2251 if (write_data.
size_ == 0)
2255 kI2CFlagAddr10Bit | kI2CFlagWriteCheckAck);
2275 if (write_data.
size_ == 0)
2277 status = i2c_master_write(
i2c_, slave_addr, addr, addr_size);
2281 status = i2c_master_address_write(
2282 i2c_, slave_addr, addr, addr_size,
2283 const_cast<uint8_t*
>(
static_cast<const uint8_t*
>(write_data.
addr_)),
2284 static_cast<uint32_t
>(write_data.
size_));
2298extern "C" void libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr) { UNUSED(ptr); }
2302 : i2c_(i2c), clock_(clock), current_config_(config), auto_board_init_(auto_board_init)
2404 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
2409 UNUSED(mem_addr_size);
2415 MemAddrLength mem_addr_size,
bool in_isr)
2420 UNUSED(mem_addr_size);
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
HPM SDK I2C 主机驱动,适配 LibXR I2C 接口 / HPM SDK based I2C master driver for the LibXR I2C interface.
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 从设备寄存器或存储器地址读取字节 / Read bytes from an I2C slave register or memory address.
ErrorCode DoTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags)
执行一段扩展标志事务,不做状态分发 / Execute one flag-based transfer without LibXR status dispatch.
void TryRecoverBusLines()
在 SDA 被拉低且硬件支持时尝试发出 I2C reset clocks / Try to generate I2C reset clocks when SDA is stuck low and the...
ErrorCode TransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags, ReadOperation &op, bool in_isr=false)
执行一段 HPM 扩展标志主机事务 / Execute one HPM master transfer with extended SDK flags.
WaitPolicy wait_policy_
当前忙等超时策略 / Current busy-wait timeout policy.
static bool ShouldRecover(hpm_stat_t status)
判断失败后是否需要重建控制器 / Decide whether the controller should be reinitialized after a failure.
ErrorCode SequenceRead(uint16_t slave_addr, RawData read_data, SequenceFrame frame, ReadOperation &op, bool in_isr=false)
执行一段 HPM 主机顺序读事务 / Execute one HPM master sequential read frame.
ErrorCode ValidateTransferArgs(uint16_t slave_addr, RawData data, bool allow_zero_size) const
校验普通读写事务入口参数 / Validate common read/write entry arguments.
ErrorCode ValidateMemWriteArgs(uint16_t slave_addr, ConstRawData write_data, MemAddrLength mem_addr_size, uint32_t &addr_size) const
校验寄存器写事务入口参数并解析寄存器地址长度 / Validate memory-write entry arguments and resolve memory-address length.
ErrorCode SetWaitPolicy(WaitPolicy policy)
设置当前实例的忙等超时策略 / Set the busy-wait timeout policy for this instance.
ErrorCode DoSequenceRead(uint16_t slave_addr, RawData read_data, SequenceFrame frame)
执行一段顺序读事务,不做状态分发 / Execute one sequential read frame without LibXR status dispatch.
ErrorCode EnsureClockReady()
确保 I2C 源时钟已可用 / Ensure the I2C source clock is available.
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) override
向 I2C 从设备写入字节 / Write bytes to an I2C slave.
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr=false) override
从 I2C 从设备读取字节 / Read bytes from an I2C slave.
static ErrorCode FinishOperation(Op &op, bool in_isr, ErrorCode ans)
完成 LibXR 操作状态更新或回调 / Complete LibXR operation status update or callback dispatch.
static ErrorCode ConvertStatus(hpm_stat_t status)
将 HPM SDK I2C 状态码转换为 LibXR 错误码 / Convert HPM SDK I2C status to LibXR ErrorCode.
AddressMode address_mode_
当前主机寻址模式 / Current master addressing mode.
ErrorCode SetAddressMode(AddressMode mode)
设置 HPM 主机寻址模式并重建控制器 / Set HPM master addressing mode and rebuild the controller.
ErrorCode ApplyConfig(const Configuration &config)
按当前后端限制下发配置并缓存成功配置 / Apply configuration under current backend limits and cache it on success.
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 从设备寄存器或存储器地址写入字节 / Write bytes to an I2C slave register or memory address.
AddressMode
HPM I2C 主机寻址模式 / HPM I2C master addressing mode.
@ ADDR_10BIT
10-bit 从地址 / 10-bit slave addressing.
bool auto_board_init_
是否自动调用板级初始化 / Whether board init is automatic.
AsyncTransferKind
HPM I2C 后台事务类型 / HPM I2C asynchronous transfer kind.
clock_name_t clock_
I2C 源时钟名称 / I2C source clock name.
ErrorCode EnsureControllerReady()
确保控制器已完成一次可用配置 / Ensure the controller has a usable configuration applied.
static void FillMemAddress(uint16_t mem_addr, MemAddrLength len, uint8_t out[2])
按 BYTE_8/BYTE_16 格式填充寄存器地址字节 / Fill register address bytes according to BYTE_8/BYTE_16 format.
static uint16_t GetMaxSlaveAddress(AddressMode mode)
获取指定寻址模式可接受的最大从地址 / Get the maximum valid slave address for the given mode.
SequenceFrame
HPM 主机顺序事务分段类型 / HPM master sequential transfer frame type.
@ FIRST
带 START 和地址阶段 / Includes START and address phase.
@ NEXT
中间段,不带 START/STOP / Middle frame without START/STOP.
@ LAST
末段,带 STOP / Final frame with STOP.
ErrorCode ValidateSlaveAddress(uint16_t slave_addr) const
校验当前寻址模式下的从地址 / Validate slave address for the current addressing mode.
LibXRHpmI2cType * i2c_
I2C 外设实例 / I2C peripheral instance.
hpm_stat_t DoManualTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags)
通过手工 phase 编排执行一笔 blocking 事务 / Execute one blocking transfer through manual phase orchestration.
Configuration current_config_
最近一次成功总线时序配置 / Most recent successful bus-timing config.
ErrorCode SequenceWrite(uint16_t slave_addr, ConstRawData write_data, SequenceFrame frame, bool check_ack, WriteOperation &op, bool in_isr=false)
执行一段 HPM 主机顺序写事务 / Execute one HPM master sequential write frame.
static ErrorCode ResolveMemAddressSize(MemAddrLength len, uint32_t &addr_size)
解析寄存器地址宽度枚举到字节数 / Resolve register-address enum to byte count.
HPMI2C(LibXRHpmI2cType *i2c, clock_name_t clock, bool auto_board_init=true, I2C::Configuration config={100000})
构造 HPM I2C 主机对象 / Construct an HPM I2C master object.
uint32_t source_clock_hz_
缓存的源时钟频率 / Cached source clock frequency.
ErrorCode DoSequenceWrite(uint16_t slave_addr, ConstRawData write_data, SequenceFrame frame, bool check_ack)
执行一段顺序写事务,不做状态分发 / Execute one sequential write frame without LibXR status dispatch.
bool configured_
是否已有成功配置 / Whether a valid config was applied.
ErrorCode SetConfig(Configuration config) override
应用 I2C 时序配置 / Apply I2C timing configuration.
void RecoverController()
复位并按缓存配置重建 I2C 控制器 / Reset and reinitialize the I2C controller with cached configuration.
uint16_t BuildTransferFlags(uint16_t flags) const
根据目标固定速率解析 HPM I2C 工作模式 / Resolve HPM I2C operating mode from a fixed target clock rate.
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
HPM I2C 主机驱动适配头文件 / Adapter header for the HPM I2C master driver.
@ SIZE_ERR
尺寸错误 | Size error
@ CHECK_ERR
校验错误 | Check error
@ INIT_ERR
初始化错误 | Initialization error
@ NO_RESPONSE
无响应 | No response
@ PTR_NULL
空指针 | Null pointer
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
HPM I2C 忙等超时策略 / HPM I2C busy-wait timeout policy.
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.