FSDev_SD_Card_BSP_CmdDataRd()

void  FSDev_SD_Card_BSP_CmdDataRd (FS_QTY               unit_nbr,
                                   FS_DEV_SD_CARD_CMD  *p_cmd,
                                   void                *p_dest,
                                   FS_DEV_SD_CARD_ERR  *p_err);

File

Called from

Code enabled by

fs_dev_sd_card_bsp.c

FSDev_SD_Card_RdData()

N/A

Read data following a command.

Arguments

unit_nbr

Unit number of SD/MMC card.

p_cmd

Pointer to command that was started.

p_dest

Pointer to destination buffer.

p_err

Pointer to variable that will receive the return error code from this function:

FS_DEV_SD_CARD_ERR_NONE

No error.

FS_DEV_SD_CARD_ERR_NO_CARD

No card present.

FS_DEV_SD_CARD_ERR_UNKNOWN

Unknown or other error.

FS_DEV_SD_CARD_ERR_WAIT_TIMEOUT

Timeout in waiting for data.

FS_DEV_SD_CARD_ERR_DATA_OVERRUN

Data overrun.

FS_DEV_SD_CARD_ERR_DATA_TIMEOUT

Timeout in receiving data.

FS_DEV_SD_CARD_ERR_DATA_CHKSUM

Error in data checksum.

FS_DEV_SD_CARD_ERR_DATA_START_BIT

Data start bit error.

FS_DEV_SD_CARD_ERR_DATA

Other data error.

Returned Value

None.

Notes/Warnings

None.

Example

The implementation of FSDev_SD_Card_BSP_CmdDataRd() in the listing below is targeted for the same host controller as the other listings in this chapter; for more information, see FSDev_SD_Card_BSP_CmdStart().

FSDev_SD_Card_BSP_CmdDataRd
void  FSDev_SD_Card_BSP_CmdDataRd (FS_QTY               unit_nbr,
                                   FS_DEV_SD_CARD_CMD  *p_cmd,
                                   void                *p_dest,
                                   FS_DEV_SD_CARD_ERR  *p_err)
{
    CPU_INT16U  interrupt_status;
    CPU_INT16U  error_status;
    CPU_INT16U  timeout;
    timeout          = 0u;                        /* Wait until data xfer compl. */  (1)
    interrupt_status = REG_INTERRUPT_STATUS;
    while (DEF_BIT_IS_CLR(interrupt_status,BIT_INTERRUPT_STATUS_ERROR | 
                                           BIT_INTERRUPT_STATUS_TRANSFER_COMPLETE) == DEF_YES)) {
        timeout++;
        interrupt_status = REG_INTERRUPT_STATUS;
        if (timeout == TIMEOUT_TRANSFER_MAX) {
           *p_err = FS_DEV_SD_CARD_ERR_WAIT_TIMEOUT;
            return;
        }
    }
                                                  /* Handle error.              */  (2)
    if (DEF_BIT_IS_SET(interrupt_status, BIT_INTERRUPT_STATUS_ERROR) == DEF_YES) {
        error_status = REG_ERROR_STATUS;
        if (DEF_BIT_IS_SET(error_status, REG_ERROR_STATUS_DATA_END_BIT) == DEF_YES) {
           *p_err = FS_DEV_SD_CARD_ERR_DATA;
        } else if (DEF_BIT_IS_SET(error_status, REG_ERROR_STATUS_DATA_CRC) == DEF_YES) {
           *p_err = FS_DEV_SD_CARD_ERR_DATA_CRC;
        } else if (DEF_BIT_IS_SET(error_status, REG_ERROR_STATUS_DATA_TIMEOUT) == DEF_YES) {
           *p_err = FS_DEV_SD_CARD_ERR_DATA_TIMEOUT;
        } else {
           *p_err = FS_DEV_SD_CARD_ERR_UNKONWN;
        }
        REG_ERROR_STATUS     = error_status;
        REG_INTERRUPT_STATUS = interrupt_status;
        return;
    }
   
   *p_err = FS_DEV_SD_CARD_ERR_NONE;                                                  (3)
}

(1) Wait until data transfer completes or an error occurs. The wait loop (or wait on semaphore) should always have a timeout to avoid blocking the task in the case of an unforeseen hardware malfunction or a software flaw.

(2) Check if an error occurred. The error status register is decoded to produce the actual error condition. That is not necessary, strictly, but error counters that accumulate within the generic driver based upon returned error values may be useful while debugging a port.

(3) Return no error. The data has been transferred already to the memory buffer using DMA.