libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
hpm_i2c.hpp
Go to the documentation of this file.
1#pragma once
2
23#include <atomic>
24
25#include "hpm_clock_drv.h"
26#include "hpm_soc.h"
27#include "i2c.hpp"
28#include "libxr_rw.hpp"
29
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;
34#else
35#define LIBXR_HPM_I2C_SUPPORTED 0
36using LibXRHpmI2cType = void;
37#endif
38
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
42#else
43#define LIBXR_HPM_I2C_HAS_DMA_MGR 0
44#endif
45
46extern "C" void libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr);
47
48namespace LibXR
49{
50
146class HPMI2C final : public I2C
147{
148 public:
152 enum class AddressMode : uint8_t
153 {
154 ADDR_7BIT,
156 };
157
161 enum class SequenceFrame : uint8_t
162 {
163 FIRST,
164 NEXT,
165 LAST
166 };
167
171 enum class TransferFlag : uint16_t
172 {
173 NONE = 0,
174#if LIBXR_HPM_I2C_SUPPORTED
175 READ = I2C_RD,
176 ADDR_10BIT = I2C_ADDR_10BIT,
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
182#else
183 READ = 0x0001U,
184 ADDR_10BIT = 0x0002U,
185 NO_START = 0x0004U,
186 NO_ADDRESS = 0x0008U,
187 NO_READ_ACK = 0x0010U,
188 NO_STOP = 0x0020U,
189 WRITE_CHECK_ACK = 0x0040U
190#endif
191 };
192
196 enum class AsyncTransferKind : uint8_t
197 {
198 NONE,
199 READ,
200 WRITE,
201 MEM_READ
202 };
203
215 {
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;
220 };
221
226 static constexpr WaitPolicy DefaultWaitPolicy()
227 {
228 return {500ULL, 1000ULL, 1000ULL, 500000ULL};
229 }
230
253 HPMI2C(LibXRHpmI2cType* i2c, clock_name_t clock, bool auto_board_init = true,
254 I2C::Configuration config = {100000});
255
272
281 ErrorCode SetWaitPolicy(WaitPolicy policy);
282
288
294
307 ErrorCode SequenceWrite(uint16_t slave_addr, ConstRawData write_data,
308 SequenceFrame frame, bool check_ack, WriteOperation& op,
309 bool in_isr = false);
310
322 ErrorCode SequenceRead(uint16_t slave_addr, RawData read_data, SequenceFrame frame,
323 ReadOperation& op, bool in_isr = false);
324
337 ErrorCode TransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags,
338 ReadOperation& op, bool in_isr = false);
339
352 ErrorCode TransferWithFlags(uint16_t slave_addr, ConstRawData data, uint16_t flags,
353 WriteOperation& op, bool in_isr = false);
354
377 ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation& op,
378 bool in_isr = false) override;
379
402 ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation& op,
403 bool in_isr = false) override;
404
437 ErrorCode MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
438 ReadOperation& op,
439 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
440 bool in_isr = false) override;
441
474 ErrorCode MemWrite(uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data,
475 WriteOperation& op,
476 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
477 bool in_isr = false) override;
478
490 ErrorCode SetConfig(Configuration config) override;
491
497 uint32_t GetClockFreq() const { return source_clock_hz_; }
498
499#if LIBXR_HPM_I2C_HAS_DMA_MGR
506 void CompleteAsyncTransfer(bool in_isr, ErrorCode ans);
507#endif
508
509 private:
510 friend void ::libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr);
511
512#if LIBXR_HPM_I2C_HAS_DMA_MGR
517 struct AsyncTransferContext
518 {
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] = {};
525 uint16_t flags = 0U;
526 RawData read_data = {nullptr, 0};
527 ConstRawData write_data = {nullptr, 0};
528 ReadOperation read_op = {};
529 WriteOperation write_op = {};
530 std::atomic<hpm_stat_t> final_status{
531 status_success};
532 std::atomic<bool> should_recover{
533 false};
534 std::atomic<bool> dma_done{
535 false};
536 std::atomic<bool> cmpl_done{false};
537 };
538
548 struct AsyncCompletionStateMachine
549 {
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);
559 };
560#endif
561
566 static constexpr uint16_t kMax7BitAddress = 0x7FU;
567
572 static constexpr uint16_t kMax10BitAddress = 0x3FFU;
573
578 static ErrorCode ConvertStatus(hpm_stat_t status);
579
584#if LIBXR_HPM_I2C_SUPPORTED
585 static ErrorCode ResolveMode(uint32_t clock_speed, i2c_mode_t& mode);
586#endif
587
588#if LIBXR_HPM_I2C_HAS_DMA_MGR
593 static ErrorCode ConvertDmaStatus(hpm_stat_t status);
594#endif
595
600#if LIBXR_HPM_I2C_SUPPORTED
601 static i2c_seq_transfer_opt_t ConvertSequenceFrame(SequenceFrame frame);
602#endif
603
608 uint16_t BuildTransferFlags(uint16_t flags) const;
609
614 static uint16_t GetMaxSlaveAddress(AddressMode mode);
615
620 ErrorCode ValidateSlaveAddress(uint16_t slave_addr) const;
621
625 ErrorCode ValidateTransferArgs(uint16_t slave_addr, RawData data,
626 bool allow_zero_size) const;
627
631 ErrorCode ValidateTransferArgs(uint16_t slave_addr, ConstRawData data,
632 bool allow_zero_size) const;
633
638 ErrorCode ValidateMemWriteArgs(uint16_t slave_addr, ConstRawData write_data,
639 MemAddrLength mem_addr_size, uint32_t& addr_size) const;
640
645 static ErrorCode ResolveMemAddressSize(MemAddrLength len, uint32_t& addr_size);
646
651 static void FillMemAddress(uint16_t mem_addr, MemAddrLength len, uint8_t out[2]);
652
657 ErrorCode DoSequenceWrite(uint16_t slave_addr, ConstRawData write_data,
658 SequenceFrame frame, bool check_ack);
659
664 ErrorCode DoSequenceRead(uint16_t slave_addr, RawData read_data, SequenceFrame frame);
665
670 ErrorCode DoTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags);
671
676 hpm_stat_t DoManualTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags);
677
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);
685
690 static uint32_t ToSystemAddress(const void* addr);
691
696 ErrorCode StartAsyncReadDma(void* dst, uint32_t size);
697
702 ErrorCode StartAsyncWriteDma(const void* src, uint32_t size);
703
708 void StopAsyncDma();
709
714 void StopAndReleaseAsyncBus();
715
719 void ResetAsyncState();
720
725 void ClearAsyncContext();
726
730 void AbortAsyncStart(bool stop_dma, bool disable_irq, bool recover_controller);
731
735 template <typename Op>
736 void StartAsyncBlockWaitIfNeeded(Op& op)
737 {
738 if (op.type == Op::OperationType::BLOCK)
739 {
740 block_wait_.Start(*op.data.sem_info.sem);
741 }
742 }
743
747 template <typename Op>
748 void CancelAsyncBlockWaitIfNeeded(Op& op)
749 {
750 if (op.type == Op::OperationType::BLOCK)
751 {
752 block_wait_.Cancel();
753 }
754 }
755
759 template <typename Op>
760 void CompleteAsyncOperation(Op& op, bool in_isr, ErrorCode ans)
761 {
762 if (op.type == Op::OperationType::BLOCK)
763 {
764 (void)block_wait_.TryPost(in_isr, ans);
765 }
766 else
767 {
768 op.UpdateStatus(in_isr, ans);
769 }
770 }
771
776 ErrorCode StartWriteAsync(uint16_t slave_addr, ConstRawData write_data,
777 WriteOperation& op);
778
783 ErrorCode StartReadAsync(uint16_t slave_addr, RawData read_data, ReadOperation& op);
784
789 ErrorCode StartMemReadAsync(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
790 ReadOperation& op, MemAddrLength mem_addr_size);
791
795 ErrorCode EnsureAsyncDmaReady();
796
801 ErrorCode WaitForAsyncBlockResult(uint32_t timeout);
802
806 void ReleaseAsyncBus();
807
812 ErrorCode EnableAsyncI2cIrq();
813
818 void DisableAsyncI2cIrq();
819
830 void HandleAsyncInterrupt(bool in_isr);
831
836 void MaybeCompleteAsyncTransfer(bool in_isr);
837
842 bool TryClaimAsyncCompletion();
843
847 static void OnDmaTcCallback(DMA_Type* base, uint32_t channel, void* cb_data_ptr);
848
852 static void OnDmaErrorCallback(DMA_Type* base, uint32_t channel, void* cb_data_ptr);
853
857 static void OnDmaAbortCallback(DMA_Type* base, uint32_t channel, void* cb_data_ptr);
858
863 bool AsyncTransferActive() const
864 {
865 return async_busy_.load(std::memory_order_acquire) != 0U;
866 }
867#endif
868
874
880
885 ErrorCode ApplyConfig(const Configuration& config);
886
891 static bool ShouldRecover(hpm_stat_t status);
892
897 void RecoverController();
898
903 void TryRecoverBusLines();
904
909 template <typename Op>
910 static ErrorCode FinishOperation(Op& op, bool in_isr, ErrorCode ans)
911 {
912 if (op.type != Op::OperationType::BLOCK)
913 {
914 op.UpdateStatus(in_isr, ans);
915 }
916 return ans;
917 }
918
919 LibXRHpmI2cType* i2c_;
920 clock_name_t clock_;
921 uint32_t source_clock_hz_ = 0;
928 bool configured_ = false;
929#if LIBXR_HPM_I2C_HAS_DMA_MGR
930 std::atomic<uint32_t> async_busy_{
931 0U};
932 AsyncTransferContext async_ctx_{};
933 AsyncBlockWait block_wait_{};
934 std::atomic<uint32_t> async_completion_claim_{
935 0U};
936 dma_resource_t async_dma_resource_{nullptr, 0U,
937 -1};
938 uint8_t async_dma_source_ =
939 0U;
940 bool async_dma_ready_ =
941 false;
942#endif
944};
945
946} // namespace LibXR
只读原始数据视图 / Immutable raw data view
HPM SDK I2C 主机驱动,适配 LibXR I2C 接口 / HPM SDK based I2C master driver for the LibXR I2C interface.
Definition hpm_i2c.hpp:147
WaitPolicy GetWaitPolicy() const
获取当前实例的忙等超时策略 / Get the current busy-wait timeout policy.
Definition hpm_i2c.hpp:287
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.
Definition hpm_i2c.cpp:2403
ErrorCode DoTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags)
执行一段扩展标志事务,不做状态分发 / Execute one flag-based transfer without LibXR status dispatch.
Definition hpm_i2c.cpp:2342
AddressMode GetAddressMode() const
获取当前 HPM 主机寻址模式 / Get current HPM master addressing mode.
Definition hpm_i2c.hpp:293
void TryRecoverBusLines()
在 SDA 被拉低且硬件支持时尝试发出 I2C reset clocks / Try to generate I2C reset clocks when SDA is stuck low and the...
Definition hpm_i2c.cpp:2378
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.
Definition hpm_i2c.cpp:2444
static constexpr uint16_t kMax7BitAddress
当前 HPM 后端支持的最大 7-bit 从地址 / Maximum 7-bit slave address supported by the current HPM backend.
Definition hpm_i2c.hpp:566
WaitPolicy wait_policy_
当前忙等超时策略 / Current busy-wait timeout policy.
Definition hpm_i2c.hpp:924
static bool ShouldRecover(hpm_stat_t status)
判断失败后是否需要重建控制器 / Decide whether the controller should be reinitialized after a failure.
Definition hpm_i2c.cpp:2370
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.
Definition hpm_i2c.cpp:2435
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.
Definition hpm_i2c.hpp:172
ErrorCode SetWaitPolicy(WaitPolicy policy)
设置当前实例的忙等超时策略 / Set the busy-wait timeout policy for this instance.
Definition hpm_i2c.cpp:76
ErrorCode DoSequenceRead(uint16_t slave_addr, RawData read_data, SequenceFrame frame)
执行一段顺序读事务,不做状态分发 / Execute one sequential read frame without LibXR status dispatch.
Definition hpm_i2c.cpp:2333
ErrorCode EnsureClockReady()
确保 I2C 源时钟已可用 / Ensure the I2C source clock is available.
Definition hpm_i2c.cpp:2359
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) override
向 I2C 从设备写入字节 / Write bytes to an I2C slave.
Definition hpm_i2c.cpp:2395
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr=false) override
从 I2C 从设备读取字节 / Read bytes from an I2C slave.
Definition hpm_i2c.cpp:2387
static ErrorCode FinishOperation(Op &op, bool in_isr, ErrorCode ans)
完成 LibXR 操作状态更新或回调 / Complete LibXR operation status update or callback dispatch.
Definition hpm_i2c.hpp:910
static ErrorCode ConvertStatus(hpm_stat_t status)
将 HPM SDK I2C 状态码转换为 LibXR 错误码 / Convert HPM SDK I2C status to LibXR ErrorCode.
Definition hpm_i2c.cpp:2315
uint32_t GetClockFreq() const
获取当前缓存的 I2C 源时钟频率 / Get cached I2C source clock frequency.
Definition hpm_i2c.hpp:497
AddressMode address_mode_
当前主机寻址模式 / Current master addressing mode.
Definition hpm_i2c.hpp:926
ErrorCode SetAddressMode(AddressMode mode)
设置 HPM 主机寻址模式并重建控制器 / Set HPM master addressing mode and rebuild the controller.
Definition hpm_i2c.cpp:2309
ErrorCode ApplyConfig(const Configuration &config)
按当前后端限制下发配置并缓存成功配置 / Apply configuration under current backend limits and cache it on success.
Definition hpm_i2c.cpp:2363
static constexpr WaitPolicy DefaultWaitPolicy()
返回默认 HPM I2C 忙等超时策略 / Return the default HPM I2C wait policy.
Definition hpm_i2c.hpp:226
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.
Definition hpm_i2c.cpp:2413
AddressMode
HPM I2C 主机寻址模式 / HPM I2C master addressing mode.
Definition hpm_i2c.hpp:153
@ 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.
Definition hpm_i2c.hpp:943
AsyncTransferKind
HPM I2C 后台事务类型 / HPM I2C asynchronous transfer kind.
Definition hpm_i2c.hpp:197
clock_name_t clock_
I2C 源时钟名称 / I2C source clock name.
Definition hpm_i2c.hpp:920
ErrorCode EnsureControllerReady()
确保控制器已完成一次可用配置 / Ensure the controller has a usable configuration applied.
Definition hpm_i2c.cpp:2361
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.
Definition hpm_i2c.cpp:71
static uint16_t GetMaxSlaveAddress(AddressMode mode)
获取指定寻址模式可接受的最大从地址 / Get the maximum valid slave address for the given mode.
Definition hpm_i2c.cpp:56
SequenceFrame
HPM 主机顺序事务分段类型 / HPM master sequential transfer frame type.
Definition hpm_i2c.hpp:162
@ 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.
Definition hpm_i2c.hpp:572
ErrorCode ValidateSlaveAddress(uint16_t slave_addr) const
校验当前寻址模式下的从地址 / Validate slave address for the current addressing mode.
Definition hpm_i2c.cpp:61
ErrorCode ValidateTransferArgs(uint16_t slave_addr, ConstRawData data, bool allow_zero_size) const
校验普通写事务入口参数 / Validate common write entry arguments.
LibXRHpmI2cType * i2c_
I2C 外设实例 / I2C peripheral instance.
Definition hpm_i2c.hpp:919
hpm_stat_t DoManualTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags)
通过手工 phase 编排执行一笔 blocking 事务 / Execute one blocking transfer through manual phase orchestration.
Definition hpm_i2c.cpp:2350
Configuration current_config_
最近一次成功总线时序配置 / Most recent successful bus-timing config.
Definition hpm_i2c.hpp:922
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.
Definition hpm_i2c.cpp:2424
static ErrorCode ResolveMemAddressSize(MemAddrLength len, uint32_t &addr_size)
解析寄存器地址宽度枚举到字节数 / Resolve register-address enum to byte count.
Definition hpm_i2c.cpp:66
HPMI2C(LibXRHpmI2cType *i2c, clock_name_t clock, bool auto_board_init=true, I2C::Configuration config={100000})
构造 HPM I2C 主机对象 / Construct an HPM I2C master object.
Definition hpm_i2c.cpp:2300
uint32_t source_clock_hz_
缓存的源时钟频率 / Cached source clock frequency.
Definition hpm_i2c.hpp:921
ErrorCode DoSequenceWrite(uint16_t slave_addr, ConstRawData write_data, SequenceFrame frame, bool check_ack)
执行一段顺序写事务,不做状态分发 / Execute one sequential write frame without LibXR status dispatch.
Definition hpm_i2c.cpp:2323
bool configured_
是否已有成功配置 / Whether a valid config was applied.
Definition hpm_i2c.hpp:928
ErrorCode SetConfig(Configuration config) override
应用 I2C 时序配置 / Apply I2C timing configuration.
Definition hpm_i2c.cpp:2380
void RecoverController()
复位并按缓存配置重建 I2C 控制器 / Reset and reinitialize the I2C controller with cached configuration.
Definition hpm_i2c.cpp:2376
uint16_t BuildTransferFlags(uint16_t flags) const
根据目标固定速率解析 HPM I2C 工作模式 / Resolve HPM I2C operating mode from a fixed target clock rate.
Definition hpm_i2c.cpp:2321
I2C(Inter-Integrated Circuit)接口类。 I2C (Inter-Integrated Circuit) interface class.
Definition i2c.hpp:17
可写原始数据视图 / Mutable raw data view
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
Operation< ErrorCode > ReadOperation
Read operation type.
Operation< ErrorCode > WriteOperation
Write operation type.
HPM I2C 忙等超时策略 / HPM I2C busy-wait timeout policy.
Definition hpm_i2c.hpp:215
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.
Definition i2c.hpp:24