📄 mci_device.c
字号:
/*----------------------------------------------------------------------------* ATMEL Microcontroller Software Support - ROUSSET -*----------------------------------------------------------------------------* The software is delivered "AS IS" without warranty or condition of any* kind, either express, implied or statutory. This includes without* limitation any warranty or condition with respect to merchantability or* fitness for any particular purpose, or against the infringements of* intellectual property rights of others.*----------------------------------------------------------------------------* File Name : mci_device.c* Object : TEST DataFlash Functions* Creation : FB 26/11/2002**----------------------------------------------------------------------------*/#include "AT91C_MCI_Device.h"/*----------------------------------------------------------------------------* \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<100) );*/ /* 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<100) ); */ /* 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_GetStatus*//** \brief Addressed card sends its status register*//**----------------------------------------------------------------------------*/AT91S_MCIDeviceStatus AT91F_MCI_GetStatus(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_Device_Handler*//** \brief MCI C interrupt handler*//**----------------------------------------------------------------------------*/void AT91F_MCI_Device_Handler( AT91PS_MciDevice pMCI_Device, unsigned int status){ /* If End of Tx Buffer Empty interrupt occurred*/ if ( status & AT91C_MCI_TXBUFE ) { AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_TXBUFE; AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTDIS; pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_IDLE; } /* End of if AT91C_MCI_TXBUFF */ /* If End of Rx Buffer Full interrupt occurred*/ if ( status & AT91C_MCI_RXBUFF ) { AT91C_BASE_MCI->MCI_IDR = AT91C_MCI_RXBUFF; AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTDIS; pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_IDLE; } /* End of if AT91C_MCI_RXBUFF*/}/**----------------------------------------------------------------------------*//** \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(pMCI_Device->pMCI_DeviceDesc->state != AT91C_MCI_IDLE) return AT91C_READ_ERROR; if( (AT91F_MCI_GetStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address) & AT91C_SR_READY_FOR_DATA) != AT91C_SR_READY_FOR_DATA) return AT91C_READ_ERROR; if ( (src + sizeToRead) > pMCI_Device->pMCI_DeviceFeatures->Memory_Capacity ) return AT91C_READ_ERROR; /* If source does not fit a begin of a block*/ if ( (src % pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) != 0 ) return AT91C_READ_ERROR; /* Test if the MMC supports Partial Read Block*/ /* ALWAYS SUPPORTED IN SD Memory Card*/ if( (sizeToRead < pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) && (pMCI_Device->pMCI_DeviceFeatures->Read_Partial == 0x00) ) return AT91C_READ_ERROR; if( sizeToRead > pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) return AT91C_READ_ERROR; /********************************/ /* Init Mode Register*/ 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; /* 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; pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_RX_SINGLE_BLOCK; /* Enable AT91C_MCI_RXBUFF Interrupt*/ AT91C_BASE_MCI->MCI_IER = AT91C_MCI_RXBUFF; /* (PDC) Receiver Transfer Enable*/ AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_RXTEN; 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( pMCI_Device->pMCI_DeviceDesc->state != AT91C_MCI_IDLE) return AT91C_WRITE_ERROR; if( (AT91F_MCI_GetStatus(pMCI_Device,pMCI_Device->pMCI_DeviceFeatures->Relative_Card_Address) & AT91C_SR_READY_FOR_DATA) != AT91C_SR_READY_FOR_DATA) return AT91C_WRITE_ERROR; if ( (dest + sizeToWrite) > pMCI_Device->pMCI_DeviceFeatures->Memory_Capacity ) return AT91C_WRITE_ERROR; /* If source does not fit a begin of a block*/ if ( (dest % pMCI_Device->pMCI_DeviceFeatures->Max_Read_DataBlock_Length) != 0 ) return AT91C_WRITE_ERROR; /* Test if the MMC supports Partial Write Block */ if( (sizeToWrite < pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length) && (pMCI_Device->pMCI_DeviceFeatures->Write_Partial == 0x00) ) return AT91C_WRITE_ERROR; if( sizeToWrite > pMCI_Device->pMCI_DeviceFeatures->Max_Write_DataBlock_Length ) return AT91C_WRITE_ERROR; /* Init Mode Register*/ 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; pMCI_Device->pMCI_DeviceDesc->state = AT91C_MCI_TX_SINGLE_BLOCK; /* Enable AT91C_MCI_TXBUFE Interrupt*/ AT91C_BASE_MCI->MCI_IER = AT91C_MCI_TXBUFE; /* Enables TX for PDC transfert requests*/ AT91C_BASE_PDC_MCI->PDC_PTCR = AT91C_PDC_TXTEN; return AT91C_WRITE_OK;}/**------------------------------------------------------------------------------------------------------------*//** \fn AT91F_MCI_MMC_SelectCard*//** \brief Toggles a card between the Stand_by and Transfer states or between Programming and Disconnect states*//**------------------------------------------------------------------------------------------------------------*/AT91S_MCIDeviceStatus AT91F_MCI_MMC_SelectCard(AT91PS_MciDevice pMCI_Device, unsigned int relative_card_address){ int status; /** Check if the MMC card chosen is already the selected one*/ status = AT91F_MCI_GetStatus(pMCI_Device,relative_card_address); if (status < 0) return AT91C_CARD_SELECTED_ERROR; if ((status & AT91C_SR_CARD_SELECTED) == AT91C_SR_CARD_SELECTED) return AT91C_CARD_SELECTED_OK; /** Search for the MMC Card to be selected, status = the Corresponding Device Number*/ status = 0; while( (pMCI_Device->pMCI_DeviceFeatures[status].Relative_Card_Address != relative_card_address) && (status < AT91C_MAX_MCI_CARDS) ) status++; if (status > AT91C_MAX_MCI_CARDS) return AT91C_CARD_SELECTED_ERROR; if (AT91F_MCI_SendCommand( pMCI_Device,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -