libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
mspm0_i2c.cpp
1#include "mspm0_i2c.hpp"
2
3#include <ti/driverlib/dl_dma.h>
4
5#include <cstdint>
6#include <cstring>
7
8using namespace LibXR;
9
10namespace
11{
12
13constexpr uint32_t MSPM0_I2C_WAIT_IDLE_TIMEOUT = 300000;
14constexpr uint32_t MSPM0_I2C_WAIT_BUS_TIMEOUT = 300000;
15constexpr uint32_t MSPM0_I2C_WAIT_FIFO_TIMEOUT = 300000;
16constexpr uint32_t MSPM0_I2C_POLLING_ATTEMPTS = 2;
17constexpr uint32_t MSPM0_I2C_MEMREAD_RS_ATTEMPTS = 2;
18constexpr uint32_t MSPM0_I2C_MEMREAD_FALLBACK_ATTEMPTS = 3;
19
20constexpr uint16_t MSPM0_I2C_MAX_TRANSFER_SIZE = 0x0FFF;
21
22#if !defined(DMA_CH_TX_CHAN_ID) || !defined(DMA_CH_RX_CHAN_ID)
23#error "MSPM0I2C requires SysConfig DMA channels (DMA_CH_TX_CHAN_ID/DMA_CH_RX_CHAN_ID)."
24#endif
25
26constexpr DL_DMA_Config MSPM0_I2C_DMA_TX_CONFIG_BASE = {
27 .trigger = 0U,
28 .triggerType = DL_DMA_TRIGGER_TYPE_EXTERNAL,
29 .transferMode = DL_DMA_SINGLE_TRANSFER_MODE,
30 .extendedMode = DL_DMA_NORMAL_MODE,
31 .srcWidth = DL_DMA_WIDTH_BYTE,
32 .destWidth = DL_DMA_WIDTH_BYTE,
33 .srcIncrement = DL_DMA_ADDR_INCREMENT,
34 .destIncrement = DL_DMA_ADDR_UNCHANGED,
35};
36
37constexpr DL_DMA_Config MSPM0_I2C_DMA_RX_CONFIG_BASE = {
38 .trigger = 0U,
39 .triggerType = DL_DMA_TRIGGER_TYPE_EXTERNAL,
40 .transferMode = DL_DMA_SINGLE_TRANSFER_MODE,
41 .extendedMode = DL_DMA_NORMAL_MODE,
42 .srcWidth = DL_DMA_WIDTH_BYTE,
43 .destWidth = DL_DMA_WIDTH_BYTE,
44 .srcIncrement = DL_DMA_ADDR_UNCHANGED,
45 .destIncrement = DL_DMA_ADDR_INCREMENT,
46};
47
48constexpr uint32_t mspm0_i2c_dma_channel_mask(uint8_t channel_id)
49{
50 return (1UL << channel_id);
51}
52
53bool mspm0_i2c_resolve_dma_triggers(I2C_Regs* instance, uint8_t& tx_trigger,
54 uint8_t& rx_trigger)
55{
56#if defined(I2C0_BASE) && defined(DMA_I2C0_TX_TRIG) && defined(DMA_I2C0_RX_TRIG)
57 if (instance == I2C0)
58 {
59 tx_trigger = DMA_I2C0_TX_TRIG;
60 rx_trigger = DMA_I2C0_RX_TRIG;
61 return true;
62 }
63#endif
64#if defined(I2C1_BASE) && defined(DMA_I2C1_TX_TRIG) && defined(DMA_I2C1_RX_TRIG)
65 if (instance == I2C1)
66 {
67 tx_trigger = DMA_I2C1_TX_TRIG;
68 rx_trigger = DMA_I2C1_RX_TRIG;
69 return true;
70 }
71#endif
72#if defined(I2C2_BASE) && defined(DMA_I2C2_TX_TRIG) && defined(DMA_I2C2_RX_TRIG)
73 if (instance == I2C2)
74 {
75 tx_trigger = DMA_I2C2_TX_TRIG;
76 rx_trigger = DMA_I2C2_RX_TRIG;
77 return true;
78 }
79#endif
80#if defined(I2C3_BASE) && defined(DMA_I2C3_TX_TRIG) && defined(DMA_I2C3_RX_TRIG)
81 if (instance == I2C3)
82 {
83 tx_trigger = DMA_I2C3_TX_TRIG;
84 rx_trigger = DMA_I2C3_RX_TRIG;
85 return true;
86 }
87#endif
88 return false;
89}
90
91constexpr uint16_t mspm0_i2c_to_addr7(uint16_t slave_addr)
92{
93 return static_cast<uint16_t>((slave_addr >> 1) & 0x7F);
94}
95
96void mspm0_i2c_recover_controller(I2C_Regs* instance)
97{
98 DL_I2C_disableInterrupt(instance, 0xFFFFFFFFU);
99 DL_I2C_clearInterruptStatus(instance, 0xFFFFFFFFU);
100 DL_I2C_disableControllerReadOnTXEmpty(instance);
101 DL_I2C_resetControllerTransfer(instance);
102 DL_I2C_enableController(instance);
103}
104
105} // namespace
106
107MSPM0I2C::MSPM0I2C(Resources res, RawData stage_buffer, uint32_t dma_enable_min_size,
108 I2C::Configuration config)
109 : I2C(),
110 res_(res),
111 stage_buffer_(stage_buffer),
112 dma_enable_min_size_(dma_enable_min_size)
113{
114 ASSERT(res_.instance != nullptr);
115 ASSERT(res_.clock_freq > 0);
116 ASSERT(res_.index < MAX_I2C_INSTANCES);
117 ASSERT(stage_buffer_.addr_ != nullptr);
118 ASSERT(stage_buffer_.size_ > 0);
119
120 if (config.clock_speed == 0)
121 {
122 config.clock_speed = res_.default_bus_speed_hz;
123 }
124 const ErrorCode SET_CFG_ANS = SetConfig(config);
125 ASSERT(SET_CFG_ANS == ErrorCode::OK);
126}
127
128ErrorCode MSPM0I2C::CheckControllerError() const
129{
130 const uint32_t STATUS = DL_I2C_getControllerStatus(res_.instance);
131 if ((STATUS & DL_I2C_CONTROLLER_STATUS_ERROR) != 0 ||
132 (STATUS & DL_I2C_CONTROLLER_STATUS_ARBITRATION_LOST) != 0)
133 {
134 return ErrorCode::FAILED;
135 }
136 return ErrorCode::OK;
137}
138
139ErrorCode MSPM0I2C::WaitControllerIdle() const
140{
141 uint32_t timeout = MSPM0_I2C_WAIT_IDLE_TIMEOUT;
142 while (timeout-- > 0)
143 {
144 if ((DL_I2C_getControllerStatus(res_.instance) & DL_I2C_CONTROLLER_STATUS_IDLE) != 0)
145 {
146 return ErrorCode::OK;
147 }
148 if (CheckControllerError() != ErrorCode::OK)
149 {
150 return ErrorCode::FAILED;
151 }
152 }
153 return ErrorCode::BUSY;
154}
155
156ErrorCode MSPM0I2C::WaitTransactionDone() const
157{
158 uint32_t timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
159 while (timeout-- > 0)
160 {
161 if (DL_I2C_getTransactionCount(res_.instance) == 0)
162 {
163 return ErrorCode::OK;
164 }
165 if (CheckControllerError() != ErrorCode::OK)
166 {
167 return ErrorCode::FAILED;
168 }
169 }
170 return ErrorCode::BUSY;
171}
172
173ErrorCode MSPM0I2C::WaitBusIdle() const
174{
175 uint32_t timeout = MSPM0_I2C_WAIT_BUS_TIMEOUT;
176 while (timeout-- > 0)
177 {
178 if ((DL_I2C_getControllerStatus(res_.instance) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) ==
179 0)
180 {
181 return ErrorCode::OK;
182 }
183 if (CheckControllerError() != ErrorCode::OK)
184 {
185 return ErrorCode::FAILED;
186 }
187 }
188 return ErrorCode::BUSY;
189}
190
192{
193 if (config.clock_speed == 0)
194 {
195 return ErrorCode::ARG_ERR;
196 }
197
198 const uint32_t PERIOD_DEN = config.clock_speed * 10U;
199 if (PERIOD_DEN == 0)
200 {
201 return ErrorCode::ARG_ERR;
202 }
203
204 uint32_t period_factor = res_.clock_freq / PERIOD_DEN;
205 if (period_factor == 0)
206 {
208 }
209 if (period_factor > 128U)
210 {
212 }
213
214 const uint8_t TIMER_PERIOD = static_cast<uint8_t>(period_factor - 1U);
215 const DL_I2C_ClockConfig CLOCK_CONFIG = {
216 .clockSel = DL_I2C_CLOCK_BUSCLK,
217 .divideRatio = DL_I2C_CLOCK_DIVIDE_1,
218 };
219
220 uint8_t dma_tx_trigger = 0U;
221 uint8_t dma_rx_trigger = 0U;
222 const bool USE_DMA =
223 mspm0_i2c_resolve_dma_triggers(res_.instance, dma_tx_trigger, dma_rx_trigger);
224 dma_enabled_ = USE_DMA;
225
226 DL_I2C_disableController(res_.instance);
227 DL_I2C_setClockConfig(res_.instance, &CLOCK_CONFIG);
228 DL_I2C_resetControllerTransfer(res_.instance);
229 DL_I2C_setTimerPeriod(res_.instance, TIMER_PERIOD);
230 DL_I2C_setControllerTXFIFOThreshold(
231 res_.instance, USE_DMA ? DL_I2C_TX_FIFO_LEVEL_EMPTY : DL_I2C_TX_FIFO_LEVEL_BYTES_1);
232 DL_I2C_setControllerRXFIFOThreshold(res_.instance, DL_I2C_RX_FIFO_LEVEL_BYTES_1);
233 DL_I2C_enableControllerClockStretching(res_.instance);
234 DL_I2C_disableInterrupt(res_.instance, 0xFFFFFFFFU);
235 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
236
237 DL_I2C_disableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_1,
238 DL_I2C_DMA_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
239 DL_I2C_disableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_2,
240 DL_I2C_DMA_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
241 DL_DMA_disableChannel(DMA, DMA_CH_TX_CHAN_ID);
242 DL_DMA_disableChannel(DMA, DMA_CH_RX_CHAN_ID);
243 DL_DMA_clearInterruptStatus(DMA, mspm0_i2c_dma_channel_mask(DMA_CH_TX_CHAN_ID) |
244 mspm0_i2c_dma_channel_mask(DMA_CH_RX_CHAN_ID));
245
246 if (USE_DMA)
247 {
248 DL_DMA_Config dma_tx_config = MSPM0_I2C_DMA_TX_CONFIG_BASE;
249 DL_DMA_Config dma_rx_config = MSPM0_I2C_DMA_RX_CONFIG_BASE;
250 dma_tx_config.trigger = dma_tx_trigger;
251 dma_rx_config.trigger = dma_rx_trigger;
252
253 DL_I2C_enableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_1,
254 DL_I2C_DMA_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
255 DL_I2C_enableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_2,
256 DL_I2C_DMA_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
257 DL_DMA_initChannel(DMA, DMA_CH_TX_CHAN_ID, &dma_tx_config);
258 DL_DMA_initChannel(DMA, DMA_CH_RX_CHAN_ID, &dma_rx_config);
259 }
260
261 DL_I2C_enableController(res_.instance);
262
263 return ErrorCode::OK;
264}
265
266ErrorCode MSPM0I2C::PollingWrite7(uint16_t addr7, const uint8_t* data, size_t size)
267{
268 if (size == 0)
269 {
270 return ErrorCode::OK;
271 }
272 if (size > MSPM0_I2C_MAX_TRANSFER_SIZE)
273 {
274 return ErrorCode::ARG_ERR;
275 }
276
277 auto attempt_once = [&]() -> ErrorCode
278 {
279 ErrorCode ans = WaitControllerIdle();
280 if (ans != ErrorCode::OK)
281 {
282 return ans;
283 }
284
285 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
286
287 size_t sent =
288 DL_I2C_fillControllerTXFIFO(res_.instance, data, static_cast<uint16_t>(size));
289 DL_I2C_startControllerTransfer(res_.instance, addr7, DL_I2C_CONTROLLER_DIRECTION_TX,
290 static_cast<uint16_t>(size));
291
292 while (sent < size)
293 {
294 uint32_t timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
295 while (DL_I2C_getRawInterruptStatus(
296 res_.instance, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER) == 0U)
297 {
298 if (CheckControllerError() != ErrorCode::OK)
299 {
300 return ErrorCode::FAILED;
301 }
302 if (timeout-- == 0)
303 {
304 return ErrorCode::BUSY;
305 }
306 }
307
308 sent += DL_I2C_fillControllerTXFIFO(res_.instance, data + sent,
309 static_cast<uint16_t>(size - sent));
310 }
311
312 ans = WaitBusIdle();
313 if (ans != ErrorCode::OK)
314 {
315 return ans;
316 }
317
318 return CheckControllerError();
319 };
320
321 ErrorCode last_error = ErrorCode::FAILED;
322 for (uint32_t attempt = 0; attempt < MSPM0_I2C_POLLING_ATTEMPTS; ++attempt)
323 {
324 last_error = attempt_once();
325 if (last_error == ErrorCode::OK)
326 {
327 return ErrorCode::OK;
328 }
329 mspm0_i2c_recover_controller(res_.instance);
330 }
331
332 return last_error;
333}
334
335ErrorCode MSPM0I2C::PollingRead7(uint16_t addr7, uint8_t* data, size_t size)
336{
337 if (size == 0)
338 {
339 return ErrorCode::OK;
340 }
341 if (size > MSPM0_I2C_MAX_TRANSFER_SIZE)
342 {
343 return ErrorCode::ARG_ERR;
344 }
345
346 auto attempt_once = [&]() -> ErrorCode
347 {
348 ErrorCode ans = WaitControllerIdle();
349 if (ans != ErrorCode::OK)
350 {
351 return ans;
352 }
353
354 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
355 DL_I2C_startControllerTransfer(res_.instance, addr7, DL_I2C_CONTROLLER_DIRECTION_RX,
356 static_cast<uint16_t>(size));
357
358 size_t received = 0;
359 while (received < size)
360 {
361 uint32_t timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
362 while (DL_I2C_isControllerRXFIFOEmpty(res_.instance))
363 {
364 if (CheckControllerError() != ErrorCode::OK)
365 {
366 return ErrorCode::FAILED;
367 }
368 if (timeout-- == 0)
369 {
370 return ErrorCode::BUSY;
371 }
372 }
373
374 while (!DL_I2C_isControllerRXFIFOEmpty(res_.instance) && received < size)
375 {
376 data[received++] = DL_I2C_receiveControllerData(res_.instance);
377 }
378 }
379
380 ans = WaitBusIdle();
381 if (ans != ErrorCode::OK)
382 {
383 return ans;
384 }
385
386 return CheckControllerError();
387 };
388
389 ErrorCode last_error = ErrorCode::FAILED;
390 for (uint32_t attempt = 0; attempt < MSPM0_I2C_POLLING_ATTEMPTS; ++attempt)
391 {
392 last_error = attempt_once();
393 if (last_error == ErrorCode::OK)
394 {
395 return ErrorCode::OK;
396 }
397 mspm0_i2c_recover_controller(res_.instance);
398 }
399
400 return last_error;
401}
402
403ErrorCode MSPM0I2C::WaitDmaTransferDone(uint8_t channel_id) const
404{
405 uint32_t timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
406 while (DL_DMA_getTransferSize(DMA, channel_id) != 0U)
407 {
408 if (CheckControllerError() != ErrorCode::OK)
409 {
410 return ErrorCode::FAILED;
411 }
412 if (timeout-- == 0U)
413 {
414 return ErrorCode::BUSY;
415 }
416 }
417 return ErrorCode::OK;
418}
419
420ErrorCode MSPM0I2C::DmaWrite7(uint16_t addr7, ConstRawData write_data)
421{
422 if (write_data.size_ == 0)
423 {
424 return ErrorCode::OK;
425 }
426 if (write_data.size_ > MSPM0_I2C_MAX_TRANSFER_SIZE)
427 {
428 return ErrorCode::ARG_ERR;
429 }
430
431 auto stop_dma = [&]()
432 {
433 const uint32_t DMA_TX_MASK = mspm0_i2c_dma_channel_mask(DMA_CH_TX_CHAN_ID);
434 DL_DMA_disableChannel(DMA, DMA_CH_TX_CHAN_ID);
435 DL_DMA_clearInterruptStatus(DMA, DMA_TX_MASK);
436 };
437
438 auto attempt_once = [&]() -> ErrorCode
439 {
440 ErrorCode ans = WaitControllerIdle();
441 if (ans != ErrorCode::OK)
442 {
443 return ans;
444 }
445
446 DL_I2C_disableInterrupt(res_.instance, 0xFFFFFFFFU);
447 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
448
449 const uint32_t DMA_TX_MASK = mspm0_i2c_dma_channel_mask(DMA_CH_TX_CHAN_ID);
450 DL_DMA_disableChannel(DMA, DMA_CH_TX_CHAN_ID);
451 DL_DMA_clearInterruptStatus(DMA, DMA_TX_MASK);
452 DL_DMA_setSrcAddr(
453 DMA, DMA_CH_TX_CHAN_ID,
454 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(write_data.addr_)));
455 DL_DMA_setDestAddr(DMA, DMA_CH_TX_CHAN_ID,
456 static_cast<uint32_t>(
457 reinterpret_cast<uintptr_t>(&res_.instance->MASTER.MTXDATA)));
458 DL_DMA_setTransferSize(DMA, DMA_CH_TX_CHAN_ID,
459 static_cast<uint16_t>(write_data.size_));
460 DL_DMA_enableChannel(DMA, DMA_CH_TX_CHAN_ID);
461
462 DL_I2C_startControllerTransfer(res_.instance, addr7, DL_I2C_CONTROLLER_DIRECTION_TX,
463 static_cast<uint16_t>(write_data.size_));
464
465 ans = WaitDmaTransferDone(DMA_CH_TX_CHAN_ID);
466 if (ans != ErrorCode::OK)
467 {
468 stop_dma();
469 return ans;
470 }
471
472 ans = WaitTransactionDone();
473 if (ans != ErrorCode::OK)
474 {
475 stop_dma();
476 return ans;
477 }
478
479 ans = WaitBusIdle();
480 if (ans != ErrorCode::OK)
481 {
482 stop_dma();
483 return ans;
484 }
485
486 stop_dma();
487 return CheckControllerError();
488 };
489
490 ErrorCode last_error = ErrorCode::FAILED;
491 for (uint32_t attempt = 0; attempt < MSPM0_I2C_POLLING_ATTEMPTS; ++attempt)
492 {
493 last_error = attempt_once();
494 if (last_error == ErrorCode::OK)
495 {
496 return ErrorCode::OK;
497 }
498 mspm0_i2c_recover_controller(res_.instance);
499 }
500
501 return last_error;
502}
503
504ErrorCode MSPM0I2C::DmaRead7(uint16_t addr7, RawData read_data)
505{
506 if (read_data.size_ == 0)
507 {
508 return ErrorCode::OK;
509 }
510 if (read_data.size_ > MSPM0_I2C_MAX_TRANSFER_SIZE)
511 {
512 return ErrorCode::ARG_ERR;
513 }
514
515 auto stop_dma = [&]()
516 {
517 const uint32_t DMA_RX_MASK = mspm0_i2c_dma_channel_mask(DMA_CH_RX_CHAN_ID);
518 DL_DMA_disableChannel(DMA, DMA_CH_RX_CHAN_ID);
519 DL_DMA_clearInterruptStatus(DMA, DMA_RX_MASK);
520 };
521
522 auto attempt_once = [&]() -> ErrorCode
523 {
524 ErrorCode ans = WaitControllerIdle();
525 if (ans != ErrorCode::OK)
526 {
527 return ans;
528 }
529
530 DL_I2C_disableInterrupt(res_.instance, 0xFFFFFFFFU);
531 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
532
533 const uint32_t DMA_RX_MASK = mspm0_i2c_dma_channel_mask(DMA_CH_RX_CHAN_ID);
534 DL_DMA_disableChannel(DMA, DMA_CH_RX_CHAN_ID);
535 DL_DMA_clearInterruptStatus(DMA, DMA_RX_MASK);
536 DL_DMA_setSrcAddr(DMA, DMA_CH_RX_CHAN_ID,
537 static_cast<uint32_t>(
538 reinterpret_cast<uintptr_t>(&res_.instance->MASTER.MRXDATA)));
539 DL_DMA_setDestAddr(
540 DMA, DMA_CH_RX_CHAN_ID,
541 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(read_data.addr_)));
542 DL_DMA_setTransferSize(DMA, DMA_CH_RX_CHAN_ID,
543 static_cast<uint16_t>(read_data.size_));
544 DL_DMA_enableChannel(DMA, DMA_CH_RX_CHAN_ID);
545
546 DL_I2C_startControllerTransfer(res_.instance, addr7, DL_I2C_CONTROLLER_DIRECTION_RX,
547 static_cast<uint16_t>(read_data.size_));
548
549 ans = WaitDmaTransferDone(DMA_CH_RX_CHAN_ID);
550 if (ans != ErrorCode::OK)
551 {
552 stop_dma();
553 return ans;
554 }
555
556 ans = WaitTransactionDone();
557 if (ans != ErrorCode::OK)
558 {
559 stop_dma();
560 return ans;
561 }
562
563 ans = WaitBusIdle();
564 if (ans != ErrorCode::OK)
565 {
566 stop_dma();
567 return ans;
568 }
569
570 stop_dma();
571 return CheckControllerError();
572 };
573
574 ErrorCode last_error = ErrorCode::FAILED;
575 for (uint32_t attempt = 0; attempt < MSPM0_I2C_POLLING_ATTEMPTS; ++attempt)
576 {
577 last_error = attempt_once();
578 if (last_error == ErrorCode::OK)
579 {
580 return ErrorCode::OK;
581 }
582 mspm0_i2c_recover_controller(res_.instance);
583 }
584
585 return last_error;
586}
587
588ErrorCode MSPM0I2C::Read(uint16_t slave_addr, RawData read_data, ReadOperation& op,
589 bool in_isr)
590{
591 if (read_data.size_ == 0)
592 {
593 if (op.type != ReadOperation::OperationType::BLOCK)
594 {
595 op.UpdateStatus(in_isr, ErrorCode::OK);
596 }
597 return ErrorCode::OK;
598 }
599
600 const uint16_t ADDR7 = mspm0_i2c_to_addr7(slave_addr);
602 if (dma_enabled_ && read_data.size_ > dma_enable_min_size_)
603 {
604 ans = DmaRead7(ADDR7, read_data);
605 }
606 else
607 {
608 ans = PollingRead7(ADDR7, static_cast<uint8_t*>(read_data.addr_), read_data.size_);
609 }
610
611 if (op.type != ReadOperation::OperationType::BLOCK)
612 {
613 op.UpdateStatus(in_isr, ans);
614 }
615 return ans;
616}
617
618ErrorCode MSPM0I2C::Write(uint16_t slave_addr, ConstRawData write_data,
619 WriteOperation& op, bool in_isr)
620{
621 if (write_data.size_ == 0)
622 {
623 if (op.type != WriteOperation::OperationType::BLOCK)
624 {
625 op.UpdateStatus(in_isr, ErrorCode::OK);
626 }
627 return ErrorCode::OK;
628 }
629
630 const uint16_t ADDR7 = mspm0_i2c_to_addr7(slave_addr);
632 if (dma_enabled_ && write_data.size_ > dma_enable_min_size_)
633 {
634 ans = DmaWrite7(ADDR7, write_data);
635 }
636 else
637 {
638 ans = PollingWrite7(ADDR7, static_cast<const uint8_t*>(write_data.addr_),
639 write_data.size_);
640 }
641
642 if (op.type != WriteOperation::OperationType::BLOCK)
643 {
644 op.UpdateStatus(in_isr, ans);
645 }
646 return ans;
647}
648
649ErrorCode MSPM0I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
650 ConstRawData write_data, WriteOperation& op,
651 MemAddrLength mem_addr_size, bool in_isr)
652{
653 const size_t ADDR_SIZE = (mem_addr_size == MemAddrLength::BYTE_8) ? 1 : 2;
654 const size_t TOTAL_SIZE = ADDR_SIZE + write_data.size_;
655 if (TOTAL_SIZE > MSPM0_I2C_MAX_TRANSFER_SIZE)
656 {
657 return ErrorCode::ARG_ERR;
658 }
659 if (TOTAL_SIZE > stage_buffer_.size_)
660 {
661 return ErrorCode::ARG_ERR;
662 }
663
664 auto* tx = static_cast<uint8_t*>(stage_buffer_.addr_);
665 if (ADDR_SIZE == 1)
666 {
667 tx[0] = static_cast<uint8_t>(mem_addr & 0xFF);
668 }
669 else
670 {
671 tx[0] = static_cast<uint8_t>((mem_addr >> 8) & 0xFF);
672 tx[1] = static_cast<uint8_t>(mem_addr & 0xFF);
673 }
674 if (write_data.size_ > 0)
675 {
676 memcpy(tx + ADDR_SIZE, write_data.addr_, write_data.size_);
677 }
678
679 return Write(slave_addr, ConstRawData(tx, TOTAL_SIZE), op, in_isr);
680}
681
682ErrorCode MSPM0I2C::MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
683 ReadOperation& op, MemAddrLength mem_addr_size, bool in_isr)
684{
685 if (read_data.size_ > MSPM0_I2C_MAX_TRANSFER_SIZE)
686 {
687 return ErrorCode::ARG_ERR;
688 }
689 if (read_data.size_ == 0)
690 {
691 if (op.type != ReadOperation::OperationType::BLOCK)
692 {
693 op.UpdateStatus(in_isr, ErrorCode::OK);
694 }
695 return ErrorCode::OK;
696 }
697
698 const uint16_t ADDR7 = mspm0_i2c_to_addr7(slave_addr);
699 const size_t ADDR_SIZE = (mem_addr_size == MemAddrLength::BYTE_8) ? 1 : 2;
700 auto* addr_bytes = static_cast<uint8_t*>(stage_buffer_.addr_);
701 if (stage_buffer_.size_ < ADDR_SIZE)
702 {
703 return ErrorCode::ARG_ERR;
704 }
705
706 if (ADDR_SIZE == 1)
707 {
708 addr_bytes[0] = static_cast<uint8_t>(mem_addr & 0xFF);
709 }
710 else
711 {
712 addr_bytes[0] = static_cast<uint8_t>((mem_addr >> 8) & 0xFF);
713 addr_bytes[1] = static_cast<uint8_t>(mem_addr & 0xFF);
714 }
715
716 auto finalize = [&](ErrorCode code)
717 {
718 if (op.type != ReadOperation::OperationType::BLOCK)
719 {
720 op.UpdateStatus(in_isr, code);
721 }
722 return code;
723 };
724
725 auto try_repeated_start = [&]() -> ErrorCode
726 {
727 ErrorCode ans = WaitControllerIdle();
728 if (ans != ErrorCode::OK)
729 {
730 return ans;
731 }
732
733 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
734
735 const uint16_t ADDR_SENT = DL_I2C_fillControllerTXFIFO(
736 res_.instance, addr_bytes, static_cast<uint16_t>(ADDR_SIZE));
737 if (ADDR_SENT != ADDR_SIZE)
738 {
739 return ErrorCode::FAILED;
740 }
741
742 DL_I2C_startControllerTransferAdvanced(
743 res_.instance, ADDR7, DL_I2C_CONTROLLER_DIRECTION_TX,
744 static_cast<uint16_t>(ADDR_SIZE), DL_I2C_CONTROLLER_START_ENABLE,
745 DL_I2C_CONTROLLER_STOP_DISABLE, DL_I2C_CONTROLLER_ACK_ENABLE);
746
747 uint32_t tx_done_timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
748 while (DL_I2C_getRawInterruptStatus(res_.instance,
749 DL_I2C_INTERRUPT_CONTROLLER_TX_DONE) == 0U)
750 {
751 if (CheckControllerError() != ErrorCode::OK)
752 {
753 return ErrorCode::FAILED;
754 }
755 if (tx_done_timeout-- == 0U)
756 {
757 return ErrorCode::BUSY;
758 }
759 }
760 DL_I2C_clearInterruptStatus(res_.instance, DL_I2C_INTERRUPT_CONTROLLER_TX_DONE);
761
762 if (CheckControllerError() != ErrorCode::OK)
763 {
764 return ErrorCode::FAILED;
765 }
766
767 DL_I2C_startControllerTransferAdvanced(
768 res_.instance, ADDR7, DL_I2C_CONTROLLER_DIRECTION_RX,
769 static_cast<uint16_t>(read_data.size_), DL_I2C_CONTROLLER_START_ENABLE,
770 DL_I2C_CONTROLLER_STOP_ENABLE, DL_I2C_CONTROLLER_ACK_DISABLE);
771
772 size_t received = 0;
773 auto* read_ptr = static_cast<uint8_t*>(read_data.addr_);
774 while (received < read_data.size_)
775 {
776 uint32_t timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
777 while (DL_I2C_isControllerRXFIFOEmpty(res_.instance))
778 {
779 if (CheckControllerError() != ErrorCode::OK)
780 {
781 return ErrorCode::FAILED;
782 }
783 if (timeout-- == 0)
784 {
785 return ErrorCode::BUSY;
786 }
787 }
788
789 while (!DL_I2C_isControllerRXFIFOEmpty(res_.instance) && received < read_data.size_)
790 {
791 read_ptr[received++] = DL_I2C_receiveControllerData(res_.instance);
792 }
793 }
794
795 uint32_t rx_done_timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
796 while (DL_I2C_getRawInterruptStatus(res_.instance,
797 DL_I2C_INTERRUPT_CONTROLLER_RX_DONE) == 0U)
798 {
799 if (CheckControllerError() != ErrorCode::OK)
800 {
801 return ErrorCode::FAILED;
802 }
803 if (rx_done_timeout-- == 0U)
804 {
805 return ErrorCode::BUSY;
806 }
807 }
808 DL_I2C_clearInterruptStatus(res_.instance, DL_I2C_INTERRUPT_CONTROLLER_RX_DONE);
809
810 ans = WaitBusIdle();
811 if (ans != ErrorCode::OK)
812 {
813 return ans;
814 }
815
816 return CheckControllerError();
817 };
818
819 ErrorCode last_error = ErrorCode::FAILED;
820 for (uint32_t attempt = 0; attempt < MSPM0_I2C_MEMREAD_RS_ATTEMPTS; ++attempt)
821 {
822 last_error = try_repeated_start();
823 if (last_error == ErrorCode::OK)
824 {
825 return finalize(ErrorCode::OK);
826 }
827 mspm0_i2c_recover_controller(res_.instance);
828 }
829
830 for (uint32_t attempt = 0; attempt < MSPM0_I2C_MEMREAD_FALLBACK_ATTEMPTS; ++attempt)
831 {
832 last_error = PollingWrite7(ADDR7, addr_bytes, ADDR_SIZE);
833 if (last_error == ErrorCode::OK)
834 {
835 last_error =
836 PollingRead7(ADDR7, static_cast<uint8_t*>(read_data.addr_), read_data.size_);
837 if (last_error == ErrorCode::OK)
838 {
839 return finalize(ErrorCode::OK);
840 }
841 }
842 mspm0_i2c_recover_controller(res_.instance);
843 }
844
845 return finalize(last_error);
846}
常量原始数据封装类。 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
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr=false) override
读取 I2C 设备的数据。 Reads data from an I2C device.
ErrorCode MemWrite(uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data, WriteOperation &op, MemAddrLength mem_addr_size=MemAddrLength::BYTE_8, bool in_isr=false) override
向 I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.
ErrorCode MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data, ReadOperation &op, MemAddrLength mem_addr_size=MemAddrLength::BYTE_8, bool in_isr=false) override
从 I2C 设备指定寄存器读取数据。 Reads data from a specific register of an I2C device.
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) override
向 I2C 设备写入数据。 Writes data to an I2C device.
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:178
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.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ BUSY
忙碌 | Busy
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
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