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

📄 sd.c

📁 可以在ARM单片机上移植的SD卡的驱动程序的原码
💻 C
📖 第 1 页 / 共 5 页
字号:
        return SD_UNREGISTER;
    }
    else
    {
        //SCI_PASSERT(0, ("SD Card manage list is NULL!"));
        return SD_CARDLIST_NULL;
    }
}

/*****************************************************************************/
//  Description:    This function is used to read one block data.    
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_ReadBlock(         //Return SD_SUCCESS - read success
                                                            //SD_UNREGISTER - theSDCard vector has not been registered.
                                                            //Return SD_BLOCK_LENGTH_INVALID - the block size is not valid block size or setting failure
                                                            //Return SD_FAILURE - read failure
    SD_CARD_T* ptSDCard,        //SDCard vector
    uint32 uiBlocknum,              //the dest block num
    uint8* pucData,                     //data buffer pointer
    uint32 uiBlockSize              //one block size - 1 ~ 512 Bytes
    )
{
    uint32 i = 0;
    uint8 tmp;
    uint32 block_address;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed

    if(g_sd_default_blocksize != uiBlockSize)
    {
        //Blocksize is not the same as last operation. We should reconfig it.
        if(SD_SetBlockLength(ptSDCard, uiBlockSize) != SD_SUCCESS)
        {
            return SD_BLOCK_LENGTH_INVALID;
        }
    }
   
    /* Adjust the block address to a linear address */
    //block_address = uiBlocknum << SD_BLOCKSIZE_NBITS;   
    block_address = uiBlocknum * uiBlockSize;
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, block_address);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD17, CMD17_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_READ_CMD17_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_READ_RESPONSE_ERROR | (g_ucResponse[0])<<8;
    }

    /* Re-assert CS to continue the transfer */
    SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);
    
    /* Wait for the token */
    i = 0;
    do
    {
        tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
        i++;
    }
    while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);

    if(tmp != SD_TOK_READ_STARTBLOCK)
    {
        /* Clock out a byte before returning */
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);
        
        /* The card returned an error response. Bail and return 0 */
        return SD_READ_TOKEN_ERROR | tmp<<8;
    }

    if (SD_BLOCKSIZE == uiBlockSize)  //When the size of block is 512, DMA read is used 
    {
        for(i = 0; i < uiBlockSize / SD_DMA_READ_LEN; i++)
        {
            SPI_DmaRead(ptSDCard->eSPIId, pucData + SD_DMA_READ_LEN * i, SD_DMA_READ_LEN);
        }
    }
    else
    {
         for(i = 0; i < uiBlockSize; i++)
        {
            pucData[i] = SPI_GetChar(ptSDCard->eSPIId);
        }        
   }

    SPI_GetChar(ptSDCard->eSPIId);      // 2 CRC bytes
    SPI_GetChar(ptSDCard->eSPIId);

    SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
    SD_Delay(ptSDCard->eSPIId, CS_NONE, 6); //send some clock to let SDCard have enough time to finish it's work.

    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to read multiple block data.    
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_ReadMultiBlock(            // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // Card vector
    uint32 uiStartBlocknum,         // the start block number
    uint32 uiBlockCounts,           // the block count
    uint8* pucData,                     // the data pointer
    uint32 uiBlockSize                  // one block size. For example, 512 bytes
    )
{
    uint32 i = 0;
    int32 j;
    uint8 tmp;
    uint32 block_address;
        
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed

    if(g_sd_default_blocksize != uiBlockSize)
    {
        //Blocksize is not the same as last operation. We should reconfig it.
        if(SD_SetBlockLength(ptSDCard, uiBlockSize) != SD_SUCCESS)
        {
            return SD_BLOCK_LENGTH_INVALID;
        }
    }
    
    
    /* Adjust the block address to a linear address */ 
    block_address = uiStartBlocknum * uiBlockSize;
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, block_address);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD18, CMD18_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_READMULTI_CMD18_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_READMULTI_RESPONSE_ERROR | (g_ucResponse[0])<<8;
    }

    /* Re-assert CS to continue the transfer */
    SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);

    for(j = 0; j < uiBlockCounts; j++)
    {
        /* Wait for the token */
        i = 0;
        do
        {
            tmp = (uint8)SPI_GetChar(ptSDCard->eSPIId);
            i++;
        }
        while((tmp == 0xFF) && i < ptSDCard->uiReadTimeout);

        if(tmp != SD_TOK_READ_STARTBLOCK_M)
        {
            /* Clock out a byte before returning */
            SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0xFF);

            /* The card returned an error response. Bail and return 0 */
            return SD_READMULTI_TOKEN_ERROR | tmp<<8;
        }

        if (SD_BLOCKSIZE == uiBlockSize)
        {
            for(i = 0; i < uiBlockSize / SD_DMA_READ_LEN; i++)
    	     {
                SPI_DmaRead(ptSDCard->eSPIId, pucData + j * uiBlockSize + SD_DMA_READ_LEN * i, SD_DMA_READ_LEN);
            }
        }
        else        
        {
 
            for (i = 0; i < uiBlockSize; i++)
            {
                pucData[i + j * uiBlockSize] = SPI_GetChar(ptSDCard->eSPIId);
            }
         }
      
        SPI_GetChar(ptSDCard->eSPIId);      // 2 CRC bytes
        SPI_GetChar(ptSDCard->eSPIId);
    }

    if(SD_WriteCmd(ptSDCard, CMD12, CMD12_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_READMULTI_CMD12_ERROR;
    }
    
    SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
    SD_Delay(ptSDCard->eSPIId, CS_NONE, 6); //send some clock to let SDCard have enough time to finish it's work.
    
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to write one block data.   
//  Author:         Benjamin.Wang
//  Note:           The block size is fixed 512 Bytes.
/*****************************************************************************/
PUBLIC uint32 SD_WriteBlock(    //SD_SUCCESS - write success
                                                        //SD_UNREGISTER - theSDCard vector has not been registered.
                                                        //SD_FAILURE - write failure
    SD_CARD_T* ptSDCard,           //SDCard vector 
    uint32 uiBlocknum,                  //the dest block num
    const uint8* pucData                          //data buffer pointer
    )
{
    uint32 i;
    uint32 block_address;
    uint8 data_response;
    uint32 result, result1;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    if (g_sd_default_blocksize != SD_BLOCKSIZE)
    {
        if(SD_SetBlockLength(ptSDCard, SD_BLOCKSIZE) != SD_SUCCESS)
        {
            return SD_BLOCK_LENGTH_INVALID;
        }
    }

    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
    
    /* Adjust the block address to a linear address */
    block_address = uiBlocknum << SD_BLOCKSIZE_NBITS;

    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, block_address);
    if(SD_WriteCmd(ptSDCard, CMD24, CMD24_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_WRITE_CMD24_ERROR;
    }

    /* Check for an error, like a misaligned write */
    if(g_ucResponse[0] != 0)
    {
        return SD_WRITE_RESPONSE_ERROR | (g_ucResponse[0])<<8;
    }
    
    /* Re-assert CS to continue the transfer */
    SPI_SetCS(ptSDCard->eSPIId, ptSDCard->uiCSId);

    /* Kick off the transfer by sending the first byte, the "start block"
    * token */
    SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, SD_TOK_WRITE_STARTBLOCK);

    for(i = 0; i < SD_BLOCKSIZE / SD_DMA_WRITE_LEN; i++)
    {
        SPI_DmaWrite(ptSDCard->eSPIId, pucData + i * SD_DMA_WRITE_LEN);
    }

    SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);
    SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);     // 2 CRC bytes
    
    data_response = (uint8)SPI_GetChar(ptSDCard->eSPIId);   // get data response 

    result = SD_FAILURE;    // default result is success.
    
    if(data_response == SD_DRSP_CC_ERROR)
    {
        result = SD_WRITE_CRC_ERROR;
    }
    else if(data_response == SD_DRSP_WR_ERROR)
    {
        result = SD_WRITE_WR_ERROR;
    }
    else if(data_response == SD_DRSP_ACCEPT)
    {
        result = SD_SUCCESS;
    }

    /* Signal that the card may be busy, so any subsequent commands
    should wait for the busy signalling to end (indicated by a
    nonzero response). */
    ptSDCard->bBusyFlag = SCI_TRUE;
    if ((result1 = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
    {
        return result1;
    }

    SPI_SetCS(ptSDCard->eSPIId, CS_NONE);
    return result;
}

/*****************************************************************************/
//  Description:    This function is used to write multiple block data.   
//  Author:         Benjamin.Wang
//  Note:           The block size is fixed 512 Bytes.
/*****************************************************************************/
PUBLIC uint32 SD_WriteMultiBlock(           // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint32 uiStartBlocknum,         // the start block
    uint32 uiBlockCounts,           // the writing counts
    const uint8* pucData                      // the data pointer
    )
{
    uint32 i;
    uint32 j;
    uint32 block_address;
    uint8 data_response;
    uint32 result, result1;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }

    if (g_sd_default_blocksize != SD_BLOCKSIZE)
    {
        if(SD_SetBlockLength(ptSDCard, SD_BLOCKSIZE) != SD_SUCCESS)
        {
            return SD_BLOCK_LENGTH_INVALID;
        }
    }

⌨️ 快捷键说明

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