SPRADD0 December   2023

 

  1.   1
  2.   2

Description

Figure 1-1 demonstrates how to transfer data or commands from a UART interface to several target I2C peripherals using the MSPM0 as an I2C controller. Incoming UART packets are specifically formatted to facilitate the transition to I2C communication. Figure 1-1 can communicate errors in communication back to the host device. Code for this example is found at UART to I2C Bridge Sub-System Code.

GUID-20231212-SS0I-KL1M-QP09-X8ZQ7GS2TH9B-low.svgFigure 1-1 Sub-System Functional Block Diagram

Requirements

Applying this application requires a UART and I2C peripheral.

Table 1-1 Required Peripherals
Sub-Block FunctionalityPeripheral UseNotes
UART TX/RX InterfaceUARTCalled UART_Bridge_INST in code. Default 9600 baud rate.
I2C ControllerI2CCalled I2C_Bridge_INST in code. Default 100 kHz transmission rate.

Compatible Devices

Compatible devices are listed in Table 1-2 with corresponding EVMs based on the requirements in Table 1-1. Using other MSPM0 devices and corresponding EVMs is possible if the requirements in Table 1-1 are met.

Table 1-2 Compatible Devices
Compatible DevicesEVM
MSPM0LxxxxLP-MSPM0L1306
MSPM0GxxxxLP-MSPM0G3507

Design Steps

  1. Set UART peripheral instance, I2C peripheral instance, and pin out to desired device pins in Sysconfig.
  2. Set UART baud rate in Sysconfig. Default is 9600 baud.
  3. Set I2C clock speed in Sysconfig. Default is 100 kHz.
  4. Define the max-I2C packet size the bridge handles.
  5. Define key UART header values (optional).
  6. Customize error handling (optional).

Design Considerations

  1. Communication speed.
    1. Increasing both interface speeds increases data throughput and decreases chances of data collisions.
    2. Adjusting external pull-up resistors according to I2C specifications is necessary to allow for communication if I2C speeds are increased.
    3. Repeated, large data packets at higher speeds can impact overall system performance. Additional optimization of this code can be necessary to meet increased bridge utilization. Additional optimizations include higher device operating speeds, multiple transfer buffers, header size reduction or state machine simplification.
      Note: Figure 1-1 example was only tested with default speeds of 9600 baud (UART) and 100 kHz (I2C) speeds.
  2. UART header.
    1. The UART packet header and start byte values are customizable for your application. Texas Instruments recommends assigning values that are less likely to occur during the start of typical data transfers.
  3. Error handling.
    1. Correspond the error values to ASCII numerical values if monitoring UART bus with a computer terminal.
    2. Make sure the host UART device can read error values and know the associated meanings so appropriate action can be taken by the host.
    3. Add additional error types by modifying the ErrorFlags structure type and add additional error detection code within the Uart_Bridge().
    4. The current implementation detects limited errors and reports back the corresponding code on the UART interface. The application code then breaks from the current communication state machine. Users can add additional error handling code to change the behavior of the bridge when an error occurs. For example, re-sending an I2C packet after a NACK occurs.
      Note: Figure 1-1 currently flags common errors and assigns them numerical values, as defined in the ErrorFlags structure type.

Software Flowcharts

Figure 1-2, Figure 1-3, and Figure 1-4 show the code flow diagrams for Main UART Bridge functionality, Main() plus UART ISR, and I2C ISR, respectively, for Figure 1-1.

GUID-20231212-SS0I-PV0L-0T96-PD8PN8H2NSKN-low.svgFigure 1-2 Software Flow Diagram for UART_Bridge()
GUID-20231212-SS0I-GSJT-HQ3L-VQL5PPN7KPKB-low.svgFigure 1-3 Software Flow Diagrams for MAIN Loop and UART ISR
GUID-20231212-SS0I-R9N1-PHGF-BSHV1RGRCZ29-low.svgFigure 1-4 Software Flow Diagram for I2C ISR

Required UART Packet

Figure 1-5 shows the required UART packet for proper bridging to the I2C interface. The values shown are the default header values defined within Figure 1-1.

  • Start Byte: The value used by the bridge to indicate a new transaction is starting. UART transmissions are ignored until this value is acknowledged by the bridge.
  • I2C Address: The address of the I2C target the host communicates with.
  • I2C Read or Write Indicator: The value that functions the bridge to read or write from the target I2C device.
  • Message Length N: The length of data transferred in bytes. This value cannot be larger than the defined I2C max packet length.
  • D0, D1...., Dn: The data transferred within the bridge.
GUID-20231212-SS0I-4XDW-PSMK-FSDBSSMMLMNP-low.svgFigure 1-5 UART Bridge Packet Description

Device Configuration

Figure 1-1 application uses the TI System Configuration Tool (SysConfig) graphical interface to generate the configuration code of the device peripherals. Using a graphical interface to configure the device peripherals streamlines the application prototyping process.

Application Code

To change the specific values used by the UART Packet or the max I2C packet size, modify the #defines in the beginning of the document, as demonstrated in the following code block:

/* Define UART Header and Start Byte*/
#define UART_HEADER_LENGTH 0x03
#define UART_START_BYTE 0xF8
#define UART_READ_I2C_BYTE 0xFA
#define UART_WRITE_I2C_BYTE 0xFB
#define ADDRESS_INDEX   0x00
#define RW_INDEX        0x01
#define LENGTH_INDEX    0x02

/*Define max packet sizes*/
#define I2C_MAX_PACKET_SIZE 16
#define UART_MAX_PACKET_SIZE (I2C_MAX_PACKET_SIZE + UART_HEADER_LENGTH)

Several points in the code are comments around error detection. A user can add custom error handling and additional error reporting at these points in the code. For brevity, not all error handling code intersections are included here. In practice, search for comments in the code similar to what is demonstrated in the following code block:

while (DL_I2C_isControllerRXFIFOEmpty(I2C_BRIDGE_INST) != true) {
    if (gI2C_Count < gI2C_Length) {
        gI2C_Data[gI2C_Count++] =
            DL_I2C_receiveControllerData(I2C_BRIDGE_INST);
    } else {
        /* 
        * Ignore and remove from FIFO if the buffer is full
        * Optionally add error flag update
         */
        DL_I2C_receiveControllerData(I2C_BRIDGE_INST);
        gError = ERROR_I2C_OVERUN;
    }
}

Additional Resources