1.1.6.2 Using The Library

The SDMMC driver can be used to communicate with SD/eMMC Cards.

Modes supported:

  • Asynchronous mode : Supported in both Bare-metal and RTOS environment

Usage Methods

  • Application can directly use the SDMMC driver API's to perform Read/Write operations.

  • Application can use File System service layer and perform file operations on the SD/eMMC Card.

  • It can be interfaced with Middleware's like USB.

Example application to Write and Read SD Card in Asynchronous mode

/* Write and Read 60KB of Data */
#define SDMMC_DATA_SIZE              (61440U)
#define SDMMC_BUFFER_SIZE            (SDMMC_DATA_SIZE / sizeof(uint32_t))

#define GEOMETRY_TABLE_READ_ENTRY   (0)
#define GEOMETRY_TABLE_WRITE_ENTRY  (1)
#define GEOMETRY_TABLE_ERASE_ENTRY  (2)

#define BLOCK_START                 0x2000

SYS_MEDIA_GEOMETRY *geometry = NULL;

APP_DATA appData;

/* Read Buffer */
uint32_t CACHE_ALIGN readBuffer[SDMMC_BUFFER_SIZE];

/* Write Buffer*/
uint32_t CACHE_ALIGN writeBuffer[SDMMC_BUFFER_SIZE];

void appTransferHandler
(
    DRV_SDMMC_EVENT event,
    DRV_SDMMC_COMMAND_HANDLE commandHandle,
    uintptr_t context
)
{
    APP_DATA* app_data = (APP_DATA *)context;

    switch(event)
    {
        case DRV_SDMMC_EVENT_COMMAND_COMPLETE:
        {
            app_data->xfer_done = true;
            break;
        }

        case DRV_SDMMC_EVENT_COMMAND_ERROR:
        {
            app_data->state = APP_STATE_ERROR;
            break;
        }

        default:
        {
            break;
        }
    }
}

void APP_Initialize ( void )
{
    uint32_t i = 0;

    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_OPEN_DRIVER;
    appData.xfer_done = false;

    for (i = 0; i < SDMMC_BUFFER_SIZE; i++)
    {
        writeBuffer[i] = i;
    }
}

void APP_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( appData.state )
    {
        case APP_STATE_OPEN_DRIVER:
        {
            appData.sdmmcHandle = DRV_SDMMC_Open(DRV_SDMMC_INDEX_0, DRV_IO_INTENT_READWRITE);

            if (appData.sdmmcHandle != DRV_HANDLE_INVALID)
            {
                DRV_SDMMC_EventHandlerSet(appData.sdmmcHandle, (const void*)appTransferHandler, (uintptr_t)&appData);
                appData.state = APP_STATE_SDCARD_ATTACHED;
            }
            else
            {
                appData.state = APP_STATE_ERROR;
            }
            break;
        }

        case APP_STATE_SDCARD_ATTACHED:
        {
            if (DRV_SDMMC_IsAttached(appData.sdmmcHandle) == true)
            {
                appData.state = APP_STATE_GEOMETRY_GET;
            }
            break;
        }

        case APP_STATE_GEOMETRY_GET:
        {
            geometry = DRV_SDMMC_GeometryGet(appData.sdmmcHandle);

            if (geometry == NULL)
            {
                appData.state = APP_STATE_ERROR;
            }
            else
            {
                appData.numReadBlocks  = (SDMMC_DATA_SIZE / geometry->geometryTable[GEOMETRY_TABLE_READ_ENTRY].blockSize);
                appData.numWriteBlocks = (SDMMC_DATA_SIZE / geometry->geometryTable[GEOMETRY_TABLE_WRITE_ENTRY].blockSize);
                appData.numEraseBlocks = (SDMMC_DATA_SIZE / geometry->geometryTable[GEOMETRY_TABLE_ERASE_ENTRY].blockSize);
                appData.state = APP_STATE_WRITE_MEMORY;
            }
            break;
        }

        case APP_STATE_WRITE_MEMORY:
        {
            DRV_SDMMC_AsyncWrite(appData.sdmmcHandle, &appData.writeHandle, (void *)writeBuffer, BLOCK_START, appData.numWriteBlocks);

            if (appData.writeHandle == DRV_SDMMC_COMMAND_HANDLE_INVALID)
            {
                appData.state = APP_STATE_ERROR;
            }
            else
            {
                appData.state = APP_STATE_READ_MEMORY;
            }
            break;
        }

        case APP_STATE_READ_MEMORY:
        {
            if (appData.xfer_done == true)
            {
                /* Write to the SD Card is complete */
                appData.xfer_done = false;

                memset((void *)readBuffer, 0, SDMMC_DATA_SIZE);

                DRV_SDMMC_AsyncRead(appData.sdmmcHandle, &appData.readHandle, (void *)readBuffer, BLOCK_START, appData.numReadBlocks);

                if (appData.readHandle == DRV_SDMMC_COMMAND_HANDLE_INVALID)
                {
                    appData.state = APP_STATE_ERROR;
                }
                else
                {
                    appData.state = APP_STATE_VERIFY_DATA;
                }
            }
            break;
        }

        case APP_STATE_VERIFY_DATA:
        {
            /* Wait until all the above queued transfer requests are done */
            if(appData.xfer_done == true)
            {
                appData.xfer_done = false;
                if (!memcmp(writeBuffer, readBuffer, SDMMC_DATA_SIZE))
                {
                    appData.state = APP_STATE_SUCCESS;
                }
                else
                {
                    appData.state = APP_STATE_ERROR;
                }
            }
            break;
        }

        case APP_STATE_SUCCESS:
        {
            DRV_SDMMC_Close(appData.sdmmcHandle);
            LED_ON();

            break;
        }

        case APP_STATE_ERROR:
        default:
        {
            DRV_SDMMC_Close(appData.sdmmcHandle);
            break;
        }
    }
}