libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::CH32I2C Class Reference
Inheritance diagram for LibXR::CH32I2C:
[legend]
Collaboration diagram for LibXR::CH32I2C:
[legend]

Public Member Functions

 CH32I2C (ch32_i2c_id_t id, RawData dma_buff, GPIO_TypeDef *scl_port, uint16_t scl_pin, GPIO_TypeDef *sda_port, uint16_t sda_pin, uint32_t pin_remap=0, uint32_t dma_enable_min_size=3, uint32_t default_clock_hz=400000, bool ten_bit_addr=false)
 构造 I2C 驱动对象 / Construct I2C driver object
 
ErrorCode Read (uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr) override
 读取 I2C 设备的数据。 Reads data from an I2C device.
 
ErrorCode Write (uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr) override
 向 I2C 设备写入数据。 Writes data to an I2C device.
 
ErrorCode MemRead (uint16_t slave_addr, uint16_t mem_addr, RawData read_data, ReadOperation &op, MemAddrLength mem_addr_size, bool in_isr) 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, bool in_isr) override
 向 I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.
 
ErrorCode SetConfig (Configuration config) override
 配置 I2C 设备参数。 Configures the I2C device settings.
 
void RxDmaIRQHandler ()
 DMA 回调入口 / DMA callbacks from CH32 DMA driver.
 
void TxDmaIRQHandler ()
 
void ErrorIRQHandler ()
 错误中断回调 / I2C error IRQ callback
 
- Public Member Functions inherited from LibXR::I2C
 I2C ()
 默认构造函数。 Default constructor.
 

Public Attributes

I2C_TypeDef * instance_
 
DMA_Channel_TypeDef * dma_rx_channel_
 
DMA_Channel_TypeDef * dma_tx_channel_
 
ch32_i2c_id_t id_
 
uint32_t dma_enable_min_size_
 
RawData dma_buff_
 
ReadOperation read_op_
 
WriteOperation write_op_
 
RawData read_buff_
 
bool read_ = false
 
bool busy_ = false
 
bool recovering_ = false
 
GPIO_TypeDef * scl_port_
 
uint16_t scl_pin_
 
GPIO_TypeDef * sda_port_
 
uint16_t sda_pin_
 
Configuration cfg_ {400000}
 
bool ten_bit_addr_ = false
 
AsyncBlockWait block_wait_ {}
 

Static Public Attributes

static CH32I2C * map_ [CH32_I2C_NUMBER] = {nullptr}
 

Additional Inherited Members

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

Detailed Description

Definition at line 19 of file ch32_i2c.hpp.

Constructor & Destructor Documentation

◆ CH32I2C()

CH32I2C::CH32I2C ( ch32_i2c_id_t id,
RawData dma_buff,
GPIO_TypeDef * scl_port,
uint16_t scl_pin,
GPIO_TypeDef * sda_port,
uint16_t sda_pin,
uint32_t pin_remap = 0,
uint32_t dma_enable_min_size = 3,
uint32_t default_clock_hz = 400000,
bool ten_bit_addr = false )

构造 I2C 驱动对象 / Construct I2C driver object

slave_addr 使用不带 R/W 位的原始 7 位或 10 位地址。 slave_addr uses raw 7-bit or 10-bit addresses without the R/W bit.

Definition at line 30 of file ch32_i2c.cpp.

34 : I2C(),
35 instance_(ch32_i2c_get_instance_id(id)),
36 dma_rx_channel_(CH32_I2C_RX_DMA_CHANNEL_MAP[id]),
37 dma_tx_channel_(CH32_I2C_TX_DMA_CHANNEL_MAP[id]),
38 id_(id),
39 dma_enable_min_size_(dma_enable_min_size),
40 dma_buff_(dma_buff),
41 scl_port_(scl_port),
42 scl_pin_(scl_pin),
43 sda_port_(sda_port),
44 sda_pin_(sda_pin),
45 ten_bit_addr_(ten_bit_addr)
46{
47 ASSERT(instance_ != nullptr);
48 ASSERT(dma_buff_.addr_ != nullptr && dma_buff_.size_ > 0);
49
50 map_[id_] = this;
51
52 // Clock configuration.
53 ch32_i2c_enable_clocks(id_);
54
55 // GPIO configuration (I2C alternate-function open-drain).
56 {
57 GPIO_InitTypeDef gpio = {};
58 gpio.GPIO_Speed = GPIO_Speed_50MHz;
59 gpio.GPIO_Mode = GPIO_Mode_AF_OD;
60
61 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(scl_port_), ENABLE);
62 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(sda_port_), ENABLE);
63
64 GPIO_SetBits(scl_port_, scl_pin_);
65 GPIO_SetBits(sda_port_, sda_pin_);
66
67 gpio.GPIO_Pin = scl_pin_;
68 GPIO_Init(scl_port_, &gpio);
69
70 gpio.GPIO_Pin = sda_pin_;
71 GPIO_Init(sda_port_, &gpio);
72
73 if (pin_remap != 0)
74 {
75 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
76 GPIO_PinRemapConfig(pin_remap, ENABLE);
77 }
78 }
79
80 // DMA configuration.
81 {
82 // RX
83 {
84 ch32_dma_callback_t cb = [](void* arg)
85 { reinterpret_cast<CH32I2C*>(arg)->RxDmaIRQHandler(); };
86 ch32_dma_register_callback(ch32_dma_get_id(dma_rx_channel_), cb, this);
87
88 DMA_InitTypeDef di = {};
89 DMA_DeInit(dma_rx_channel_);
90 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
91 di.DMA_MemoryBaseAddr = (uint32_t)dma_buff_.addr_;
92 di.DMA_DIR = DMA_DIR_PeripheralSRC;
93 di.DMA_BufferSize = 0;
94 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
95 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
96 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
97 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
98 di.DMA_Mode = DMA_Mode_Normal;
99 di.DMA_Priority = DMA_Priority_High;
100 di.DMA_M2M = DMA_M2M_Disable;
101 DMA_Init(dma_rx_channel_, &di);
102 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
103 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
104 }
105
106 // TX
107 {
108 ch32_dma_callback_t cb = [](void* arg)
109 { reinterpret_cast<CH32I2C*>(arg)->TxDmaIRQHandler(); };
110 ch32_dma_register_callback(ch32_dma_get_id(dma_tx_channel_), cb, this);
111
112 DMA_InitTypeDef di = {};
113 DMA_DeInit(dma_tx_channel_);
114 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
115 di.DMA_MemoryBaseAddr = (uint32_t)dma_buff_.addr_;
116 di.DMA_DIR = DMA_DIR_PeripheralDST;
117 di.DMA_BufferSize = 0;
118 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
119 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
120 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
121 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
122 di.DMA_Mode = DMA_Mode_Normal;
123 di.DMA_Priority = DMA_Priority_VeryHigh;
124 di.DMA_M2M = DMA_M2M_Disable;
125 DMA_Init(dma_tx_channel_, &di);
126 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
127 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
128 }
129 }
130
131 // I2C error interrupt for asynchronous transfer abort handling.
132 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
133 NVIC_EnableIRQ(CH32_I2C_ER_IRQ_MAP[id_]);
134
135 // Default runtime parameters.
136 cfg_.clock_speed = default_clock_hz;
137 (void)SetConfig(cfg_);
138}
void RxDmaIRQHandler()
DMA 回调入口 / DMA callbacks from CH32 DMA driver.
Definition ch32_i2c.cpp:949
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
Definition ch32_i2c.cpp:140
I2C()
默认构造函数。 Default constructor.
Definition i2c.hpp:39
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz) / The I2C clock speed (in Hz).
Definition i2c.hpp:26

Member Function Documentation

◆ ErrorIRQHandler()

void CH32I2C::ErrorIRQHandler ( )

错误中断回调 / I2C error IRQ callback

Definition at line 989 of file ch32_i2c.cpp.

990{
991 bool has_err = false;
992
993 const uint32_t ITS[] = {I2C_IT_BERR, I2C_IT_ARLO, I2C_IT_AF, I2C_IT_OVR,
994 I2C_IT_TIMEOUT, I2C_IT_PECERR, I2C_IT_SMBALERT};
995
996 for (uint32_t it : ITS)
997 {
998 if (I2C_GetITStatus(instance_, it) == SET)
999 {
1000 I2C_ClearITPendingBit(instance_, it);
1001 has_err = true;
1002 }
1003 }
1004
1005 if (has_err && busy_ && !recovering_)
1006 {
1007 AbortTransfer(ErrorCode::FAILED);
1008 }
1009}
@ FAILED
操作失败 / Operation failed

◆ MemRead()

ErrorCode CH32I2C::MemRead ( uint16_t slave_addr,
uint16_t mem_addr,
RawData read_data,
ReadOperation & op,
MemAddrLength mem_addr_size,
bool in_isr )
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 787 of file ch32_i2c.cpp.

789{
790 if (read_data.size_ == 0)
791 {
792 if (op.type != ReadOperation::OperationType::BLOCK)
793 {
794 op.UpdateStatus(in_isr, ErrorCode::OK);
795 }
796 return ErrorCode::OK;
797 }
798
799 ASSERT(read_data.size_ <= dma_buff_.size_);
800 if (DmaBusy())
801 {
802 return ErrorCode::BUSY;
803 }
804
805 read_ = true;
806 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
807
808 // 1) 地址阶段:发送写地址 + mem addr
809 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
810 if (ec != ErrorCode::OK)
811 {
812 return ec;
813 }
814
815 ec = SendMemAddr(mem_addr, mem_addr_size);
816 if (ec != ErrorCode::OK)
817 {
818 I2C_GenerateSTOP(instance_, ENABLE);
819 if (op.type != ReadOperation::OperationType::BLOCK)
820 {
821 op.UpdateStatus(in_isr, ec);
822 }
823 return ec;
824 }
825
826 // 2) Repeated START + 读地址阶段
827 if (!ten_bit_addr_)
828 {
829 const uint8_t ADDR8 = Addr7ToAddr8(slave_addr);
830
831 I2C_GenerateSTART(instance_, ENABLE);
832 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
833 {
834 I2C_GenerateSTOP(instance_, ENABLE);
835 ec = ErrorCode::BUSY;
836 if (op.type != ReadOperation::OperationType::BLOCK)
837 {
838 op.UpdateStatus(in_isr, ec);
839 }
840 return ec;
841 }
842
843 I2C_Send7bitAddress(instance_, ADDR8, I2C_Direction_Receiver);
844 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
845 {
846 I2C_GenerateSTOP(instance_, ENABLE);
847 ec = ErrorCode::BUSY;
848 if (op.type != ReadOperation::OperationType::BLOCK)
849 {
850 op.UpdateStatus(in_isr, ec);
851 }
852 return ec;
853 }
854 ClearAddrFlag();
855 }
856 else
857 {
858 const uint16_t ADDR10 = Addr10Clamp(slave_addr);
859 const uint8_t HEADER = static_cast<uint8_t>(0xF0 | ((ADDR10 >> 7) & 0x06));
860
861 I2C_GenerateSTART(instance_, ENABLE);
862 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
863 {
864 I2C_GenerateSTOP(instance_, ENABLE);
865 ec = ErrorCode::BUSY;
866 if (op.type != ReadOperation::OperationType::BLOCK)
867 {
868 op.UpdateStatus(in_isr, ec);
869 }
870 return ec;
871 }
872
873 I2C_Send7bitAddress(instance_, HEADER, I2C_Direction_Receiver);
874 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
875 {
876 I2C_GenerateSTOP(instance_, ENABLE);
877 ec = ErrorCode::BUSY;
878 if (op.type != ReadOperation::OperationType::BLOCK)
879 {
880 op.UpdateStatus(in_isr, ec);
881 }
882 return ec;
883 }
884 ClearAddrFlag();
885 }
886
887 // 短传输:轮询
888 if (read_data.size_ <= dma_enable_min_size_)
889 {
890 ec = PollingReadBytes(reinterpret_cast<uint8_t*>(read_data.addr_), read_data.size_);
891 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
892 if (op.type != ReadOperation::OperationType::BLOCK)
893 {
894 op.UpdateStatus(in_isr, ec);
895 }
896 return ec;
897 }
898
899 // 长传输:DMA
900 read_op_ = op;
901 read_buff_ = read_data;
902 busy_ = true;
903
904 if (op.type == ReadOperation::OperationType::BLOCK)
905 {
906 block_wait_.Start(*op.data.sem_info.sem);
907 }
908 op.MarkAsRunning();
909 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
910 StartRxDma(read_data.size_);
911
912 if (op.type == ReadOperation::OperationType::BLOCK)
913 {
914 return block_wait_.Wait(op.data.sem_info.timeout);
915 }
916 return ErrorCode::OK;
917}
void Start(Semaphore &sem)
绑定信号量并开始等待 / Bind a semaphore and start waiting.
ErrorCode Wait(uint32_t timeout)
等待完成或超时交接 / Wait for completion or a timeout handoff.
uint32_t timeout
等待超时值 / Wait timeout.
void UpdateStatus(bool in_isr, Status &&status)
按通知方式报告完成结果 / Report completion using the selected mode.
union LibXR::Operation::@6 data
完成通知对象,由 type 选择有效成员 / Notification target selected by type.
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
Semaphore * sem
借用的信号量 / Borrowed semaphore.
OperationType type
当前通知方式 / Current notification mode.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ BUSY
忙碌 / Busy
@ OK
操作成功 / Operation successful

◆ MemWrite()

ErrorCode CH32I2C::MemWrite ( uint16_t slave_addr,
uint16_t mem_addr,
ConstRawData write_data,
WriteOperation & op,
MemAddrLength mem_addr_size,
bool in_isr )
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 714 of file ch32_i2c.cpp.

717{
718 if (write_data.size_ == 0)
719 {
720 if (op.type != WriteOperation::OperationType::BLOCK)
721 {
722 op.UpdateStatus(in_isr, ErrorCode::OK);
723 }
724 return ErrorCode::OK;
725 }
726
727 ASSERT(write_data.size_ <= dma_buff_.size_);
728 if (DmaBusy())
729 {
730 return ErrorCode::BUSY;
731 }
732
733 read_ = false;
734 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
735
736 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
737 if (ec != ErrorCode::OK)
738 {
739 return ec;
740 }
741
742 ec = SendMemAddr(mem_addr, mem_addr_size);
743 if (ec != ErrorCode::OK)
744 {
745 I2C_GenerateSTOP(instance_, ENABLE);
746 if (op.type != WriteOperation::OperationType::BLOCK)
747 {
748 op.UpdateStatus(in_isr, ec);
749 }
750 return ec;
751 }
752
753 if (write_data.size_ <= dma_enable_min_size_)
754 {
755 ec = PollingWriteBytes(reinterpret_cast<const uint8_t*>(write_data.addr_),
756 write_data.size_);
757 I2C_GenerateSTOP(instance_, ENABLE);
758 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
759
760 if (op.type != WriteOperation::OperationType::BLOCK)
761 {
762 op.UpdateStatus(in_isr, ec);
763 }
764 return ec;
765 }
766
767 Memory::FastCopy(dma_buff_.addr_, write_data.addr_, write_data.size_);
768
769 write_op_ = op;
770 busy_ = true;
771
772 if (op.type == WriteOperation::OperationType::BLOCK)
773 {
774 block_wait_.Start(*op.data.sem_info.sem);
775 }
776 op.MarkAsRunning();
777 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
778 StartTxDma(write_data.size_);
779
780 if (op.type == WriteOperation::OperationType::BLOCK)
781 {
782 return block_wait_.Wait(op.data.sem_info.timeout);
783 }
784 return ErrorCode::OK;
785}
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy

◆ Read()

ErrorCode CH32I2C::Read ( uint16_t slave_addr,
RawData read_data,
ReadOperation & op,
bool in_isr )
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 655 of file ch32_i2c.cpp.

657{
658 if (read_data.size_ == 0)
659 {
660 if (op.type != ReadOperation::OperationType::BLOCK)
661 {
662 op.UpdateStatus(in_isr, ErrorCode::OK);
663 }
664 return ErrorCode::OK;
665 }
666
667 ASSERT(read_data.size_ <= dma_buff_.size_);
668 if (DmaBusy())
669 {
670 return ErrorCode::BUSY;
671 }
672
673 read_ = true;
674 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
675
676 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Receiver);
677 if (ec != ErrorCode::OK)
678 {
679 return ec;
680 }
681
682 // 短传输:轮询
683 if (read_data.size_ <= dma_enable_min_size_)
684 {
685 ec = PollingReadBytes(reinterpret_cast<uint8_t*>(read_data.addr_), read_data.size_);
686 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
687 if (op.type != ReadOperation::OperationType::BLOCK)
688 {
689 op.UpdateStatus(in_isr, ec);
690 }
691 return ec;
692 }
693
694 // 长传输:DMA
695 read_op_ = op;
696 read_buff_ = read_data;
697 busy_ = true;
698
699 if (op.type == ReadOperation::OperationType::BLOCK)
700 {
701 block_wait_.Start(*op.data.sem_info.sem);
702 }
703 op.MarkAsRunning();
704 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
705 StartRxDma(read_data.size_);
706
707 if (op.type == ReadOperation::OperationType::BLOCK)
708 {
709 return block_wait_.Wait(op.data.sem_info.timeout);
710 }
711 return ErrorCode::OK;
712}

◆ RxDmaIRQHandler()

void CH32I2C::RxDmaIRQHandler ( )

DMA 回调入口 / DMA callbacks from CH32 DMA driver.

Definition at line 949 of file ch32_i2c.cpp.

950{
951 if (DMA_GetITStatus(CH32_I2C_RX_DMA_IT_MAP[id_]) == RESET)
952 {
953 return;
954 }
955 DMA_ClearITPendingBit(CH32_I2C_RX_DMA_IT_MAP[id_]);
956
957 DMA_Cmd(dma_rx_channel_, DISABLE);
958 I2C_DMACmd(instance_, DISABLE);
959 I2C_DMALastTransferCmd(instance_, DISABLE);
960
961 if (recovering_ || !busy_)
962 {
963 return;
964 }
965
966 I2C_GenerateSTOP(instance_, ENABLE);
967
968 if (read_buff_.size_ > 0)
969 {
970 Memory::FastCopy(read_buff_.addr_, dma_buff_.addr_, read_buff_.size_);
971 read_buff_.size_ = 0;
972 }
973
974 // 恢复默认 ACK/NACK 配置
975 I2C_AcknowledgeConfig(instance_, ENABLE);
976 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
977
978 busy_ = false;
979 if (read_op_.type == ReadOperation::OperationType::BLOCK)
980 {
981 (void)block_wait_.TryPost(true, ErrorCode::OK);
982 }
983 else
984 {
985 read_op_.UpdateStatus(true, ErrorCode::OK);
986 }
987}
bool TryPost(bool in_isr, ErrorCode ec)
尝试认领完成并唤醒调用者 / Try to claim completion and wake the caller.

◆ SetConfig()

ErrorCode CH32I2C::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 140 of file ch32_i2c.cpp.

141{
142 if (instance_ == nullptr || config.clock_speed == 0U)
143 {
144 return ErrorCode::ARG_ERR;
145 }
146 if (config.clock_speed > 400000U)
147 {
149 }
150 if (recovering_ || DmaBusy() || I2C_GetFlagStatus(instance_, I2C_FLAG_BUSY) != RESET)
151 {
152 return ErrorCode::BUSY;
153 }
154
155 RCC_ClocksTypeDef clocks{};
156 RCC_GetClocksFreq(&clocks);
157 const uint64_t denominator =
158 uint64_t(config.clock_speed) * (config.clock_speed <= 100000U ? 2U : 3U);
159 // CKCFGR.CCR is 12 bits; the SDK otherwise silently truncates low-rate dividers.
160 if (clocks.PCLK1_Frequency == 0U ||
161 (uint64_t(clocks.PCLK1_Frequency) + denominator - 1U) / denominator > 0x0FFFU)
162 {
164 }
165
166 ApplyConfig(config);
167 cfg_ = config;
168 return ErrorCode::OK;
169}
@ NOT_SUPPORT
不支持 / Not supported
@ ARG_ERR
参数错误 / Argument error

◆ TxDmaIRQHandler()

void CH32I2C::TxDmaIRQHandler ( )

Definition at line 919 of file ch32_i2c.cpp.

920{
921 if (DMA_GetITStatus(CH32_I2C_TX_DMA_IT_MAP[id_]) == RESET)
922 {
923 return;
924 }
925 DMA_ClearITPendingBit(CH32_I2C_TX_DMA_IT_MAP[id_]);
926
927 DMA_Cmd(dma_tx_channel_, DISABLE);
928 I2C_DMACmd(instance_, DISABLE);
929
930 if (recovering_ || !busy_)
931 {
932 return;
933 }
934
935 (void)WaitFlag(I2C_FLAG_BTF, SET, 20000);
936 I2C_GenerateSTOP(instance_, ENABLE);
937
938 busy_ = false;
939 if (write_op_.type == WriteOperation::OperationType::BLOCK)
940 {
941 (void)block_wait_.TryPost(true, ErrorCode::OK);
942 }
943 else
944 {
945 write_op_.UpdateStatus(true, ErrorCode::OK);
946 }
947}

◆ Write()

ErrorCode CH32I2C::Write ( uint16_t slave_addr,
ConstRawData write_data,
WriteOperation & op,
bool in_isr )
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 592 of file ch32_i2c.cpp.

594{
595 if (write_data.size_ == 0)
596 {
597 if (op.type != WriteOperation::OperationType::BLOCK)
598 {
599 op.UpdateStatus(in_isr, ErrorCode::OK);
600 }
601 return ErrorCode::OK;
602 }
603
604 ASSERT(write_data.size_ <= dma_buff_.size_);
605 if (DmaBusy())
606 {
607 return ErrorCode::BUSY;
608 }
609
610 read_ = false;
611 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
612
613 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
614 if (ec != ErrorCode::OK)
615 {
616 return ec;
617 }
618
619 // 短传输:轮询
620 if (write_data.size_ <= dma_enable_min_size_)
621 {
622 ec = PollingWriteBytes(reinterpret_cast<const uint8_t*>(write_data.addr_),
623 write_data.size_);
624 I2C_GenerateSTOP(instance_, ENABLE);
625 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
626
627 if (op.type != WriteOperation::OperationType::BLOCK)
628 {
629 op.UpdateStatus(in_isr, ec);
630 }
631 return ec;
632 }
633
634 // 长传输:DMA
635 Memory::FastCopy(dma_buff_.addr_, write_data.addr_, write_data.size_);
636
637 write_op_ = op;
638 busy_ = true;
639
640 if (op.type == WriteOperation::OperationType::BLOCK)
641 {
642 block_wait_.Start(*op.data.sem_info.sem);
643 }
644 op.MarkAsRunning();
645 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
646 StartTxDma(write_data.size_);
647
648 if (op.type == WriteOperation::OperationType::BLOCK)
649 {
650 return block_wait_.Wait(op.data.sem_info.timeout);
651 }
652 return ErrorCode::OK;
653}

Member Data Documentation

◆ block_wait_

AsyncBlockWait LibXR::CH32I2C::block_wait_ {}

Definition at line 132 of file ch32_i2c.hpp.

132{};

◆ busy_

bool LibXR::CH32I2C::busy_ = false

Definition at line 121 of file ch32_i2c.hpp.

◆ cfg_

Configuration LibXR::CH32I2C::cfg_ {400000}

Definition at line 129 of file ch32_i2c.hpp.

129{400000};

◆ dma_buff_

RawData LibXR::CH32I2C::dma_buff_

Definition at line 115 of file ch32_i2c.hpp.

◆ dma_enable_min_size_

uint32_t LibXR::CH32I2C::dma_enable_min_size_

Definition at line 113 of file ch32_i2c.hpp.

◆ dma_rx_channel_

DMA_Channel_TypeDef* LibXR::CH32I2C::dma_rx_channel_

Definition at line 110 of file ch32_i2c.hpp.

◆ dma_tx_channel_

DMA_Channel_TypeDef* LibXR::CH32I2C::dma_tx_channel_

Definition at line 111 of file ch32_i2c.hpp.

◆ id_

ch32_i2c_id_t LibXR::CH32I2C::id_

Definition at line 112 of file ch32_i2c.hpp.

◆ instance_

I2C_TypeDef* LibXR::CH32I2C::instance_

Definition at line 109 of file ch32_i2c.hpp.

◆ map_

CH32I2C * CH32I2C::map_ = {nullptr}
static

Definition at line 54 of file ch32_i2c.hpp.

◆ read_

bool LibXR::CH32I2C::read_ = false

Definition at line 120 of file ch32_i2c.hpp.

◆ read_buff_

RawData LibXR::CH32I2C::read_buff_

Definition at line 119 of file ch32_i2c.hpp.

◆ read_op_

ReadOperation LibXR::CH32I2C::read_op_

Definition at line 117 of file ch32_i2c.hpp.

◆ recovering_

bool LibXR::CH32I2C::recovering_ = false

Definition at line 122 of file ch32_i2c.hpp.

◆ scl_pin_

uint16_t LibXR::CH32I2C::scl_pin_

Definition at line 125 of file ch32_i2c.hpp.

◆ scl_port_

GPIO_TypeDef* LibXR::CH32I2C::scl_port_

Definition at line 124 of file ch32_i2c.hpp.

◆ sda_pin_

uint16_t LibXR::CH32I2C::sda_pin_

Definition at line 127 of file ch32_i2c.hpp.

◆ sda_port_

GPIO_TypeDef* LibXR::CH32I2C::sda_port_

Definition at line 126 of file ch32_i2c.hpp.

◆ ten_bit_addr_

bool LibXR::CH32I2C::ten_bit_addr_ = false

Definition at line 131 of file ch32_i2c.hpp.

◆ write_op_

WriteOperation LibXR::CH32I2C::write_op_

Definition at line 118 of file ch32_i2c.hpp.


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