RISCV_SPI USER GUIDE


1. OVERVIEW

Serial Peripheral Interface (SPI), referred to as SPI, is a high-speed synchronous serial interface technology launched by Motorola. It is mainly used in EEPROM, Flash, real-time clock (RTC), analog-to-digital converter (ADC), digital signal processor (DSP) and other devices.

MSPI, or Master SPI device, is an IP provided by SigmaStar specifically for SPI communication master devices. It can communicate with various external SPI slave devices and meet the needs of most SPI communication protocol devices.


2. KEYWORD DESCRIPTION

  • MISO / SDO: Master input slave output. (data comes from the slave)

  • MOSI / SDI: Master output slave input. (data comes from the master)

  • SCLK / SCK: Serial clock signal, generated by the master and sent to the slave.

  • CS / SS: Slave Select chip select signal, sent by the master to control which slave to communicate with, usually a low-level valid signal.

  • CPOL / CKP: Clock polarity, indicating the high and low levels of the clock in the default state.

  • CPHA / CKE: Clock phase, indicating the specific phase of the clock signal when collecting data.

  • SPI Mode: The configuration of the SPI clock polarity and phase can output 4 SPI modes.

    SPI Mode CPOL CPHA
    0 [00] 0 0
    1 [01] 0 1
    2 [10] 1 0
    3 [11] 1 1

3. Functional Description

  • MSPI (Master SPI) can only be used as a master device, not a slave device.

  • The hardware supports 2 groups of MSPI and Motorola SPI standard timing. The register bank of MSPI and the maximum software chip select supported are as follows:

    MSPI Bus bank addr cs_num
    0 1110H 2
    1 1119H 2
  • Supports full-duplex read and write, half-duplex read and write in FIFO mode, and only supports half-duplex read and write in DMA mode.

  • Supports 4-wire communication (MISO + MOSI + SCLK + CS) and 3-wire communication. (MOSI + SCLK + CS)

  • 8-byte read and write buffer (FIFO mode), byte transmission 1-bit to 16-bit configurable bit width.

  • Source Clock: 12M, 104M, 108M, 144M. The actual SPI communication frequency optional gear is 8 gears of each Source Clock division (the division coefficient is 2, 4, 8, 16, 32, 64, 128, 256), a total of 32 gears, so the SPI communication frequency range is 46875HZ~72MHz. The target frequency can be set by assigning the max_speed_hz variable in the struct mspi_setup structure; and the actual communication frequency will select the gear closest to the target frequency but less than the target frequency. Frequency gear table is as follows.

    NO. SPI Clock Rate
    1 46875
    2 93750
    3 187500
    4 375000
    5 421861
    6 421875
    7 562500
    8 750000
    9 843723
    10 843750
    11 1125000
    12 1500000
    13 1687446
    14 1687500
    15 2250000
    16 3000000
    17 3374892
    18 3375000
    19 4500000
    20 6000000
    21 6749785
    22 6750000
    23 9000000
    24 13499571
    25 13500000
    26 18000000
    27 26999143
    28 27000000
    29 36000000
    30 53998287
    31 54000000
    32 72000000

4. HARDWARE CONNECTION INTRODUCTION

MSPI only supports one master and multiple slaves architecture. As the name implies, there can be only one master device and one or more slave devices on one bus. The slave selection signal line is often called the chip select signal line, also known as CS and SS, and is represented by SS below. When multiple SPI slave devices are connected to the SPI host, the other signal lines SCLK, MOSI and MISO of the device are connected in parallel to the same SPI bus at the same time, that is, no matter how many slave devices there are, they only use these three lines together; and each slave device has an independent SS signal line, which occupies a pin of the host, that is, there are as many chip select signal lines as there are slave devices. There is no device address in the SPI protocol. It uses the SS signal line for addressing. When the host wants to select a slave device, it sets the SS signal line of the slave device to a low level (the default is a low level), and the slave device is selected, that is, the chip select is valid, and then the host starts SPI communication with the selected slave device. Therefore, SPI communication starts with the SS line being set to a low level and ends with the SS line being pulled high.


Figure 4-1: Mspi_connect

5. RISCV USAGE INTRODUCTION

When communicating via MSPI, the following basic steps must be followed:

  • Hardware device connection;

  • Confirm whether CONFIG_MSPI_SUPPORT is enabled;

  • SYSDESC file configures requirement attributes;

  • PADMUX settings;

  • API calls to execute communication.

5.1. DRIVER PATH

sc/driver/sysdriver/mspi/drv/src/drv_mspi.c

sc/driver/sysdriver/mspi/hal/pcupid/src/hal_mspi.c

sc/driver/sysdriver/mspi/hal/pcupid/inc/hal_mspi.h

sc/driver/sysdriver/mspi/hal/pcupid/inc/hal_mspireg.h

sc/driver/sysdriver/mspi/hal/pcupid/inc/hal_mspi_cfg.h

sc/driver/sysdriver/mspi/os/mspi_os.h

sc/driver/sysdriver/mspi/drv/pub/drv_mspi.h

sc/driver/sysdriver/mspi/drv/src/drv_mspi_test.c

5.2. CONFIG Configuration

The config file is located at mak/options_chipname_riscv_isw.mak, enable CONFIG_MSPI_SUPPORT.

CONFIG_MSPI_SUPPORT = TRUE

5.3. SYSDESC Configuration

The chipname.sys file is located at sc/driver/sysdriver/sysdesc/hal/chipname/pub.

<mspi0>
    [reg_u32_u16] 0x2222000 0x200;
    [interrupts_u8] INT_IRQ_MSPI_0;
    [camclk_u16] CAMCLK_mspi0;
    [dma_u8] 1;
    [cs_num_u8] 2;
    [cs_ext_u32] PAD_UNKNOWN;
    [4to3_mode_u8] 0;
    [clk_out_mode_u32] 0;
    [padmux_u16] PINMUX_FOR_UNKNOWN_MODE, PINMUX_FOR_UNKNOWN_MODE;
    [status_u8] 1;

The attributes supported by the SPI master driver are as follows:

Attribute Description Remark
reg_u32_u16 Used to specify the IO address of the SPI register bank No need to modify
interrupts_u8 Used to specify the hardware interrupt number to be used No need to modify
camclk_u16 Used to specify the mspi clock No need to modify
dma_u8 Used to specify whether to enable DMA mode Can be modified as needed
clk_out_mode_u32 Used to specify whether to enable clk-out-mode Can be modified as needed
cs_num_u8 Used to specify the number of cs pads that come with the Engine Used with cs-ext_u32
cs_ext_u32 Used to specify the pad index to be used in addition to the cs that comes with the Engine Can be modified as needed
4to3_mode_u8 Used to specify whether to enable 4Wires as 3Wires Can be modified as needed
padmux_u16 Used to select the padmux of mspi Can be modified as needed
status_u8 Used to specify whether to enable mspi Can be modified as needed

5.3.1 DMA Mode

SigmaStar SPI Master supports two basic communication modes: fifo mode and dma mode. When the SPI Master is in fifo mode, the SPI Master driver writes the data to be sent into the SPI Master's send buffer and reads the received data from the receive buffer. The send buffer and receive buffer are registers in the SPI Master peripheral, and the capacity of the send buffer and receive buffer is 8 bytes each. Since the SPI Master works in fifo mode, the software needs to participate in the operation of the send buffer and receive buffer, so the waveform will be affected by software scheduling, and there will be a certain interval between each transmission.

When the SPI Master is in dma mode, the driver only needs to set the address of the data to be sent and the address where the received data needs to be stored to the SPI Master DMA-related registers, and the SPI Master will automatically send and receive data continuously. This process does not require software participation. Therefore, when the SPI Master works in dma mode, the SPI waveform continuity is better.

When the amount of data sent or received during the communication between the SPI Master and the SPI Device is small, you can consider using fifo mode, which has higher work efficiency. When the SPI Master and SPI Device communicate, the amount of data sent or received is large, such as receiving SPI Sensor data, etc. If fifo mode is used for such large-scale data communication, the system CPU usage will be very high, affecting system efficiency. In the scenario of large-scale data communication, dma mode can be considered.

[Note] Currently, SigmaStar SPI Master dma mode only supports half-duplex working mode, and the sending and receiving of SPI Master share the same dma channel. When the device needs to use full-duplex communication, only fifo mode can be used. The dma_u8 attribute specifies whether to use fifo mode or dma mode in half-duplex mode. When the Device driver needs to use full-duplex communication, the Master driver will automatically switch to fifo mode. When dma mode is turned on, full-duplex can be enabled through the transmission parameters, so if you want to use full-duplex mode, you can also specify the dma_u8 attribute.

5.3.2 cs-num

The maximum value of the hardware preset cs number, cs_num_u8 = n, the software chip select number is the MSPI chip select 0 ~ n-1; if you want to use the MSPI software chip select cs0, cs1, you need to configure cs_num_u8 = 2.

5.3.3 cs-ext

The function of adding additional cs pins implemented by the driver. When the hardware preset cs pins are not enough, you can configure additional cs pins in dtsi as an expansion. The cs_ext_u32 chip select number starts from the value of cs_num_u8. For example, if cs_ext_u32 = 2, the first cs-ext pin is cs2. The method to configure additional cs is to open the cs_ext_u32 property under the dtsi node and configure the pad id to be used as an expansion of cs. At the same time, it is recommended to configure the corresponding pad as GPIO MODE in xxx-padmux.dtsi. The following is to use PAD_I2C0_SCL as an expansion of cs:

<PAD_GPIOE_14           PINMUX_FOR_MSPI0_MODE_1       MDRV_PUSE_SPI0_CK>,
<PAD_GPIOE_16           PINMUX_FOR_MSPI0_MODE_1       MDRV_PUSE_SPI0_DI>,
<PAD_GPIOE_17           PINMUX_FOR_MSPI0_MODE_1       MDRV_PUSE_SPI0_DO>,
<PAD_GPIOE_15           PINMUX_FOR_MSPI0_MODE_1       MDRV_PUSE_SPI0_CZ>,
<PAD_I2C0_SCL           PINMUX_FOR_GPIO_MODE          MDRV_PUSE_SPI0_CZ2>,

5.3.4 clk-out-mode

clk-out-mode is a special mode supported by SigmaStar SPI Master. When SPI Master is in clk_out_mode_u32, MOSI and MISO of SPI Master no longer send or receive data according to the given data, and the Clock signal of SPI Master will continuously output square waves. The application scenario of this function is to use the clock output by SPI Master as the working clock of other devices. The value of clk_out_mode_u32 attribute is used to specify the frequency of the output clock. To configure clk_out_mode_u32, you only need to turn on the clk_out_mode_u32 attribute of that device in chipname.sys and configure the corresponding waveform frequency to be output:

[clk_out_mode_u32] 3750000; //Enable clk-out-mode, output the 3.75M frequency waveform

The selectable output frequency is the same as the normal operating frequency of MSPI, refer to the Frequency Range Table.

5.3.5 4 to 3 Mode

The SPI Master 3-wire mode of some platforms does not support dma mode. If you need 3-wire dma mode communication, you can enable 4 to 3 mode. In terms of hardware, short the MOSI and MISO of the Master and connect them to the SDAT of the Device, as shown below:


Figure 5-1: 4to3 Mode

When the driver is reading data, MOSI will automatically switch to GPIO Input Mode so as not to interfere with the waveform input of MISO, thereby achieving the goal of using the 4-wire mode as the 3-wire mode. If you want to use this function, just turn on the 4to3-mode attribute in the dtsi node, that is:

[4to3_mode_u8] 1; //Enable 4to3-mode

Note: The pins of MSPI in 4to3 mode cannot be used as other modes. MISO in 3-wire mode can be used as other functions, provided that the mode has a higher priority than MSPI, such as gpio.

5.4. PADMUX Setting

CONFIG configuration: CONFIG_PADMUX_SUPPORT=TRUE

If the chipname_xxx.sys file is configured with the attribute <padmux>, then the PADMUX setting is directly configured here:

<padmux>
    [schematic_u32_u32_u32]
              PAD_GPIOE_14   PINMUX_FOR_MSPI0_MODE_1    MDRV_PUSE_SPI0_CZ,
              PAD_GPIOE_16   PINMUX_FOR_MSPI0_MODE_1    MDRV_PUSE_SPI0_CK,
              PAD_GPIOE_17   PINMUX_FOR_MSPI0_MODE_1    MDRV_PUSE_SPI0_DI,
              PAD_GPIOE_15   PINMUX_FOR_MSPI0_MODE_1    MDRV_PUSE_SPI0_DO,
    [status_u8] 1;

Otherwise, enable the PADMUX driver and configure the pin multiplexing function in the chipname-xxx-padmux.c file, which is located in sc/driver/sysdriver/padmux/hal/chipname/src. You only need to add the following content to the corresponding schematic attribute:

pad_info_t schematic[] =
{
    {PAD_GPIOE_14,    PINMUX_FOR_MSPI0_MODE_1,    MDRV_PUSE_SPI0_CZ},
    {PAD_GPIOE_16,    PINMUX_FOR_MSPI0_MODE_1,    MDRV_PUSE_SPI0_CK},
    {PAD_GPIOE_17,    PINMUX_FOR_MSPI0_MODE_1,    MDRV_PUSE_SPI0_DI},
    {PAD_GPIOE_15,    PINMUX_FOR_MSPI0_MODE_1,    MDRV_PUSE_SPI0_DO},
};

The first column is the pin index number, which can be queried in sc/drivers/sysdriver/gpio/hal/chipname/pub/gpio.h;

The second column is the mode definition, which can be queried in sc/drivers/sysdriver/gpio/hal/chipname/pub/padmux.h;

The third column is the index name of the pin and matching mode, which can be queried in sc/drivers/sysdriver/padmux/drv/pub/drv_puse.h.

MSPI0 hardware group padmux list

MSPI Bus Register addr Padmod Pad Pin Name
0 bank 103CH offset 6CH bit[6:4] 1 MSPI0_CZ0 PAD_GPIOE_15
MSPI0_CK PAD_GPIOE_14
MSPI0_DI PAD_GPIOE_16
MSPI0_DO PAD_GPIOE_17
2 MSPI0_CZ0 PAD_GPIOA_12
MSPI0_CK PAD_GPIOA_13
MSPI0_DI PAD_GPIOA_14
MSPI0_DO PAD_GPIOA_15
3 MSPI0_CZ0 PAD_GPIOC_07
MSPI0_CK PAD_GPIOC_06
MSPI0_DI PAD_GPIOC_04
MSPI0_DO PAD_GPIOC_05
4 MSPI0_CZ0 PAD_GPIOE_21
MSPI0_CK PAD_GPIOE_22
MSPI0_DI PAD_GPIOE_23
MSPI0_DO PAD_GPIOE_24
bank 103CH offset 6CH bit[1:0] mspi0 cz1 mode 1 MSPI0_CZ1 PAD_GPIOE_13
mspi0 cz1 mode 2 MSPI0_CZ1 PAD_EMMC_D7

5.5 Sample code

The demo source code is located in sc/driver/sysdriver/mspi/drv/src/drv_mspi_test.c

Usage examples:

static int spi_ut_test(CLI_t * cli, char * p)
{
    u32  i;
    s32  ret;
    u8   argc;
    u32  port;
    u32  cs_select;
    u32  speed;
    char *cmd;
    struct mspi_setup setup = {0};
    struct mspi_tfr transfers[2] = {0};

    argc = CliTokenCount(cli);

    if (argc != 4)
        return eCLI_PARSE_INPUT_ERROR;

    cmd = CliTokenPop(cli);

    if (CliTokenPopNum(cli, &port, 0) != eCLI_PARSE_OK)
    {
        return eCLI_PARSE_INPUT_ERROR;
    }

    if (CliTokenPopNum(cli, &cs_select, 0) != eCLI_PARSE_OK)
    {
        return eCLI_PARSE_INPUT_ERROR;
    }

    if (CliTokenPopNum(cli, &speed, 0) != eCLI_PARSE_OK)
    {
        return eCLI_PARSE_INPUT_ERROR;
    }

    setup.bus_num = (u8)port;
    setup.chip_select = (u8)cs_select;
    setup.max_speed_hz = speed;
    setup.mode &= ~(MSPI_SETUP_CPHA | MSPI_SETUP_CPOL);
    //mspi initial configure
    ret = drv_mspi_setup(&setup);
    if(ret)
    {
        cliPrintf("drv_mspi_setup fail : %d\n", ret);
        return eCLI_PARSE_UNKNOWN;
    }
    //read
    if (strcmp(cmd, "r") == 0)
    {
        wdata[0] = 0x03;
        wdata[1] = 0x00;
        wdata[2] = 0x00;
        wdata[3] = 0x00;
        transfers[0].tx_buf = wdata;
        transfers[0].rx_buf = NULL;
        transfers[0].len = 4;
        transfers[0].bits_per_word = 8;
        transfers[1].tx_buf = NULL;
        transfers[1].rx_buf = rdata;
        transfers[1].len = 256;
        transfers[1].bits_per_word = 8;
        ret = drv_mspi_transfer(&setup, transfers, 2);
        if (ret)
        {
            cliPrintf("drv_mspi_transfer fail : %d\n", ret);
            return eCLI_PARSE_UNKNOWN;
        }
    }
    //write
    else if (strcmp(cmd, "w") == 0)
    {
        wdata[0] = 0x06;
        transfers[0].tx_buf = wdata;
        transfers[0].rx_buf = NULL;
        transfers[0].len = 1;
        transfers[0].bits_per_word = 8;
        ret = drv_mspi_transfer(&setup, transfers, 1);
        if (ret)
        {
            cliPrintf("drv_mspi_transfer fail : %d\n", ret);
            return eCLI_PARSE_UNKNOWN;
        }

        wdata[0] = 0x02;
        wdata[1] = 0x00;
        wdata[2] = 0x00;
        wdata[3] = 0x00;
        for (i = 0; i < 256; i++)
        {
            wdata[i+4] = i;
        }
        transfers[0].tx_buf = wdata;
        transfers[0].rx_buf = NULL;
        transfers[0].len = 260;
        transfers[0].bits_per_word = 8;
        ret = drv_mspi_transfer(&setup, transfers, 1);
        if (ret)
        {
            cliPrintf("drv_mspi_transfer fail : %d\n", ret);
            return eCLI_PARSE_UNKNOWN;
        }
    }
    ...
    return eCLI_PARSE_OK;
}

When .rx_buff is not null and .tx_buff is null in struct mspi_tfr, MSPI Master performs half-duplex read operation; when .rx_buff is null and .tx_buff is not null, half-duplex write operation is performed; when .rx_buff and .tx_buff are not null, full-duplex read and write operation is performed even if dma mode is turned on. The corresponding waveform diagram is as follows:


Figure 5-2: Waveform Diagram

In the figure, MOSI corresponds to the data in .tx_buff, and MISO corresponds to the data in .rx_buff.

6. API Reference

  1. The header file is located at sc/driver/sysdriver/mspi/drv/pub/drv_mspi.h

    struct mspi_setup
    {
        u8  bus_num;                        /* mspi bus number */
        u32 max_speed_hz;                   /* transfer speed */
        u8  chip_select;
        u32 mode;                           /* define below */
    #define SPI_CPHA        0x01            /* clock phase */
    #define SPI_CPOL        0x02            /* clock polarity */
    #define SPI_MODE_0      (0|0)           /* (original MicroWire) */
    #define SPI_MODE_1      (0|SPI_CPHA)
    #define SPI_MODE_2      (SPI_CPOL|0)
    #define SPI_MODE_3      (SPI_CPOL|SPI_CPHA)
    #define SPI_CS_HIGH     0x04            /* chipselect active high? */
    #define SPI_LSB_FIRST   0x08            /* per-word bits-on-wire */
    #define SPI_3WIRE       0x10            /* SI/SO signals shared */
    #define SPI_LOOP        0x20            /* loopback mode */
    #define SPI_NO_CS       0x40            /* 1 dev/bus, no chipselect */
    #define SPI_READY       0x80            /* slave pulls low to pause */
    #define SPI_TX_DUAL     0x100           /* transmit with 2 wires */
    #define SPI_TX_QUAD     0x200           /* transmit with 4 wires */
    #define SPI_RX_DUAL     0x400           /* receive with 2 wires */
    #define SPI_RX_QUAD     0x800           /* receive with 4 wires */
    #define SPI_CS_WORD     0x1000          /* toggle cs after each word */
    #define SPI_TX_OCTAL    0x2000          /* transmit with 8 wires */
    #define SPI_RX_OCTAL    0x4000          /* receive with 8 wires */
    #define SPI_3WIRE_HIZ   0x8000          /* high impedance turnaround */
    };
    
  2. This function module provides the following interfaces:

    API name Function
    drv_mspi_setup Set properties including mode, frequency, chip select, etc.
    drv_mspi_transfer Data transmission.

6.1 drv_mspi_setup

  • Function

    Set properties including mode, frequency, chip select, etc.

  • Syntax

    int drv_mspi_setup(struct mspi_setup *setup)

  • Parameters

    Parameter name Description
    setup struct mspi_setup describes the communication parameter configuration, the parameters include the bus number to be set, cs chip select number, communication frequency, mode, etc.
  • Return value

    Result Description
    Success Return 0
    Failure Return non-zero value

6.2 drv_mspi_transfer

  • Function

    Data Transfer

  • Syntax

    int drv_mspi_transfer(struct mspi_setup *setup, struct mspi_tfr *tfr, u32 length)

  • Parameters

    Parameter name Description
    setup mspi parameter configuration, the parameters include the bus number to be set, cs chip select number, communication frequency, mode, etc.
    tfr struct mspi_tfr is used to describe communication information, including communication data, bit width, etc.
    length The number of mspi_tfr
  • Return value

    Result Description
    Success Return 0
    Failure Return non-zero value

7. FAQ

When communication anomalies occur, you can refer to the following aspects for problem debugging. Several common troubleshooting directions are provided. In addition, it is recommended to capture the waveform during the debugging process for easy analysis.

Troubleshooting
Common Problems
Notes
padmux 1. No waveform, cannot be triggered Check whether the register value has been set. For padmux settings, refer to the PADMUX section or the padmux module description
Is the linux dtsi configuration in conflict with riscv It may cause mspi to fail to take effect under riscv Turn off the linux dtsi configuration
Clock source 1. LA captures data incorrectly; This situation may occur when the clock rate is set too high, such as exceeding 45m. At this time, you can adjust the gpio drive capability
cs_ext The extension pin function cannot be used Please confirm whether it is an old architecture. The old architecture does not support the extension pin function. For details, refer to the cs_ext section