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
14namespace
15{
16
17constexpr uint32_t CH32_I2C_ERROR_FLAGS =
18 ((I2C_FLAG_BERR & 0xFFFFu) | (I2C_FLAG_ARLO & 0xFFFFu) | (I2C_FLAG_AF & 0xFFFFu) |
19 (I2C_FLAG_OVR & 0xFFFFu) | (I2C_FLAG_PECERR & 0xFFFFu) |
20 (I2C_FLAG_TIMEOUT & 0xFFFFu) | (I2C_FLAG_SMBALERT & 0xFFFFu));
21
22} // namespace
23
24static inline void ch32_i2c_enable_clocks(ch32_i2c_id_t id)
25{
26 RCC_APB1PeriphClockCmd(CH32_I2C_RCC_PERIPH_MAP[id], ENABLE);
27 RCC_AHBPeriphClockCmd(CH32_I2C_RCC_PERIPH_MAP_DMA[id], ENABLE);
28}
29
30CH32I2C::CH32I2C(ch32_i2c_id_t id, RawData dma_buff, GPIO_TypeDef* scl_port,
31 uint16_t scl_pin, GPIO_TypeDef* sda_port, uint16_t sda_pin,
32 uint32_t pin_remap, uint32_t dma_enable_min_size,
33 uint32_t default_clock_hz, bool ten_bit_addr)
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}
139
141{
142 cfg_ = config;
143
144 I2C_Cmd(instance_, DISABLE);
145 I2C_DeInit(instance_);
146
147 I2C_InitTypeDef init = {};
148 init.I2C_ClockSpeed = cfg_.clock_speed;
149 init.I2C_Mode = I2C_Mode_I2C;
150 init.I2C_DutyCycle = I2C_DutyCycle_2;
151 init.I2C_OwnAddress1 = 0;
152 init.I2C_Ack = I2C_Ack_Enable;
153 init.I2C_AcknowledgedAddress =
154 ten_bit_addr_ ? I2C_AcknowledgedAddress_10bit : I2C_AcknowledgedAddress_7bit;
155
156 I2C_Init(instance_, &init);
157 I2C_Cmd(instance_, ENABLE);
158
159 // 默认 ACK/NACK 状态
160 I2C_AcknowledgeConfig(instance_, ENABLE);
161 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
162
163 return ErrorCode::OK;
164}
165
166bool CH32I2C::WaitEvent(uint32_t evt, uint32_t timeout_us)
167{
168 const uint64_t START = static_cast<uint64_t>(Timebase::GetMicroseconds());
169 while ((static_cast<uint64_t>(Timebase::GetMicroseconds()) - START) < timeout_us)
170 {
171 if ((instance_->STAR1 & CH32_I2C_ERROR_FLAGS) != 0u)
172 {
173 return false;
174 }
175 if (I2C_CheckEvent(instance_, evt) == READY)
176 {
177 return true;
178 }
179 }
180 return false;
181}
182
183bool CH32I2C::WaitFlag(uint32_t flag, FlagStatus st, uint32_t timeout_us)
184{
185 const uint64_t START = static_cast<uint64_t>(Timebase::GetMicroseconds());
186 while ((static_cast<uint64_t>(Timebase::GetMicroseconds()) - START) < timeout_us)
187 {
188 if ((flag != I2C_FLAG_BUSY) && ((instance_->STAR1 & CH32_I2C_ERROR_FLAGS) != 0u))
189 {
190 return false;
191 }
192 if (I2C_GetFlagStatus(instance_, flag) == st)
193 {
194 return true;
195 }
196 }
197 return false;
198}
199
200ErrorCode CH32I2C::WaitEventOrRecover(uint32_t evt, uint32_t timeout_us)
201{
202 if (WaitEvent(evt, timeout_us))
203 {
204 return ErrorCode::OK;
205 }
206 RecoverAfterImmediateFailure();
207 return ErrorCode::BUSY;
208}
209
210ErrorCode CH32I2C::WaitFlagOrRecover(uint32_t flag, FlagStatus st, uint32_t timeout_us)
211{
212 if (WaitFlag(flag, st, timeout_us))
213 {
214 return ErrorCode::OK;
215 }
216 RecoverAfterImmediateFailure();
217 return ErrorCode::BUSY;
218}
219
220void CH32I2C::ClearAddrFlag()
221{
222 volatile uint16_t tmp1 = instance_->STAR1;
223 volatile uint16_t tmp2 = instance_->STAR2;
224 (void)tmp1;
225 (void)tmp2;
226}
227
228ErrorCode CH32I2C::MasterStartAndAddress10Bit(uint16_t addr10, uint8_t final_dir)
229{
230 addr10 = Addr10Clamp(addr10);
231
232 // 等待 BUSY 释放
233 if (auto ec = WaitFlagOrRecover(I2C_FLAG_BUSY, RESET); ec != ErrorCode::OK)
234 {
235 return ec;
236 }
237
238 // --- 1) START ---
239 I2C_GenerateSTART(instance_, ENABLE);
240 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_MODE_SELECT); ec != ErrorCode::OK)
241 {
242 return ec;
243 }
244
245 // --- 2) 发送 10-bit 头字节(地址阶段固定以写方向发送,R/W=0)---
246 // header (8-bit,left-shifted): 11110 A9 A8 0 => 0xF0/0xF2/0xF4/0xF6
247 const uint8_t HEADER = static_cast<uint8_t>(0xF0 | ((addr10 >> 7) & 0x06));
248 I2C_Send7bitAddress(instance_, HEADER, I2C_Direction_Transmitter);
249
250 // 等待 EVT9(ADD10)
251 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_MODE_ADDRESS10); ec != ErrorCode::OK)
252 {
253 return ec;
254 }
255
256 // --- 3) 发送地址低 8 位 ---
257 I2C_SendData(instance_, static_cast<uint8_t>(addr10 & 0xFF));
258
259 // 等待 EVT6(作为 Transmitter 完成地址阶段)
260 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
261 ec != ErrorCode::OK)
262 {
263 return ec;
264 }
265 ClearAddrFlag();
266
267 if (final_dir == I2C_Direction_Transmitter)
268 {
269 return ErrorCode::OK;
270 }
271
272 // --- 4) 若最终为读:Repeated START + 头字节(R/W=1) ---
273 I2C_GenerateSTART(instance_, ENABLE);
274 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_MODE_SELECT); ec != ErrorCode::OK)
275 {
276 return ec;
277 }
278
279 I2C_Send7bitAddress(instance_, HEADER, I2C_Direction_Receiver);
280 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);
281 ec != ErrorCode::OK)
282 {
283 return ec;
284 }
285 ClearAddrFlag();
286
287 return ErrorCode::OK;
288}
289
290ErrorCode CH32I2C::MasterStartAndAddress(uint16_t slave_addr, uint8_t dir)
291{
292 if (!ten_bit_addr_)
293 {
294 // 7-bit:输入为原始 7-bit 地址
295 const uint8_t ADDR8 = Addr7ToAddr8(slave_addr);
296
297 if (auto ec = WaitFlagOrRecover(I2C_FLAG_BUSY, RESET); ec != ErrorCode::OK)
298 {
299 return ec;
300 }
301
302 I2C_GenerateSTART(instance_, ENABLE);
303 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_MODE_SELECT); ec != ErrorCode::OK)
304 {
305 return ec;
306 }
307
308 I2C_Send7bitAddress(instance_, ADDR8, dir);
309
310 if (dir == I2C_Direction_Transmitter)
311 {
312 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
313 ec != ErrorCode::OK)
314 {
315 return ec;
316 }
317 }
318 else
319 {
320 if (auto ec = WaitEventOrRecover(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);
321 ec != ErrorCode::OK)
322 {
323 return ec;
324 }
325 }
326
327 ClearAddrFlag();
328 return ErrorCode::OK;
329 }
330
331 // 10-bit:输入为原始 10-bit 地址
332 return MasterStartAndAddress10Bit(slave_addr, dir);
333}
334
335ErrorCode CH32I2C::SendMemAddr(uint16_t mem_addr, MemAddrLength len)
336{
337 if (len == MemAddrLength::BYTE_16)
338 {
339 if (auto ec = WaitFlagOrRecover(I2C_FLAG_TXE, SET); ec != ErrorCode::OK)
340 {
341 return ec;
342 }
343 I2C_SendData(instance_, static_cast<uint8_t>((mem_addr >> 8) & 0xFF));
344 if (auto ec = WaitFlagOrRecover(I2C_FLAG_TXE, SET); ec != ErrorCode::OK)
345 {
346 return ec;
347 }
348 I2C_SendData(instance_, static_cast<uint8_t>(mem_addr & 0xFF));
349 }
350 else
351 {
352 if (auto ec = WaitFlagOrRecover(I2C_FLAG_TXE, SET); ec != ErrorCode::OK)
353 {
354 return ec;
355 }
356 I2C_SendData(instance_, static_cast<uint8_t>(mem_addr & 0xFF));
357 }
358
359 if (auto ec = WaitFlagOrRecover(I2C_FLAG_BTF, SET); ec != ErrorCode::OK)
360 {
361 return ec;
362 }
363 return ErrorCode::OK;
364}
365
366ErrorCode CH32I2C::PollingWriteBytes(const uint8_t* data, uint32_t len)
367{
368 for (uint32_t i = 0; i < len; ++i)
369 {
370 if (auto ec = WaitFlagOrRecover(I2C_FLAG_TXE, SET); ec != ErrorCode::OK)
371 {
372 return ec;
373 }
374 I2C_SendData(instance_, data[i]);
375 }
376 if (auto ec = WaitFlagOrRecover(I2C_FLAG_BTF, SET); ec != ErrorCode::OK)
377 {
378 return ec;
379 }
380 return ErrorCode::OK;
381}
382
383ErrorCode CH32I2C::PollingReadBytes(uint8_t* data, uint32_t len)
384{
385 if (len == 0)
386 {
387 return ErrorCode::OK;
388 }
389
390 // 长度=1
391 if (len == 1)
392 {
393 I2C_AcknowledgeConfig(instance_, DISABLE);
394 I2C_GenerateSTOP(instance_, ENABLE);
395 if (auto ec = WaitFlagOrRecover(I2C_FLAG_RXNE, SET); ec != ErrorCode::OK)
396 {
397 return ec;
398 }
399 data[0] = I2C_ReceiveData(instance_);
400 I2C_AcknowledgeConfig(instance_, ENABLE);
401 return ErrorCode::OK;
402 }
403
404 // 长度=2
405 if (len == 2)
406 {
407 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Next);
408 I2C_AcknowledgeConfig(instance_, DISABLE);
409
410 if (auto ec = WaitFlagOrRecover(I2C_FLAG_BTF, SET); ec != ErrorCode::OK)
411 {
412 return ec;
413 }
414 I2C_GenerateSTOP(instance_, ENABLE);
415
416 data[0] = I2C_ReceiveData(instance_);
417 data[1] = I2C_ReceiveData(instance_);
418
419 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
420 I2C_AcknowledgeConfig(instance_, ENABLE);
421 return ErrorCode::OK;
422 }
423
424 // 长度>=3
425 I2C_AcknowledgeConfig(instance_, ENABLE);
426 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
427
428 uint32_t idx = 0;
429 while (len > 3)
430 {
431 if (auto ec = WaitFlagOrRecover(I2C_FLAG_RXNE, SET); ec != ErrorCode::OK)
432 {
433 return ec;
434 }
435 data[idx++] = I2C_ReceiveData(instance_);
436 --len;
437 }
438
439 // 剩余 3 字节处理
440 if (auto ec = WaitFlagOrRecover(I2C_FLAG_BTF, SET); ec != ErrorCode::OK)
441 {
442 return ec;
443 }
444 I2C_AcknowledgeConfig(instance_, DISABLE);
445 data[idx++] = I2C_ReceiveData(instance_);
446 I2C_GenerateSTOP(instance_, ENABLE);
447 data[idx++] = I2C_ReceiveData(instance_);
448
449 if (auto ec = WaitFlagOrRecover(I2C_FLAG_RXNE, SET); ec != ErrorCode::OK)
450 {
451 return ec;
452 }
453 data[idx++] = I2C_ReceiveData(instance_);
454
455 I2C_AcknowledgeConfig(instance_, ENABLE);
456 return ErrorCode::OK;
457}
458
459void CH32I2C::StartTxDma(uint32_t len)
460{
461 dma_tx_channel_->MADDR = reinterpret_cast<uint32_t>(dma_buff_.addr_);
462 dma_tx_channel_->CNTR = len;
463
464 I2C_DMACmd(instance_, ENABLE);
465 DMA_Cmd(dma_tx_channel_, ENABLE);
466}
467
468void CH32I2C::StartRxDma(uint32_t len)
469{
470 // DMA 接收需保持 ACK 使能
471 I2C_AcknowledgeConfig(instance_, ENABLE);
472 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
473
474 dma_rx_channel_->MADDR = reinterpret_cast<uint32_t>(dma_buff_.addr_);
475 dma_rx_channel_->CNTR = len;
476
477 I2C_DMALastTransferCmd(instance_, ENABLE);
478 I2C_DMACmd(instance_, ENABLE);
479 DMA_Cmd(dma_rx_channel_, ENABLE);
480}
481
482void CH32I2C::AbortTransfer(ErrorCode ec)
483{
484 I2C_DMACmd(instance_, DISABLE);
485 I2C_DMALastTransferCmd(instance_, DISABLE);
486 DMA_Cmd(dma_tx_channel_, DISABLE);
487 DMA_Cmd(dma_rx_channel_, DISABLE);
488
489 // 恢复默认 ACK/NACK 配置
490 I2C_AcknowledgeConfig(instance_, ENABLE);
491 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
492
493 I2C_GenerateSTOP(instance_, ENABLE);
494
495 busy_ = false;
496
497 if (read_)
498 {
499 if (read_op_.type == ReadOperation::OperationType::BLOCK)
500 {
501 (void)block_wait_.TryPost(true, ec);
502 }
503 else
504 {
505 read_op_.UpdateStatus(true, ec);
506 }
507 }
508 else
509 {
510 if (write_op_.type == WriteOperation::OperationType::BLOCK)
511 {
512 (void)block_wait_.TryPost(true, ec);
513 }
514 else
515 {
516 write_op_.UpdateStatus(true, ec);
517 }
518 }
519}
520
521void CH32I2C::RecoverAfterImmediateFailure()
522{
523 recovering_ = true;
524 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
525 I2C_DMACmd(instance_, DISABLE);
526 I2C_DMALastTransferCmd(instance_, DISABLE);
527 DMA_Cmd(dma_tx_channel_, DISABLE);
528 DMA_Cmd(dma_rx_channel_, DISABLE);
529 dma_tx_channel_->CNTR = 0;
530 dma_rx_channel_->CNTR = 0;
531
532 DMA_ClearITPendingBit(CH32_I2C_TX_DMA_IT_MAP[id_]);
533 DMA_ClearITPendingBit(CH32_I2C_RX_DMA_IT_MAP[id_]);
534
535 const uint32_t err_its[] = {I2C_IT_BERR, I2C_IT_ARLO, I2C_IT_AF, I2C_IT_OVR,
536 I2C_IT_PECERR, I2C_IT_TIMEOUT, I2C_IT_SMBALERT};
537 for (uint32_t it : err_its)
538 {
539 I2C_ClearITPendingBit(instance_, it);
540 }
541
542 I2C_GenerateSTOP(instance_, ENABLE);
543 if (!WaitFlag(I2C_FLAG_BUSY, RESET, K_DEFAULT_TIMEOUT_US))
544 {
545 (void)SetConfig(cfg_);
546 }
547 else
548 {
549 I2C_AcknowledgeConfig(instance_, ENABLE);
550 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
551 }
552
553 busy_ = false;
554 read_ = false;
555 read_op_ = {};
556 write_op_ = {};
557 read_buff_ = {nullptr, 0};
558 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
559 recovering_ = false;
560}
561
562ErrorCode CH32I2C::Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation& op,
563 bool in_isr)
564{
565 if (write_data.size_ == 0)
566 {
567 if (op.type != WriteOperation::OperationType::BLOCK)
568 {
569 op.UpdateStatus(in_isr, ErrorCode::OK);
570 }
571 return ErrorCode::OK;
572 }
573
574 ASSERT(write_data.size_ <= dma_buff_.size_);
575 if (DmaBusy())
576 {
577 return ErrorCode::BUSY;
578 }
579
580 read_ = false;
581 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
582
583 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
584 if (ec != ErrorCode::OK)
585 {
586 return ec;
587 }
588
589 // 短传输:轮询
590 if (write_data.size_ <= dma_enable_min_size_)
591 {
592 ec = PollingWriteBytes(reinterpret_cast<const uint8_t*>(write_data.addr_),
593 write_data.size_);
594 I2C_GenerateSTOP(instance_, ENABLE);
595 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
596
597 if (op.type != WriteOperation::OperationType::BLOCK)
598 {
599 op.UpdateStatus(in_isr, ec);
600 }
601 return ec;
602 }
603
604 // 长传输:DMA
605 Memory::FastCopy(dma_buff_.addr_, write_data.addr_, write_data.size_);
606
607 write_op_ = op;
608 busy_ = true;
609
610 if (op.type == WriteOperation::OperationType::BLOCK)
611 {
612 block_wait_.Start(*op.data.sem_info.sem);
613 }
614 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
615 StartTxDma(write_data.size_);
616
617 op.MarkAsRunning();
618 if (op.type == WriteOperation::OperationType::BLOCK)
619 {
620 return block_wait_.Wait(op.data.sem_info.timeout);
621 }
622 return ErrorCode::OK;
623}
624
625ErrorCode CH32I2C::Read(uint16_t slave_addr, RawData read_data, ReadOperation& op,
626 bool in_isr)
627{
628 if (read_data.size_ == 0)
629 {
630 if (op.type != ReadOperation::OperationType::BLOCK)
631 {
632 op.UpdateStatus(in_isr, ErrorCode::OK);
633 }
634 return ErrorCode::OK;
635 }
636
637 ASSERT(read_data.size_ <= dma_buff_.size_);
638 if (DmaBusy())
639 {
640 return ErrorCode::BUSY;
641 }
642
643 read_ = true;
644 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
645
646 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Receiver);
647 if (ec != ErrorCode::OK)
648 {
649 return ec;
650 }
651
652 // 短传输:轮询
653 if (read_data.size_ <= dma_enable_min_size_)
654 {
655 ec = PollingReadBytes(reinterpret_cast<uint8_t*>(read_data.addr_), read_data.size_);
656 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
657 if (op.type != ReadOperation::OperationType::BLOCK)
658 {
659 op.UpdateStatus(in_isr, ec);
660 }
661 return ec;
662 }
663
664 // 长传输:DMA
665 read_op_ = op;
666 read_buff_ = read_data;
667 busy_ = true;
668
669 if (op.type == ReadOperation::OperationType::BLOCK)
670 {
671 block_wait_.Start(*op.data.sem_info.sem);
672 }
673 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
674 StartRxDma(read_data.size_);
675
676 op.MarkAsRunning();
677 if (op.type == ReadOperation::OperationType::BLOCK)
678 {
679 return block_wait_.Wait(op.data.sem_info.timeout);
680 }
681 return ErrorCode::OK;
682}
683
684ErrorCode CH32I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
685 ConstRawData write_data, WriteOperation& op,
686 MemAddrLength mem_addr_size, bool in_isr)
687{
688 if (write_data.size_ == 0)
689 {
690 if (op.type != WriteOperation::OperationType::BLOCK)
691 {
692 op.UpdateStatus(in_isr, ErrorCode::OK);
693 }
694 return ErrorCode::OK;
695 }
696
697 ASSERT(write_data.size_ <= dma_buff_.size_);
698 if (DmaBusy())
699 {
700 return ErrorCode::BUSY;
701 }
702
703 read_ = false;
704 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
705
706 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
707 if (ec != ErrorCode::OK)
708 {
709 return ec;
710 }
711
712 ec = SendMemAddr(mem_addr, mem_addr_size);
713 if (ec != ErrorCode::OK)
714 {
715 I2C_GenerateSTOP(instance_, ENABLE);
716 if (op.type != WriteOperation::OperationType::BLOCK)
717 {
718 op.UpdateStatus(in_isr, ec);
719 }
720 return ec;
721 }
722
723 if (write_data.size_ <= dma_enable_min_size_)
724 {
725 ec = PollingWriteBytes(reinterpret_cast<const uint8_t*>(write_data.addr_),
726 write_data.size_);
727 I2C_GenerateSTOP(instance_, ENABLE);
728 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
729
730 if (op.type != WriteOperation::OperationType::BLOCK)
731 {
732 op.UpdateStatus(in_isr, ec);
733 }
734 return ec;
735 }
736
737 Memory::FastCopy(dma_buff_.addr_, write_data.addr_, write_data.size_);
738
739 write_op_ = op;
740 busy_ = true;
741
742 if (op.type == WriteOperation::OperationType::BLOCK)
743 {
744 block_wait_.Start(*op.data.sem_info.sem);
745 }
746 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
747 StartTxDma(write_data.size_);
748
749 op.MarkAsRunning();
750 if (op.type == WriteOperation::OperationType::BLOCK)
751 {
752 return block_wait_.Wait(op.data.sem_info.timeout);
753 }
754 return ErrorCode::OK;
755}
756
757ErrorCode CH32I2C::MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
758 ReadOperation& op, MemAddrLength mem_addr_size, bool in_isr)
759{
760 if (read_data.size_ == 0)
761 {
762 if (op.type != ReadOperation::OperationType::BLOCK)
763 {
764 op.UpdateStatus(in_isr, ErrorCode::OK);
765 }
766 return ErrorCode::OK;
767 }
768
769 ASSERT(read_data.size_ <= dma_buff_.size_);
770 if (DmaBusy())
771 {
772 return ErrorCode::BUSY;
773 }
774
775 read_ = true;
776 I2C_ITConfig(instance_, I2C_IT_ERR, DISABLE);
777
778 // 1) 地址阶段:发送写地址 + mem addr
779 ErrorCode ec = MasterStartAndAddress(slave_addr, I2C_Direction_Transmitter);
780 if (ec != ErrorCode::OK)
781 {
782 return ec;
783 }
784
785 ec = SendMemAddr(mem_addr, mem_addr_size);
786 if (ec != ErrorCode::OK)
787 {
788 I2C_GenerateSTOP(instance_, ENABLE);
789 if (op.type != ReadOperation::OperationType::BLOCK)
790 {
791 op.UpdateStatus(in_isr, ec);
792 }
793 return ec;
794 }
795
796 // 2) Repeated START + 读地址阶段
797 if (!ten_bit_addr_)
798 {
799 const uint8_t ADDR8 = Addr7ToAddr8(slave_addr);
800
801 I2C_GenerateSTART(instance_, ENABLE);
802 if (!WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
803 {
804 I2C_GenerateSTOP(instance_, ENABLE);
805 ec = ErrorCode::BUSY;
806 if (op.type != ReadOperation::OperationType::BLOCK)
807 {
808 op.UpdateStatus(in_isr, ec);
809 }
810 return ec;
811 }
812
813 I2C_Send7bitAddress(instance_, ADDR8, I2C_Direction_Receiver);
814 if (!WaitEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
815 {
816 I2C_GenerateSTOP(instance_, ENABLE);
817 ec = ErrorCode::BUSY;
818 if (op.type != ReadOperation::OperationType::BLOCK)
819 {
820 op.UpdateStatus(in_isr, ec);
821 }
822 return ec;
823 }
824 ClearAddrFlag();
825 }
826 else
827 {
828 const uint16_t ADDR10 = Addr10Clamp(slave_addr);
829 const uint8_t HEADER = static_cast<uint8_t>(0xF0 | ((ADDR10 >> 7) & 0x06));
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_, HEADER, 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
857 // 短传输:轮询
858 if (read_data.size_ <= dma_enable_min_size_)
859 {
860 ec = PollingReadBytes(reinterpret_cast<uint8_t*>(read_data.addr_), read_data.size_);
861 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
862 if (op.type != ReadOperation::OperationType::BLOCK)
863 {
864 op.UpdateStatus(in_isr, ec);
865 }
866 return ec;
867 }
868
869 // 长传输:DMA
870 read_op_ = op;
871 read_buff_ = read_data;
872 busy_ = true;
873
874 if (op.type == ReadOperation::OperationType::BLOCK)
875 {
876 block_wait_.Start(*op.data.sem_info.sem);
877 }
878 I2C_ITConfig(instance_, I2C_IT_ERR, ENABLE);
879 StartRxDma(read_data.size_);
880
881 op.MarkAsRunning();
882 if (op.type == ReadOperation::OperationType::BLOCK)
883 {
884 return block_wait_.Wait(op.data.sem_info.timeout);
885 }
886 return ErrorCode::OK;
887}
888
889void CH32I2C::TxDmaIRQHandler()
890{
891 if (DMA_GetITStatus(CH32_I2C_TX_DMA_IT_MAP[id_]) == RESET)
892 {
893 return;
894 }
895 DMA_ClearITPendingBit(CH32_I2C_TX_DMA_IT_MAP[id_]);
896
897 DMA_Cmd(dma_tx_channel_, DISABLE);
898 I2C_DMACmd(instance_, DISABLE);
899
900 if (recovering_ || !busy_)
901 {
902 return;
903 }
904
905 (void)WaitFlag(I2C_FLAG_BTF, SET, 20000);
906 I2C_GenerateSTOP(instance_, ENABLE);
907
908 busy_ = false;
909 if (write_op_.type == WriteOperation::OperationType::BLOCK)
910 {
911 (void)block_wait_.TryPost(true, ErrorCode::OK);
912 }
913 else
914 {
915 write_op_.UpdateStatus(true, ErrorCode::OK);
916 }
917}
918
920{
921 if (DMA_GetITStatus(CH32_I2C_RX_DMA_IT_MAP[id_]) == RESET)
922 {
923 return;
924 }
925 DMA_ClearITPendingBit(CH32_I2C_RX_DMA_IT_MAP[id_]);
926
927 DMA_Cmd(dma_rx_channel_, DISABLE);
928 I2C_DMACmd(instance_, DISABLE);
929 I2C_DMALastTransferCmd(instance_, DISABLE);
930
931 if (recovering_ || !busy_)
932 {
933 return;
934 }
935
936 I2C_GenerateSTOP(instance_, ENABLE);
937
938 if (read_buff_.size_ > 0)
939 {
940 Memory::FastCopy(read_buff_.addr_, dma_buff_.addr_, read_buff_.size_);
941 read_buff_.size_ = 0;
942 }
943
944 // 恢复默认 ACK/NACK 配置
945 I2C_AcknowledgeConfig(instance_, ENABLE);
946 I2C_NACKPositionConfig(instance_, I2C_NACKPosition_Current);
947
948 busy_ = false;
949 if (read_op_.type == ReadOperation::OperationType::BLOCK)
950 {
951 (void)block_wait_.TryPost(true, ErrorCode::OK);
952 }
953 else
954 {
955 read_op_.UpdateStatus(true, ErrorCode::OK);
956 }
957}
958
960{
961 bool has_err = false;
962
963 const uint32_t ITS[] = {I2C_IT_BERR, I2C_IT_ARLO, I2C_IT_AF, I2C_IT_OVR,
964 I2C_IT_TIMEOUT, I2C_IT_PECERR, I2C_IT_SMBALERT};
965
966 for (uint32_t it : ITS)
967 {
968 if (I2C_GetITStatus(instance_, it) == SET)
969 {
970 I2C_ClearITPendingBit(instance_, it);
971 has_err = true;
972 }
973 }
974
975 if (has_err && busy_ && !recovering_)
976 {
977 AbortTransfer(ErrorCode::FAILED);
978 }
979}
980
981// I2C ER IRQ entry.
982extern "C"
983{
984#if defined(I2C1)
985 void i2_c1_er_irq_handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
986 void i2_c1_er_irq_handler(void)
987 {
988 auto* p = LibXR::CH32I2C::map_[ch32_i2c_get_id(I2C1)];
989 if (p)
990 {
991 p->ErrorIRQHandler();
992 }
993 }
994#endif
995
996#if defined(I2C2)
997 void i2_c2_er_irq_handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
998 void i2_c2_er_irq_handler(void)
999 {
1000 auto* p = LibXR::CH32I2C::map_[ch32_i2c_get_id(I2C2)];
1001 if (p)
1002 {
1003 p->ErrorIRQHandler();
1004 }
1005 }
1006#endif
1007} // extern "C"
1008
1009// 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:684
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:757
void RxDmaIRQHandler()
DMA 回调入口 / DMA callbacks from CH32 DMA driver.
Definition ch32_i2c.cpp:919
void ErrorIRQHandler()
错误中断回调 / I2C error IRQ callback
Definition ch32_i2c.cpp:959
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:562
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:625
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:30
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
Definition ch32_i2c.cpp:140
static constexpr uint32_t K_DEFAULT_TIMEOUT_US
默认超时(微秒) / Default timeout in microseconds
Definition ch32_i2c.hpp:58
常量原始数据封装类。 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:5
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:178
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:213
OperationType type
Definition libxr_rw.hpp:237
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
Definition timebase.hpp:49
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ BUSY
忙碌 | Busy
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
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