Hardware Abstraction Layer (HAL)
SDIO (Secure Digital Input Output)

General Description

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

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_obj;
#define SDIO_CMD_PIN (P12_4)
#define SDIO_CLK_PIN (P12_5)
#define SDIO_DATA0_PIN (P13_0)
#define SDIO_DATA1_PIN (P13_1)
#define SDIO_DATA2_PIN (P13_2)
#define SDIO_DATA3_PIN (P13_3)
#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_obj,
SDIO_CMD_PIN ,
SDIO_CLK_PIN,
SDIO_DATA0_PIN,
SDIO_DATA1_PIN,
SDIO_DATA2_PIN,
SDIO_DATA3_PIN);
rslt = cyhal_sdio_configure(&sdio_obj, &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)
{
{
/* Triggered when card insertion is detected in present state */
/* Insert application code to handle events */
break;
}
{
/* Triggered when command transfer is complete */
/* Insert application code to handle events */
break;
}
{
/* 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()
{
cyhal_sdio_t sdio_obj;
#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;
cyhal_sdio_t sdio_obj;
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_CMD_COMPLETE | 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 CYHAL_SDIO_CMD_COMPLETE and CYHAL_SDIO_XFER_COMPLETE are triggered once
* async transfer is complete. Handle event in the event handler.
*/
/* 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));
}

API Reference

 SDIO HAL Results
 SDIO specific return codes.
 

Data Structures

struct  cyhal_sdio_cfg_t
 SDIO controller initial configuration. More...
 

Macros

#define CYHAL_SDIO_RET_NO_ERRORS   (0x00)
 No error.
 
#define CYHAL_SDIO_RET_NO_SP_ERRORS   (0x01)
 Non-specific error code.
 
#define CYHAL_SDIO_RET_CMD_CRC_ERROR   (0x02)
 There was a CRC error on the Command/Response.
 
#define CYHAL_SDIO_RET_CMD_IDX_ERROR   (0x04)
 The index for the command didn't match.
 
#define CYHAL_SDIO_RET_CMD_EB_ERROR   (0x08)
 There was an end bit error on the command.
 
#define CYHAL_SDIO_RET_DAT_CRC_ERROR   (0x10)
 There was a data CRC Error.
 
#define CYHAL_SDIO_RET_CMD_TIMEOUT   (0x20)
 The command didn't finish before the timeout period was over.
 
#define CYHAL_SDIO_RET_DAT_TIMEOUT   (0x40)
 The data didn't finish before the timeout period was over.
 
#define CYHAL_SDIO_RET_RESP_FLAG_ERROR   (0x80)
 There was an error in the resposne flag for command 53.
 
#define CYHAL_SDIO_CLOCK_ERROR   (0x100)
 Failed to initial clock for SDIO.
 
#define CYHAL_SDIO_BAD_ARGUMENT   (0x200)
 Bad argument passed for SDIO.
 
#define CYHAL_SDIO_SEMA_NOT_INITED   (0x400)
 Semaphore is not initiated.
 
#define CYHAL_SDIO_FUNC_NOT_SUPPORTED   (0x800)
 Function is not supported.
 
#define CYHAL_SDIO_CANCELED   (0x1000)
 Operation canceled.
 
#define CYHAL_SDIO_PM_PENDING_ERROR   (0x2000)
 Transfer cannot be initiated after power mode transition allowed. More...
 

Typedefs

typedef void(* cyhal_sdio_event_callback_t) (void *callback_arg, cyhal_sdio_event_t event)
 Callback for SDIO events.
 

Enumerations

enum  cyhal_sdio_command_t {
  CYHAL_SDIO_CMD_GO_IDLE_STATE = 0,
  CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR = 3,
  CYHAL_SDIO_CMD_IO_SEND_OP_COND = 5,
  CYHAL_SDIO_CMD_SELECT_CARD = 7,
  CYHAL_SDIO_CMD_GO_INACTIVE_STATE = 15,
  CYHAL_SDIO_CMD_IO_RW_DIRECT = 52,
  CYHAL_SDIO_CMD_IO_RW_EXTENDED = 53
}
 Commands that can be issued. More...
 
enum  cyhal_transfer_t {
  CYHAL_READ,
  CYHAL_WRITE
}
 Types of transfer that can be performed. More...
 
enum  cyhal_sdio_event_t {
  CYHAL_SDIO_CMD_COMPLETE = 0x00001,
  CYHAL_SDIO_XFER_COMPLETE = 0x00002,
  CYHAL_SDIO_BGAP_EVENT = 0x00004,
  CYHAL_SDIO_DMA_INTERRUPT = 0x00008,
  CYHAL_SDIO_BUF_WR_READY = 0x00010,
  CYHAL_SDIO_BUF_RD_READY = 0x00020,
  CYHAL_SDIO_CARD_INSERTION = 0x00040,
  CYHAL_SDIO_CARD_REMOVAL = 0x00080,
  CYHAL_SDIO_CARD_INTERRUPT = 0x00100,
  CYHAL_SDIO_INT_A = 0x00200,
  CYHAL_SDIO_INT_B = 0x00400,
  CYHAL_SDIO_INT_C = 0x00800,
  CYHAL_SDIO_RE_TUNE_EVENT = 0x01000,
  CYHAL_SDIO_FX_EVENT = 0x02000,
  CYHAL_SDIO_CQE_EVENT = 0x04000,
  CYHAL_SDIO_ERR_INTERRUPT = 0x08000,
  CYHAL_SDIO_GOING_DOWN = 0x10000,
  CYHAL_SDIO_COMING_UP = 0x20000,
  CYHAL_SDIO_ALL_INTERRUPTS = 0x0E1FF
}
 Types of events that could be asserted by SDIO. More...
 

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. More...
 
void cyhal_sdio_free (cyhal_sdio_t *obj)
 Release the SDIO block. More...
 
cy_rslt_t cyhal_sdio_configure (cyhal_sdio_t *obj, const cyhal_sdio_cfg_t *config)
 Configure the SDIO block with required parameters. More...
 
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. More...
 
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. More...
 
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. More...
 
bool cyhal_sdio_is_busy (const cyhal_sdio_t *obj)
 Checks if the specified SDIO is in use. More...
 
cy_rslt_t cyhal_sdio_abort_async (const cyhal_sdio_t *obj)
 Abort an SDIO transfer. More...
 
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. More...
 
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. More...
 

Data Structure Documentation

◆ cyhal_sdio_cfg_t

struct cyhal_sdio_cfg_t
Data Fields
uint32_t frequencyhal_hz Clock frequency, in hertz.
uint16_t block_size Block size.

Macro Definition Documentation

◆ CYHAL_SDIO_PM_PENDING_ERROR

#define CYHAL_SDIO_PM_PENDING_ERROR   (0x2000)

Transfer cannot be initiated after power mode transition allowed.

Enumeration Type Documentation

◆ cyhal_sdio_command_t

Commands that can be issued.

Enumerator
CYHAL_SDIO_CMD_GO_IDLE_STATE 

Go to idle state.

CYHAL_SDIO_CMD_SEND_RELATIVE_ADDR 

Send a relative address.

CYHAL_SDIO_CMD_IO_SEND_OP_COND 

Send an OP IO.

CYHAL_SDIO_CMD_SELECT_CARD 

Send a card select.

CYHAL_SDIO_CMD_GO_INACTIVE_STATE 

Go to inactive state.

CYHAL_SDIO_CMD_IO_RW_DIRECT 

Perform a direct read/write.

CYHAL_SDIO_CMD_IO_RW_EXTENDED 

Perform an extended read/write.

◆ cyhal_transfer_t

Types of transfer that can be performed.

Enumerator
CYHAL_READ 

Read from the card.

CYHAL_WRITE 

Write to the card.

◆ cyhal_sdio_event_t

Types of events that could be asserted by SDIO.

Enumerator
CYHAL_SDIO_CMD_COMPLETE 

Command Complete.

CYHAL_SDIO_XFER_COMPLETE 

Host read/write transfer is complete.

CYHAL_SDIO_BGAP_EVENT 

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

CYHAL_SDIO_DMA_INTERRUPT 

Host controller detects an SDMA Buffer Boundary during transfer.

CYHAL_SDIO_BUF_WR_READY 

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

CYHAL_SDIO_BUF_RD_READY 

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

CYHAL_SDIO_CARD_INSERTION 

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

CYHAL_SDIO_CARD_REMOVAL 

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

CYHAL_SDIO_CARD_INTERRUPT 

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

CYHAL_SDIO_INT_A 

Reserved: set to 0.

CYHAL_SDIO_INT_B 

Reserved: set to 0.

CYHAL_SDIO_INT_C 

Reserved: set to 0.

CYHAL_SDIO_RE_TUNE_EVENT 

Reserved: set to 0.

CYHAL_SDIO_FX_EVENT 

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

CYHAL_SDIO_CQE_EVENT 

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

CYHAL_SDIO_ERR_INTERRUPT 

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

CYHAL_SDIO_GOING_DOWN 

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

CYHAL_SDIO_COMING_UP 

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

CYHAL_SDIO_ALL_INTERRUPTS 

Is used to enable/disable all interrupts events.

Function Documentation

◆ cyhal_sdio_init()

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.

Parameters
[out]objPointer to an SDIO object. The caller must allocate the memory for this object but the init function will initialize its contents.
[out]clkThe pin connected to the clk signal
[in]cmdThe pin connected to the command signal
[in]data0The pin connected to the data0 signal
[in]data1The pin connected to the data1 signal
[in]data2The pin connected to the data2 signal
[in]data3The pin connected to the data3 signal
Returns
The status of the init request

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

◆ cyhal_sdio_free()

void cyhal_sdio_free ( cyhal_sdio_t obj)

Release the SDIO block.

Parameters
[in,out]objThe SDIO object

◆ cyhal_sdio_configure()

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.

Parameters
[in,out]objThe SDIO object
[in]configThe SDIO configuration to apply
Returns
The status of the configure request.

Returns CY_RSLT_SUCCESS on successful operation.

◆ cyhal_sdio_send_cmd()

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.

Parameters
[in,out]objThe SDIO object
[in]directionThe direction of transfer (read/write)
[in]commandThe command to send to the SDIO device
[in]argumentThe argument to the command
[out]responseThe response from the SDIO device
Returns
The status of the command transfer.

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

◆ cyhal_sdio_bulk_transfer()

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.

Parameters
[in,out]objThe SDIO object
[in]directionThe direction of transfer (read/write)
[in]argumentThe argument to the command
[in]dataThe 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]lengthThe number of bytes to send
[out]responseThe response from the SDIO device
Returns
The status of the bulk transfer operation.

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

◆ cyhal_sdio_transfer_async()

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.

To complete the asynchronous transfer, call cyhal_sdio_is_busy() until it returns false. 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.

Parameters
[in,out]objThe SDIO object
[in]directionThe direction of transfer (read/write)
[in]argumentThe argument to the command
[in]dataThe data to send to the SDIO device
[in]lengthThe number of bytes to send
Returns
The status of the async tranfer operation.

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

◆ cyhal_sdio_is_busy()

bool cyhal_sdio_is_busy ( const cyhal_sdio_t obj)

Checks if the specified SDIO is in use.

Parameters
[in]objThe SDIO peripheral to check
Returns
true if SDIO is in use. false, otherwise.

◆ cyhal_sdio_abort_async()

cy_rslt_t cyhal_sdio_abort_async ( const cyhal_sdio_t obj)

Abort an SDIO transfer.

Parameters
[in]objThe SDIO peripheral to stop
Returns
The status of the abort_async request.

Returns CY_RSLT_SUCCESS on successful operation.

◆ cyhal_sdio_register_callback()

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.

Parameters
[in]objThe SDIO object
[in]callbackThe callback function which will be invoked when the event triggers
[in]callback_argGeneric argument that will be provided to the callback when executed

Refer Snippet2: Configure Interrupt for more implementation.

◆ cyhal_sdio_enable_event()

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.

Parameters
[in]objThe SDIO object
[in]eventThe SDIO event type
[in]intr_priorityThe priority for NVIC interrupt events
[in]enableSet to true to enable events, or false to disable them

Refer Snippet2: Configure Interrupt for more information.