/*
 * 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);
}
Exemple #2
0
/*************************************************************************
 * 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);
  }