cancel
Showing results for 
Search instead for 
Did you mean: 

SDIO CLK unable init

KHowe
Visitor

Hi 

I had a custom board and my SD clock (SD_CLK) is always stuck at 400 kHz, this is typically due to the initialization phase of the SD card interface. As such i unable access the content in my SD card.

https://github.com/EdgeTX/edgetx/blob/v2.7.1/radio/src/targets/common/arm/stm32/sdio_sd.c 

KHowe_0-1728303188086.png

 

OPTIMIZE("O0") SD_Error SD_PowerON(void)

{
__IO SD_Error errorstatus = SD_OK;
uint32_t response = 0, count = 0, validvoltage = 0;
uint32_t SDType = SD_STD_CAPACITY;

/*!< Power ON Sequence -----------------------------------------------------*/
/*!< Configure the SDIO peripheral */
/*!< SDIO_CK = SDIOCLK / (SDIO_INIT_CLK_DIV + 2) */
/*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */
/*!< SDIO_CK for initialization should not exceed 400 KHz */
SDIO_InitStructure.SDIO_ClockDiv = SD_SDIO_INIT_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);

/*!< Set Power State to ON */
SDIO_SetPowerState(SDIO_PowerState_ON);

/*!< Enable SDIO Clock */
SDIO_ClockCmd(ENABLE);

/*!< CMD0: GO_IDLE_STATE ---------------------------------------------------*/
/*!< No CMD response required */
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_GO_IDLE_STATE;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdError();

if (errorstatus != SD_OK) {
TRACE("SD_CMD_GO_IDLE_STATE status=%d", errorstatus);
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return 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 */
SDIO_CmdInitStructure.SDIO_Argument = SD_CHECK_PATTERN;
SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SEND_IF_COND;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp7Error();

if (errorstatus == SD_OK) {
CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /*!< SD Card 2.0 */
SDType = SD_HIGH_CAPACITY;
}
else {
/*!< CMD55 */
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_APP_CMD);
}
/*!< CMD55 */
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
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 */
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_APP_CMD);

if (errorstatus != SD_OK) {
TRACE("SD_CMD_APP_CMD status=%d", errorstatus);
return errorstatus;
}
SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_OP_COND;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp3Error();
if (errorstatus != SD_OK) {
TRACE("SD_CMD_SD_APP_OP_COND status=%d", errorstatus);
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;
}

}

return errorstatus;
}

/**
* @brief Turns the SDIO output signals off.
*  None
* @retval SD_Error: SD Card Error code.
*/
OPTIMIZE("O0") SD_Error SD_PowerOFF(void)
{
SD_Error errorstatus = SD_OK;

/*!< Set Power State to OFF */
SDIO_SetPowerState(SDIO_PowerState_OFF);

return errorstatus;
}

/**
* @brief Intialises all cards or single card as the case may be Card(s) come
* into standby state.
*  None
* @retval SD_Error: SD Card Error code.
*/
OPTIMIZE("O0") SD_Error SD_InitializeCards(void)
{
SD_Error errorstatus = SD_OK;
uint16_t rca = 0x01;

if (SDIO_GetPowerState() == SDIO_PowerState_OFF) {
errorstatus = SD_REQUEST_NOT_APPLICABLE;
return errorstatus;
}

if (SDIO_SECURE_DIGITAL_IO_CARD != CardType) {
/*!< Send CMD2 ALL_SEND_CID */
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp2Error();

if (SD_OK != errorstatus) {
return errorstatus;
}

CID_Tab[0] = SDIO_GetResponse(SDIO_RESP1);
CID_Tab[1] = SDIO_GetResponse(SDIO_RESP2);
CID_Tab[2] = SDIO_GetResponse(SDIO_RESP3);
CID_Tab[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. */
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp6Error(SD_CMD_SET_REL_ADDR, &rca);

if (SD_OK != errorstatus) {
return errorstatus;
}
}

if (SDIO_SECURE_DIGITAL_IO_CARD != CardType) {
RCA = rca;

/*!< Send CMD9 SEND_CSD with argument as card's RCA */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)(rca << 16);
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp2Error();

if (SD_OK != errorstatus) {
return errorstatus;
}

CSD_Tab[0] = SDIO_GetResponse(SDIO_RESP1);
CSD_Tab[1] = SDIO_GetResponse(SDIO_RESP2);
CSD_Tab[2] = SDIO_GetResponse(SDIO_RESP3);
CSD_Tab[3] = SDIO_GetResponse(SDIO_RESP4);
}

errorstatus = SD_OK; /*!< All cards get intialized */

return errorstatus;
}
1 REPLY 1
Andrew Neil
Evangelist III