I2S GDMA Operation

This sample code demonstrates I2S master sending and receiving data via GDMA handshake as I2S masster. In this sample, the I2S is configured as the master, and the chip simultaneously sends data to the I2S slave and receives data sent by the I2S slave.

Requirements

For hardware requirements, please refer to the Requirements.

Wiring

Connect P0_0 to the LRCK of the I2S slave, connect P0_1 to the BCLK of the I2S slave, connect P0_2 to the SDI of the I2S slave, and connect P0_3 to the SDO of the I2S slave.

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

../../../_images/I2S_Master_GDMA_Operation_Sample_Code_Hardware_Connection_Diagram.png

I2S Sample Code Hardware Connection Diagram

Configurations

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

    • #define I2S_LRCK_PIN P0_0

    • #define I2S_BCLK_PIN P0_1

    • #define I2S_SDO_PIN P0_2

    • #define I2S_SDI_PIN P0_3

  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.

    i2s_master_dma_operation_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.

  2. The I2S master device continuously transmits data, starting with both the left and right channel data at 0x12340000, and incrementing by 0x100, formatted as 24-bit data.

  3. The I2S master receives data sent by the I2S slave simultaneously.

Code Overview

Source Code Directory

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

  • Source code directory: sdk\src\sample\io_demo\i2s\dma_operation\i2s_master_dma_operation_demo.c.

Initialization

The initialization flow for peripherals can refer to Initialization Flow.

I2S initialization flow is shown in the following figure.

../../../_images/I2S_Master_Init_Flow.png

I2S Master Init Flow Chart

Note

As mentioned in PINMUX and PAD function descriptions, I2S PAD should be configured as software mode and pulled down when I2S is disabled to prevent PAD from floating during low power mode.

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

    static void board_i2s_init(void)
    {
        /* set PAD_SW_MODE & PAD_PULL_DOWN when I2S disable to prevent PAD floating */
        Pad_Config(I2S_BCLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(I2S_LRCK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(I2S_SDO_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(I2S_SDI_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
    
        Pinmux_Config(I2S_BCLK_PIN, I2S_BCLK_PINMUX);
        Pinmux_Config(I2S_LRCK_PIN, I2S_LRCK_PINMUX);
        Pinmux_Config(I2S_SDO_PIN, I2S_SDO_PINMUX);
        Pinmux_Config(I2S_SDI_PIN, I2S_SDI_PINMUX);
    }
    
  2. Initialize the I2S peripheral:

    1. Define the I2S_InitTypeDef type I2S_InitStruct, and call I2S_StructInit() to pre-fill I2S_InitStruct with default values.

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

    3. Call I2S_Init() to initialize the I2S peripheral.

    I2S Initialization Parameters

    I2S Hardware Parameters

    Setting in the I2S_InitStruct

    I2S

    Device Role

    I2S_InitTypeDef::I2S_DeviceMode

    I2S_DeviceMode_Master

    Bit Clock Divider (Mi)

    I2S_InitTypeDef::I2S_BClockMi

    0x271

    Bit Clock Divider (Ni)

    I2S_InitTypeDef::I2S_BClockNi

    0x30

    LR Clock Divider

    I2S_InitTypeDef::I2S_BClockDiv

    0x3F

    Tx Data Width

    I2S_InitTypeDef::I2S_TxDataWidth

    I2S_Data_Width_24Bits

    Rx Data Width

    I2S_InitTypeDef::I2S_RxDataWidth

    I2S_Data_Width_24Bits

    Tx Channel Width

    I2S_InitTypeDef::I2S_TxChannelWidth

    I2S_Channel_Width_32Bits

    Rx Channel Width

    I2S_InitTypeDef::I2S_RxChannelWidth

    I2S_Channel_Width_32Bits

    Tx Channel Type

    I2S_InitTypeDef::I2S_TxChannelType

    I2S_Channel_Mono

    Rx Channel Type

    I2S_InitTypeDef::I2S_RxChannelType

    I2S_Channel_Mono

    Tx Data Format

    I2S_InitTypeDef::I2S_TxDataFormat

    I2S_Mode

    Rx Data Format

    I2S_InitTypeDef::I2S_RxDataFormat

    I2S_Mode

  3. Call RCC_PeriphClockCmd() to enable the GDMA clock and function for I2S TX.

  4. Call GDMA_channel_request to request an unused GDMA channel for I2S TX.

  5. Initialize the GDMA peripheral for I2S TX:

    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

    I2S_TX_DMA_CHANNEL_NUM

    Transfer Direction

    GDMA_InitTypeDef::GDMA_DIR

    GDMA_DIR_MemoryToPeripheral

    Buffer Size

    GDMA_InitTypeDef::GDMA_BufferSize

    I2S_DMA_BUF_LEN

    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_Word

    Destination Data Size

    GDMA_InitTypeDef::GDMA_DestinationDataSize

    GDMA_DataSize_Word

    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)(i2s_send_buff)

    Destination Address

    GDMA_InitTypeDef::GDMA_DestinationAddr

    I2S_TX_ADDR

    Destination Handshake

    GDMA_InitTypeDef::GDMA_DestHandshake

    I2S_TX_DMA_HANDSHAKE

  6. Call NVIC_Init() to enable NVIC of GDMA for I2S TX.

  7. Call RCC_PeriphClockCmd() to enable the GDMA clock and function for I2S RX.

  8. Call GDMA_channel_request to request an unused GDMA channel for I2S RX.

  9. Initialize the GDMA peripheral for I2S RX:

    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

    I2S_RX_DMA_CHANNEL_NUM

    Transfer Direction

    GDMA_InitTypeDef::GDMA_DIR

    GDMA_DIR_PeripheralToMemory

    Buffer Size

    GDMA_InitTypeDef::GDMA_BufferSize

    I2S_DMA_BUF_LEN

    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_Word

    Destination Data Size

    GDMA_InitTypeDef::GDMA_DestinationDataSize

    GDMA_DataSize_Word

    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

    I2S_RX_ADDR

    Destination Address

    GDMA_InitTypeDef::GDMA_DestinationAddr

    (uint32_t)(i2s_recv_buff)

    Source Handshake

    GDMA_InitTypeDef::GDMA_SourceHandshake

    I2S_RX_DMA_HANDSHAKE

  10. Call NVIC_Init() to enable NVIC of GDMA for I2S RX.

  11. Call GDMA_INTConfig() to enable GDMA transfer complete interrupt.

  12. Call GDMA_Cmd() to enable GDMA.

  13. Call I2S_Cmd() to enable I2S.

Functional Implementation

TX GDMA Handshake Operation

  1. Turn on the peripheral clock source of the GDMA.

  2. I2S TX and GDMA initialization: Set GDMA handshake with I2S TX.

  3. Enable the GDMA_INT_Transfer interrupt and enable GDMA.

  4. Invoke I2S_Cmd() to generate LRCK and start retrieving data from TX FIFO.

  5. Initiate GDMA request if TX FIFO water level is lower than TX GDMA burst size.

  6. Trigger GDMA transfer interrupt and wait for GDMA transfer to complete.

  7. Clear GDMA_INT_Transfer interrupt.

The flow chart of I2S TX GDMA handshake operation is shown in the following figure.

../../../_images/I2S_TX_GDMA_Flow.png

I2S TX GDMA Flow

RX GDMA Handshake Operation

  1. Turn on the peripheral clock source of the GDMA.

  2. I2S RX and GDMA initialization: Set GDMA handshake with I2S RX.

  3. Enable the GDMA_INT_Transfer interrupt and enable GDMA.

  4. Invoke I2S_Cmd() to generate LRCK and start sending data to RX FIFO.

  5. Wait for RX FIFO data to exceed RX GDMA burst size and initiate GDMA request.

  6. Trigger GDMA transfer interrupt and wait for GDMA transfer to complete.

  7. Clear GDMA_INT_Transfer interrupt.

The flow chart of I2S RX GDMA handshake operation is shown in the following figure.

../../../_images/I2S_RX_GDMA_Flow.png

I2S RX GDMA Flow

Interrupt Handle

When I2S TX or RX GDMA transfer is completed, transfer complete interrupt is triggered:

  1. Call GDMA_ClearAllTypeINT() to clear all interrupt of GDMA Channelx.

  2. Call GDMA_Cmd() to re-enable GDMA and conitune data transfer.

  3. Alternatively, after the data transfer is complete, call GDMA_Cmd() to disable GDMA, and then call I2S_Cmd() to disable I2S.