libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_i2c.cpp
1// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
2// ch32_i2c.cpp
3#include "ch32_i2c.hpp"
4
5#include <cstring>
6
7#include "ch32_dma.hpp"
8#include "ch32_gpio.hpp"
9
10using namespace LibXR;
11
12CH32I2C* CH32I2C::map_[CH32_I2C_NUMBER] = {nullptr};
13
14static inline void ch32_i2c_enable_clocks(ch32_i2c_id_t id)
15{
16 RCC_APB1PeriphClockCmd(CH32_I2C_RCC_PERIPH_MAP[id], ENABLE);
17 RCC_AHBPeriphClockCmd(CH32_I2C_RCC_PERIPH_MAP_DMA[id], ENABLE);
18}
19
20CH32I2C::CH32I2C(ch32_i2c_id_t id, RawData dma_buff, GPIO_TypeDef* scl_port,
21 uint16_t scl_pin, GPIO_TypeDef* sda_port, uint16_t sda_pin,
22 uint32_t pin_remap, uint32_t dma_enable_min_size,
23 uint32_t default_clock_hz, bool ten_bit_addr)
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}
129
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}
155
156bool CH32I2C::WaitEvent(uint32_t evt, uint32_t timeout_us)
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}
168
169bool CH32I2C::WaitFlag(uint32_t flag, FlagStatus st, uint32_t timeout_us)
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}
181
182void CH32I2C::ClearAddrFlag()
183{
184 volatile uint16_t tmp1 = instance_->STAR1;
185 volatile uint16_t tmp2 = instance_->STAR2;
186 (void)tmp1;
187 (void)tmp2;
188}
189
190ErrorCode CH32I2C::MasterStartAndAddress10Bit(uint16_t addr10, uint8_t final_dir)
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}
249
250ErrorCode CH32I2C::MasterStartAndAddress(uint16_t slave_addr, uint8_t dir)
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}
292
293ErrorCode CH32I2C::SendMemAddr(uint16_t mem_addr, MemAddrLength len)
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}
323
324ErrorCode CH32I2C::PollingWriteBytes(const uint8_t* data, uint32_t len)
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}
340
341ErrorCode CH32I2C::PollingReadBytes(uint8_t* data, uint32_t len)
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}
416
417void CH32I2C::StartTxDma(uint32_t len)
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}
425
426void CH32I2C::StartRxDma(uint32_t len)
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}
439
440void CH32I2C::AbortTransfer(ErrorCode ec)
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}
464
465ErrorCode CH32I2C::Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation& op,
466 bool in_isr)
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}
522
523ErrorCode CH32I2C::Read(uint16_t slave_addr, RawData read_data, ReadOperation& op,
524 bool in_isr)
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}
576
577ErrorCode CH32I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
578 ConstRawData write_data, WriteOperation& op,
579 MemAddrLength mem_addr_size, bool in_isr)
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}
645
646ErrorCode CH32I2C::MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
647 ReadOperation& op, MemAddrLength mem_addr_size, bool in_isr)
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}
777
778void CH32I2C::TxDmaIRQHandler()
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}
795
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}
823
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}
845
846// I2C ER IRQ entry.
847extern "C"
848{
849#if defined(I2C1)
850 void i2_c1_er_irq_handler(void)
851 {
852 auto* p = LibXR::CH32I2C::map_[ch32_i2c_get_id(I2C1)];
853 if (p)
854 {
855 p->ErrorIRQHandler();
856 }
857 }
858#endif
859
860#if defined(I2C2)
861 void i2_c2_er_irq_handler(void)
862 {
863 auto* p = LibXR::CH32I2C::map_[ch32_i2c_get_id(I2C2)];
864 if (p)
865 {
866 p->ErrorIRQHandler();
867 }
868 }
869#endif
870} // extern "C"
871
872// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
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.
Definition ch32_i2c.cpp:577
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.
Definition ch32_i2c.cpp:646
void RxDmaIRQHandler()
DMA 回调入口 / DMA callbacks from CH32 DMA driver.
Definition ch32_i2c.cpp:796
void ErrorIRQHandler()
错误中断回调 / I2C error IRQ callback
Definition ch32_i2c.cpp:824
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr) override
向 I2C 设备写入数据。 Writes data to an I2C device.
Definition ch32_i2c.cpp:465
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr) override
读取 I2C 设备的数据。 Reads data from an I2C device.
Definition ch32_i2c.cpp:523
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
Definition ch32_i2c.cpp:20
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
Definition ch32_i2c.cpp:130
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
I2C(Inter-Integrated Circuit)接口类。 I2C (Inter-Integrated Circuit) interface class.
Definition i2c.hpp:17
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:3
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:172
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:205
OperationType type
Definition libxr_rw.hpp:229
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
Definition timebase.hpp:49
LibXR 命名空间
Definition ch32_can.hpp:14
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.
Definition i2c.hpp:24
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz)。 The I2C clock speed (in Hz).
Definition i2c.hpp:26