I2C GDMA Mode

This sample code guide is written to help users easily and completely understand I2C sample. This sample demonstrates communication between an I2C master device and a slave device using GDMA. Meanwhile, the master and the slave are interconnected to achieve transmission that master receive data and slave transmit data.

The master device acts as the receiver, using GDMA for receive data; the slave device acts as the sender, using GDMA for transmit data.

In this sample, I2C1 is configured as the master device; I2C0 is configured as the slave device.

Requirements

For hardware requirements, please refer to the Requirements.

Wiring

Connect P0_1 (master SCL) to P1_1 (slave SCL), P0_0 (master SDA) to P1_0 (slave SDA) on the EVB, need to connect 2.2k pull-up resistor.

The hardware connection of I2C sample code is shown in the figure below.

../../../_images/I2C_GDMA_Sample_Code_Hardware_Connection_Diagram.png

I2C Sample Code Hardware Connection Diagram

Configurations

  1. The following macros can be configured to modify pin definitions.

    • #define I2C0_SDA                P1_0

    • #define I2C0_SCL                P1_1

    • #define I2C1_SDA                P0_0

    • #define I2C1_SCL                P0_1

  2. The entry function is as follows, call this function in main() to run this sample code. For more details, please refer to the Initialization.

    i2c_dma_demo();
    

Building and Downloading

For building and downloading, please refer to the Building and Downloading.

Experimental Verification

  1. Press the Reset button on the EVB, master send read command to slave.

  2. When the slave device receives a read request from the master device, the I2C_INT_RD_REQ interrupt is triggered which GDMA is enabled to transfer data in the interrupt handler. The slave device sends data to the master via GDMA. when completing the transmission, it enters the GDMA interrupt and prints log.

    i2c_tx_dma_handler
    
  3. The Master receives the data sent by the slave via GDMA, and when completing the transmission, it enters the GDMA interrupt and prints log.

    i2c_rx_dma_handler
    

Code Overview

This section introduces the code and process description for initialization and corresponding function implementation in the sample.

Source Code Directory

  • For project directory, please refer to Source Code Directory.

  • Source code directory: sdk\src\sample\io_demo\gdma\i2c_dma\MasterRx+SlaveTx\i2c_dma_demo.c.

I2C Master (I2C1) Initialization

I2C master mode initialization flow is shown in the following figure.

../../../_images/I2C_Master_GDMA_Mode_Initialization_Flow_Chart.png

I2C Master Mode Initialization Flow Chart

  1. Call Pad_Config() and Pinmux_Config() to initialize the pin.

    Pad_Config(I2C1_SDA, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
    Pad_Config(I2C1_SCL, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
    
    Pinmux_Config(I2C1_SDA, I2C1_DAT);
    Pinmux_Config(I2C1_SCL, I2C1_CLK);
    
  2. Call RCC_PeriphClockCmd() to enable the I2C clock and function.

  3. Initialize the I2C peripheral:

    1. Define the I2C_InitTypeDef type I2C_InitStructure, and call I2C_StructInit() to pre-fill I2C_InitStructure with default values.

    2. Modify the I2C_InitStructure parameters as needed. The I2C initialization parameter configuration is shown in the table below.

    3. Call I2C_Init() to initialize the I2C peripheral.

    I2C Initialization Parameters

    I2C Hardware Parameters

    Setting in the I2C_InitStructure

    I2C

    Clock

    I2C_InitTypeDef::I2C_ClockSpeed

    400000

    Device Role (I2C Master or I2C Slave)

    I2C_InitTypeDef::I2C_DeviveMode

    I2C_DeviveMode_Master

    Address Mode (7bits/10bits Mode)

    I2C_InitTypeDef::I2C_AddressMode

    I2CAddressMode_TypeDef::I2C_AddressMode_7BIT

    Slave Address

    I2C_InitTypeDef::I2C_SlaveAddress

    0x50

    Auto ACK Enable

    I2C_InitTypeDef::I2C_Ack

    ENABLE

    RX GDMA Enable

    I2C_InitTypeDef::I2C_RxDmaEn

    I2C_Ack_Enable

    RX Waterlevel

    I2C_InitTypeDef::I2C_RxWaterlevel

    3

  4. Call NVIC_Init() to enable NVIC of I2C.

  5. Call I2C_INTConfig() to enable I2C RX FIFO underflow interrupt I2C_INT_RX_UNDER and stop signal detection interrupt I2C_INT_STOP_DET.

  6. Call I2C_Cmd() to enable I2C.

I2C Slave (I2C0) Initialization

I2C slave mode initialization flow is shown in the following figure.

../../../_images/I2C_Slave_GDMA_Mode_Initialization_Flow_Chart.png

I2C Slave Mode Initialization Flow Chart

  1. Call Pad_Config() and Pinmux_Config() to initialize the pin.

    Pad_Config(I2C0_SDA, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
    Pad_Config(I2C0_SCL, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH);
    
    Pinmux_Config(I2C0_SDA, I2C0_DAT);
    Pinmux_Config(I2C0_SCL, I2C0_CLK);
    
  2. Call RCC_PeriphClockCmd() to enable the I2C clock and function.

  3. Initialize the I2C peripheral:

    1. Define the I2C_InitTypeDef type I2C_InitStructure, and call I2C_StructInit() to pre-fill I2C_InitStructure with default values.

    2. Modify the I2C_InitStructure parameters as needed. The I2C initialization parameter configuration is shown in the table below.

    3. Call I2C_Init() to initialize the I2C peripheral.

    I2C Initialization Parameters

    I2C Hardware Parameters

    Setting in the I2C_InitStructure

    I2C

    Clock

    I2C_InitTypeDef::I2C_ClockSpeed

    400000

    Device Role (I2C Master or I2C Slave)

    I2C_InitTypeDef::I2C_DeviveMode

    I2C_DeviveMode_Slave

    Address Mode (7bits/10bits Mode)

    I2C_InitTypeDef::I2C_AddressMode

    I2CAddressMode_TypeDef::I2C_AddressMode_7BIT

    Slave Address

    I2C_InitTypeDef::I2C_SlaveAddress

    0x50

    Auto ACK Enable

    I2C_InitTypeDef::I2C_Ack

    I2C_Ack_Enable

    TX GDMA Enable

    I2C_InitTypeDef::I2C_TxDmaEn

    FunctionalState::ENABLE

    TX Waterlevel

    I2C_InitTypeDef::I2C_TxWaterlevel

    16

  4. Call NVIC_Init() to enable NVIC of I2C.

  5. Call I2C_INTConfig() to enable read request interrupt I2C_INT_RD_REQ and RX full interrupt I2C_INT_RX_FULL.

  6. Call I2C_Cmd() to enable I2C.

GDMA Initialization (I2C Master)

GDMA used by I2C master initialization flow is shown in the following figure.

../../../_images/I2C_Master_GDMA_Initialization_Flow_Chart.png

GDMA Initialization Flow Chart

  1. Call RCC_PeriphClockCmd() to enable the GDMA clock and function.

  2. Call GDMA_channel_request to request an unused GDMA channel.

  3. Initialize the GDMA peripheral:

    1. Define the GDMA_InitTypeDef type GDMA_InitStruct, and call GDMA_StructInit() to pre-fill GDMA_InitStruct with default values.

    2. Modify the GDMA_InitStruct parameters as needed. The GDMA initialization parameter configuration is shown in the table below.

    3. Call GDMA_Init() to initialize the GDMA peripheral.

    GDMA Initialization Parameters

    GDMA Hardware Parameters

    Setting in the GDMA_InitStruct Variables

    GDMA

    Channel Num

    GDMA_InitTypeDef::GDMA_ChannelNum

    I2C_RX_DMA_CHANNEL_NUM

    Transfer Direction

    GDMA_InitTypeDef::GDMA_DIR

    GDMA_DIR_PeripheralToMemory

    Buffer Size

    GDMA_InitTypeDef::GDMA_BufferSize

    TEST_SIZE

    Source Address Increment or Fix

    GDMA_InitTypeDef::GDMA_SourceInc

    DMA_SourceInc_Fix

    Destination Address Increment or Fix

    GDMA_InitTypeDef::GDMA_DestinationInc

    DMA_DestinationInc_Inc

    Source Data Size

    GDMA_InitTypeDef::GDMA_SourceDataSize

    GDMA_DataSize_Byte

    Destination Data Size

    GDMA_InitTypeDef::GDMA_DestinationDataSize

    GDMA_DataSize_Byte

    Source Burst Transaction Length

    GDMA_InitTypeDef::GDMA_SourceMsize

    GDMA_Msize_4

    Destination Burst Transaction Length

    GDMA_InitTypeDef::GDMA_DestinationMsize

    GDMA_Msize_4

    Source Address

    GDMA_InitTypeDef::GDMA_SourceAddr

    (uint32_t) & (I2C1->IC_DATA_CMD)

    Destination Address

    GDMA_InitTypeDef::GDMA_DestinationAddr

    (uint32_t)(readbuf)

    Source Handshake

    GDMA_InitTypeDef::GDMA_SourceHandshake

    GDMA_Handshake_I2C1_RX

  4. Call NVIC_Init() to enable NVIC of GDMA.

  5. Call GDMA_INTConfig() to enable GDMA transfer complete interrupt GDMA_INT_Transfer.

  6. Call GDMA_Cmd() to enable GDMA.

GDMA Initialization (I2C Slave)

GDMA used by I2C slave initialization flow is shown in the following figure.

../../../_images/I2C_Slave_GDMA_Initialization_Flow_Chart.png

GDMA Initialization Flow Chart

  1. Call RCC_PeriphClockCmd() to enable the GDMA clock and function.

  2. Call GDMA_channel_request to request an unused GDMA channel.

  3. Initialize the GDMA peripheral:

    1. Define the GDMA_InitTypeDef type GDMA_InitStruct, and call GDMA_StructInit() to pre-fill GDMA_InitStruct with default values.

    2. Modify the GDMA_InitStruct parameters as needed. The GDMA initialization parameter configuration is shown in the table below.

    3. Call GDMA_Init() to initialize the GDMA peripheral.

    GDMA Initialization Parameters

    GDMA Hardware Parameters

    Setting in the GDMA_InitStruct Variables

    GDMA

    Channel Num

    GDMA_InitTypeDef::GDMA_ChannelNum

    I2C_TX_DMA_CHANNEL_NUM

    Transfer Direction

    GDMA_InitTypeDef::GDMA_DIR

    GDMA_DIR_MemoryToPeripheral

    Buffer Size

    GDMA_InitTypeDef::GDMA_BufferSize

    TEST_SIZE

    Source Address Increment or Fix

    GDMA_InitTypeDef::GDMA_SourceInc

    DMA_SourceInc_Inc

    Destination Address Increment or Fix

    GDMA_InitTypeDef::GDMA_DestinationInc

    DMA_DestinationInc_Fix

    Source Data Size

    GDMA_InitTypeDef::GDMA_SourceDataSize

    GDMA_DataSize_HalfWord

    Destination Data Size

    GDMA_InitTypeDef::GDMA_DestinationDataSize

    GDMA_DataSize_HalfWord

    Source Burst Transaction Length

    GDMA_InitTypeDef::GDMA_SourceMsize

    GDMA_Msize_4

    Destination Burst Transaction Length

    GDMA_InitTypeDef::GDMA_DestinationMsize

    GDMA_Msize_4

    Source Address

    GDMA_InitTypeDef::GDMA_SourceAddr

    (uint32_t)sendbuf

    Destination Address

    GDMA_InitTypeDef::GDMA_DestinationAddr

    (uint32_t)(&(I2C0->IC_DATA_CMD))

    Destination Handshake

    GDMA_InitTypeDef::GDMA_DestHandshake

    GDMA_Handshake_I2C0_TX

  4. Call NVIC_Init() to enable NVIC of GDMA.

  5. Call GDMA_INTConfig() to enable GDMA transfer complete interrupt GDMA_INT_Transfer.

Functional Implementation

I2C Master Send Read Command

  1. Call I2C_SendCmd() to send read command to slave.

  2. Call I2C_GetFlagState() to check I2C_FLAG_TFNF flag status and wait for transmit FIFO is full.

  3. Repeat the above process and send all read command.

I2C Master Interrupt Handle

  1. When the master detects a stop signal, stop signal detection interrupt will be triggered and enters the interrupt handler:

    1. Call I2C_GetINTStatus() to check I2C_INT_STOP_DET interrupt status.

    2. Call I2C_ClearINTPendingBit() to clear I2C_INT_STOP_DET interrupt.

  2. When the processor attempts to read an empty FIFO, I2C RX FIFO underflow interrupt will be triggered and enters the interrupt handler:

    1. Call I2C_GetINTStatus() to check I2C_INT_RX_UNDER interrupt status.

    2. Call I2C_ClearINTPendingBit() to clear I2C_INT_RX_UNDER interrupt.

I2C Slave Interrupt Handle

  1. When the receive buffer reaches or goes above the receive FIFO threshold level (I2C_InitTypeDef::I2C_RxThresholdLevel + 1), RX full interrupt will be triggered and enters the interrupt handler:

    1. Call I2C_GetINTStatus() to check I2C_INT_RX_FULL interrupt status.

    2. Call I2C_INTConfig() to disable RX full interrupt I2C_INT_RX_FULL.

    3. Call I2C_ClearINTPendingBit() to clear I2C_INT_RX_FULL interrupt.

  2. When I2C master is attempting to read data from I2C slave, read request interrupt will be triggered and enters the interrupt handler:

    1. Call I2C_GetINTStatus() to check I2C_INT_RD_REQ interrupt status.

    2. Call GDMA_Cmd() to enable GDMA to send data to master.

    3. Call I2C_ClearINTPendingBit() to clear I2C_INT_RD_REQ interrupt.

    4. Call I2C_INTConfig() to disable read request interrupt I2C_INT_RD_REQ.

GDMA (I2C Master) Interrupt Handle

When GDMA transfer is completed, transfer complete interrupt is triggered:

  1. Call GDMA_INTConfig() to disable GDMA transfer complete interrupt GDMA_INT_Transfer.

  2. Call GDMA_ClearINTPendingBit() to clear GDMA_INT_Transfer interrupt.

  3. Call GDMA_channel_release() to release the GDMA channel used by I2C master.

GDMA (I2C Slave) Interrupt Handle

When GDMA transfer is completed, transfer complete interrupt is triggered:

  1. Call GDMA_INTConfig() to disable GDMA transfer complete interrupt GDMA_INT_Transfer.

  2. Call GDMA_ClearINTPendingBit() to clear GDMA_INT_Transfer interrupt.

  3. Call GDMA_channel_release() to release the GDMA channel used by I2C slave.