?? sdmmc_mci.c
字號:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <mci/mci.h>
#include "sdmmc_mci.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
#include <string.h>
//------------------------------------------------------------------------------
// Local constants
//------------------------------------------------------------------------------
// SD card operation states
#define SD_STATE_STBY 0
#define SD_STATE_DATA 1
#define SD_STATE_RCV 2
// Card type
#define UNKNOWN_CARD 0
#define CARD_SD 1
#define CARD_SDHC 2
#define CARD_MMC 3
// Delay between sending MMC commands
#define MMC_DELAY 0x4FF
#define SD_ADDRESS(pSd, address) (((pSd)->cardType == CARD_SDHC) ? \
(address):((address) << SD_BLOCK_SIZE_BIT))
//-----------------------------------------------------------------------------
/// MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
/// R1 is the low order byte; R2 is the next highest byte, when present.
//-----------------------------------------------------------------------------
#define R1_SPI_IDLE (1 << 0)
#define R1_SPI_ERASE_RESET (1 << 1)
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
#define R1_SPI_COM_CRC (1 << 3)
#define R1_SPI_ERASE_SEQ (1 << 4)
#define R1_SPI_ADDRESS (1 << 5)
#define R1_SPI_PARAMETER (1 << 6)
// R1 bit 7 is always zero
#define R2_SPI_CARD_LOCKED (1 << 0)
#define R2_SPI_WP_ERASE_SKIP (1 << 1)
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
#define R2_SPI_ERROR (1 << 2)
#define R2_SPI_CC_ERROR (1 << 3)
#define R2_SPI_CARD_ECC_ERROR (1 << 4)
#define R2_SPI_WP_VIOLATION (1 << 5)
#define R2_SPI_ERASE_PARAM (1 << 6)
#define R2_SPI_OUT_OF_RANGE (1 << 7)
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
// Status register constants
#define STATUS_READY_FOR_DATA (1 << 8)
#define STATUS_IDLE (0 << 9)
#define STATUS_READY (1 << 9)
#define STATUS_IDENT (2 << 9)
#define STATUS_STBY (3 << 9)
#define STATUS_TRAN (4 << 9)
#define STATUS_DATA (5 << 9)
#define STATUS_RCV (6 << 9)
#define STATUS_PRG (7 << 9)
#define STATUS_DIS (8 << 9)
#define STATUS_STATE (0xF << 9)
//-----------------------------------------------------------------------------
/// OCR Register
//-----------------------------------------------------------------------------
#define AT91C_VDD_16_17 (1 << 4)
#define AT91C_VDD_17_18 (1 << 5)
#define AT91C_VDD_18_19 (1 << 6)
#define AT91C_VDD_19_20 (1 << 7)
#define AT91C_VDD_20_21 (1 << 8)
#define AT91C_VDD_21_22 (1 << 9)
#define AT91C_VDD_22_23 (1 << 10)
#define AT91C_VDD_23_24 (1 << 11)
#define AT91C_VDD_24_25 (1 << 12)
#define AT91C_VDD_25_26 (1 << 13)
#define AT91C_VDD_26_27 (1 << 14)
#define AT91C_VDD_27_28 (1 << 15)
#define AT91C_VDD_28_29 (1 << 16)
#define AT91C_VDD_29_30 (1 << 17)
#define AT91C_VDD_30_31 (1 << 18)
#define AT91C_VDD_31_32 (1 << 19)
#define AT91C_VDD_32_33 (1 << 20)
#define AT91C_VDD_33_34 (1 << 21)
#define AT91C_VDD_34_35 (1 << 22)
#define AT91C_VDD_35_36 (1 << 23)
#define AT91C_CARD_POWER_UP_BUSY (1 << 31)
#define AT91C_MMC_HOST_VOLTAGE_RANGE (AT91C_VDD_27_28 +\
AT91C_VDD_28_29 +\
AT91C_VDD_29_30 +\
AT91C_VDD_30_31 +\
AT91C_VDD_31_32 +\
AT91C_VDD_32_33)
#define AT91C_CCS (1 << 30)
// MCI_CMD Register Value
#define AT91C_POWER_ON_INIT (0 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_INIT | AT91C_MCI_OPDCMD)
//-----------------------------------------------------------------------------
// Command Classes
//-----------------------------------------------------------------------------
//
// Class 0, 2, 4, 5, 7 and 8 are mandatory and shall be supported by all SD Memory Cards.
// Basic Commands (class 0)
//
// Cmd0 MCI + SPI
#define AT91C_GO_IDLE_STATE_CMD (0 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE )
// Cmd1 SPI
#define AT91C_MMC_SEND_OP_COND_CMD (1 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_OPDCMD)
// Cmd2 MCI
#define AT91C_ALL_SEND_CID_CMD (2 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_136 )
// Cmd3 MCI
#define AT91C_SET_RELATIVE_ADDR_CMD (3 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
// Cmd4 MCI
//#define AT91C_SET_DSR_CMD (4 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_NO | AT91C_MCI_MAXLAT )
// cmd7 MCI
#define AT91C_SEL_DESEL_CARD_CMD (7 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
// Cmd8 MCI + SPI
#define AT91C_SEND_IF_COND (8 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
// Cmd9 MCI + SPI
#define AT91C_SEND_CSD_CMD (9 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_136 | AT91C_MCI_MAXLAT )
// Cmd10 MCI + SPI
#define AT91C_SEND_CID_CMD (10 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_136 | AT91C_MCI_MAXLAT )
// Cmd12 MCI + SPI
#define AT91C_STOP_TRANSMISSION_CMD (12 | AT91C_MCI_TRCMD_STOP | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
// Cmd13 MCI + SPI
#define AT91C_SEND_STATUS_CMD (13 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
// Cmd15 MCI
//#define AT91C_GO_INACTIVE_STATE_CMD (15 | AT91C_MCI_RSPTYP_NO )
// Cmd58 SPI
#define AT91C_READ_OCR_CMD (58 | AT91C_MCI_RSPTYP_48 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_MAXLAT )
// Cmd59 SPI
#define AT91C_CRC_ON_OFF_CMD (59 | AT91C_MCI_RSPTYP_48 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_MAXLAT )
//#define AT91C_MMC_ALL_SEND_CID_CMD (2 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_136| AT91C_MCI_OPDCMD)
//#define AT91C_MMC_SET_RELATIVE_ADDR_CMD (3 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT | AT91C_MCI_OPDCMD)
//#define AT91C_MMC_READ_DAT_UNTIL_STOP_CMD (11 | AT91C_MCI_TRTYP_STREAM| AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRDIR | AT91C_MCI_TRCMD_START | AT91C_MCI_MAXLAT )
//#define AT91C_STOP_TRANSMISSION_SYNC_CMD (12 | AT91C_MCI_TRCMD_STOP | AT91C_MCI_SPCMD_SYNC | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
//*------------------------------------------------
//* Class 2 commands: Block oriented Read commands
//*------------------------------------------------
// Cmd16
#define AT91C_SET_BLOCKLEN_CMD (16 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_MAXLAT )
// Cmd17
#define AT91C_READ_SINGLE_BLOCK_CMD (17 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_START | AT91C_MCI_TRTYP_BLOCK | AT91C_MCI_TRDIR | AT91C_MCI_MAXLAT)
// Cmd18
#define AT91C_READ_MULTIPLE_BLOCK_CMD (18 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_START | AT91C_MCI_TRTYP_MULTIPLE | AT91C_MCI_TRDIR | AT91C_MCI_MAXLAT)
//*------------------------------------------------
//* Class 4 commands: Block oriented write commands
//*------------------------------------------------
// Cmd24
#define AT91C_WRITE_BLOCK_CMD (24 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_START | (AT91C_MCI_TRTYP_BLOCK & ~(AT91C_MCI_TRDIR)) | AT91C_MCI_MAXLAT)
// Cmd25
#define AT91C_WRITE_MULTIPLE_BLOCK_CMD (25 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_START | (AT91C_MCI_TRTYP_MULTIPLE & ~(AT91C_MCI_TRDIR)) | AT91C_MCI_MAXLAT)
// Cmd27
//#define AT91C_PROGRAM_CSD_CMD (27 | AT91C_MCI_RSPTYP_48 )
//*----------------------------------------
//* Class 5 commands: Erase commands
//*----------------------------------------
// Cmd32
//#define AT91C_TAG_SECTOR_START_CMD (32 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// Cmd33
//#define AT91C_TAG_SECTOR_END_CMD (33 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// Cmd38
//#define AT91C_ERASE_CMD (38 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT )
//*----------------------------------------
//* Class 7 commands: Lock commands
//*----------------------------------------
// Cmd42
//#define AT91C_LOCK_UNLOCK (42 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT) // not tested
//*-----------------------------------------------
// Class 8 commands: Application specific commands
//*-----------------------------------------------
// Cmd55
#define AT91C_APP_CMD (55 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// cmd 56
//#define AT91C_GEN_CMD (56 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT) // not tested
// ACMD6
#define AT91C_SDCARD_SET_BUS_WIDTH_CMD (6 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// ACMD13
//#define AT91C_SDCARD_STATUS_CMD (13 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_START | AT91C_MCI_TRTYP_BLOCK | AT91C_MCI_TRDIR | AT91C_MCI_MAXLAT)
// ACMD22
//#define AT91C_SDCARD_SEND_NUM_WR_BLOCKS_CMD (22 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// ACMD23
//#define AT91C_SDCARD_SET_WR_BLK_ERASE_COUNT_CMD (23 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// ACMD41
#define AT91C_SDCARD_APP_OP_COND_CMD (41 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO )
// ACMD42
//#define AT91C_SDCARD_SET_CLR_CARD_DETECT_CMD (42 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
// ACMD51
#define AT91C_SDCARD_SEND_SCR_CMD (51 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO | AT91C_MCI_MAXLAT)
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Sends the current SD card driver command to the card.
/// Returns 0 if successful; Otherwise, returns the transfer status code or
/// SD_ERROR_DRIVER if there was a problem with the SD transfer.
/// \param pSd Pointer to a SdCard driver instance.
//------------------------------------------------------------------------------
static unsigned char SendCommand(SdCard *pSd)
{
SdCmd *pCommand = &(pSd->command);
SdDriver *pSdDriver = pSd->pSdDriver;
unsigned char error;
unsigned int i;
// Send command
error = MCI_SendCommand((Mci *)pSdDriver, (MciCmd *)pCommand);
if (error) {
TRACE_ERROR("MCI SendCommand: Failed to send command (%d)\n\r", error);
return SD_ERROR_DRIVER;
}
// Wait for command to complete
while (!MCI_IsTxComplete((MciCmd *)pCommand));
if(pCommand->cmd == AT91C_STOP_TRANSMISSION_CMD) {
while (MCI_CheckBusy((Mci *)pSdDriver) != 0);
}
// Delay between sending commands, only for MMC card test.
if((pSd->cardType == CARD_MMC)
||(pSd->cardType == UNKNOWN_CARD)
||(pSd->cardType == CARD_SD)) {
for(i=0; i < MMC_DELAY; i++);
}
return pCommand->status;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void DecodeR1(unsigned char R1)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -