SDIO (Secure Digital Input Output)

group group_hal_sdio

High level interface to the Secure Digital Input Output (SDIO).

This driver allows commands to be sent over the SDIO bus; the supported commands can be found in cyhal_sdio_command_t. Bulk data transfer is also supported via cyhal_sdio_bulk_transfer().

The SDIO protocol is an extension of the SD interface for general I/O functions. Refer to the SD Specifications Part 1 SDIO Specifications Version 4.10 for more information on the SDIO protocol and specifications.

Features

  • Supports 4-bit interface

  • Supports Ultra High Speed (UHS-I) mode

  • Supports Default Speed (DS), High Speed (HS), SDR12, SDR25 and SDR50 speed modes

  • Supports SDIO card interrupts in both 1-bit and 4-bit modes

  • Supports Standard capacity (SDSC), High capacity (SDHC) and Extended capacity (SDXC) memory

Quick Start

cyhal_sdio_init initializes the SDIO peripheral and passes a pointer to the SDIO block through the obj object of type cyhal_sdio_t.

Code Snippets

Snippet1: Simple SDIO Initialization example

The following snippet shows how to initialize the SDIO interface with a pre-defined configuration


    cy_rslt_t    rslt;
    cyhal_sdio_t sdio_object;

    #define BLOCK_SIZE     (512)
    #define SDIO_FREQ_HF   (100000000UL)

    cyhal_sdio_cfg_t my_sdio_cfg =
    {
        .block_size      = BLOCK_SIZE,
        .frequencyhal_hz = SDIO_FREQ_HF
    };

    rslt = cyhal_sdio_init(&sdio_object,
                           SDIO_CMD_PIN,
                           SDIO_CLK_PIN,
                           SDIO_DATA0_PIN,
                           SDIO_DATA1_PIN,
                           SDIO_DATA2_PIN,
                           SDIO_DATA3_PIN);

    rslt = cyhal_sdio_configure(&sdio_object, &my_sdio_cfg);

Snippet2: Configure Interrupt

The following snippet shows how to configure an interrupt and handle specific events. Refer cyhal_sdio_event_t for different types of events.


// Event handler callback function
void sdio_event_handler(void* handler_arg, cyhal_sdio_event_t event)
{
    CY_UNUSED_PARAMETER(handler_arg);
    CY_UNUSED_PARAMETER(event);

    switch (event)
    {
        case CYHAL_SDIO_CARD_INSERTION:
        {
            // Triggered when card insertion is detected in present state
            // Insert application code to handle events
            break;
        }

        case CYHAL_SDIO_CMD_COMPLETE:
        {
            // Triggered when command transfer is complete
            // Insert application code to handle events
            break;
        }

        case CYHAL_SDIO_XFER_COMPLETE:
        {
            // Triggered when host read/write transfer is complete
            // Insert application code to handle events
            break;
        }

        default:
        {
            // Anything for other commands
            break;
        }
    }
}


void snippet_cyhal_sdio_interrupt_init()
{
    #define INTERRUPT_PRIORITY (3u)

    // Register the event callback
    cyhal_sdio_register_callback(&sdio_obj, &sdio_event_handler, NULL);

    // Enable events that should trigger the callback
    cyhal_sdio_enable_event(&sdio_obj, CYHAL_SDIO_ALL_INTERRUPTS, INTERRUPT_PRIORITY, true);
}

Snippet3: Sending Commands

The following snippet shows how to send a particular command. Some steps of the card initialization have been provided for reference. Refer cyhal_sdio_command_t for different commands.


    cy_rslt_t    rslt;
    uint32_t     response;
    bool         f8Flag = false; // The CMD8 valid flag.

    #define MY_SDIO_CMD_NO_ARG               (0u)
    #define MY_SDIO_CMD8                     ((cyhal_sdio_command_t)8u)
    #define MY_SDIO_CMD8_VHS_27_36           (0x100UL) // CMD8 voltage supplied 2.7-3.6 V.
    #define MY_SDIO_CMD8_PATTERN_MASK        (0xFFUL)
    #define MY_SDIO_CMD8_CHECK_PATTERN       (0xAAUL)

    // Start the card initialization process

    // Reset Card (CMD0).
    rslt = cyhal_sdio_send_cmd(&sdio_obj, CYHAL_WRITE, CYHAL_SDIO_CMD_GO_IDLE_STATE,
                               MY_SDIO_CMD_NO_ARG, &response);

    // Voltage check (CMD8).
    rslt = cyhal_sdio_send_cmd(&sdio_obj, CYHAL_WRITE, MY_SDIO_CMD8, MY_SDIO_CMD8_VHS_27_36 |
                               MY_SDIO_CMD8_CHECK_PATTERN, &response);

    // Check the pattern.
    if (MY_SDIO_CMD8_CHECK_PATTERN == (response & MY_SDIO_CMD8_PATTERN_MASK))
    {
        // The pattern is valid.
        f8Flag = true;
    }
    else
    {
        // SDIO Card is unusable
    }

    if (f8Flag)
    {
        // Add further initialization commands based on SDIO card
    }

Snippet4: Bulk Data Transfer

The following snippet shows how to start a bulk data transfer.

    #define DATA_LENGTH                      (5u)
    #define MY_SDIO_CMD_NO_ARG               (0u)

    cy_rslt_t rslt;
    uint32_t  data[DATA_LENGTH] = { '1', '2', '3', '4', '5' };
    uint32_t  response;

    // Begin bulk data transfer
    rslt = cyhal_sdio_bulk_transfer(&sdio_obj, CYHAL_WRITE, MY_SDIO_CMD_NO_ARG, data, DATA_LENGTH,
                                    &response);

Snippet5: Async Data Transfer

The following snippet shows how to start an async data transfer.

void sdio_async_interrupt_handler(void* handler_arg, cyhal_sdio_event_t event)
{
    if ((handler_arg != NULL) && (event == CYHAL_SDIO_XFER_COMPLETE))
    {
        // Triggered when host read/write async transfer is complete
        // Insert application code to handle events
    }
}


void snippet_cyhal_sdio_async_transfer()
{
    #define DATA_LENGTH                      (5u)
    #define MY_SDIO_CMD_NO_ARG               (0u)
    #define INTERRUPT_PRIORITY               (3u)

    uint32_t data[DATA_LENGTH] = { '1', '2', '3', '4', '5' };
    uint32_t handler_args      = 0;

    // Register the event callback
    cyhal_sdio_register_callback(&sdio_obj, &sdio_async_interrupt_handler, (void*)&handler_args);

    // Enable events CYHAL_SDIO_CMD_COMPLETE and CYHAL_SDIO_XFER_COMPLETE events.
    // Event CYHAL_SDIO_XFER_COMPLETE is triggered once
    // async transfer is complete. Handle event in the event handler.
    cyhal_sdio_enable_event(&sdio_obj,
                            (cyhal_sdio_event_t)(CYHAL_SDIO_CMD_COMPLETE |
                                                 CYHAL_SDIO_XFER_COMPLETE),
                            INTERRUPT_PRIORITY,
                            true);

    // Begin async data transfer
    cyhal_sdio_transfer_async(&sdio_obj, CYHAL_WRITE, MY_SDIO_CMD_NO_ARG, data, DATA_LENGTH);

    // Wait for transfer to finish
    while (cyhal_sdio_is_busy(&sdio_obj))
    {
        // Halt here until condition is false
    }
}

Typedefs

typedef void (*cyhal_sdio_event_callback_t)(void *callback_arg, cyhal_sdio_event_t event)

Callback for SDIO events.

Enums

enum cyhal_sdio_command_t

cyhal_sdio_command_t: Commands that can be issued.

Values:

enumerator CYHAL_SDIO_CMD_GO_IDLE_STATE

Go to idle state.

enumerator CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR

Send a relative address.

enumerator CYHAL_SDIO_CMD_IO_SEND_OP_COND

Send an OP IO.

enumerator CYHAL_SDIO_CMD_SELECT_CARD

Send a card select.

enumerator CYHAL_SDIO_CMD_GO_INACTIVE_STATE

Go to inactive state.

enumerator CYHAL_SDIO_CMD_IO_RW_DIRECT

Perform a direct read/write.

enumerator CYHAL_SDIO_CMD_IO_RW_EXTENDED

Perform an extended read/write.

enum cyhal_transfer_t

cyhal_transfer_t: Types of transfer that can be performed.

Values:

enumerator CYHAL_READ

Read from the card.

enumerator CYHAL_WRITE

Write to the card.

enum cyhal_sdio_event_t

cyhal_sdio_event_t: Types of events that could be asserted by SDIO.

Values:

enumerator CYHAL_SDIO_CMD_COMPLETE

Command Complete.

enumerator CYHAL_SDIO_XFER_COMPLETE

Host read/write transfer is complete.

enumerator CYHAL_SDIO_BGAP_EVENT

This bit is set when both read/write transaction is stopped.

enumerator CYHAL_SDIO_DMA_INTERRUPT

Host controller detects an SDMA Buffer Boundary during transfer.

enumerator CYHAL_SDIO_BUF_WR_READY

This bit is set if the Buffer Write Enable changes from 0 to 1.

enumerator CYHAL_SDIO_BUF_RD_READY

This bit is set if the Buffer Read Enable changes from 0 to 1.

enumerator CYHAL_SDIO_CARD_INSERTION

This bit is set if the Card Inserted in the Present State.

enumerator CYHAL_SDIO_CARD_REMOVAL

This bit is set if the Card Inserted in the Present State.

enumerator CYHAL_SDIO_CARD_INTERRUPT

The synchronized value of the DAT[1] interrupt input for SD mode.

enumerator CYHAL_SDIO_INT_A

Reserved: set to 0.

enumerator CYHAL_SDIO_INT_B

Reserved: set to 0.

enumerator CYHAL_SDIO_INT_C

Reserved: set to 0.

enumerator CYHAL_SDIO_RE_TUNE_EVENT

Reserved: set to 0.

enumerator CYHAL_SDIO_FX_EVENT

This status is set when R[14] of response register is set to 1.

enumerator CYHAL_SDIO_CQE_EVENT

This status is set if Command Queuing/Crypto event has occurred.

enumerator CYHAL_SDIO_ERR_INTERRUPT

If any of the bits in the Error Interrupt Status register are set.

enumerator CYHAL_SDIO_GOING_DOWN

The interface is going away (eg: powering down for some period of time)

enumerator CYHAL_SDIO_COMING_UP

The interface is back up (eg: came back from a low power state)

enumerator CYHAL_SDIO_ALL_INTERRUPTS

Is used to enable/disable all interrupts events.

Functions

cy_rslt_t cyhal_sdio_init(cyhal_sdio_t *obj, cyhal_gpio_t cmd, cyhal_gpio_t clk, cyhal_gpio_t data0, cyhal_gpio_t data1, cyhal_gpio_t data2, cyhal_gpio_t data3)

Initialize the SDIO peripheral.

Returns

CY_RSLT_SUCCESS on successful operation. Refer Snippet1: Simple SDIO Initialization example for more information.
Return

The status of the init request

Parameters
  • [out] obj: Pointer to an SDIO object. The caller must allocate the memory for this object but the init function will initialize its contents.

  • [out] clk: The pin connected to the clk signal

  • [in] cmd: The pin connected to the command signal

  • [in] data0: The pin connected to the data0 signal

  • [in] data1: The pin connected to the data1 signal

  • [in] data2: The pin connected to the data2 signal

  • [in] data3: The pin connected to the data3 signal

void cyhal_sdio_free(cyhal_sdio_t *obj)

Release the SDIO block.

Parameters
  • [inout] obj: The SDIO object

cy_rslt_t cyhal_sdio_configure(cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)

Configure the SDIO block with required parameters.

Refer cyhal_sdio_cfg_t for more information.

Returns

CY_RSLT_SUCCESS on successful operation.
Return

The status of the configure request.

Parameters
  • [inout] obj: The SDIO object

  • [in] config: The SDIO configuration to apply

cy_rslt_t cyhal_sdio_send_cmd(const cyhal_sdio_t *obj, cyhal_transfer_t direction, cyhal_sdio_command_t command, uint32_t argument, uint32_t *response)

Sends command to the SDIO device.

See cyhal_sdio_command_t for list of available commands.

This will block until the command is completed.

Returns

CY_RSLT_SUCCESS on successful operation. Refer Snippet3: Sending Commands for more information.
Return

The status of the command transfer.

Parameters
  • [inout] obj: The SDIO object

  • [in] direction: The direction of transfer (read/write)

  • [in] command: The command to send to the SDIO device

  • [in] argument: The argument to the command

  • [out] response: The response from the SDIO device

cy_rslt_t cyhal_sdio_bulk_transfer(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument, const uint32_t *data, uint16_t length, uint32_t *response)

Performs a bulk data transfer.

Sends CYHAL_SDIO_CMD_IO_RW_EXTENDED command (CMD=53) which allows writing and reading of a large number of I/O registers with a single command.

This will block until the transfer is completed.

Returns

CY_RSLT_SUCCESS on successful operation. Refer Snippet4: Bulk Data Transfer for more information.
Return

The status of the bulk transfer operation.

Parameters
  • [inout] obj: The SDIO object

  • [in] direction: The direction of transfer (read/write)

  • [in] argument: The argument to the command

  • [in] data: The data to send to the SDIO device. A bulk transfer is done in block size (default: 64 bytes) chunks for better performance. Therefore, the size of the data buffer passed into this function must be at least length bytes and a multiple of the block size. For example, when requesting to read 100 bytes of data with a block size 64 bytes, the data buffer needs to be at least 128 bytes. The first 100 bytes of data in the buffer will be the requested data.

  • [in] length: The number of bytes to send

  • [out] response: The response from the SDIO device

cy_rslt_t cyhal_sdio_transfer_async(cyhal_sdio_t *obj, cyhal_transfer_t direction, uint32_t argument, const uint32_t *data, uint16_t length)

Performs a bulk asynchronous data transfer by issuing the CYHAL_SDIO_CMD_IO_RW_EXTENDED command(CMD=53) to the SDIO block.

After exiting this function the CYHAL_SDIO_CMD_COMPLETE and CYHAL_SDIO_XFER_COMPLETE events are not asserted.

The CYHAL_SDIO_CMD_COMPLETE and CYHAL_SDIO_XFER_COMPLETE events are enabled after the asynchronous transfer is complete and in the condition they were enabled in before the transfer operation started. Handle these events in the interrupt callback.

When the transfer is complete, the CYHAL_SDIO_XFER_COMPLETE event will be raised. See cyhal_sdio_register_callback and cyhal_sdio_enable_event.

Returns

CY_RSLT_SUCCESS on successful operation. Refer Snippet5: Async Data Transfer for more information.
Return

The status of the async tranfer operation.

Parameters
  • [inout] obj: The SDIO object

  • [in] direction: The direction of transfer (read/write)

  • [in] argument: The argument to the command

  • [in] data: The data to send to the SDIO device

  • [in] length: The number of bytes to send

bool cyhal_sdio_is_busy(const cyhal_sdio_t *obj)

Checks if the specified SDIO is in use.

Return

true if SDIO is in use. false, otherwise.

Parameters
  • [in] obj: The SDIO peripheral to check

cy_rslt_t cyhal_sdio_abort_async(const cyhal_sdio_t *obj)

Abort an SDIO transfer.

Returns

CY_RSLT_SUCCESS on successful operation.
Return

The status of the abort_async request.

Parameters
  • [in] obj: The SDIO peripheral to stop

void cyhal_sdio_register_callback(cyhal_sdio_t *obj, cyhal_sdio_event_callback_t callback, void *callback_arg)

Register an SDIO event callback to be invoked when the event is triggered.

This function will be called when one of the events enabled by cyhal_sdio_enable_event occurs.

Refer

Snippet2: Configure Interrupt for more implementation.
Parameters
  • [in] obj: The SDIO object

  • [in] callback: The callback function which will be invoked when the event triggers

  • [in] callback_arg: Generic argument that will be provided to the callback when executed

void cyhal_sdio_enable_event(cyhal_sdio_t *obj, cyhal_sdio_event_t event, uint8_t intr_priority, bool enable)

Enables callbacks to be triggered for specified SDIO events.

Refer cyhal_sdio_event_t for all events.

Refer

Snippet2: Configure Interrupt for more information.
Parameters
  • [in] obj: The SDIO object

  • [in] event: The SDIO event type

  • [in] intr_priority: The priority for NVIC interrupt events

  • [in] enable: Set to true to enable events, or false to disable them

struct cyhal_sdio_cfg_t
#include <cyhal_sdio.h>

SDIO controller initial configuration.

Public Members

uint32_t frequencyhal_hz

Clock frequency, in hertz.

uint16_t block_size

Block size.