?? mmc.c.svn-base
字號:
/*-----------------------------------------------------------------------*/
/* MMC/SDC (in SPI mode) control module (C)ChaN, 2006 */
/*-----------------------------------------------------------------------*/
/* Only rcvr_spi(), xmit_spi(), disk_timerproc(), disk_initialize () and */
/* some macros are platform dependent. */
/*-----------------------------------------------------------------------*/
#include "AT91SAM7S64.h"
#include "diskio.h"
#define USE_DMA
/* MMC/SD command (in SPI) */
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND */
#define CMD9 (0x40+9) /* SEND_CSD */
#define CMD10 (0x40+10) /* SEND_CID */
#define CMD12 (0x40+12) /* STOP_TRANSMISSION */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD18 (0x40+18) /* READ_MULTIPLE_BLOCK */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD25 (0x40+25) /* WRITE_MULTIPLE_BLOCK */
#define CMD58 (0x40+58) /* READ_OCR */
/* Control signals */
#define SELECT() //PORTB &= ~1 /* MMC CS = L */
#define DESELECT() //PORTB |= 1 /* MMC CS = H */
//#define SOCKPORT PINB /* Socket contact port */
//#define SOCKWP 0x20 /* Write protect switch (PB5) */
//#define SOCKINS 0x10 /* Card detect switch (PB4) */
#define POWER_ON() //PORTE &= ~0x80 /* Socke power (PE7) */
#define POWER_OFF() //PORTE |= 0x80
/*
AT91SAM7S64 SPI Pins: Function (A/B)
PA12 - MISO - AT91C_PA12_MISO (1/0)
PA13 - MOSI - AT91C_PA13_MOSI (1/0)
PA14 - SCK - AT91C_PA14_SPCK (1/0)
Chip-Selects (available on different pins)
PA11 - NPCS0 - AT91C_PA11_NPCS0 (1/0)
PA31 - NPCS1 - AT91C_PA31_NPCS1 (1/0)
PA09 - NPCS1 - AT91C_PA9_NPCS1 (1/0)
...AT91C_PA3_NPCS3 (0/1)
...AT91C_PA5_NPCS3 (0/1)
...AT91C_PA10_NPCS2 (0/1)
...AT91C_PA22_NPCS3 (0/1)
...AT91C_PA30_NPCS2 (0/1)
*/
/* here: use NCPS0 @ PA11: */
#define NCPS_PDR_BIT AT91C_PA11_NPCS0
#define NCPS_ASR_BIT AT91C_PA11_NPCS0
#define NPCS_BSR_BIT 0
#define SPI_CSR_NUM 0
#define SPI_SCBR_MIN 2
/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */
#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3))
#define PCS_1 ((1<<1)|(0<<1)|(1<<2)|(1<<3))
#define PCS_2 ((1<<1)|(1<<1)|(0<<2)|(1<<3))
#define PCS_3 ((1<<1)|(1<<1)|(1<<2)|(0<<3))
/* TODO: ## */
#if (SPI_CSR_NUM == 0)
#define SPI_MR_PCS PCS_0
#elif (SPI_CSR_NUM == 1)
#define SPI_MR_PCS PCS_1
#elif (SPI_CSR_NUM == 2)
#define SPI_MR_PCS PCS_2
#elif (SPI_CSR_NUM == 3)
#define SPI_MR_PCS PCS_3
#else
#error "SPI_CSR_NUM invalid"
// not realy - when using an external address decoder...
// but this code takes over the complete SPI-interace anyway
#endif
static volatile
DSTATUS Stat = STA_NOINIT; /* Disk status */
static volatile
BYTE Timer; /* 100Hz decrement timer */
/*-----------------------------------------------------------------------*/
/* Module Private Functions */
/*--------------------------------*/
/* Transmit a byte to MMC via SPI */
//#define xmit_spi(dat) SPDR=(dat); loop_until_bit_is_set(SPSR,SPIF)
static
BYTE xmit_spi(BYTE dat)
{
AT91PS_SPI pSPI = AT91C_BASE_SPI;
while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer compl. wait
pSPI->SPI_TDR = dat;
while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for char
return (BYTE)( pSPI->SPI_RDR ); // it's important to read RDR here!
}
static
BYTE rcvr_spi()
{
BYTE dat;
AT91PS_SPI pSPI = AT91C_BASE_SPI;
while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer compl. wait
pSPI->SPI_TDR = 0xFF;
while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for char
dat = (BYTE)( pSPI->SPI_RDR );
//iprintf("r: %x\n", dat);
return dat;
}
static
void rcvr_spi_m(BYTE *dest)
{
BYTE dat;
AT91PS_SPI pSPI = AT91C_BASE_SPI;
while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer compl. wait
pSPI->SPI_TDR = 0xFF;
while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for char
dat = (BYTE)( pSPI->SPI_RDR );
*dest = dat;
}
/*---------------------*/
/* Wait for card ready */
static
BYTE wait_ready ()
{
BYTE res;
Timer = 50; /* Wait for ready in timeout of 500ms */
rcvr_spi();
do
res = rcvr_spi();
while ((res != 0xFF) && Timer);
return res;
}
/*--------------------------------*/
/* Receive a data packet from MMC */
static
BOOL rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
BYTE wc /* Word count (0 means 256 words) */
)
{
BYTE token;
#ifdef USE_DMA
/* TODO: deuglyfy */
static const BYTE dummy_ff_block[512] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#endif
Timer = 10;
do { /* Wait for data packet in timeout of 100ms */
token = rcvr_spi();
} while ((token == 0xFF) && Timer);
//iprintf("token: %x\n", token);
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
#ifdef USE_DMA
// enable DMA transfer
*AT91C_SPI_RPR = (unsigned long)buff;
*AT91C_SPI_RCR = 2 * (wc == 0 ? 256 : wc);
*AT91C_SPI_TPR = (unsigned long)dummy_ff_block;
*AT91C_SPI_TCR = 2 * (wc == 0 ? 256 : wc);
*AT91C_SPI_PTCR = AT91C_PDC_RXTEN;
*AT91C_SPI_PTCR = AT91C_PDC_TXTEN;
/*while(i++ < 512)
*AT91C_SPI_TDR = 0xFF; // start transfer*/
while(! (*AT91C_SPI_SR & AT91C_SPI_ENDRX));
*AT91C_SPI_PTCR = AT91C_PDC_RXTDIS;
*AT91C_SPI_PTCR = AT91C_PDC_TXTDIS;
#else
do { /* Receive the data block into buffer */
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
} while (--wc);
#endif
rcvr_spi(); /* Discard CRC */
rcvr_spi();
//puts("rcvr_datablock success");
return TRUE; /* Return with success */
}
/*---------------------------*/
/* Send a data packet to MMC */
#ifndef _READONLY
static
BOOL xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
AT91PS_SPI pSPI = AT91C_BASE_SPI;
BYTE resp, wc = 0;
if (wait_ready() != 0xFF) return FALSE;
xmit_spi(token); /* Xmit data token */
if (token != 0xFD) { /* Is data token */
#ifdef USE_DMA
// enable DMA transfer
*AT91C_SPI_TPR = buff;
*AT91C_SPI_TCR = 512;
*AT91C_SPI_PTCR = AT91C_PDC_TXTEN;
while(! (*AT91C_SPI_SR & AT91C_SPI_ENDTX));
*AT91C_SPI_PTCR = AT91C_PDC_TXTDIS;
(BYTE)( pSPI->SPI_RDR ); // it's important to read RDR here!
#else
do { /* Xmit the 512 byte data block to MMC */
xmit_spi(*buff++);
xmit_spi(*buff++);
} while (--wc);
#endif
xmit_spi(0xFF); /* CRC (Dummy) */
xmit_spi(0xFF);
resp = rcvr_spi(); /* Reveive data response */
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
return FALSE;
}
return TRUE;
}
#endif
/*------------------------------*/
/* Send a command packet to MMC */
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
BYTE n, res;
if (wait_ready() != 0xFF) return 0xFF;
/* Send command packet */
xmit_spi(cmd); /* Command */
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xmit_spi((BYTE)arg); /* Argument[7..0] */
xmit_spi(0x95); /* CRC (valid for only CMD0) */
/* Receive command response */
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
res = rcvr_spi();
while ((res & 0x80) && --n);
//iprintf("res: %i\n", res);
return res; /* Return with the response value */
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -