libxr  1.0
Want to be the best embedded framework
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.
 

Data Fields

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
 
GPIO_TypeDef * scl_port_
 
uint16_t scl_pin_
 
GPIO_TypeDef * sda_port_
 
uint16_t sda_pin_
 
Configuration cfg_ {400000}
 
bool ten_bit_addr_ = false
 

Static Public Attributes

static CH32I2Cmap_ [CH32_I2C_NUMBER] = {nullptr}
 

Private Member Functions

bool DmaBusy () const
 
bool WaitEvent (uint32_t evt, uint32_t timeout_us=K_DEFAULT_TIMEOUT_US)
 
bool WaitFlag (uint32_t flag, FlagStatus st, uint32_t timeout_us=K_DEFAULT_TIMEOUT_US)
 
void ClearAddrFlag ()
 
ErrorCode MasterStartAndAddress (uint16_t slave_addr, uint8_t dir)
 
ErrorCode MasterStartAndAddress10Bit (uint16_t addr10, uint8_t final_dir)
 
ErrorCode SendMemAddr (uint16_t mem_addr, MemAddrLength len)
 
ErrorCode PollingWriteBytes (const uint8_t *data, uint32_t len)
 
ErrorCode PollingReadBytes (uint8_t *data, uint32_t len)
 
void StartTxDma (uint32_t len)
 
void StartRxDma (uint32_t len)
 
void AbortTransfer (ErrorCode ec)
 

Static Private Member Functions

static uint8_t Addr7ToAddr8 (uint16_t addr7)
 
static uint16_t Addr10Clamp (uint16_t addr10)
 

Static Private Attributes

static constexpr uint32_t K_DEFAULT_TIMEOUT_US = 20000
 默认超时(微秒) / Default timeout in microseconds
 

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 20 of file ch32_i2c.cpp.

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

Member Function Documentation

◆ AbortTransfer()

void CH32I2C::AbortTransfer ( ErrorCode ec)
private

Definition at line 440 of file ch32_i2c.cpp.

441{
442 I2C_DMACmd(instance_, DISABLE);
443 I2C_DMALastTransferCmd(instance_, DISABLE);
444 DMA_Cmd(dma_tx_channel_, DISABLE);
445 DMA_Cmd(dma_rx_channel_, DISABLE);
446
447 // 恢复默认 ACK/NACK 配置
448 I2C_AcknowledgeConfig(instance_, ENABLE);
449 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
450
451 I2C_GenerateSTOP(instance_, ENABLE);
452
453 busy_ = false;
454
455 if (read_)
456 {
457 read_op_.UpdateStatus(true, ec);
458 }
459 else
460 {
461 write_op_.UpdateStatus(true, ec);
462 }
463}
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:172

◆ Addr10Clamp()

static uint16_t LibXR::CH32I2C::Addr10Clamp ( uint16_t addr10)
inlinestaticprivate

Definition at line 73 of file ch32_i2c.hpp.

74 {
75 ASSERT(addr10 <= 0x3FF);
76 return static_cast<uint16_t>(addr10 & 0x3FF);
77 }

◆ Addr7ToAddr8()

static uint8_t LibXR::CH32I2C::Addr7ToAddr8 ( uint16_t addr7)
inlinestaticprivate

Definition at line 65 of file ch32_i2c.hpp.

66 {
67 // WCH SPL 在 I2C_Send7bitAddress 中仅更新 bit0(R/W)。
68 // WCH SPL updates only bit0 (R/W) in I2C_Send7bitAddress.
69 ASSERT(addr7 <= 0x7F);
70 return static_cast<uint8_t>(((addr7 & 0x7F) << 1) & 0xFE);
71 }

◆ ClearAddrFlag()

void CH32I2C::ClearAddrFlag ( )
private

Definition at line 182 of file ch32_i2c.cpp.

183{
184 volatile uint16_t tmp1 = instance_->STAR1;
185 volatile uint16_t tmp2 = instance_->STAR2;
186 (void)tmp1;
187 (void)tmp2;
188}

◆ DmaBusy()

bool LibXR::CH32I2C::DmaBusy ( ) const
inlineprivate

Definition at line 60 of file ch32_i2c.hpp.

61 {
62 return (dma_rx_channel_->CNTR != 0) || (dma_tx_channel_->CNTR != 0) || busy_;
63 }

◆ ErrorIRQHandler()

void CH32I2C::ErrorIRQHandler ( )

错误中断回调 / I2C error IRQ callback

Definition at line 824 of file ch32_i2c.cpp.

825{
826 bool has_err = false;
827
828 const uint32_t ITS[] = {I2C_IT_BERR, I2C_IT_ARLO, I2C_IT_AF, I2C_IT_OVR,
829 I2C_IT_TIMEOUT, I2C_IT_PECERR, I2C_IT_SMBALERT};
830
831 for (uint32_t it : ITS)
832 {
833 if (I2C_GetITStatus(instance_, it) == SET)
834 {
835 I2C_ClearITPendingBit(instance_, it);
836 has_err = true;
837 }
838 }
839
840 if (has_err && busy_)
841 {
842 AbortTransfer(ErrorCode::FAILED);
843 }
844}

◆ MasterStartAndAddress()

ErrorCode CH32I2C::MasterStartAndAddress ( uint16_t slave_addr,
uint8_t dir )
private

Definition at line 250 of file ch32_i2c.cpp.

251{
252 if (!ten_bit_addr_)
253 {
254 // 7-bit:输入为原始 7-bit 地址
255 const uint8_t ADDR8 = Addr7ToAddr8(slave_addr);
256
257 if (!WaitFlag(I2C_FLAG_BUSY, RESET))
258 {
259 return ErrorCode::BUSY;
260 }
261
262 I2C_GenerateSTART(instance_, ENABLE);
263 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
264 {
265 return ErrorCode::BUSY;
266 }
267
268 I2C_Send7bitAddress(instance_, ADDR8, dir);
269
270 if (dir == I2C_Direction_Transmitter)
271 {
272 if (!WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
273 {
274 return ErrorCode::BUSY;
275 }
276 }
277 else
278 {
279 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
280 {
281 return ErrorCode::BUSY;
282 }
283 }
284
285 ClearAddrFlag();
286 return ErrorCode::OK;
287 }
288
289 // 10-bit:输入为原始 10-bit 地址
290 return MasterStartAndAddress10Bit(slave_addr, dir);
291}

◆ MasterStartAndAddress10Bit()

ErrorCode CH32I2C::MasterStartAndAddress10Bit ( uint16_t addr10,
uint8_t final_dir )
private

Definition at line 190 of file ch32_i2c.cpp.

191{
192 addr10 = Addr10Clamp(addr10);
193
194 // 等待 BUSY 释放
195 if (!WaitFlag(I2C_FLAG_BUSY, RESET))
196 {
197 return ErrorCode::BUSY;
198 }
199
200 // --- 1) START ---
201 I2C_GenerateSTART(instance_, ENABLE);
202 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
203 {
204 return ErrorCode::BUSY;
205 }
206
207 // --- 2) 发送 10-bit 头字节(地址阶段固定以写方向发送,R/W=0)---
208 // header (8-bit,left-shifted): 11110 A9 A8 0 => 0xF0/0xF2/0xF4/0xF6
209 const uint8_t HEADER = static_cast<uint8_t>(0xF0 | ((addr10 >> 7) & 0x06));
210 I2C_Send7bitAddress(instance_, HEADER, I2C_Direction_Transmitter);
211
212 // 等待 EVT9(ADD10)
213 if (!WaitEvent(I2C_EVENT_MASTER_MODE_ADDRESS10))
214 {
215 return ErrorCode::BUSY;
216 }
217
218 // --- 3) 发送地址低 8 位 ---
219 I2C_SendData(instance_, static_cast<uint8_t>(addr10 & 0xFF));
220
221 // 等待 EVT6(作为 Transmitter 完成地址阶段)
222 if (!WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
223 {
224 return ErrorCode::BUSY;
225 }
226 ClearAddrFlag();
227
228 if (final_dir == I2C_Direction_Transmitter)
229 {
230 return ErrorCode::OK;
231 }
232
233 // --- 4) 若最终为读:Repeated START + 头字节(R/W=1) ---
234 I2C_GenerateSTART(instance_, ENABLE);
235 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
236 {
237 return ErrorCode::BUSY;
238 }
239
240 I2C_Send7bitAddress(instance_, HEADER, I2C_Direction_Receiver);
241 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
242 {
243 return ErrorCode::BUSY;
244 }
245 ClearAddrFlag();
246
247 return ErrorCode::OK;
248}

◆ 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 646 of file ch32_i2c.cpp.

648{
649 if (read_data.size_ == 0)
650 {
651 op.UpdateStatus(in_isr, ErrorCode::OK);
652 if (op.type == ReadOperation::OperationType::BLOCK)
653 {
654 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
655 }
656 return ErrorCode::OK;
657 }
658
659 ASSERT(read_data.size_ <= dma_buff_.size_);
660 if (DmaBusy())
661 {
662 return ErrorCode::BUSY;
663 }
664
665 read_ = true;
666
667 // 1) 地址阶段:发送写地址 + mem addr
668 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
669 if (ec != ErrorCode::OK)
670 {
671 return ec;
672 }
673
674 ec = SendMemAddr(mem_addr, mem_addr_size);
675 if (ec != ErrorCode::OK)
676 {
677 I2C_GenerateSTOP(instance_, ENABLE);
678 op.UpdateStatus(in_isr, ec);
679 if (op.type == ReadOperation::OperationType::BLOCK)
680 {
681 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
682 }
683 return ec;
684 }
685
686 // 2) Repeated START + 读地址阶段
687 if (!ten_bit_addr_)
688 {
689 const uint8_t ADDR8 = Addr7ToAddr8(slave_addr);
690
691 I2C_GenerateSTART(instance_, ENABLE);
692 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
693 {
694 I2C_GenerateSTOP(instance_, ENABLE);
695 ec = ErrorCode::BUSY;
696 op.UpdateStatus(in_isr, ec);
697 if (op.type == ReadOperation::OperationType::BLOCK)
698 {
699 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
700 }
701 return ec;
702 }
703
704 I2C_Send7bitAddress(instance_, ADDR8, I2C_Direction_Receiver);
705 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
706 {
707 I2C_GenerateSTOP(instance_, ENABLE);
708 ec = ErrorCode::BUSY;
709 op.UpdateStatus(in_isr, ec);
710 if (op.type == ReadOperation::OperationType::BLOCK)
711 {
712 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
713 }
714 return ec;
715 }
716 ClearAddrFlag();
717 }
718 else
719 {
720 const uint16_t ADDR10 = Addr10Clamp(slave_addr);
721 const uint8_t HEADER = static_cast<uint8_t>(0xF0 | ((ADDR10 >> 7) & 0x06));
722
723 I2C_GenerateSTART(instance_, ENABLE);
724 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
725 {
726 I2C_GenerateSTOP(instance_, ENABLE);
727 ec = ErrorCode::BUSY;
728 op.UpdateStatus(in_isr, ec);
729 if (op.type == ReadOperation::OperationType::BLOCK)
730 {
731 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
732 }
733 return ec;
734 }
735
736 I2C_Send7bitAddress(instance_, HEADER, I2C_Direction_Receiver);
737 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
738 {
739 I2C_GenerateSTOP(instance_, ENABLE);
740 ec = ErrorCode::BUSY;
741 op.UpdateStatus(in_isr, ec);
742 if (op.type == ReadOperation::OperationType::BLOCK)
743 {
744 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
745 }
746 return ec;
747 }
748 ClearAddrFlag();
749 }
750
751 // 短传输:轮询
752 if (read_data.size_ <= dma_enable_min_size_)
753 {
754 ec = PollingReadBytes(reinterpret_cast<uint8_t*>(read_data.addr_), read_data.size_);
755 op.UpdateStatus(in_isr, ec);
756 if (op.type == ReadOperation::OperationType::BLOCK)
757 {
758 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
759 }
760 return ec;
761 }
762
763 // 长传输:DMA
764 read_op_ = op;
765 read_buff_ = read_data;
766 busy_ = true;
767
768 StartRxDma(read_data.size_);
769
770 op.MarkAsRunning();
771 if (op.type == ReadOperation::OperationType::BLOCK)
772 {
773 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
774 }
775 return ErrorCode::OK;
776}
union LibXR::Operation::@5 data
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:205
OperationType type
Definition libxr_rw.hpp:229
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25

◆ 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 577 of file ch32_i2c.cpp.

580{
581 if (write_data.size_ == 0)
582 {
583 op.UpdateStatus(in_isr, ErrorCode::OK);
584 if (op.type == WriteOperation::OperationType::BLOCK)
585 {
586 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
587 }
588 return ErrorCode::OK;
589 }
590
591 ASSERT(write_data.size_ <= dma_buff_.size_);
592 if (DmaBusy())
593 {
594 return ErrorCode::BUSY;
595 }
596
597 read_ = false;
598
599 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
600 if (ec != ErrorCode::OK)
601 {
602 return ec;
603 }
604
605 ec = SendMemAddr(mem_addr, mem_addr_size);
606 if (ec != ErrorCode::OK)
607 {
608 I2C_GenerateSTOP(instance_, ENABLE);
609 op.UpdateStatus(in_isr, ec);
610 if (op.type == WriteOperation::OperationType::BLOCK)
611 {
612 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
613 }
614 return ec;
615 }
616
617 if (write_data.size_ <= dma_enable_min_size_)
618 {
619 ec = PollingWriteBytes(reinterpret_cast<const uint8_t*>(write_data.addr_),
620 write_data.size_);
621 I2C_GenerateSTOP(instance_, ENABLE);
622
623 op.UpdateStatus(in_isr, ec);
624 if (op.type == WriteOperation::OperationType::BLOCK)
625 {
626 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
627 }
628 return ec;
629 }
630
631 Memory::FastCopy(dma_buff_.addr_, write_data.addr_, write_data.size_);
632
633 write_op_ = op;
634 busy_ = true;
635
636 StartTxDma(write_data.size_);
637
638 op.MarkAsRunning();
639 if (op.type == WriteOperation::OperationType::BLOCK)
640 {
641 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
642 }
643 return ErrorCode::OK;
644}
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:3

◆ PollingReadBytes()

ErrorCode CH32I2C::PollingReadBytes ( uint8_t * data,
uint32_t len )
private

Definition at line 341 of file ch32_i2c.cpp.

342{
343 if (len == 0)
344 {
345 return ErrorCode::OK;
346 }
347
348 // 长度=1
349 if (len == 1)
350 {
351 I2C_AcknowledgeConfig(instance_, DISABLE);
352 I2C_GenerateSTOP(instance_, ENABLE);
353 if (!WaitFlag(I2C_FLAG_RXNE, SET))
354 {
355 return ErrorCode::BUSY;
356 }
357 data[0] = I2C_ReceiveData(instance_);
358 I2C_AcknowledgeConfig(instance_, ENABLE);
359 return ErrorCode::OK;
360 }
361
362 // 长度=2
363 if (len == 2)
364 {
365 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Next);
366 I2C_AcknowledgeConfig(instance_, DISABLE);
367
368 if (!WaitFlag(I2C_FLAG_BTF, SET))
369 {
370 return ErrorCode::BUSY;
371 }
372 I2C_GenerateSTOP(instance_, ENABLE);
373
374 data[0] = I2C_ReceiveData(instance_);
375 data[1] = I2C_ReceiveData(instance_);
376
377 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
378 I2C_AcknowledgeConfig(instance_, ENABLE);
379 return ErrorCode::OK;
380 }
381
382 // 长度>=3
383 I2C_AcknowledgeConfig(instance_, ENABLE);
384 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
385
386 uint32_t idx = 0;
387 while (len > 3)
388 {
389 if (!WaitFlag(I2C_FLAG_RXNE, SET))
390 {
391 return ErrorCode::BUSY;
392 }
393 data[idx++] = I2C_ReceiveData(instance_);
394 --len;
395 }
396
397 // 剩余 3 字节处理
398 if (!WaitFlag(I2C_FLAG_BTF, SET))
399 {
400 return ErrorCode::BUSY;
401 }
402 I2C_AcknowledgeConfig(instance_, DISABLE);
403 data[idx++] = I2C_ReceiveData(instance_);
404 I2C_GenerateSTOP(instance_, ENABLE);
405 data[idx++] = I2C_ReceiveData(instance_);
406
407 if (!WaitFlag(I2C_FLAG_RXNE, SET))
408 {
409 return ErrorCode::BUSY;
410 }
411 data[idx++] = I2C_ReceiveData(instance_);
412
413 I2C_AcknowledgeConfig(instance_, ENABLE);
414 return ErrorCode::OK;
415}

◆ PollingWriteBytes()

ErrorCode CH32I2C::PollingWriteBytes ( const uint8_t * data,
uint32_t len )
private

Definition at line 324 of file ch32_i2c.cpp.

325{
326 for (uint32_t i = 0; i < len; ++i)
327 {
328 if (!WaitFlag(I2C_FLAG_TXE, SET))
329 {
330 return ErrorCode::BUSY;
331 }
332 I2C_SendData(instance_, data[i]);
333 }
334 if (!WaitFlag(I2C_FLAG_BTF, SET))
335 {
336 return ErrorCode::BUSY;
337 }
338 return ErrorCode::OK;
339}

◆ 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 523 of file ch32_i2c.cpp.

525{
526 if (read_data.size_ == 0)
527 {
528 op.UpdateStatus(in_isr, ErrorCode::OK);
529 if (op.type == ReadOperation::OperationType::BLOCK)
530 {
531 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
532 }
533 return ErrorCode::OK;
534 }
535
536 ASSERT(read_data.size_ <= dma_buff_.size_);
537 if (DmaBusy())
538 {
539 return ErrorCode::BUSY;
540 }
541
542 read_ = true;
543
544 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Receiver);
545 if (ec != ErrorCode::OK)
546 {
547 return ec;
548 }
549
550 // 短传输:轮询
551 if (read_data.size_ <= dma_enable_min_size_)
552 {
553 ec = PollingReadBytes(reinterpret_cast<uint8_t*>(read_data.addr_), read_data.size_);
554 op.UpdateStatus(in_isr, ec);
555 if (op.type == ReadOperation::OperationType::BLOCK)
556 {
557 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
558 }
559 return ec;
560 }
561
562 // 长传输:DMA
563 read_op_ = op;
564 read_buff_ = read_data;
565 busy_ = true;
566
567 StartRxDma(read_data.size_);
568
569 op.MarkAsRunning();
570 if (op.type == ReadOperation::OperationType::BLOCK)
571 {
572 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
573 }
574 return ErrorCode::OK;
575}

◆ RxDmaIRQHandler()

void CH32I2C::RxDmaIRQHandler ( )

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

Definition at line 796 of file ch32_i2c.cpp.

797{
798 if (DMA_GetITStatus(CH32_I2C_RX_DMA_IT_MAP[id_]) == RESET)
799 {
800 return;
801 }
802 DMA_ClearITPendingBit(CH32_I2C_RX_DMA_IT_MAP[id_]);
803
804 DMA_Cmd(dma_rx_channel_, DISABLE);
805 I2C_DMACmd(instance_, DISABLE);
806 I2C_DMALastTransferCmd(instance_, DISABLE);
807
808 I2C_GenerateSTOP(instance_, ENABLE);
809
810 if (read_buff_.size_ > 0)
811 {
812 Memory::FastCopy(read_buff_.addr_, dma_buff_.addr_, read_buff_.size_);
813 read_buff_.size_ = 0;
814 }
815
816 // 恢复默认 ACK/NACK 配置
817 I2C_AcknowledgeConfig(instance_, ENABLE);
818 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
819
820 busy_ = false;
821 read_op_.UpdateStatus(true, ErrorCode::OK);
822}

◆ SendMemAddr()

ErrorCode CH32I2C::SendMemAddr ( uint16_t mem_addr,
MemAddrLength len )
private

Definition at line 293 of file ch32_i2c.cpp.

294{
295 if (len == MemAddrLength::BYTE_16)
296 {
297 if (!WaitFlag(I2C_FLAG_TXE, SET))
298 {
299 return ErrorCode::BUSY;
300 }
301 I2C_SendData(instance_, static_cast<uint8_t>((mem_addr >> 8) & 0xFF));
302 if (!WaitFlag(I2C_FLAG_TXE, SET))
303 {
304 return ErrorCode::BUSY;
305 }
306 I2C_SendData(instance_, static_cast<uint8_t>(mem_addr & 0xFF));
307 }
308 else
309 {
310 if (!WaitFlag(I2C_FLAG_TXE, SET))
311 {
312 return ErrorCode::BUSY;
313 }
314 I2C_SendData(instance_, static_cast<uint8_t>(mem_addr & 0xFF));
315 }
316
317 if (!WaitFlag(I2C_FLAG_BTF, SET))
318 {
319 return ErrorCode::BUSY;
320 }
321 return ErrorCode::OK;
322}

◆ 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 130 of file ch32_i2c.cpp.

131{
132 cfg_ = config;
133
134 I2C_Cmd(instance_, DISABLE);
135 I2C_DeInit(instance_);
136
137 I2C_InitTypeDef init = {};
138 init.I2C_ClockSpeed = cfg_.clock_speed;
139 init.I2C_Mode = I2C_Mode_I2C;
140 init.I2C_DutyCycle = I2C_DutyCycle_2;
141 init.I2C_OwnAddress1 = 0;
142 init.I2C_Ack = I2C_Ack_Enable;
143 init.I2C_AcknowledgedAddress =
144 ten_bit_addr_ ? I2C_AcknowledgedAddress_10bit : I2C_AcknowledgedAddress_7bit;
145
146 I2C_Init(instance_, &init);
147 I2C_Cmd(instance_, ENABLE);
148
149 // 默认 ACK/NACK 状态
150 I2C_AcknowledgeConfig(instance_, ENABLE);
151 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
152
153 return ErrorCode::OK;
154}

◆ StartRxDma()

void CH32I2C::StartRxDma ( uint32_t len)
private

Definition at line 426 of file ch32_i2c.cpp.

427{
428 // DMA 接收需保持 ACK 使能
429 I2C_AcknowledgeConfig(instance_, ENABLE);
430 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
431
432 dma_rx_channel_->MADDR = reinterpret_cast<uint32_t>(dma_buff_.addr_);
433 dma_rx_channel_->CNTR = len;
434
435 I2C_DMALastTransferCmd(instance_, ENABLE);
436 I2C_DMACmd(instance_, ENABLE);
437 DMA_Cmd(dma_rx_channel_, ENABLE);
438}

◆ StartTxDma()

void CH32I2C::StartTxDma ( uint32_t len)
private

Definition at line 417 of file ch32_i2c.cpp.

418{
419 dma_tx_channel_->MADDR = reinterpret_cast<uint32_t>(dma_buff_.addr_);
420 dma_tx_channel_->CNTR = len;
421
422 I2C_DMACmd(instance_, ENABLE);
423 DMA_Cmd(dma_tx_channel_, ENABLE);
424}

◆ TxDmaIRQHandler()

void CH32I2C::TxDmaIRQHandler ( )

Definition at line 778 of file ch32_i2c.cpp.

779{
780 if (DMA_GetITStatus(CH32_I2C_TX_DMA_IT_MAP[id_]) == RESET)
781 {
782 return;
783 }
784 DMA_ClearITPendingBit(CH32_I2C_TX_DMA_IT_MAP[id_]);
785
786 DMA_Cmd(dma_tx_channel_, DISABLE);
787 I2C_DMACmd(instance_, DISABLE);
788
789 (void)WaitFlag(I2C_FLAG_BTF, SET, 20000);
790 I2C_GenerateSTOP(instance_, ENABLE);
791
792 busy_ = false;
793 write_op_.UpdateStatus(true, ErrorCode::OK);
794}

◆ WaitEvent()

bool CH32I2C::WaitEvent ( uint32_t evt,
uint32_t timeout_us = K_DEFAULT_TIMEOUT_US )
private

Definition at line 156 of file ch32_i2c.cpp.

157{
158 const uint64_t START = static_cast<uint64_t>(Timebase::GetMicroseconds());
159 while ((static_cast<uint64_t>(Timebase::GetMicroseconds()) - START) < timeout_us)
160 {
161 if (I2C_CheckEvent(instance_, evt) == READY)
162 {
163 return true;
164 }
165 }
166 return false;
167}
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
Definition timebase.hpp:49

◆ WaitFlag()

bool CH32I2C::WaitFlag ( uint32_t flag,
FlagStatus st,
uint32_t timeout_us = K_DEFAULT_TIMEOUT_US )
private

Definition at line 169 of file ch32_i2c.cpp.

170{
171 const uint64_t START = static_cast<uint64_t>(Timebase::GetMicroseconds());
172 while ((static_cast<uint64_t>(Timebase::GetMicroseconds()) - START) < timeout_us)
173 {
174 if (I2C_GetFlagStatus(instance_, flag) == st)
175 {
176 return true;
177 }
178 }
179 return false;
180}

◆ 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 465 of file ch32_i2c.cpp.

467{
468 if (write_data.size_ == 0)
469 {
470 op.UpdateStatus(in_isr, ErrorCode::OK);
471 if (op.type == WriteOperation::OperationType::BLOCK)
472 {
473 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
474 }
475 return ErrorCode::OK;
476 }
477
478 ASSERT(write_data.size_ <= dma_buff_.size_);
479 if (DmaBusy())
480 {
481 return ErrorCode::BUSY;
482 }
483
484 read_ = false;
485
486 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
487 if (ec != ErrorCode::OK)
488 {
489 return ec;
490 }
491
492 // 短传输:轮询
493 if (write_data.size_ <= dma_enable_min_size_)
494 {
495 ec = PollingWriteBytes(reinterpret_cast<const uint8_t*>(write_data.addr_),
496 write_data.size_);
497 I2C_GenerateSTOP(instance_, ENABLE);
498
499 op.UpdateStatus(in_isr, ec);
500 if (op.type == WriteOperation::OperationType::BLOCK)
501 {
502 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
503 }
504 return ec;
505 }
506
507 // 长传输:DMA
508 Memory::FastCopy(dma_buff_.addr_, write_data.addr_, write_data.size_);
509
510 write_op_ = op;
511 busy_ = true;
512
513 StartTxDma(write_data.size_);
514
515 op.MarkAsRunning();
516 if (op.type == WriteOperation::OperationType::BLOCK)
517 {
518 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
519 }
520 return ErrorCode::OK;
521}

Field Documentation

◆ busy_

bool LibXR::CH32I2C::busy_ = false

Definition at line 114 of file ch32_i2c.hpp.

◆ cfg_

Configuration LibXR::CH32I2C::cfg_ {400000}

Definition at line 121 of file ch32_i2c.hpp.

121{400000};

◆ dma_buff_

RawData LibXR::CH32I2C::dma_buff_

Definition at line 108 of file ch32_i2c.hpp.

◆ dma_enable_min_size_

uint32_t LibXR::CH32I2C::dma_enable_min_size_

Definition at line 106 of file ch32_i2c.hpp.

◆ dma_rx_channel_

DMA_Channel_TypeDef* LibXR::CH32I2C::dma_rx_channel_

Definition at line 103 of file ch32_i2c.hpp.

◆ dma_tx_channel_

DMA_Channel_TypeDef* LibXR::CH32I2C::dma_tx_channel_

Definition at line 104 of file ch32_i2c.hpp.

◆ id_

ch32_i2c_id_t LibXR::CH32I2C::id_

Definition at line 105 of file ch32_i2c.hpp.

◆ instance_

I2C_TypeDef* LibXR::CH32I2C::instance_

Definition at line 102 of file ch32_i2c.hpp.

◆ K_DEFAULT_TIMEOUT_US

uint32_t LibXR::CH32I2C::K_DEFAULT_TIMEOUT_US = 20000
staticconstexprprivate

默认超时(微秒) / Default timeout in microseconds

Definition at line 58 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 113 of file ch32_i2c.hpp.

◆ read_buff_

RawData LibXR::CH32I2C::read_buff_

Definition at line 112 of file ch32_i2c.hpp.

◆ read_op_

ReadOperation LibXR::CH32I2C::read_op_

Definition at line 110 of file ch32_i2c.hpp.

◆ scl_pin_

uint16_t LibXR::CH32I2C::scl_pin_

Definition at line 117 of file ch32_i2c.hpp.

◆ scl_port_

GPIO_TypeDef* LibXR::CH32I2C::scl_port_

Definition at line 116 of file ch32_i2c.hpp.

◆ sda_pin_

uint16_t LibXR::CH32I2C::sda_pin_

Definition at line 119 of file ch32_i2c.hpp.

◆ sda_port_

GPIO_TypeDef* LibXR::CH32I2C::sda_port_

Definition at line 118 of file ch32_i2c.hpp.

◆ ten_bit_addr_

bool LibXR::CH32I2C::ten_bit_addr_ = false

Definition at line 123 of file ch32_i2c.hpp.

◆ write_op_

WriteOperation LibXR::CH32I2C::write_op_

Definition at line 111 of file ch32_i2c.hpp.


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