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

📄 sd.c

📁 可以在ARM单片机上移植的SD卡的驱动程序的原码
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************
 ** File Name:      sd.c                                                                *
 ** Author:         Benjamin.Wang                                             *
 ** DATE:           01/26/2005                                                *
 ** Copyright:      2005 Spreadtrum, Incoporated. All Rights Reserved.         *
 ** Description:    This file defines the basic operation interfaces of SD Card.    *
 **                                                                           *
 ******************************************************************************

 ******************************************************************************
 **                        Edit History                                       *
 ** ------------------------------------------------------------------------- *
 ** DATE           NAME             DESCRIPTION                               *
 ** 01/26/2005     Benjamin.Wang    Create.                                   *
 ******************************************************************************/

/**---------------------------------------------------------------------------*
 **                         Dependencies                                      *
 **---------------------------------------------------------------------------*/ 
#include "os_api.h"
#include "sd.h"
#include "spi_drv.h"
#include "sci_types.h"
/**---------------------------------------------------------------------------*
 **                         Debugging Flag                                    *
 **---------------------------------------------------------------------------*/
#define DEBUG_SD

#ifdef DEBUG_SD
#define SD_PRINT( _format_string )   SCI_TRACE_LOW _format_string 
#else
#define SD_PRINT( _format_string )  
#endif
 
/**---------------------------------------------------------------------------*
 **                         Compiler Flag                                     *
 **---------------------------------------------------------------------------*/
#ifdef   __cplusplus
    extern   "C" 
    {
#endif
/**---------------------------------------------------------------------------*
 **                         Macro Definition                                   *
 **---------------------------------------------------------------------------*/
#define CS_NONE 0xF

#define SD_BLOCKSIZE 512
#define SD_BLOCKSIZE_NBITS 9

#define SD_DEFAULT_CLOCK 400000

#define SD_DMA_READ_LEN 128
#define SD_DMA_WRITE_LEN 32
#define SD_TIMEOUT      200000

/**---------------------------------------------------------------------------*
 **                         Global Variables                                  *
 **---------------------------------------------------------------------------*/
SD_CARD_T* g_sd_ptCardList = NULL;
uint8 g_ucArgument[4];
uint8 g_ucResponse[5];

uint32 g_sd_default_blocksize = SD_BLOCKSIZE; 

/**---------------------------------------------------------------------------*
 **                         Constant Variables                                *
 **---------------------------------------------------------------------------*/
 
/**---------------------------------------------------------------------------*
 **                     Local Function Prototypes                             *
 **---------------------------------------------------------------------------*/
LOCAL uint32 SD_WriteCmd(SD_CARD_T* ptSDCard, 
                                uint8 ucCmd, 
                                uint8 ucRspType, 
                                uint8* pucResponse, 
                                uint8* pucArgument);

LOCAL void SD_Delay(SD_SPIPORT_E eSPIId, uint32 uiCSId, uint32 uiNum);

LOCAL void SD_Packarg(uint8* pucArgument, uint32 uiValue);

LOCAL BOOLEAN SD_RegisterVerify(SD_CARD_T* ptSDCard);

LOCAL uint32 SD_WaitNotBusy (SD_CARD_T* ptSDCard);

/**---------------------------------------------------------------------------*
 **                         Function Definitions                              *
 **---------------------------------------------------------------------------*/
/*****************************************************************************/
//  Description:    This function is used to register the SPI hardware interface.    
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC SD_CARD_T* SD_Register(  // success - return the hardware interface vector
                                                            // failure - return NULL
    SD_SPIPORT_E eId, // SPI port num
    SD_SPICS_E uiCSId, // Chip select id
    uint32 uiClockRate, // SPI clock
    uint32 uiReadTimeout, // Max read timeout. typical value: uiClockRate / 20
    uint32 uiWriteTimeout // Max write timeout. typical value: uiClockRate / 8
)
{
    SD_CARD_T* ptNewItem = NULL;
    SD_CARD_T* ptCurrentItem = NULL;
    SPI_CONFIG_T tSPIConfig;
    SPI_PORT_T* ptSPIPort;
    
    tSPIConfig.freq = SD_DEFAULT_CLOCK; /* Start out with a slow SPI clock, 400kHz, as required by the SD spec (for MMC compatibility). */
    tSPIConfig.lsb_first = SCI_FALSE;
    tSPIConfig.rx_shift_edge = SCI_TRUE;
    tSPIConfig.tx_bit_length = 8;
    tSPIConfig.tx_shift_edge = SCI_TRUE;

    /* Initialize the SPI controller */
    ptSPIPort = SPI_Create(eId, &tSPIConfig, SCI_FALSE);
    if(ptSPIPort == NULL)
    {
        /*It has two possibilities: 
         * 1. Both the SPI port and the CS has been occupied.
         * 2. Only SPI port is occupied, but CS is free. This case is all right. But SPI driver hadn't differentiated them. 
         */
        SD_PRINT(("SDCard: This SPI Port Has been occupied!"));
        SCI_PASSERT(SCI_FALSE, ("SDCard: This SPI Port Has been occupied!"));
        return NULL;
    }
    
    ptCurrentItem = g_sd_ptCardList;   //get root element
    if(ptCurrentItem != NULL)
    {
        while(ptCurrentItem->pNextElement != NULL)
        {
            if(ptCurrentItem->eSPIId == eId)
            {
                if(ptCurrentItem->uiCSId == uiCSId)
                {
                    SCI_PASSERT(SCI_FALSE, ("This SDCard has been initialized!"));
                    return NULL;
                }
            }
            ptCurrentItem = ptCurrentItem->pNextElement;
        }
        ptNewItem = (SD_CARD_T*)SCI_ALLOC(sizeof(SD_CARD_T));
        ptNewItem->eSPIId = eId;
        ptNewItem->bBusyFlag = SCI_FALSE;
        ptNewItem->uiClockRate = uiClockRate;
        ptNewItem->uiReadTimeout = uiReadTimeout;
        ptNewItem->uiWriteTimeout = uiWriteTimeout;
        ptNewItem->uiCSId = uiCSId;
        ptNewItem->pPreElement = NULL;
        ptNewItem->pNextElement = NULL;
        
        ptCurrentItem->pNextElement = ptNewItem;
        ptNewItem->pPreElement = ptCurrentItem;
    }
    else
    {
        ptNewItem = (SD_CARD_T*)SCI_ALLOC(sizeof(SD_CARD_T));
        ptNewItem->eSPIId = eId;
        ptNewItem->bBusyFlag = SCI_FALSE;
        ptNewItem->uiClockRate = uiClockRate;
        ptNewItem->uiReadTimeout = uiReadTimeout;
        ptNewItem->uiWriteTimeout = uiWriteTimeout;
        ptNewItem->uiCSId = uiCSId;
        ptNewItem->pPreElement = NULL;
        ptNewItem->pNextElement = NULL;
        
        g_sd_ptCardList = ptNewItem;
        ptNewItem->pPreElement = g_sd_ptCardList;
    }
    
    return ptNewItem;
}
/*****************************************************************************/
//  Description:    This function is used to initialize the SDCard.    
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_Initialize(    // SD_SUCCESS - SDCard init success 
                                                    // SD_UNREGISTER - the SDCard hardware interface has not been registered.
                                                    // SD_FAILURE - SDCard init failure
    SD_CARD_T* ptSDCard             // SDCard vector
    )
{
    uint32 i, j;
    uint32 result;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, SD_DEFAULT_CLOCK); /* Start out with a slow SPI clock, 400kHz, as required by the SD spec (for MMC compatibility). */
    
    /* SPI SD initialization sequence:
    * CMD0
    * CMD55
    * ACMD41
    * CMD58
    * (Note there is no CMD2 or CMD3 in SPI mode. These
    * instructions are devoted to addressing on the SD bus.)
    *
    * SD memory card SD initialization sequence:
    * CMD0
    * CMD55
    * ACMD41
    * CMD2
    * CMD3
    */
    if(ptSDCard != NULL)
    {
        ptSDCard->bBusyFlag = SCI_FALSE;
        for (i = 0; i < 4; i++)
        {
            g_ucArgument[i] = 0;
        }

	//wait until sdcard DI pin has no data
        SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
        ptSDCard->bBusyFlag = SCI_TRUE;
        if ((result = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
        {
        	return result;
        }

        /* Delay for at least 74 clock cycles. This means to actually
        * *clock* out at least 74 clock cycles with no data present on
        * the clock. In SPI mode, send at least 10 idle bytes (0xFF). */
        SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
        for(i = 0; i < 10; i++);    //Just wait a moment so that the waveform will be more beautiful.
        SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
        SD_Delay(ptSDCard->eSPIId, ptSDCard->uiCSId, 200);
        for(i = 0; i < 5; i++);     //we can't set CS at once.
        SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
        SD_Delay(ptSDCard->eSPIId, CS_NONE, 50);

        /* Put the card in the idle state */
        do
        {
            if (SD_WriteCmd(ptSDCard, CMD0, CMD0_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
            {
                return SD_INIT_CMD0_ERROR;
            }
        }
        while(g_ucResponse[0] & 0xFE);
  

        /* Now wait until the card goes idle. Retry at most SD_IDLE_WAIT_MAX
        times */
        j = 0;
        do
        {
            j++;
            /* Flag the next command as an application-specific command */
            if (SD_WriteCmd(ptSDCard, CMD55, CMD55_R, g_ucResponse, g_ucArgument)== SD_SUCCESS)
            {
                /* Tell the card to send its OCR */
                SD_WriteCmd(ptSDCard, ACMD41, ACMD41_R, g_ucResponse, g_ucArgument);
            }
           
        }
        while ((g_ucResponse[0] & MSK_IDLE) == MSK_IDLE && j < SD_IDLE_WAIT_MAX);

        /* As long as we didn't hit the timeout, assume we're OK. */
        if (j >= SD_IDLE_WAIT_MAX)
        {
            return SD_INIT_WAIT_IDLE_ERROR;
        }

        //if (SD_WriteCmd(ptSDCard, CMD58, CMD58_R, g_ucResponse, g_ucArgument) == SD_FAILURE)
        //{
            //return SD_FAILURE - 1;
        //}

        /* At a very minimum, we must allow 3.3V. */
        //if ((g_ucResponse[2] & MSK_OCR_33) != MSK_OCR_33)
        //{
            //return SD_FAILURE - 2;
        //}
        /* Set the block length */
        //if (sd_set_blocklen (sdc, SD_BLOCKSIZE) != 1)
            //return 0;
        /* If we got this far, initialization was OK. */
        /* Set the maximum SPI clock rate possible */
        SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate);
        
        /*Trace out Card's CSD Info for debug.*/
        {
            uint8 card_specific_data[16 + 2];   //16Bytes CSD + 2 CRC Bytes
            uint32 i = 0;
	
            if(SD_ReadCSD(ptSDCard, (uint8*)card_specific_data) == SD_SUCCESS)
            {
                for(i = 0; i < 16 + 2; i++)
                {
                    SD_PRINT(("SDCard:CSD[%d]:0x%x", i, card_specific_data[i]));
                }
            }
        }

        return SD_SUCCESS;
    }

    return SCI_ERROR;
}
/*****************************************************************************/
//  Description:    This function is used to unregister the SDCard hardware interface.    
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_Close(     //SD_SUCCESS - SDCard hardware interface close success
			                            //SD_UNREGISTER - SDCard unregistered
			                            //SD_CARDLIST_NULL - SDCard linklist is null
    SD_CARD_T* ptSDCard     // SDCard vector
    )
{
    SD_CARD_T* ptCurrent;

    ptCurrent = g_sd_ptCardList;
    if(ptCurrent != NULL)
    {
        if(ptCurrent == ptSDCard)         //the first element is the closed.
        {
            g_sd_ptCardList = ptCurrent->pNextElement;             //reset the header
            ptCurrent->pNextElement->pPreElement = g_sd_ptCardList;
            SPI_Close(ptCurrent->eSPIId);
            SCI_FREE(ptCurrent);                                //free it
            return SD_SUCCESS;
        }

        while(ptCurrent->pNextElement != NULL)          //is tail?
        {
            ptCurrent = ptCurrent->pNextElement;
            if(ptCurrent == ptSDCard)                             //is the closed element?
            {
                ptCurrent->pPreElement->pNextElement = ptCurrent->pNextElement; //adjust queue pointer
                if (ptCurrent->pNextElement != NULL) //modified by xingyun.he 2005/12/24
                {
                    ptCurrent->pNextElement->pPreElement = ptCurrent->pPreElement;
                }
                SPI_Close(ptCurrent->eSPIId);
                SCI_FREE(ptCurrent);                    //free the element.
                return SD_SUCCESS;
            }
        }
        SD_PRINT(("This Card Can't be found in CardList!"));

⌨️ 快捷键说明

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