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

Classes

struct  Resources
 

Public Member Functions

 MSPM0I2C (Resources res, RawData stage_buffer, uint32_t dma_enable_min_size=8, I2C::Configuration config={100000})
 
ErrorCode Read (uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr=false) override
 读取 I2C 设备的数据。 Reads data from an I2C device.
 
ErrorCode Write (uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) 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=MemAddrLength::BYTE_8, bool in_isr=false) 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=MemAddrLength::BYTE_8, bool in_isr=false) override
 向 I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.
 
ErrorCode SetConfig (Configuration config) override
 配置 I2C 设备参数。 Configures the I2C device settings.
 
- Public Member Functions inherited from LibXR::I2C
 I2C ()
 默认构造函数。 Default constructor.
 

Static Public Member Functions

static constexpr uint8_t ResolveIndex (IRQn_Type irqn)
 

Additional Inherited Members

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

Detailed Description

Definition at line 11 of file mspm0_i2c.hpp.

Constructor & Destructor Documentation

◆ MSPM0I2C()

MSPM0I2C::MSPM0I2C ( Resources res,
RawData stage_buffer,
uint32_t dma_enable_min_size = 8,
I2C::Configuration config = {100000} )

Definition at line 122 of file mspm0_i2c.cpp.

124 : I2C(),
125 res_(res),
126 stage_buffer_(stage_buffer),
127 dma_enable_min_size_(dma_enable_min_size)
128{
129 ASSERT(res_.instance != nullptr);
130 ASSERT(res_.clock_freq > 0);
131 ASSERT(res_.index < MAX_I2C_INSTANCES);
132 ASSERT(stage_buffer_.addr_ != nullptr);
133 ASSERT(stage_buffer_.size_ > 0);
134
135 if (config.clock_speed == 0)
136 {
137 config.clock_speed = res_.default_bus_speed_hz;
138 }
139 const ErrorCode SET_CFG_ANS = SetConfig(config);
140 REQUIRE(SET_CFG_ANS == ErrorCode::OK);
141}
I2C()
默认构造函数。 Default constructor.
Definition i2c.hpp:39
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ OK
操作成功 / Operation successful
uint32_t clock_speed
I2C 通信时钟速率(单位:Hz) / The I2C clock speed (in Hz).
Definition i2c.hpp:26

Member Function Documentation

◆ MemRead()

ErrorCode MSPM0I2C::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 )
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 734 of file mspm0_i2c.cpp.

736{
737 if (read_data.size_ > MSPM0_I2C_MAX_TRANSFER_SIZE)
738 {
739 return ErrorCode::ARG_ERR;
740 }
741 if (read_data.size_ == 0)
742 {
743 if (op.type != ReadOperation::OperationType::BLOCK)
744 {
745 op.UpdateStatus(in_isr, ErrorCode::OK);
746 }
747 return ErrorCode::OK;
748 }
749
750 if (!mspm0_i2c_is_valid_addr7(slave_addr))
751 {
752 if (op.type != ReadOperation::OperationType::BLOCK)
753 {
755 }
756 return ErrorCode::ARG_ERR;
757 }
758
759 const uint16_t ADDR7 = slave_addr;
760 const size_t ADDR_SIZE = (mem_addr_size == MemAddrLength::BYTE_8) ? 1 : 2;
761 auto* addr_bytes = static_cast<uint8_t*>(stage_buffer_.addr_);
762 if (stage_buffer_.size_ < ADDR_SIZE)
763 {
764 return ErrorCode::ARG_ERR;
765 }
766
767 if (ADDR_SIZE == 1)
768 {
769 addr_bytes[0] = static_cast<uint8_t>(mem_addr & 0xFF);
770 }
771 else
772 {
773 addr_bytes[0] = static_cast<uint8_t>((mem_addr >> 8) & 0xFF);
774 addr_bytes[1] = static_cast<uint8_t>(mem_addr & 0xFF);
775 }
776
777 auto finalize = [&](ErrorCode code)
778 {
779 if (op.type != ReadOperation::OperationType::BLOCK)
780 {
781 op.UpdateStatus(in_isr, code);
782 }
783 return code;
784 };
785
786 auto try_repeated_start = [&]() -> ErrorCode
787 {
788 ErrorCode ans = WaitControllerIdle();
789 if (ans != ErrorCode::OK)
790 {
791 return ans;
792 }
793
794 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
795
796 const uint16_t ADDR_SENT = DL_I2C_fillControllerTXFIFO(
797 res_.instance, addr_bytes, static_cast<uint16_t>(ADDR_SIZE));
798 if (ADDR_SENT != ADDR_SIZE)
799 {
800 return ErrorCode::FAILED;
801 }
802
803 DL_I2C_startControllerTransferAdvanced(
804 res_.instance, ADDR7, DL_I2C_CONTROLLER_DIRECTION_TX,
805 static_cast<uint16_t>(ADDR_SIZE), DL_I2C_CONTROLLER_START_ENABLE,
806 DL_I2C_CONTROLLER_STOP_DISABLE, DL_I2C_CONTROLLER_ACK_ENABLE);
807
808 uint32_t tx_done_timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
809 while (DL_I2C_getRawInterruptStatus(res_.instance,
810 DL_I2C_INTERRUPT_CONTROLLER_TX_DONE) == 0U)
811 {
812 if (CheckControllerError() != ErrorCode::OK)
813 {
814 return ErrorCode::FAILED;
815 }
816 if (tx_done_timeout-- == 0U)
817 {
818 return ErrorCode::BUSY;
819 }
820 }
821 DL_I2C_clearInterruptStatus(res_.instance, DL_I2C_INTERRUPT_CONTROLLER_TX_DONE);
822
823 if (CheckControllerError() != ErrorCode::OK)
824 {
825 return ErrorCode::FAILED;
826 }
827
828 DL_I2C_startControllerTransferAdvanced(
829 res_.instance, ADDR7, DL_I2C_CONTROLLER_DIRECTION_RX,
830 static_cast<uint16_t>(read_data.size_), DL_I2C_CONTROLLER_START_ENABLE,
831 DL_I2C_CONTROLLER_STOP_ENABLE, DL_I2C_CONTROLLER_ACK_DISABLE);
832
833 size_t received = 0;
834 auto* read_ptr = static_cast<uint8_t*>(read_data.addr_);
835 while (received < read_data.size_)
836 {
837 uint32_t timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
838 while (DL_I2C_isControllerRXFIFOEmpty(res_.instance))
839 {
840 if (CheckControllerError() != ErrorCode::OK)
841 {
842 return ErrorCode::FAILED;
843 }
844 if (timeout-- == 0)
845 {
846 return ErrorCode::BUSY;
847 }
848 }
849
850 while (!DL_I2C_isControllerRXFIFOEmpty(res_.instance) && received < read_data.size_)
851 {
852 read_ptr[received++] = DL_I2C_receiveControllerData(res_.instance);
853 }
854 }
855
856 uint32_t rx_done_timeout = MSPM0_I2C_WAIT_FIFO_TIMEOUT;
857 while (DL_I2C_getRawInterruptStatus(res_.instance,
858 DL_I2C_INTERRUPT_CONTROLLER_RX_DONE) == 0U)
859 {
860 if (CheckControllerError() != ErrorCode::OK)
861 {
862 return ErrorCode::FAILED;
863 }
864 if (rx_done_timeout-- == 0U)
865 {
866 return ErrorCode::BUSY;
867 }
868 }
869 DL_I2C_clearInterruptStatus(res_.instance, DL_I2C_INTERRUPT_CONTROLLER_RX_DONE);
870
871 ans = WaitBusIdle();
872 if (ans != ErrorCode::OK)
873 {
874 return ans;
875 }
876
877 return CheckControllerError();
878 };
879
880 ErrorCode last_error = ErrorCode::FAILED;
881 for (uint32_t attempt = 0; attempt < MSPM0_I2C_MEMREAD_RS_ATTEMPTS; ++attempt)
882 {
883 last_error = try_repeated_start();
884 if (last_error == ErrorCode::OK)
885 {
886 return finalize(ErrorCode::OK);
887 }
888 mspm0_i2c_recover_controller(res_.instance);
889 }
890
891 for (uint32_t attempt = 0; attempt < MSPM0_I2C_MEMREAD_FALLBACK_ATTEMPTS; ++attempt)
892 {
893 last_error = PollingWrite7(ADDR7, addr_bytes, ADDR_SIZE);
894 if (last_error == ErrorCode::OK)
895 {
896 last_error =
897 PollingRead7(ADDR7, static_cast<uint8_t*>(read_data.addr_), read_data.size_);
898 if (last_error == ErrorCode::OK)
899 {
900 return finalize(ErrorCode::OK);
901 }
902 }
903 mspm0_i2c_recover_controller(res_.instance);
904 }
905
906 return finalize(last_error);
907}
void UpdateStatus(bool in_isr, Status &&status)
按通知方式报告完成结果 / Report completion using the selected mode.
OperationType type
当前通知方式 / Current notification mode.
@ BUSY
忙碌 / Busy
@ FAILED
操作失败 / Operation failed
@ ARG_ERR
参数错误 / Argument error

◆ MemWrite()

ErrorCode MSPM0I2C::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 )
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 693 of file mspm0_i2c.cpp.

696{
697 if (!mspm0_i2c_is_valid_addr7(slave_addr))
698 {
699 if (op.type != WriteOperation::OperationType::BLOCK)
700 {
702 }
703 return ErrorCode::ARG_ERR;
704 }
705 const size_t ADDR_SIZE = (mem_addr_size == MemAddrLength::BYTE_8) ? 1 : 2;
706 const size_t TOTAL_SIZE = ADDR_SIZE + write_data.size_;
707 if (TOTAL_SIZE > MSPM0_I2C_MAX_TRANSFER_SIZE)
708 {
709 return ErrorCode::ARG_ERR;
710 }
711 if (TOTAL_SIZE > stage_buffer_.size_)
712 {
713 return ErrorCode::ARG_ERR;
714 }
715
716 auto* tx = static_cast<uint8_t*>(stage_buffer_.addr_);
717 if (ADDR_SIZE == 1)
718 {
719 tx[0] = static_cast<uint8_t>(mem_addr & 0xFF);
720 }
721 else
722 {
723 tx[0] = static_cast<uint8_t>((mem_addr >> 8) & 0xFF);
724 tx[1] = static_cast<uint8_t>(mem_addr & 0xFF);
725 }
726 if (write_data.size_ > 0)
727 {
728 memcpy(tx + ADDR_SIZE, write_data.addr_, write_data.size_);
729 }
730
731 return Write(slave_addr, ConstRawData(tx, TOTAL_SIZE), op, in_isr);
732}
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) override
向 I2C 设备写入数据。 Writes data to an I2C device.

◆ Read()

ErrorCode MSPM0I2C::Read ( uint16_t slave_addr,
RawData read_data,
ReadOperation & op,
bool in_isr = false )
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 614 of file mspm0_i2c.cpp.

616{
617 if (read_data.size_ == 0)
618 {
619 if (op.type != ReadOperation::OperationType::BLOCK)
620 {
621 op.UpdateStatus(in_isr, ErrorCode::OK);
622 }
623 return ErrorCode::OK;
624 }
625
626 if (!mspm0_i2c_is_valid_addr7(slave_addr))
627 {
628 if (op.type != ReadOperation::OperationType::BLOCK)
629 {
631 }
632 return ErrorCode::ARG_ERR;
633 }
634
635 const uint16_t ADDR7 = slave_addr;
637 if (dma_enabled_ && read_data.size_ > dma_enable_min_size_)
638 {
639 ans = DmaRead7(ADDR7, read_data);
640 }
641 else
642 {
643 ans = PollingRead7(ADDR7, static_cast<uint8_t*>(read_data.addr_), read_data.size_);
644 }
645
646 if (op.type != ReadOperation::OperationType::BLOCK)
647 {
648 op.UpdateStatus(in_isr, ans);
649 }
650 return ans;
651}
@ NOT_SUPPORT
不支持 / Not supported

◆ ResolveIndex()

static constexpr uint8_t LibXR::MSPM0I2C::ResolveIndex ( IRQn_Type irqn)
inlinestaticconstexpr

Definition at line 44 of file mspm0_i2c.hpp.

45 {
46 switch (irqn)
47 {
48#if defined(I2C0_BASE)
49 case I2C0_INT_IRQn:
50 return 0;
51#endif
52#if defined(I2C1_BASE)
53 case I2C1_INT_IRQn:
54 return 1;
55#endif
56#if defined(I2C2_BASE)
57 case I2C2_INT_IRQn:
58 return 2;
59#endif
60#if defined(I2C3_BASE)
61 case I2C3_INT_IRQn:
62 return 3;
63#endif
64 default:
65 return INVALID_INSTANCE_INDEX;
66 }
67 }

◆ SetConfig()

ErrorCode MSPM0I2C::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 206 of file mspm0_i2c.cpp.

207{
208 if (res_.instance == nullptr || res_.clock_freq == 0U || config.clock_speed == 0U)
209 {
210 return ErrorCode::ARG_ERR;
211 }
212 if (config.clock_speed > 1000000U)
213 {
215 }
216
217 // SCL = BUSCLK / (10 * (TPR + 1)); round up to avoid exceeding the request.
218 const uint64_t PERIOD_DEN = uint64_t(config.clock_speed) * 10U;
219 const uint64_t period_factor =
220 (uint64_t(res_.clock_freq) + PERIOD_DEN - 1U) / PERIOD_DEN;
221 if (period_factor == 0)
222 {
224 }
225 if (period_factor > 128U)
226 {
228 }
229
230 if ((DL_I2C_getControllerStatus(res_.instance) &
231 (DL_I2C_CONTROLLER_STATUS_BUSY | DL_I2C_CONTROLLER_STATUS_BUSY_BUS)) != 0U)
232 {
233 return ErrorCode::BUSY;
234 }
235
236 const uint8_t TIMER_PERIOD = static_cast<uint8_t>(period_factor - 1U);
237 const DL_I2C_ClockConfig CLOCK_CONFIG = {
238 .clockSel = DL_I2C_CLOCK_BUSCLK,
239 .divideRatio = DL_I2C_CLOCK_DIVIDE_1,
240 };
241
242 uint8_t dma_tx_trigger = 0U;
243 uint8_t dma_rx_trigger = 0U;
244 const bool USE_DMA =
245 I2C_DMA_CONFIGURED &&
246 mspm0_i2c_resolve_dma_triggers(res_.instance, dma_tx_trigger, dma_rx_trigger);
247 dma_enabled_ = USE_DMA;
248
249 DL_I2C_disableController(res_.instance);
250 DL_I2C_setClockConfig(res_.instance, &CLOCK_CONFIG);
251 DL_I2C_resetControllerTransfer(res_.instance);
252 DL_I2C_setTimerPeriod(res_.instance, TIMER_PERIOD);
253 DL_I2C_setControllerTXFIFOThreshold(
254 res_.instance, USE_DMA ? DL_I2C_TX_FIFO_LEVEL_EMPTY : DL_I2C_TX_FIFO_LEVEL_BYTES_1);
255 DL_I2C_setControllerRXFIFOThreshold(res_.instance, DL_I2C_RX_FIFO_LEVEL_BYTES_1);
256 DL_I2C_enableControllerClockStretching(res_.instance);
257 DL_I2C_disableInterrupt(res_.instance, 0xFFFFFFFFU);
258 DL_I2C_clearInterruptStatus(res_.instance, 0xFFFFFFFFU);
259
260 DL_I2C_disableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_1,
261 DL_I2C_DMA_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
262 DL_I2C_disableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_2,
263 DL_I2C_DMA_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
264 if (USE_DMA)
265 {
266 DL_DMA_disableChannel(DMA, I2C_DMA_TX_CHANNEL);
267 DL_DMA_disableChannel(DMA, I2C_DMA_RX_CHANNEL);
268 DL_DMA_clearInterruptStatus(DMA, mspm0_i2c_dma_channel_mask(I2C_DMA_TX_CHANNEL) |
269 mspm0_i2c_dma_channel_mask(I2C_DMA_RX_CHANNEL));
270 }
271
272 if (USE_DMA)
273 {
274 DL_DMA_Config dma_tx_config = MSPM0_I2C_DMA_TX_CONFIG_BASE;
275 DL_DMA_Config dma_rx_config = MSPM0_I2C_DMA_RX_CONFIG_BASE;
276 dma_tx_config.trigger = dma_tx_trigger;
277 dma_rx_config.trigger = dma_rx_trigger;
278
279 DL_I2C_enableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_1,
280 DL_I2C_DMA_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
281 DL_I2C_enableDMAEvent(res_.instance, DL_I2C_EVENT_ROUTE_2,
282 DL_I2C_DMA_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
283 DL_DMA_initChannel(DMA, I2C_DMA_TX_CHANNEL, &dma_tx_config);
284 DL_DMA_initChannel(DMA, I2C_DMA_RX_CHANNEL, &dma_rx_config);
285 }
286
287 DL_I2C_enableController(res_.instance);
288
289 return ErrorCode::OK;
290}

◆ Write()

ErrorCode MSPM0I2C::Write ( uint16_t slave_addr,
ConstRawData write_data,
WriteOperation & op,
bool in_isr = false )
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 653 of file mspm0_i2c.cpp.

655{
656 if (write_data.size_ == 0)
657 {
658 if (op.type != WriteOperation::OperationType::BLOCK)
659 {
660 op.UpdateStatus(in_isr, ErrorCode::OK);
661 }
662 return ErrorCode::OK;
663 }
664
665 if (!mspm0_i2c_is_valid_addr7(slave_addr))
666 {
667 if (op.type != WriteOperation::OperationType::BLOCK)
668 {
670 }
671 return ErrorCode::ARG_ERR;
672 }
673
674 const uint16_t ADDR7 = slave_addr;
676 if (dma_enabled_ && write_data.size_ > dma_enable_min_size_)
677 {
678 ans = DmaWrite7(ADDR7, write_data);
679 }
680 else
681 {
682 ans = PollingWrite7(ADDR7, static_cast<const uint8_t*>(write_data.addr_),
683 write_data.size_);
684 }
685
686 if (op.type != WriteOperation::OperationType::BLOCK)
687 {
688 op.UpdateStatus(in_isr, ans);
689 }
690 return ans;
691}

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