General Serial Peripheral Interface (GSPI) Usage Scenarios#

This section describes practical use cases for the Generic Serial Peripheral Interface (GSPI) on the SiWx917 device.

The GSPI driver supports both interrupt-driven and Direct Memory Access (DMA)-based data transfers for high-performance serial communication.

The example below demonstrates a non-blocking transfer using interrupts.
To enable DMA operation, set the DMA Enable parameter in the Unified Configurator (UC) within Simplicity Studio’s Project Configurator for the GSPI component.
No additional code modifications are required.

Typical Use Case: GSPI Primary (Non-DMA)#

The GSPI Primary configuration is ideal for short or infrequent data transfers where the CPU can actively wait for the transaction to complete.

This setup provides a simple, low-latency mechanism to exchange data with a Secondary device.

Workflow Overview#

  1. Initialize the GSPI driver and configure the hardware instance.

  2. Set the Secondary device number (chip-select line).

  3. Register a callback function to handle transfer completion and error events.

  4. Use transmit and receive APIs to exchange data.

  5. Deinitialize the driver when operations are complete.

Step 1: Include Headers and Define Buffers#

#include "sl_si91x_gspi.h"

uint8_t tx_buffer[256] = {0x01, 0x02, 0x03, /* ... */};
uint8_t rx_buffer[256] = {0};

Step 2: Define Callback and State Variables#

static volatile bool data_received = false;
static volatile bool transfer_error = false;

// Define callback function for interrupt events
static void gspi_irq_callback(uint32_t event)
{
        if (event & SL_GSPI_TRANSFER_COMPLETE) {
                data_received = true;
        }
        if ((event & SL_GSPI_DATA_LOST) || (event & SL_GSPI_MODE_FAULT)) {
                transfer_error = true;
        }
}

Step 3: Initialize the GSPI Primary#

sl_gspi_handle_t gspi_handle;
sl_gspi_control_config_t gspi_primary_config = {0};
gspi_primary_config.data_width = 8;
gspi_primary_config.clock_mode = SL_GSPI_MODE_0;
gspi_primary_config.bit_rate = 10000000;
gspi_primary_config.slave_select_mode = SL_GSPI_MASTER_HW_OUTPUT;
gspi_primary_config.swap_read = false;
gspi_primary_config.swap_write = false;

sl_status_t status = sl_si91x_gspi_init(SL_GSPI_MASTER, &gspi_handle);
if (status != SL_STATUS_OK) {
        // Handle initialization error
}

Step 4: Configure the Secondary Select and GSPI#

sl_si91x_gspi_set_slave_number(GSPI_SLAVE_0);
status = sl_si91x_gspi_set_configuration(gspi_handle, &gspi_primary_config);
if (status != SL_STATUS_OK) {
        // Handle configuration error
}

Step 5: Register the Callback#

status = sl_si91x_gspi_register_event_callback(gspi_handle, gspi_callback);
if (status != SL_STATUS_OK) {
        // Handle callback registration error
}

Step 6: Send Data#

status = sl_si91x_gspi_send_data(gspi_handle, tx_buffer, sizeof(tx_buffer));
if (status != SL_STATUS_OK) {
        // Handle send error
}

Step 7: Receive Data#

status = sl_si91x_gspi_receive_data(gspi_handle, rx_buffer, sizeof(rx_buffer));
if (status != SL_STATUS_OK) {
        // Handle receive error
}

Step 8: Deinitialize GSPI#

sl_si91x_gspi_deinit(gspi_handle);

Non-Blocking Transfers with DMA#

In addition to event-driven transfers, GSPI supports non-blocking DMA transfers. When you enable DMA for the GSPI component in your project configuration, the driver automatically routes data through the MCU’s GPDMA — no application code changes required.

Concept Overview:

  • Application Layer: Calls GSPI APIs (sl_si91x_gspi_transfer_data(), sl_si91x_gspi_send_data(), sl_si91x_gspi_receive_data()).

  • GSPI Driver Layer: Configures and triggers UDMA channels for transmission and reception.

  • UDMA Layer: Manages memory-to-peripheral and peripheral-to-memory transfers.

Application Responsibilities:

  • Enable DMA in the project configuration or API.

  • Register a callback to handle completion and error events.

Typical Event Handling:

  • SL_GSPI_TRANSFER_COMPLETE: Transfer completed successfully.

  • SL_GSPI_DATA_LOST / SL_GSPI_MODE_FAULT: Error conditions that require application handling.

Minimal Callback Template#

static void gspi_event_cb(uint32_t event)
{
    if (event & SL_GSPI_TRANSFER_COMPLETE) {
        // Process received data or queue next DMA transfer
    }
    if ((event & SL_GSPI_DATA_LOST) || (event & SL_GSPI_MODE_FAULT)) {
        // Handle error: cleanup or retry
    }
}

DMA Transfer Flow#

  1. Configure GSPI and register the callback.

  2. Call sl_si91x_gspi_transfer_data() (or send/receive functions).

  3. CPU executes other tasks while UDMA transfers data.

  4. Callback executes on completion or error.

  5. Optionally, queue the next transfer in the callback.

Data Widths Greater Than 8 Bits#

For data widths greater than 8 bits (for example, 9-16), GSPI transfers

Requirements:

  • Use uint16_t arrays for transmit and receive buffers.

  • Ensure the receive buffer matches the transmit buffer size.

Example: 12-bit Frames#

sl_gspi_control_config_t gspi_config = {
    .clock_mode        = SL_GSPI_MODE_0,
    .bit_rate          = 10000000,
    .data_width        = 12,
    .slave_select_mode = SL_GSPI_MASTER_HW_OUTPUT,
    .swap_read         = false,
    .swap_write        = false
};

uint16_t tx16[] = { 0xA55, 0x123, 0x0F0, 0xBAD };
uint16_t rx16[sizeof(tx16)/sizeof(tx16[0])] = {0};

sl_si91x_gspi_transfer_data(gspi_handle,
                           tx16,
                           rx16,
                           sizeof(tx16)); // Size in bytes; API moves size/(data_width<=8?1:2) frames

Examples and References#

You can explore additional usage in the GSPI example project: