⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 可以在ARM单片机上移植的SD卡的驱动程序的原码
💻 C
📖 第 1 页 / 共 5 页
字号:
}

/*****************************************************************************/
//  Description:    This function is used to set read timeout times which will be used in read operating.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_GetReadTimeout(     // return the timeout value
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return 0;
    }
    return ptSDCard->uiReadTimeout;
}

/*****************************************************************************/
//  Description:    This function is used to set write timeout times which will be used in read operating.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_SetWriteTimeout(     // return SD_SUCCESS
    SD_CARD_T* ptSDCard,         // the card vector
    uint32 uiWriteTimeout              // wtite timeout times
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    ptSDCard->uiWriteTimeout = uiWriteTimeout;
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to set write timeout times which will be used in write operating.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_GetWriteTimeout(     // return the timeout value
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return 0;
    }
    return ptSDCard->uiWriteTimeout;
}

/*****************************************************************************/
//  Description:    This function is used to check whether sdcard does exist. 
//  Author:         xingyun.he
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_GetStatus(     // return sdcard exist status
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    int32 count = 5;
    if (PNULL == ptSDCard)
    {
        SCI_TRACE_LOW("sdcard vector is null");
        return SD_NOT_EXIST;
    }
    if (SD_SUCCESS == SD_Initialize(ptSDCard))
    {
        return SD_EXIST;    
    }
    else
    {
        for (; count>0; count--)
        {
            if (SD_SUCCESS == SD_Initialize(ptSDCard))
            {
                return SD_EXIST;    
            }
        }
    }
    return SD_NOT_EXIST;
}

/*****************************************************************************/
//  Description:    This function is used to get sdcard block length by 
//                   reading READ_BL_LEN in sdcard csd register. 
//  Author:         xingyun.he
//  Note:       At present, the sdcard driver only supports the card whose capability
//              is less than or equal to 2GB. 
/*****************************************************************************/
PUBLIC uint32 SD_GetBlockLength(     // return the sdcard block length  0 - ERROR!
    SD_CARD_T* ptSDCard         // the card vector
    )
{
	uint8 card_specific_data[16 + 2];   //16Bytes CSD + 2 CRC Bytes
	
    if(SD_ReadCSD(ptSDCard, (uint8*)card_specific_data) == SD_SUCCESS)
    {
		int i;
		uint32 read_bl_len;
		uint32 block_length = 1;

		read_bl_len = card_specific_data[5]&0x0f;
		for (i = 0; i < read_bl_len; i++)
		{
			block_length *= 2; 
		} 
		return block_length;
    }  
    return 0;  
}

/**---------------------------------------------------------------------------*
 **                         Local Function Definitions                              *
 **---------------------------------------------------------------------------*/
/*****************************************************************************/
//  Description:    This function is used to write a SD command to Card and get the response.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
LOCAL uint32 SD_WriteCmd(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint8 ucCmd,                        // the CMD number
    uint8 ucRspType,                // the response type
    uint8* pucResponse,         // response
    uint8* pucArgument          // argument list
    )
{
    int i, j;
    uint8 response_length;
    uint8 tmp;
    
    SD_Delay(ptSDCard->eSPIId, CS_NONE, 1);        //After response, SDCard perhaps keep MOSI signal low. So I have to output a data to pull up MOSI signal.
    
    /* All data is sent MSB first*/
    /* Send the header/command */
    /* Format:
    cmd[7:6] : 01
    cmd[5:0] : command */
    SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
    SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, (ucCmd & 0x3F) | 0x40);
    for(i = 3; i >= 0; i--)
    {
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, pucArgument[i]);
    }
    /* This is the CRC. It only matters what we put here for the first
    command. Otherwise, the CRC is ignored for SPI mode unless we
    enable CRC checking. */
    SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0x95);
    
    response_length = 0;
    switch(ucRspType)
    {
        case R1:
        case R1B:
            response_length = 1;
            break;
            
        case R2:
            response_length = 2;
            break;
            
        case R3:
            response_length = 5;
            break;
            
        default:
            break;
    }
    
    /* Wait for a response. A response can be recognized by the start bit (a zero) */
    i = 0;
    j = response_length - 1;
    do
    {
        tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        i++;
    }
    while(((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT);
    
    /* Just bail if we never got a response */
    if(i >= SD_CMD_TIMEOUT)
    {
        SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
        return SD_WRITECMD_TIMEOUT_ERROR;
    }
    
    pucResponse[j] = tmp;
    
    j--;
    for(; j >= 0; j--)
    {
        tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        pucResponse[j] = tmp;
    }

    /* If the response is a "busy" type (R1B), then there's some
    * special handling that needs to be done. The card will
    * output a continuous stream of zeros, so the end of the BUSY
    * state is signaled by any nonzero response. The bus idles
    * high.
    */
    i = 0;
    if(ucRspType == R1B)
    {
        do
        {
            i++;
            tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        }
        /* This should never time out, unless SPI_DI is grounded.
        * Don't bother forcing a timeout condition here. */
        while (tmp != 0xFF);
        for(i = 0; i < 10; i++)
        {
            SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);  //KingMax card's requirement
        }
    }

    for(i = 0; i < 20; i++);
    SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
    
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to do a delay. The delay unit is 8 clock.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
LOCAL void SD_Delay(
    SD_SPIPORT_E eSPIId,    // the SPI ID
    uint32 uiCSId,          // the CS id
    uint32 uiNum        // delay number
    )
{
    uint8 i;
    /* Null for now */
    for (i = 0; i < uiNum; i++)
    {
        /* Clock out an idle byte (0xFF) */
        SPI_PutChar(eSPIId, uiCSId, 0xFF);
    }
}

/*****************************************************************************/
//  Description:    This function is used to pack the argument to the needed order.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
LOCAL void SD_Packarg(
    uint8* pucArgument,     // output argument list
    uint32 uiValue              // input argument
    )
{
    pucArgument[3] = (uint8)(uiValue >> 24);
    pucArgument[2] = (uint8)(uiValue >> 16);
    pucArgument[1] = (uint8)(uiValue >> 8);
    pucArgument[0] = (uint8)(uiValue);
}

/*****************************************************************************/
//  Description:    This function is used to verify the register validity.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
LOCAL BOOLEAN SD_RegisterVerify(        // return status. SCI_TRUE - Registered
                                                                    //                    SCI_FALSE - Unregistered
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    SD_CARD_T* ptCurrent;

    if(ptSDCard == NULL)
    {
        return SCI_FALSE;       //ptSDCard should not be NULL.
    }
    
    ptCurrent = g_sd_ptCardList;
    if(ptCurrent != NULL)
    {
        if(ptCurrent == ptSDCard)         //the first element is the card.
        {
            return SCI_TRUE;
        }

        while(ptCurrent->pNextElement != NULL)          //is tail?
        {
            ptCurrent = ptCurrent->pNextElement;
            if(ptCurrent == ptSDCard)                             //is the card element?
            {
                return SCI_TRUE;
            }
        }
        return SCI_FALSE;           //Can't find the dest card
    }

    return SCI_FALSE;       //Card list is NULL!
}

/*****************************************************************************/
//  Description:    After a data block is received the card will respond with a data-response 
//                      token, and if the data block is received with no errors, it will be programmed. 
//                      As long as the card is busy programming, a continuous stream of busy tokens 
//                      will be sent to the host(effectively holding the dataOut line low).
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
LOCAL uint32 SD_WaitNotBusy (
    SD_CARD_T* ptSDCard         // the card vector
    )
{
    uint8 ichar;
    int count;
    
	count = 0;
    /* Check for the busy flag (set on a write block) */
    while(ptSDCard->bBusyFlag == SCI_TRUE)
    {
    	count++;
    	if (count > SD_TIMEOUT)
    	{
    		return SD_WAITNOTBUSY_TIMEOUT;
    	}
        ichar = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        if(ichar == 0xFF)
        {
            ptSDCard->bBusyFlag = SCI_FALSE;
        }
    }
    return SD_SUCCESS;
}
/**---------------------------------------------------------------------------*
 **                         Compiler Flag                                     *
 **---------------------------------------------------------------------------*/
#ifdef   __cplusplus
    }
    
#endif  // End of sd.c

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -