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

📄 mci.c

📁 关于测试at91sam9260的各种驱动和功能的测试源代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************** Copyright (c) *************************************************
*
*			            POLAR STAR
*				   北天星国际有限公司
*				   http://www.po-star.com
*
*文 件 名: mci.c    
*
*编译环境:ADS1.2
*
********************************************************************************************************/


#include "main.h"
#include "mci.h"

#include <stdio.h>

// Global Variables
AT91S_MciDeviceFeatures   MCI_Device_Features;
AT91S_MciDeviceDesc       MCI_Device_Desc;
AT91S_MciDevice		  	  MCI_Device;
char                      Buffer[BUFFER_SIZE_MCI_DEVICE];

//*----------------------------------------------------------------------------
//* \fn    AT91F_CfgDevice
//* \brief This function is used to initialise MMC or SDCard Features
//*----------------------------------------------------------------------------
void AT91F_CfgDevice(void)
{
	// Init Device Structure
	MCI_Device_Features.Relative_Card_Address 	= 0;
	MCI_Device_Features.Card_Inserted 		= AT91C_CARD_REMOVED;
	MCI_Device_Features.Max_Read_DataBlock_Length	= 0;
	MCI_Device_Features.Max_Write_DataBlock_Length 	= 0;
	MCI_Device_Features.Read_Partial 		= 0;
	MCI_Device_Features.Write_Partial 		= 0;
	MCI_Device_Features.Erase_Block_Enable 		= 0;
	MCI_Device_Features.Sector_Size 		= 0;
	MCI_Device_Features.Memory_Capacity 		= 0;
	
	MCI_Device_Desc.state				= AT91C_MCI_IDLE;
	MCI_Device_Desc.SDCard_bus_width		= AT91C_MCI_SCDBUS;

	MCI_Device.pMCI_DeviceDesc 	= &MCI_Device_Desc;
	MCI_Device.pMCI_DeviceFeatures 	= &MCI_Device_Features;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_MCI_SendCommand
//* \brief Generic function to send a command to the MMC or SDCard
//*----------------------------------------------------------------------------
AT91S_MCIDeviceStatus AT91F_MCI_SendCommand (
	AT91PS_MciDevice pMCI_Device,
	unsigned int Cmd,
	unsigned int Arg)
{
    unsigned int	error,status;
    unsigned int	tick=0;

    // Send the command
    AT91C_BASE_MCI->MCI_ARGR = Arg;
    AT91C_BASE_MCI->MCI_CMDR = Cmd;

    // wait for CMDRDY Status flag to read the response
    do  {
            status = AT91C_BASE_MCI->MCI_SR;
            tick++;
    }
    while( !(status & AT91C_MCI_CMDRDY) && (tick<AT91C_TIMEOUT_CMDRDY) );

    // Test error  ==> if crc error and response R3 ==> don't check error
    error = (AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR;
    if(error != 0 )
    {
        // if the command is SEND_OP_COND the CRC error flag is always present (cf : R3 response)
        if ( (Cmd != AT91C_SDCARD_APP_OP_COND_CMD) && (Cmd != AT91C_MMC_SEND_OP_COND_CMD) )
                return ((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR);
        else
        {
                if (error != AT91C_MCI_RCRCE)
                        return ((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR);
        }
    }
    return AT91C_CMD_SEND_OK;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_MCI_SDCard_SendAppCommand
//* \brief Specific function to send a specific command to the SDCard
//*----------------------------------------------------------------------------
AT91S_MCIDeviceStatus AT91F_MCI_SDCard_SendAppCommand (
	AT91PS_MciDevice pMCI_Device,
	unsigned int Cmd_App,
	unsigned int Arg	)
{
    unsigned int status;
    unsigned int tick=0;

	// Send the CMD55 for application specific command
    AT91C_BASE_MCI->MCI_ARGR = (pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address << 16 );
    AT91C_BASE_MCI->MCI_CMDR = AT91C_APP_CMD;

    // wait for CMDRDY Status flag to read the response
    do  {
            status = AT91C_BASE_MCI->MCI_SR;
            tick++;
    }
    while( !(status & AT91C_MCI_CMDRDY) && (tick<AT91C_TIMEOUT_CMDRDY) );	

    // if an error occurs
    if (((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR) != 0 )
    	return ((AT91C_BASE_MCI->MCI_SR) & AT91C_MCI_SR_ERROR);

    // check if it is a specific command and then send the command
    if ( (Cmd_App && AT91C_SDCARD_APP_ALL_CMD) == 0)
      return AT91C_CMD_SEND_ERROR;

   return( AT91F_MCI_SendCommand(pMCI_Device,Cmd_App,Arg) );
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_MCI_GetCardStatus
//* \brief Addressed card sends its status register
//*----------------------------------------------------------------------------
AT91S_MCIDeviceStatus AT91F_MCI_GetCardStatus(AT91PS_MciDevice pMCI_Device,unsigned int relative_card_address)
{
	if (AT91F_MCI_SendCommand(pMCI_Device,
            AT91C_SEND_STATUS_CMD,
            relative_card_address <<16) == AT91C_CMD_SEND_OK)
    	return (AT91C_BASE_MCI->MCI_RSPR[0]);

    return AT91C_CMD_SEND_ERROR;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_MCI_ReadBlock
//* \brief Read an ENTIRE block or PARTIAL block
//*----------------------------------------------------------------------------
AT91S_MCIDeviceStatus AT91F_MCI_ReadBlock(
	AT91PS_MciDevice pMCI_Device,
	int src,
	unsigned int *dataBuffer,
	int sizeToRead )
{
    if( (AT91F_MCI_GetCardStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address) & AT91C_SR_READY_FOR_DATA) != AT91C_SR_READY_FOR_DATA)
    	return AT91C_READ_ERROR;
      
    // Init Mode Register
    AT91C_BASE_MCI->MCI_MR &= ~AT91C_MCI_BLKLEN;
    AT91C_BASE_MCI->MCI_MR |= ((pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length << 16) | AT91C_MCI_PDCMODE);
	 
    if (sizeToRead %4)
        sizeToRead = (sizeToRead /4)+1;
    else
        sizeToRead = sizeToRead/4;

    AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS);
    AT91C_BASE_PDC_MCI->PDC_RPR  = (unsigned int)dataBuffer;
    AT91C_BASE_PDC_MCI->PDC_RCR  = sizeToRead;

    // (PDC) Receiver Transfer Enable
    AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN;   

    // Send the Read single block command
    if ( AT91F_MCI_SendCommand(pMCI_Device, AT91C_READ_SINGLE_BLOCK_CMD, src) != AT91C_CMD_SEND_OK )
        return AT91C_READ_ERROR;

    while( (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_RXBUFF) !=  AT91C_MCI_RXBUFF);
    AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS;

    return AT91C_READ_OK;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_MCI_WriteBlock
//* \brief  Write an ENTIRE block but not always PARTIAL block !!!
//*----------------------------------------------------------------------------
AT91S_MCIDeviceStatus AT91F_MCI_WriteBlock(
	AT91PS_MciDevice pMCI_Device,
	int dest,
	unsigned int *dataBuffer,
	int sizeToWrite )
{
    if( (AT91F_MCI_GetCardStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address) & AT91C_SR_READY_FOR_DATA) != AT91C_SR_READY_FOR_DATA)
    	return AT91C_WRITE_ERROR;
    	
    // Init Mode Register
    AT91C_BASE_MCI->MCI_MR &= ~AT91C_MCI_BLKLEN;
    AT91C_BASE_MCI->MCI_MR |= ((pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length << 16) | AT91C_MCI_PDCMODE);
    
    if (sizeToWrite %4)
        sizeToWrite = (sizeToWrite /4)+1;
    else
        sizeToWrite = sizeToWrite/4;

    // Init PDC for write sequence
    AT91C_BASE_PDC_MCI->PDC_PTCR = (AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS);
    AT91C_BASE_PDC_MCI->PDC_TPR = (unsigned int) dataBuffer;
    AT91C_BASE_PDC_MCI->PDC_TCR = sizeToWrite;

    // Send the write single block command
    if ( AT91F_MCI_SendCommand(pMCI_Device, AT91C_WRITE_BLOCK_CMD, dest) != AT91C_CMD_SEND_OK)
    	return AT91C_WRITE_ERROR;

    // Enables TX for PDC transfert requests
    AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTEN;
  
    while( (AT91C_BASE_MCI->MCI_SR & AT91C_MCI_TXBUFE) !=  AT91C_MCI_TXBUFE);
    AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS;

    return AT91C_WRITE_OK;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_MCI_GetCSD
//* \brief Asks to the specified card to send its CSD

⌨️ 快捷键说明

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