SPI Master High Speed

This sample demonstrates how SPI0 sends and receives data in high-speed mode. In this example, SPI is configured as a master and the direction is full-duplex. The SPI clock is set to 40MHz, and it is recommended to use DMA mode and dedicated pins for high speed. The chip writes some data to SPI slave and then chip reads data from SPI slave.

Requirements

For hardware requirements, please refer to the Requirements.

Wiring

Connect P1_2 (master CS) to CS of SPI slave device, connect P1_3 (master SCK) to SCK of SPI slave device, connect P1_4 (master MOSI) to MOSI of SPI slave device, and connect P1_5 (master MISO) to MISO of SPI slave device.

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

../../../_images/SPI_Demo_5_1_Hardware_Connection_Diagram.png

SPI Sample Code Hardware Connection Diagram

Configurations

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

    • #define SPI0_HS_CS P1_2

    • #define SPI0_HS_SCK P1_3

    • #define SPI0_HS_MOSI P1_4

    • #define SPI0_HS_MISO P1_5

  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.

    spi0_hs_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, the data in the array sendbuf is sent to SPI slave device.

  2. When completing the transmission, it enters the GDMA interrupt and prints log.

    spi_tx_dma_handler
    
  3. After the slave device receives the data, the slave device sends data to the chip. The chip stores the received data in array readbuf and prints the received data in Debug Analyzer.

    spi_rx_dma_handler: readbuf[0] 0x%x
    ...
    spi_rx_dma_handler: readbuf[1023] 0x%x
    

Code Overview

Source Code Directory

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

  • Source code directory: sdk\src\sample\io_demo\spi\spi0_hs\spi0_hs_dma_demo.c .

SPI Initialization Flow

The initialization flow for peripherals can refer to Initialization Flow.

SPI initialization flow is shown in the following figure.

../../../_images/SPI_Initialization_Flow_Chart.png

SPI Initialization Flow Chart

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

    static void board_spi_init(void)
    {
       /* SPI0 */
       Pinmux_Config(SPI0_HS_SCK, SPI0_CLK_MASTER);
       Pinmux_Config(SPI0_HS_MOSI, SPI0_MO_MASTER);
       Pinmux_Config(SPI0_HS_MISO, SPI0_MI_MASTER);
       Pinmux_Config(SPI0_HS_CS, SPI0_SS_N_0_MASTER);
    
       Pad_Config(SPI0_HS_SCK, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW);
       Pad_Config(SPI0_HS_MOSI, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
                   PAD_OUT_LOW);
       Pad_Config(SPI0_HS_MISO, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
                   PAD_OUT_LOW);
       Pad_Config(SPI0_HS_CS, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW);
    }
    
  2. Call pm_cpu_freq_set() to set CPU frequency to 120MHz.

  3. Call pll4_enable_cko1 to enable PLL4 clock, and call RCC_SPIClkSourceSwitch() to switch PLL4 as SPI0 clock source.

  4. Call RCC_PeriphClockCmd() to enable the SPI clock and function.

  5. Initialize the SPI peripheral:

    1. Define the SPI_InitTypeDef type SPI_InitStructure, and call SPI_StructInit() to pre-fill SPI_InitStructure with default values.

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

    3. Call SPI_Init() to initialize the SPI peripheral, SPI0_HS is seleted.

    SPI Initialization Parameters

    SPI Hardware Parameters

    Setting in the SPI_InitStructure

    SPI

    Direction

    SPI_InitTypeDef::SPI_Direction

    SPI_Direction_FullDuplex

    Device Role (SPI Master or SPI Slave)

    SPI_InitTypeDef::SPI_Mode

    SPI_Mode_Master

    Data Frame Size

    SPI_InitTypeDef::SPI_DataSize

    SPI_DataSize_8b

    Clock Polarity

    SPI_InitTypeDef::SPI_CPOL

    SPI_CPOL_High

    Clock Phase

    SPI_InitTypeDef::SPI_CPHA

    SPI_CPHA_1Edge

    Clock Div

    SPI_InitTypeDef::SPI_BaudRatePrescaler

    4

    Receive FIFO Threshold Level

    SPI_InitTypeDef::SPI_RxThresholdLevel

    0

    Frame Format

    SPI_InitTypeDef::SPI_FrameFormat

    SPI_Frame_Motorola

    RX Sample Delay

    SPI_InitTypeDef::SPI_RxSampleDly

    1

    TX Water Level

    SPI_InitTypeDef::SPI_RxWaterlevel

    25

    RX Water Level

    SPI_InitTypeDef::SPI_TxWaterlevel

    31

  6. Call SPI_Cmd() to enable SPI, SPI0_HS is seleted.

TX DMA Initialization Flow

The initialization flow for peripherals can refer to Initialization Flow.

SPI TX DMA initialization flow is shown in the following figure.

../../../_images/SPI_TX_DMA_Initialization_Flow_Chart.png

SPI TX DMA Initialization Flow Chart

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

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

    GDMA

    Channel Num

    GDMA_InitTypeDef::GDMA_ChannelNum

    SPI_TX_DMA_CHANNEL_NUM

    Transfer Direction

    GDMA_InitTypeDef::GDMA_DIR

    GDMA_DIR_MemoryToPeripheral

    Buffer Size

    GDMA_InitTypeDef::GDMA_BufferSize

    DMA_BUFFER_SIZE

    Source Address Increment or Decrement

    GDMA_InitTypeDef::GDMA_SourceInc

    DMA_SourceInc_Inc

    Destination Address Increment or Decrement

    GDMA_InitTypeDef::GDMA_DestinationInc

    DMA_DestinationInc_Fix

    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_32

    Destination Burst Transaction Length

    GDMA_InitTypeDef::GDMA_DestinationMsize

    GDMA_Msize_32

    Source Address

    GDMA_InitTypeDef::GDMA_SourceAddr

    sendbuf

    Destination Address

    GDMA_InitTypeDef::GDMA_DestinationAddr

    SPI0_HS->DR

    Destination Handshake

    GDMA_InitTypeDef::GDMA_DestHandshake

    GDMA_Handshake_SPI0_TX

  3. Call RamVectorTableUpdate() to register the TX GDMA interrupt handler.

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

  5. Call NVIC_Init() to enable NVIC of TX GDMA.

RX DMA Initialization Flow

The initialization flow for peripherals can refer to Initialization Flow.

SPI RX DMA initialization flow is shown in the following figure.

../../../_images/SPI_RX_DMA_Initialization_Flow_Chart.png

SPI RX DMA Initialization Flow Chart

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

    GDMA

    Channel Num

    GDMA_InitTypeDef::GDMA_ChannelNum

    SPI_RX_DMA_CHANNEL_NUM

    Transfer Direction

    GDMA_InitTypeDef::GDMA_DIR

    GDMA_DIR_PeripheralToMemory

    Buffer Size

    GDMA_InitTypeDef::GDMA_BufferSize

    DMA_BUFFER_SIZE

    Source Address Increment or Decrement

    GDMA_InitTypeDef::GDMA_SourceInc

    DMA_SourceInc_Fix

    Destination Address Increment or Decrement

    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_32

    Destination Burst Transaction Length

    GDMA_InitTypeDef::GDMA_DestinationMsize

    GDMA_Msize_32

    Source Address

    GDMA_InitTypeDef::GDMA_SourceAddr

    SPI0_HS->DR

    Destination Address

    GDMA_InitTypeDef::GDMA_DestinationAddr

    readbuf

    Source Handshake

    GDMA_InitTypeDef::GDMA_SourceHandshake

    GDMA_Handshake_SPI0_RX

  2. Call RamVectorTableUpdate() to register the RX GDMA interrupt handler.

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

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

Functional Implementation

Master Receive Data by DMA

  1. Call SPI_GDMACmd() to disable and then enable SPI GDMA RX Function.

  2. Call GDMA_Cmd() to enable RX DMA transfers.

  3. When GDMA transfer is completed, transfer complete interrupt is triggered. Then call GDMA_ClearINTPendingBit() to clear GDMA_INT_Transfer interrupt.

Master Send Data by DMA

  1. Call SPI_GDMACmd() to disable and then enable SPI GDMA TX Function.

  2. Call GDMA_Cmd() to enable TX DMA transfers.

  3. When GDMA transfer is completed, transfer complete interrupt is triggered. Then call GDMA_ClearINTPendingBit() to clear GDMA_INT_Transfer interrupt.