SSDA014 September   2026 MSPM0G5117 , MSPM0G5187

 

  1.   1
  2. Description
  3. Required Peripherals
  4. Compatible Devices
  5. Design Steps
  6. Design Considerations
  7. Software Flowchart
  8. Application Code
  9. Data Flow Examples
  10. Additional Resources
  11. 10Trademarks

Design Considerations

  1. Buffer sizing: USB_FRAME_PACKAGE defaults to 64 bytes, matching the USB Full Speed maximum packet size. Each FIFO queue holds up to 8 tasks (USB_TX_BUF_SIZE / I2C_TX_BUF_SIZE) for 512 bytes per direction. Increase the queue depth to handle burst traffic at the cost of RAM.
    // ===== Queue Configuration =====
    #define USB_TX_BUF_SIZE     8              // Max tasks in USB→I2C queue
    #define I2C_TX_BUF_SIZE    8              // Max tasks in I2C→USB queue
    
    // ===== USB/I2C Parameters =====
    #define USB_FRAME_PACKAGE   64             // USB Full Speed max packet size (bytes)
     Buffer
                            Structure Figure 5-1 Buffer Structure
    // Represents one 64-byte unit of data (one USB frame)
    typedef struct {
        uint8_t buffer[USB_FRAME_PACKAGE];   // Data payload (up to 64 bytes)
        uint16_t length;                     // Actual data length in buffer
    } TxElement_t;
    
    // ===== FIFO Queue Structure =====
    // Circular queue to manage multiple tasks
    typedef struct {
        uint16_t fifoIn;                     // Write pointer (next task to add)
        uint16_t fifoOut;                    // Read pointer (next task to process)
        uint16_t fifoCount;                  // Number of pending tasks in queue
        TxElement_t *fifoPointer;            // Pointer to task array
    } TxFIFO_t;
  2. GPIO data-ready signal: The I2C target device asserts a dedicated GPIO output (active high) when it has data ready for the controller to read. The bridge detects the rising edge via GPIO interrupt and sets the i2ctargetDataReady flag. The main loop polls this flag and calls i2c2usb_pushTask() to initiate the I2C read transaction. The target must hold the GPIO high until the controller completes the read. The GPIO pin uses an internal pull-down resistor so the line idles low when the target has no data.
  3. DMA for I2C TX: DMA channel CH1 runs in Block addr. to Fixed addr mode and loads the I2C TX FIFO directly from the task buffer without CPU involvement. After the DMA loads the last byte into the FIFO, the DMA done interrupt fires. The bridge then enables the I²C STOP condition interrupt dynamically. Only when the STOP interrupt fires—indicating the last bit has been transmitted on the bus—does the bridge release the TX task and clear i2cInProgress.
  4. DMA for I2C RX: DMA channel CH0 runs in Fixed addr. to Block addr. mode and moves received bytes from the I2C RX FIFO directly to the task buffer. When the expected number of bytes has been received, the DMA done interrupt happens. The handler marks the task ready for USB transmission and clears i2ctargetDataReady and i2cInProgress.
  5. Overflow protection: When the USB-to-I2C queue is full, incoming USB data is read into a dummy buffer to prevent stalling the TinyUSB RX buffer. When the I2C-to-USB queue is full, the i2c2usb_pushTask() function returns immediately without initiating a new I²C read. For production designs, add application-level flow control or increase the queue depth.