25#include "hpm_clock_drv.h"
28#include "libxr_rw.hpp"
30#if defined(HPMSOC_HAS_HPMSDK_I2C) && __has_include("hpm_i2c_drv.h")
31#include "hpm_i2c_drv.h"
32#define LIBXR_HPM_I2C_SUPPORTED 1
33using LibXRHpmI2cType = I2C_Type;
35#define LIBXR_HPM_I2C_SUPPORTED 0
36using LibXRHpmI2cType = void;
39#if LIBXR_HPM_I2C_SUPPORTED && __has_include("hpm_dma_mgr.h")
40#include "hpm_dma_mgr.h"
41#define LIBXR_HPM_I2C_HAS_DMA_MGR 1
43#define LIBXR_HPM_I2C_HAS_DMA_MGR 0
46extern "C" void libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr);
174#if LIBXR_HPM_I2C_SUPPORTED
177 NO_START = I2C_NO_START,
178 NO_ADDRESS = I2C_NO_ADDRESS,
179 NO_READ_ACK = I2C_NO_READ_ACK,
180 NO_STOP = I2C_NO_STOP,
181 WRITE_CHECK_ACK = I2C_WRITE_CHECK_ACK
186 NO_ADDRESS = 0x0008U,
187 NO_READ_ACK = 0x0010U,
189 WRITE_CHECK_ACK = 0x0040U
216 uint64_t addr_hit_timeout_us;
217 uint64_t stop_timeout_us;
218 uint64_t bus_idle_timeout_us;
219 uint64_t transfer_timeout_us;
228 return {500ULL, 1000ULL, 1000ULL, 500000ULL};
253 HPMI2C(LibXRHpmI2cType* i2c, clock_name_t clock,
bool auto_board_init =
true,
309 bool in_isr =
false);
378 bool in_isr =
false)
override;
403 bool in_isr =
false)
override;
439 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
440 bool in_isr =
false)
override;
476 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
477 bool in_isr =
false)
override;
499#if LIBXR_HPM_I2C_HAS_DMA_MGR
506 void CompleteAsyncTransfer(
bool in_isr,
ErrorCode ans);
510 friend void ::libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr);
512#if LIBXR_HPM_I2C_HAS_DMA_MGR
517 struct AsyncTransferContext
519 AsyncTransferKind kind = AsyncTransferKind::NONE;
520 uint16_t slave_addr = 0U;
521 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8;
522 uint16_t mem_addr = 0U;
523 uint32_t mem_addr_size_in_byte = 0U;
524 uint8_t mem_addr_bytes[2] = {};
526 RawData read_data = {
nullptr, 0};
527 ConstRawData write_data = {
nullptr, 0};
530 std::atomic<hpm_stat_t> final_status{
532 std::atomic<bool> should_recover{
534 std::atomic<bool> dma_done{
536 std::atomic<bool> cmpl_done{
false};
548 struct AsyncCompletionStateMachine
550 static void Reset(AsyncTransferContext& ctx);
551 static void MarkDmaDone(AsyncTransferContext& ctx);
552 static void MarkI2cDone(AsyncTransferContext& ctx, hpm_stat_t status,
bool recover);
553 static void MarkFailure(AsyncTransferContext& ctx, hpm_stat_t status,
bool recover);
554 static void SetFinalStatus(AsyncTransferContext& ctx, hpm_stat_t status);
555 static bool DmaDone(
const AsyncTransferContext& ctx);
556 static bool Ready(
const AsyncTransferContext& ctx);
557 static hpm_stat_t FinalStatus(
const AsyncTransferContext& ctx);
558 static bool ShouldRecover(
const AsyncTransferContext& ctx);
584#if LIBXR_HPM_I2C_SUPPORTED
585 static ErrorCode ResolveMode(uint32_t clock_speed, i2c_mode_t& mode);
588#if LIBXR_HPM_I2C_HAS_DMA_MGR
593 static ErrorCode ConvertDmaStatus(hpm_stat_t status);
600#if LIBXR_HPM_I2C_SUPPORTED
601 static i2c_seq_transfer_opt_t ConvertSequenceFrame(
SequenceFrame frame);
626 bool allow_zero_size)
const;
632 bool allow_zero_size)
const;
639 MemAddrLength mem_addr_size, uint32_t& addr_size)
const;
651 static void FillMemAddress(uint16_t mem_addr, MemAddrLength len, uint8_t out[2]);
678#if LIBXR_HPM_I2C_HAS_DMA_MGR
683 ErrorCode PrepareAsyncTransfer(uint16_t slave_addr, uint16_t flags, uint32_t size,
684 bool clear_fifo =
true,
bool require_bus_idle =
true);
690 static uint32_t ToSystemAddress(
const void* addr);
696 ErrorCode StartAsyncReadDma(
void* dst, uint32_t size);
702 ErrorCode StartAsyncWriteDma(
const void* src, uint32_t size);
714 void StopAndReleaseAsyncBus();
719 void ResetAsyncState();
725 void ClearAsyncContext();
730 void AbortAsyncStart(
bool stop_dma,
bool disable_irq,
bool recover_controller);
735 template <
typename Op>
736 void StartAsyncBlockWaitIfNeeded(Op& op)
738 if (op.type == Op::OperationType::BLOCK)
740 block_wait_.Start(*op.data.sem_info.sem);
747 template <
typename Op>
748 void CancelAsyncBlockWaitIfNeeded(Op& op)
750 if (op.type == Op::OperationType::BLOCK)
752 block_wait_.Cancel();
759 template <
typename Op>
760 void CompleteAsyncOperation(Op& op,
bool in_isr,
ErrorCode ans)
762 if (op.type == Op::OperationType::BLOCK)
764 (void)block_wait_.TryPost(in_isr, ans);
768 op.UpdateStatus(in_isr, ans);
776 ErrorCode StartWriteAsync(uint16_t slave_addr, ConstRawData write_data,
789 ErrorCode StartMemReadAsync(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
801 ErrorCode WaitForAsyncBlockResult(uint32_t timeout);
806 void ReleaseAsyncBus();
818 void DisableAsyncI2cIrq();
830 void HandleAsyncInterrupt(
bool in_isr);
836 void MaybeCompleteAsyncTransfer(
bool in_isr);
842 bool TryClaimAsyncCompletion();
847 static void OnDmaTcCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr);
852 static void OnDmaErrorCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr);
857 static void OnDmaAbortCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr);
863 bool AsyncTransferActive()
const
865 return async_busy_.load(std::memory_order_acquire) != 0U;
909 template <
typename Op>
912 if (op.type != Op::OperationType::BLOCK)
914 op.UpdateStatus(in_isr, ans);
929#if LIBXR_HPM_I2C_HAS_DMA_MGR
930 std::atomic<uint32_t> async_busy_{
932 AsyncTransferContext async_ctx_{};
933 AsyncBlockWait block_wait_{};
934 std::atomic<uint32_t> async_completion_claim_{
936 dma_resource_t async_dma_resource_{
nullptr, 0U,
938 uint8_t async_dma_source_ =
940 bool async_dma_ready_ =
只读原始数据视图 / Immutable raw data view
HPM SDK I2C 主机驱动,适配 LibXR I2C 接口 / HPM SDK based I2C master driver for the LibXR I2C interface.
WaitPolicy GetWaitPolicy() const
获取当前实例的忙等超时策略 / Get the current busy-wait timeout policy.
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.
AddressMode GetAddressMode() const
获取当前 HPM 主机寻址模式 / Get current HPM master addressing mode.
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.
static constexpr uint16_t kMax7BitAddress
当前 HPM 后端支持的最大 7-bit 从地址 / Maximum 7-bit slave address supported by the current HPM backend.
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.
TransferFlag
HPM 主机扩展事务标志 / HPM master extended transfer flags.
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.
uint32_t GetClockFreq() const
获取当前缓存的 I2C 源时钟频率 / Get cached I2C source clock frequency.
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.
static constexpr WaitPolicy DefaultWaitPolicy()
返回默认 HPM I2C 忙等超时策略 / Return the default HPM I2C wait policy.
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.
@ ADDR_7BIT
7-bit 从地址 / 7-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.
static constexpr uint16_t kMax10BitAddress
当前 HPM 后端支持的最大 10-bit 从地址 / Maximum 10-bit slave address supported by the current HPM backend.
ErrorCode ValidateSlaveAddress(uint16_t slave_addr) const
校验当前寻址模式下的从地址 / Validate slave address for the current addressing mode.
ErrorCode ValidateTransferArgs(uint16_t slave_addr, ConstRawData data, bool allow_zero_size) const
校验普通写事务入口参数 / Validate common write entry arguments.
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.
I2C(Inter-Integrated Circuit)接口类。 I2C (Inter-Integrated Circuit) interface class.
可写原始数据视图 / Mutable raw data view
Operation< ErrorCode > ReadOperation
Read operation type.
Operation< ErrorCode > WriteOperation
Write operation type.
HPM I2C 忙等超时策略 / HPM I2C busy-wait timeout policy.
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.