/* * Handle a command that has been completed */ static void stm32f4xx_sdio_completed_command(struct stm32f4xx_sdio *sdio, rt_uint32_t status) { struct rt_mmcsd_cmd *cmd = sdio->cmd; struct rt_mmcsd_data *data = cmd->data; cmd->resp[0] = SDIO_GetResponse(SDIO_RESP1); cmd->resp[1] = SDIO_GetResponse(SDIO_RESP2); cmd->resp[2] = SDIO_GetResponse(SDIO_RESP3); cmd->resp[3] = SDIO_GetResponse(SDIO_RESP4); sdio_dbg("Status = %08X/%08x [%08X %08X %08X %08X]\n", status, SDIO->MASK, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); if (status & STM32F4XX_SDIO_ERRORS) { if ((status & SDIO_IT_CCRCFAIL) && (resp_type(cmd) & (RESP_R3 | RESP_R4))) { cmd->err = 0; } else { if (status & (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_TXUNDERR)) { if (data) { if (status & SDIO_IT_DTIMEOUT) data->err = -RT_ETIMEOUT; else if (status & SDIO_IT_DCRCFAIL) data->err = -RT_ERROR; } } else { if (status & SDIO_IT_CTIMEOUT) cmd->err = -RT_ETIMEOUT; else if (status & SDIO_IT_CCRCFAIL) cmd->err = -RT_ERROR; else cmd->err = -RT_ERROR; } rt_kprintf("error detected and set to %d/%d (cmd = %d),0x%08x\n", cmd->err, data ? data->err : 0, cmd->cmd_code, status); } } else cmd->err = 0; stm32f4xx_sdio_process_next(sdio); }
/************************************************************************* * Function Name: _SdSendCmd * Parameters: SdCmdInd_t ComdInd,Int32U Arg * * Return: SdState_t * * Description: SD/MMC commands implement * *************************************************************************/ static SdState_t _SdSendCmd(SdCmdInd_t ComdInd,pInt32U pArg) { SDIO_CmdInitTypeDef SDIO_CmdInitStructure; Int32U Status; Int32U timeout; // Send Command SDIO_CmdInitStructure.SDIO_CmdIndex = _SdCmd[ComdInd].TxData; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; if(pArg != NULL) { switch(_SdCmd[ComdInd].Resp) { case SdR2: SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; break; case SdR1: case SdR1b: case SdR3: case SdR7: SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; } } // Send command's arguments if(_SdCmd[ComdInd].Arg != SdNoArg) { SDIO_CmdInitStructure.SDIO_Argument = *pArg; } else { SDIO_CmdInitStructure.SDIO_Argument = 0; } // Clear all the static flags SDIO_ClearFlag(SDIO_STATIC_FLAGS); SDIO_SendCommand(&SDIO_CmdInitStructure); // Wait command respond if(CMD0 == ComdInd) { timeout = SDIO_CMD0TIMEOUT; do { if(0 == --timeout) { // Clear all the static flags return(SdNoResponse); } Status = SDIO->STA; } while (0 == (Status & SDIO_FLAG_CMDSENT)); } else { do { Status = SDIO->STA; } while(!(Status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))); } SDIO_ClearFlag(SDIO_FLAG_CMDSENT); if (Status & SDIO_FLAG_CTIMEOUT) { SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT); return(SdNoResponse); } if (Status & SDIO_FLAG_CCRCFAIL) { SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL); switch(_SdCmd[ComdInd].TxData) { // Ignore CRC Error case 1: // CMD1 case 41: // ACMD42 case 12: // CMD12 break; default: return(SdCardError); } } if(pArg != NULL) { switch (_SdCmd[ComdInd].Resp) { case SdNoResp: break; case SdR3: case SdR7: *pArg = SDIO_GetResponse(SDIO_RESP1); break; case SdR2: *pArg++ = SDIO_GetResponse(SDIO_RESP1); *pArg++ = SDIO_GetResponse(SDIO_RESP2); *pArg++ = SDIO_GetResponse(SDIO_RESP3); *pArg++ = SDIO_GetResponse(SDIO_RESP4); break; default: // Check response received is of desired command if (SDIO_GetCommandResponse() != _SdCmd[ComdInd].TxData) { return(SdCardError); } *pArg = SDIO_GetResponse(SDIO_RESP1); } } SDIO_ClearFlag(SDIO_FLAG_CMDREND); return(SdOk); }
bool SdCardSdioFeature::powerOn() { SD_Error errorstatus=SD_OK; uint32_t response=0,count=0,validvoltage=0; uint32_t SDType=SD_STD_CAPACITY; SDIO_InitTypeDef sdioInit; SDIO_CmdInitTypeDef cmdInit; /*!< Power ON Sequence -----------------------------------------------------*/ sdioInit.SDIO_ClockDiv=_initDivider; sdioInit.SDIO_ClockEdge=SDIO_ClockEdge_Rising; sdioInit.SDIO_ClockBypass=SDIO_ClockBypass_Disable; sdioInit.SDIO_ClockPowerSave=SDIO_ClockPowerSave_Disable; sdioInit.SDIO_BusWide=SDIO_BusWide_1b; sdioInit.SDIO_HardwareFlowControl=SDIO_HardwareFlowControl_Disable; SDIO_Init(&sdioInit); /*!< Set Power State to ON */ SDIO_SetPowerState(SDIO_PowerState_ON); /*!< Enable SDIO Clock */ SDIO_ClockCmd(ENABLE); /*!< CMD0: GO_IDLE_STATE ---------------------------------------------------*/ /*!< No CMD response required */ cmdInit.SDIO_Argument=0x0; cmdInit.SDIO_CmdIndex=SD_CMD_GO_IDLE_STATE; cmdInit.SDIO_Response=SDIO_Response_No; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdError(); if(errorstatus != SD_OK) return errorProvider.set(ErrorProvider::ERROR_PROVIDER_SD_SDIO,E_SDIO_ERROR,errorstatus); /*!< CMD8: SEND_IF_COND ----------------------------------------------------*/ /*!< Send CMD8 to verify SD card interface operating condition */ /*!< Argument: - [31:12]: Reserved (shall be set to '0') - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) - [7:0]: Check Pattern (recommended 0xAA) */ /*!< CMD Response: R7 */ cmdInit.SDIO_Argument=SD_CHECK_PATTERN; cmdInit.SDIO_CmdIndex=SDIO_SEND_IF_COND; cmdInit.SDIO_Response=SDIO_Response_Short; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp7Error(); if(errorstatus == SD_OK) { _cardType=SDIO_STD_CAPACITY_SD_CARD_V2_0; /*!< SD Card 2.0 */ SDType=SD_HIGH_CAPACITY; } else { /*!< CMD55 */ cmdInit.SDIO_Argument=0x00; cmdInit.SDIO_CmdIndex=SD_CMD_APP_CMD; cmdInit.SDIO_Response=SDIO_Response_Short; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp1Error(SD_CMD_APP_CMD); } /*!< CMD55 */ cmdInit.SDIO_Argument=0x00; cmdInit.SDIO_CmdIndex=SD_CMD_APP_CMD; cmdInit.SDIO_Response=SDIO_Response_Short; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp1Error(SD_CMD_APP_CMD); /*!< If errorstatus is Command TimeOut, it is a MMC card */ /*!< If errorstatus is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch) or SD card 1.x */ if(errorstatus == SD_OK) { /*!< SD CARD */ /*!< Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */ while((!validvoltage) && (count < SD_MAX_VOLT_TRIAL)) { /*!< SEND CMD55 APP_CMD with RCA as 0 */ cmdInit.SDIO_Argument=0x00; cmdInit.SDIO_CmdIndex=SD_CMD_APP_CMD; cmdInit.SDIO_Response=SDIO_Response_Short; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp1Error(SD_CMD_APP_CMD); if(errorstatus != SD_OK) return errorstatus; cmdInit.SDIO_Argument=SD_VOLTAGE_WINDOW_SD | SDType; cmdInit.SDIO_CmdIndex=SD_CMD_SD_APP_OP_COND; cmdInit.SDIO_Response=SDIO_Response_Short; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp3Error(); if(errorstatus != SD_OK) return errorstatus; response=SDIO_GetResponse(SDIO_RESP1); validvoltage=(((response >> 31) == 1) ? 1 : 0); count++; } if(count >= SD_MAX_VOLT_TRIAL) { errorstatus=SD_INVALID_VOLTRANGE; return errorstatus; } if(response&=SD_HIGH_CAPACITY) _cardType=SDIO_HIGH_CAPACITY_SD_CARD; }/*!< else MMC Card */ if(errorstatus != SD_OK) return errorProvider.set(ErrorProvider::ERROR_PROVIDER_SD_SDIO,E_SDIO_ERROR,errorstatus); return true; }
bool SdCardSdioFeature::initialiseCard() { SD_Error errorstatus=SD_OK; uint16_t rca=0x01; SDIO_CmdInitTypeDef cmdInit; SDIO_InitTypeDef sdioInit; if(SDIO_GetPowerState() == SDIO_PowerState_OFF) return errorProvider.set(ErrorProvider::ERROR_PROVIDER_SD_SDIO,E_SDIO_ERROR,SD_REQUEST_NOT_APPLICABLE); if(SDIO_SECURE_DIGITAL_IO_CARD != _cardType) { /*!< Send CMD2 ALL_SEND_CID */ cmdInit.SDIO_Argument=0x0; cmdInit.SDIO_CmdIndex=SD_CMD_ALL_SEND_CID; cmdInit.SDIO_Response=SDIO_Response_Long; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp2Error(); if(SD_OK != errorstatus) return errorProvider.set(ErrorProvider::ERROR_PROVIDER_SD_SDIO,E_SDIO_ERROR,errorstatus); _cidTab[0]=SDIO_GetResponse(SDIO_RESP1); _cidTab[1]=SDIO_GetResponse(SDIO_RESP2); _cidTab[2]=SDIO_GetResponse(SDIO_RESP3); _cidTab[3]=SDIO_GetResponse(SDIO_RESP4); } if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == _cardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == _cardType) || (SDIO_SECURE_DIGITAL_IO_COMBO_CARD == _cardType) || (SDIO_HIGH_CAPACITY_SD_CARD == _cardType)) { /*!< Send CMD3 SET_REL_ADDR with argument 0 */ /*!< SD Card publishes its RCA. */ cmdInit.SDIO_Argument=0x00; cmdInit.SDIO_CmdIndex=SD_CMD_SET_REL_ADDR; cmdInit.SDIO_Response=SDIO_Response_Short; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp6Error(SD_CMD_SET_REL_ADDR,&rca); if(SD_OK != errorstatus) return errorProvider.set(ErrorProvider::ERROR_PROVIDER_SD_SDIO,E_SDIO_ERROR,errorstatus); } if(SDIO_SECURE_DIGITAL_IO_CARD != _cardType) { _rca=rca; /*!< Send CMD9 SEND_CSD with argument as card's RCA */ cmdInit.SDIO_Argument=(uint32_t)(rca << 16); cmdInit.SDIO_CmdIndex=SD_CMD_SEND_CSD; cmdInit.SDIO_Response=SDIO_Response_Long; cmdInit.SDIO_Wait=SDIO_Wait_No; cmdInit.SDIO_CPSM=SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit); errorstatus=cmdResp2Error(); if(SD_OK != errorstatus) return errorProvider.set(ErrorProvider::ERROR_PROVIDER_SD_SDIO,E_SDIO_ERROR,errorstatus); _csdTab[0]=SDIO_GetResponse(SDIO_RESP1); _csdTab[1]=SDIO_GetResponse(SDIO_RESP2); _csdTab[2]=SDIO_GetResponse(SDIO_RESP3); _csdTab[3]=SDIO_GetResponse(SDIO_RESP4); } /*!< Configure the SDIO peripheral */ sdioInit.SDIO_ClockDiv = _transferDivider; sdioInit.SDIO_ClockEdge = SDIO_ClockEdge_Rising; sdioInit.SDIO_ClockBypass = SDIO_ClockBypass_Disable; sdioInit.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; sdioInit.SDIO_BusWide = SDIO_BusWide_1b; sdioInit.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; SDIO_Init(&sdioInit); return detectCardInfo() && selectDeselect((uint32_t) (_cardInfo.RCA << 16)) && enableWideBusOperation(SDIO_BusWide_4b); }