?? mci_lpc23xx.c
字號(hào):
/*----------------------------------------------------------------------------
* R T L - F l a s h F i l e S y s t e m
*----------------------------------------------------------------------------
* Name: MCI_LPC23XX.C
* Purpose: Multimedia Card Interface Driver for LPC23xx
* Rev.: V3.05 / 22-mar-2007
*----------------------------------------------------------------------------
* This code is part of the RealView Run-Time Library.
* Copyright (c) 2004-2007 KEIL - An ARM Company. All rights reserved.
*---------------------------------------------------------------------------*/
#include <File_Config.h>
#include <LPC23xx.h> /* LPC23xx/24xx definitions */
#include "MCI_LPC23xx.h"
/* Local variables */
static U8 CardType;
static U16 CardRCA;
static MMCFG mmc_cfg;
/*----------------------------------------------------------------------------
* MMC Driver Functions
*----------------------------------------------------------------------------
* Required functions for MMC driver module:
* - BOOL mci_init ()
* - BOOL mci_read_sect (U32 sect, U8 *buf)
* - BOOL mci_write_sect (U32 sect, U8 *buf)
* - BOOL mmc_read_config (MMCFG *cfg)
*---------------------------------------------------------------------------*/
/* Local Function Prototypes */
static void mci_set_speed (U32 speed);
static void mci_bus_mode (U32 mode);
static BOOL mci_send_acmd (void);
static BOOL mci_set_address (void);
static BOOL mci_read_cid (void);
static BOOL mci_read_csd (void);
static BOOL mci_select_card (void);
static BOOL mci_set_bus_4bit (void);
static BOOL mci_set_block_len (void);
static BOOL mci_cmd_read_block (U32 block);
static BOOL mci_cmd_write_block (U32 block);
static U32 mci_read_status (void);
static BOOL mci_send_stop (void);
static U32 mci_command (U8 cmd, U32 arg, U32 resp, U32 *rp);
static void mci_dma_start (U32 mode, U8 *buf);
/*--------------------------- mci_init --------------------------------------*/
BOOL mci_init (void) {
/* Initialize and enable the Flash Card. */
U32 i,rstat,rval[4];
/* Power Up the MCI and DMA controller. */
PCONP |= 0x30000000;
/* Enable MCI Pins on P0,P2. */
PINSEL1 &= ~0x00003FC0;
PINSEL1 |= 0x00002A80;
PINSEL4 &= ~0x0FC00000;
PINSEL4 |= 0x0A800000;
/* Clear all pending interrupts. */
MCI_COMMAND = 0;
MCI_DATA_CTRL = 0;
MCI_CLEAR = 0x7FF;
/* Power up, switch on VCC for the Flash Card. */
MCI_POWER = 0x02;
for (i = 0; i < 50000; i++);
mci_set_speed (LOW_SPEED);
/* Power on the Flash Card. */
MCI_POWER |= 0x01;
for (i = 0; i < 50000; i++);
/* Reset the card, send CMD0. */
mci_command (GO_IDLE_STATE, 0, RESP_NONE, NULL);
/* Set Open Drain output control for MMC */
mci_bus_mode (OPEN_DRAIN_MODE);
CardType = CARD_NONE;
/* First try MMC, send CMD1. */
for (i = 0; i < 100; i++) {
rstat = mci_command (SEND_OP_COND, OCR_INDEX, RESP_SHORT, &rval[0]);
if (!(rstat & MCI_CMD_TIMEOUT) && rval[0] & 0x80000000) {
CardType = CARD_MMC;
break;
}
}
if (CardType == CARD_NONE) {
/* Check for SD card, clear Open Drain output control. */
mci_bus_mode (PUSH_PULL_MODE);
for (i = 0; i < 500; i++) {
if (mci_send_acmd () == __TRUE) {
rstat = mci_command (SEND_APP_OP_COND,
OCR_INDEX, RESP_SHORT, &rval[0]);
if (!(rstat & MCI_CMD_TIMEOUT) && rval[0] & 0x80000000) {
/* OK, SD card initialized. */
CardType = CARD_SD;
break;
}
}
}
}
if (CardType == CARD_NONE) {
/* Failed, no card found. */
goto fail;
}
/* Initialize the Card to SD/MMC mode. */
if (mci_read_cid () == __FALSE) {
goto fail;
}
if (mci_set_address () == __FALSE) {
goto fail;
}
/* Disable Open Drain mode for MMC. */
if (CardType == CARD_MMC) {
mci_bus_mode (PUSH_PULL_MODE);
}
/* Data Transfer Mode, end of Card-Identification Mode. */
mci_set_speed (HIGH_SPEED);
if (mci_read_csd () == __FALSE) {
goto fail;
}
if (mci_select_card () == __FALSE) {
goto fail;
}
if (CardType == CARD_SD) {
/* Use wide 4-bit bus for SD */
MCI_CLOCK |= 0x0800;
for (i = 0; i < 100; i++);
if (mci_set_bus_4bit () == __FALSE) {
/* Failed to enable 4-bit bus. */
goto fail;
}
}
/* Set block length to 512 bytes. */
if (mci_set_block_len () == __FALSE) {
fail: MCI_POWER = 0x00;
return (__FALSE);
}
/* Success, card initialized. */
return (__TRUE);
}
/*--------------------------- mci_set_speed ---------------------------------*/
static void mci_set_speed (U32 speed) {
/* Set a MCI clock speed to desired value. */
U32 i,clkdiv;
if (speed == HIGH_SPEED) {
/* Max. 20 MBit used for Data Transfer. */
clkdiv = 1;
}
else {
/* Max. 400 kBit used in Card Initialization. */
clkdiv = 120;
}
MCI_CLOCK = (MCI_CLOCK & ~0xFF) | 0x300 | clkdiv;
/* delay 3MCLK + 2PCLK before next write */
for ( i = 0; i < 100; i++ );
}
/*--------------------------- mci_bus_mode ----------------------------------*/
static void mci_bus_mode (U32 mode) {
/* Set MCI Bus mode to Open Drain or Push Pull. */
U32 i;
if (mode == OPEN_DRAIN_MODE) {
MCI_POWER |= 0x40;
}
else {
MCI_POWER &= ~0x40;
}
/* A small delay after switching mode. */
for (i = 0; i < 100; i++);
}
/*--------------------------- mci_send_acmd ---------------------------------*/
static BOOL mci_send_acmd (void) {
/* Send CMD55 to enable ACMD */
U32 arg,rstat,rval;
arg = 0;
if (CardType == CARD_SD) {
/* Use address from SET_RELATIVE_ADDR. */
arg = CardRCA << 16;
}
rstat = mci_command (APP_CMD, arg, RESP_SHORT, &rval);
if (rstat == 0 && (rval & STAT_ACMD_ENABLE)) {
return (__TRUE);
}
return (__FALSE);
}
/*--------------------------- mci_set_address -------------------------------*/
static BOOL mci_set_address (void) {
/* Set Relative Address, send CMD3 after CMD2. */
U32 i,arg,rstat,rval;
arg = 0;
if (CardType == CARD_MMC) {
/* Fix the RCA address for MMC card. */
arg = 0x00010000;
}
for (i = 0; i < 20; i++) {
rstat = mci_command (SET_RELATIVE_ADDR, arg, RESP_SHORT, &rval);
if (!(rstat & MCI_CMD_TIMEOUT) && (rval & 0x0F00) == 0x0500) {
/* Response is back and correct. */
CardRCA = rval >> 16;
return (__TRUE);
}
}
return (__FALSE);
}
/*--------------------------- mci_read_cid ----------------------------------*/
static BOOL mci_read_cid (void) {
/* Check CID, send CMD2 after CMD1 (MMC) or ACMD41 (SD). */
U32 i,rstat,v,rval[4];
for (i = 0; i < 20; i++) {
rstat = mci_command (ALL_SEND_CID, 0, RESP_LONG, &rval[0]);
if (!(rstat & MCI_CMD_TIMEOUT)) {
/* Response is back and correct. */
if (CardType == CARD_SD) {
/* Serial Number for SD Card. */
v = (rval[2] << 8) | (rval[3] >> 24);
}
else {
/* Serial Number for MMC Card. */
v = (rval[2] << 16) | (rval[3] >> 16);
}
mmc_cfg.sernum = v;
return (__TRUE);
}
}
mmc_cfg.sernum = 0;
return (__FALSE);
}
/*--------------------------- mci_read_csd ----------------------------------*/
static BOOL mci_read_csd (void) {
/* Send Card Specific Data, send CMD9 after CMD3. */
U32 i,arg,rstat,v,m,rval[4];
arg = 0x00010000;
if (CardType == CARD_SD) {
/* Use address from SET_RELATIVE_ADDR. */
arg = CardRCA << 16;
}
for (i = 0; i < 20; i++) {
rstat = mci_command (SEND_CSD, arg, RESP_LONG, &rval[0]);
if (rstat == 0) {
/* Response is back and correct, Read Block length */
v = (rval[1] >> 16) & 0x0F;
mmc_cfg.read_blen = 1 << v;
/* Write Block length */
v = (rval[3] >> 22) & 0x0F;
mmc_cfg.write_blen = 1 << v;
/* Total Number of blocks */
v = ((rval[1] << 2) | (rval[2] >> 30)) & 0x0FFF;
m = (rval[2] >> 15) & 0x07;
mmc_cfg.blocknr = (v + 1) << (m + 2);
/* File Format information */
v = (rval[3] >> 8) & 0x83;
switch (v) {
case 0x00:
case 0x03:
mmc_cfg.format = HDD_TYPE;
break;
case 0x01:
mmc_cfg.format = FLOPPY_TYPE;
break;
default:
mmc_cfg.format = UNKNOWN_TYPE;
break;
}
return (__TRUE);
}
}
return (__FALSE);
}
/*--------------------------- mci_select_card -------------------------------*/
static BOOL mci_select_card (void) {
/* Select the Card, send CMD7 after CMD9, inter-change state */
/* between STBY and TRANS after this command. */
U32 i,arg,rstat,rval;
arg = 0x00010000;
if (CardType == CARD_SD) {
/* Use address from SET_RELATIVE_ADDR. */
arg = CardRCA << 16;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -