FSDev_SD_Card_BSP_CmdStart()
void FSDev_SD_Card_BSP_CmdStart (FS_QTY unit_nbr,
FS_DEV_SD_CARD_CMD *p_cmd,
void *p_data,
FS_DEV_SD_CARD_ERR *p_err);
File | Called from | Code enabled by |
---|---|---|
| SD/MMC cardmode driver | N/A |
Start a command.
Arguments
unit_nbr
Unit number of SD/MMC card.
p_cmd
Pointer to command to transmit (see Note #2).
p_data
Pointer to buffer address for DMA transfer (see Note #3).
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_BUSY
Controller is busy.
FS_DEV_SD_CARD_ERR_UNKNOWN
Unknown or other error.
Returned Value
None.
Notes/Warnings
- The command start will be followed by zero, one or two additional BSP function calls, depending on whether data should be transferred and on whether any errors occur.
FSDev_SD_Card_BSP_CmdStart()
starts execution of the command. IT may also set up the DMA transfer (if necessary).FSDev_SD_Card_BSP_CmdWaitEnd()
waits for the execution of the command to end, getting the command response (if any).- If data should transferred from the card to the host,
FSDev_SD_Card_BSP_CmdDataRd()
will read that data; if data should be transferred from the host to the card,FSDev_SD_Card_BSP_CmdDataWr()
will write that data.
- The command
p_cmd
has the following parameters:p_cmd->Cmd
is the command index.p_cmd->Arg
is the 32-bit argument (or 0 if there is no argument).p_cmd->Flags
is a bit-mapped variable with zero or more command flags:FS_DEV_SD_CARD_CMD_FLAG_INIT
Initialization sequence before command. FS_DEV_SD_CARD_CMD_FLAG_BUSY
Busy signal expected after command. FS_DEV_SD_CARD_CMD_FLAG_CRC_VALID
CRC valid after command. FS_DEV_SD_CARD_CMD_FLAG_IX_VALID
Index valid after command. FS_DEV_SD_CARD_CMD_FLAG_OPEN_DRAIN
Command line is open drain. FS_DEV_SD_CARD_CMD_FLAG_DATA_START
Data start command. FS_DEV_SD_CARD_CMD_FLAG_DATA_STOP
Data stop command. FS_DEV_SD_CARD_CMD_FLAG_RESP
Response expected. FS_DEV_SD_CARD_CMD_FLAG_RESP_LONG
Long response expected. p_cmd->DataDir
indicates the direction of any data transfer that should follow this command, if any:FS_DEV_SD_CARD_DATA_DIR_NONE
No data transfer. FS_DEV_SD_CARD_DATA_DIR_HOST_TO_CARD
Transfer host-to-card (write). FS_DEV_SD_CARD_DATA_DIR_CARD_TO_HOST
Transfer card-to-host (read). p_cmd->DataType
indicates the type of the data transfer that should follow this command, if any:FS_DEV_SD_CARD_DATA_TYPE_NONE
No data transfer. FS_DEV_SD_CARD_DATA_TYPE_SINGLE_BLOCK
Single data block. FS_DEV_SD_CARD_DATA_TYPE_MULTI_BLOCK
Multiple data blocks. FS_DEV_SD_CARD_DATA_TYPE_STREAM
Stream data. p_cmd->RespType
indicates the type of the response that should be expected from this command:FS_DEV_SD_CARD_RESP_TYPE_NONE
No response. FS_DEV_SD_CARD_RESP_TYPE_R1
R1 response: Normal Response Command. FS_DEV_SD_CARD_RESP_TYPE_R1B
R1b response. FS_DEV_SD_CARD_RESP_TYPE_R2
R2 response: CID, CSD Register. FS_DEV_SD_CARD_RESP_TYPE_R3
R3 response: OCR Register. FS_DEV_SD_CARD_RESP_TYPE_R4
R4 response: Fast I/O Response (MMC). FS_DEV_SD_CARD_RESP_TYPE_R5
R5 response: Interrupt Request Response (MMC). FS_DEV_SD_CARD_RESP_TYPE_R5B
R5B response. FS_DEV_SD_CARD_RESP_TYPE_R6
R6 response: Published RCA Response. FS_DEV_SD_CARD_RESP_TYPE_R7
R7 response: Card Interface Condition. p_cmd->BlkSize
andp_cmd->BlkCnt
are the block size and block count of the data transfer that should follow this command, if any.
- The pointer to the data buffer that will receive the data transfer that should follow this command,
p_data
, is given so that a DMA transfer can be set up.
Example
The example implementation of FSDev_SD_Card_BSP_CmdStart()
, like the examples in subsequent sections, targets a generic host conformant to the SD card association’s host controller specification. While few hosts do conform, most have a similar mixture of registers and registers fields and require the same sequences of basic actions.
void FSDev_SD_Card_BSP_CmdStart (FS_QTY unit_nbr, FS_DEV_SD_CARD_CMD *p_cmd, void *p_data, FS_DEV_SD_CARD_ERR *p_err) { CPU_INT16U command; CPU_INT32U present_state; CPU_INT16U transfer_mode; present_state = REG_STATE; /* Chk if controller busy. */ (1) if (DEF_BIT_IS_SET_ANY(present_state, BIT_STATE_CMD_INHIBIT_DAT | BIT_STATE_CMD_INHIBIT_CMD) == DEF_YES) { *p_err = FS_DEV_SD_CARD_ERR_BUSY; return; } transfer_mode = DEF_BIT_NONE; /* Calc transfer mode reg value. */ (2) if (p_cmd->DataType == FS_DEV_SD_CARD_DATA_TYPE_MULTIPLE_BLOCK) { transfer_mode |= BIT_TRANSFER_MODE_MULTIPLE_BLOCK | BIT_TRANSFER_MODE_AUTO_CMD12 | BIT_TRANSFER_MODE_BLOCK_COUNT_ENABLE; } if (p_cmd->DataDir == FS_DEV_SD_CARD_DATA_DIR_CARD_TO_HOST) { transfer_mode |= BIT_TRANSFER_MODE_READ | BIT_TRANSFER_MODE_DMA_ENABLE; } else { transfer_mode |= BIT_TRANSFER_MODE_DMA_ENABLE; } command = (CPU_INT16U)p_cmd->Cmd << 8; /* Calc command register value */ (3) if (DEF_BIT_IS_SET(p_cmd->Flags, FS_DEV_SD_CARD_CMD_FLAG_DATA_START) == DEF_YES) { command |= BIT_COMMAND_DATA_PRESENT; } if (DEF_BIT_IS_SET(p_cmd->Flags, FS_DEV_SD_CARD_CMD_FLAG_IX_VALID) == DEF_YES) { command |= BIT_COMMAND_DATA_COMMAND_IX_CHECK; } if (DEF_BIT_IS_SET(p_cmd->Flags, FS_DEV_SD_CARD_CMD_FLAG_CRC_VALID) == DEF_YES) { command |= BIT_COMMAND_DATA_COMMAND_CRC_CHECK; } if (DEF_BIT_IS_SET(p_cmd->Flags, FS_DEV_SD_CARD_CMD_FLAG_RESP) == DEF_YES) { if (DEF_BIT_IS_SET(p_cmd->Flags, FS_DEV_SD_CARD_CMD_FLAG_RESP_LONG) == DEF_YES) { command |= BIT_COMMAND_DATA_COMMAND_RESPONSE_LENGTH_136; } else { if (DEF_BIT_IS_SET(p_cmd->Flags, FS_DEV_SD_CARD_CMD_FLAG_BUSY) == DEF_YES) { command |= BIT_COMMAND_DATA_COMMAND_RESPONSE_LENGTH_48; } else { command |= BIT_COMMAND_DATA_COMMAND_RESPONSE_LENGTH_48_BUSY; } } } /* Write registers to exec cmd. */ (4) REG_SDMA_ADDESS = p_data; REG_BLOCK_COUNT = p_cmd->BlkCnt; REG_BLOCK_SIZE = p_cmd->BlkSize; REG_ARGUMENT = p_cmd->Arg; REG_TRANSFER_MODE = transfer_mode; REG_COMMAND = command; *p_err = FS_DEV_SD_CARD_ERR_NONE; }
(1) Check whether the controller is busy. Though no successful operation should return without the controller idle, an error condition, programming mistake or unexpected condition could make an assumption about initial controller state false. This simple validation is recommended to avoid side-effects and to aid port debugging.
(2) Calculate the transfer mode register value. The command’s DataType and DataDir members specify the type and direction of any transfer. Since this examples uses DMA, DMA is enabled in the transfer mode register.
(3) Calculate the command register value. The command index is available in the command’s Cmd member, which is supplemented by the bits OR’d into Flags to describe the expected result—response and data transfer—following the command execution.
(4) The hardware registers are written to execute the command. The sequence in which the registers are written is important. Typically, as in this example, the assignment to the command register actually triggers execution.