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

📄 sd.c

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

    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
    
    /* Adjust the block address to a linear address */
    block_address = uiStartBlocknum << SD_BLOCKSIZE_NBITS;
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, block_address);
    if(SD_WriteCmd(ptSDCard, CMD25, CMD25_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_WRITEMULTI_CMD25_ERROR;
    }

    /* Check for an error, like a misaligned write */
    if(g_ucResponse[0] != 0)
    {
        return SD_WRITEMULTI_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++)
    {
        /* Kick off the transfer by sending the first byte, the "start block"
        * token */
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, SD_TOK_WRITE_STARTBLOCK_M);
    
        //sd card DMA write
        for(i = 0; i < SD_BLOCKSIZE / SD_DMA_WRITE_LEN; i++)
        {
            SPI_DmaWrite(ptSDCard->eSPIId, pucData + j * SD_BLOCKSIZE + i * SD_DMA_WRITE_LEN);
        }
    
        /* Write 2 invalid CRC bytes*/
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);
        SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, 0);     

        i = 0;
        do
        {
            data_response = (uint8)SPI_GetChar(ptSDCard->eSPIId);
            i++;
        }
        while((data_response == 0xFF) && i < ptSDCard->uiWriteTimeout);

        if((data_response & MSK_TOK_DATAERROR) != MSK_TOK_DATAERROR)
        {
            /* 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_WRITEMULTI_DATA_RESPONSE_ERROR | data_response<<8;
        }

        result = SD_FAILURE;    // default result is success.
    
        if(data_response == SD_DRSP_CC_ERROR)
        {
            result = SD_WRITE_CRC_ERROR;
            break;
        }
        else if(data_response == SD_DRSP_WR_ERROR)
        {
            result = SD_WRITE_WR_ERROR;
            break;
        }
        else if(data_response == SD_DRSP_ACCEPT)
        {
            result = SD_SUCCESS;
        }
        else
        {
             return result;
        }
        
        ptSDCard->bBusyFlag = SCI_TRUE;
		if ((result1 = SD_WaitNotBusy( ptSDCard)) != SD_SUCCESS)
        {
        	return result1;
        }
    }
    
    SPI_PutChar(ptSDCard->eSPIId, ptSDCard->uiCSId, SD_TOK_STOP_MULTI);

    /* 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:    Once the programming operation is completed, the host must check the 
//                      results of  the programming using the SEND_STATUS command(CMD13). 
//                      Some errors(e.g., address out of range, write protect violation, etc.)are 
//                      detected during programming only.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_SendStatus(        // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint8* pucStatus                    // the response status(2 bytes)
                                                // Byte[0] - bit7: Always 0
                                                //                bit6: Parameter Error
                                                //                bit5: Address Error
                                                //                bit4: Erase Sequence Error
                                                //                bit3: Com CRC Error
                                                //                bit2: Illegal Command
                                                //                bit1: Erase Reset
                                                //                bit0:In Idle State
                                                // Byte[1] - bit7: Out of Range, CSD_Overwrite
                                                //                bit6: Erase Param
                                                //                bit5: WP Violation
                                                //                bit4: Card ECC Failed
                                                //                bit3: CC Error
                                                //                bit2: Error
                                                //                bit1: WP Erase Skip, Lock/Unlock Cmd Failed
                                                //                bit0: Card is Locked
    )
{  
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to the setting speed

    /* Pack the arguments */
    SD_Packarg(g_ucArgument, 0);
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD13, CMD13_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_SENDSTATUS_CMD13_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[1] != 0)
    {
        return SD_SENDSTATUS_RESPONSE_ERROR | (g_ucResponse[1])<<8;
    }

    pucStatus[0] = g_ucResponse[1];
    pucStatus[1] = g_ucResponse[0];
    
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    In multiple-block write operations, the stop transmission is done by sending, 
//                      at the beginning of the next block, a Stop Tran token, instead of a Start Block 
//                      token. In case of Write Error indication(on the data response)the host shall use 
//                      SEND_NUM_WR_BLOCKS(ACMD22) in order to get the number of well written 
//                      write blocks.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_SendNumWrBlocks(       // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the Card Vector
    uint8* pucData                      // the number of well written write blocks
    )
{  
    uint32 i = 0;
    uint8 tmp;
    
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to the setting speed

    /* Pack the arguments */
    SD_Packarg(g_ucArgument, 0);
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);

    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD55, CMD55_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_SENDNUMWRBLOCKS_CMD55_ERROR;
    }

     /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_SENDNUMWRBLOCKS_RESPONSE_ERROR1 | (g_ucResponse[0])<<8;
    }
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, ACMD22, ACMD22_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_SENDNUMWRBLOCKS_CMD22_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_SENDNUMWRBLOCKS_RESPONSE_ERROR2 | (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 & MSK_TOK_DATAERROR) == 0)
    {
        /* 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_SENDNUMWRBLOCKS_TOKEN_ERROR | tmp<<8;
    }

    for(i = 0; i < 4 + 2; i++)      //32bits + CRC data block
    {
        pucData[i] = (uint8)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 set the read block length. The maximum block length 
//                      is 512 bytes. Block lengths can be any number between 1 and 512 bytes. But 
//                      in write mode, the only valid block length is 512 bytes.
//  Author:         Benjamin.Wang
//  Note:       At present, the sdcard driver only supports the card whose capability
//              is less than or equal to 2GB.     
/*****************************************************************************/
PUBLIC uint32 SD_SetBlockLength(        // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,        // the card vector
    uint32 uiBlockLength            // the block length
    )
{
	if (uiBlockLength > 512)
	{
		return SD_SETBLOCKLENGTH_PARAM_ERROR;
	}
    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to the setting speed

    /* Pack the arguments */
    SD_Packarg(g_ucArgument, uiBlockLength);
    
    /* Wait until any old transfers are finished */
    //SD_WaitNotBusy(ptSDCard);
    
    /* Need to add size checking */
    if(SD_WriteCmd(ptSDCard, CMD16, CMD16_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_SETBLOCKLENGTH_CMD16_ERROR;
    }
    
    /* Check for an error, like a misaligned read */
    if(g_ucResponse[0] != 0)
    {
        return SD_SETBLOCKLENGTH_RESPONSE_ERROR | (g_ucResponse[0])<<8;
    }
    g_sd_default_blocksize = uiBlockLength;
    return SD_SUCCESS;
}

/*****************************************************************************/
//  Description:    This function is used to erase data.
//  Author:         Benjamin.Wang
//  Note:           
/*****************************************************************************/
PUBLIC uint32 SD_Erase(     // return status. SD_SUCCESS - success
    SD_CARD_T* ptSDCard,    // the card vector
    uint32 uiStartBlock,        // the start block
    uint32 uiEndBlock           // the end block 
    )
{
    uint32 start_block_address;
    uint32 end_block_address;
    uint32 result;

    if(!SD_RegisterVerify(ptSDCard))    //verify the SDCard vector
    {
        return SD_UNREGISTER;
    }
    
    SPI_SetBusClk(ptSDCard->eSPIId, ptSDCard->uiClockRate); // set spi bus clock to max speed
    
    /* Adjust the block address to a linear address */
    start_block_address = uiStartBlock << SD_BLOCKSIZE_NBITS;
    
    /* Pack the address */
    SD_Packarg(g_ucArgument, start_block_address);
    if(SD_WriteCmd(ptSDCard, CMD32, CMD32_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_ERASE_CMD32_ERROR;
    }

    /* Check for an error, like a misaligned write */
    if(g_ucResponse[0] != 0)
    {
        return SD_ERASE_RESPONSE_ERROR1 | (g_ucResponse[0])<<8;
    }

    /* Adjust the end block address to a linear address */
    end_block_address = ((uiEndBlock + 1) << SD_BLOCKSIZE_NBITS) - 1;
    /* Pack the address */
    SD_Packarg(g_ucArgument, end_block_address);
    if(SD_WriteCmd(ptSDCard, CMD33, CMD33_R, g_ucResponse, g_ucArgument) != SD_SUCCESS)
    {
        return SD_ERASE_CMD33_ERROR;
    }

    /* Check for an error, like a misaligned write */
    if(g_ucResponse[0] != 0)
    {
        return SD_ERASE_RESPONSE_ERROR2 | (g_ucResponse[0])<<8;
    }

    /* Pack the address */
    SD_Packarg(g_ucArgument, 0);

⌨️ 快捷键说明

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