📄 sd.c
字号:
// sd.c
// SD/MMC access routines
// modified from holger.klabunde from AVR to C8051
//#########################################################################
#include "common.h"
#include "sd.h"
#include "fat.h"
#include "rbccmd.h"
#define BYTE_PER_SEC 512
extern SYS_INFO_BLOCK xdata DeviceInfo;
extern UINT8 xdata DBUF[512]; // defined in the main program
extern UINT8 xdata FATBUF[512];
extern UINT8 xdata RDIRBUF[512];
extern UINT8 xdata respBuf[16];
unsigned int c_size, c_size_mult, read_bl_len;
unsigned long drive_size, maxsect;
unsigned char GetDevInfo( )
{
unsigned long FATSz;
unsigned long TotSec;
unsigned long RootDirSectors;
unsigned long DataSec;
unsigned long CountofClusters;
pMBR_BLOCK pMBR;
pBPB_BLOCK pBPB;
pBPB_BLOCK32 pBPB32;
pMBR=(pMBR_BLOCK)FATBUF;
DeviceInfo.BPB_BytesPerSec=512; //暂假设为512
// Read sector 0 (Partition table)
if(!SDReadFat(0x0))
return 0;
//////////////////////////////////
SendUart(FATBUF, 512); // debug
if(FATBUF[0]==0xeb||FATBUF[0]==0xe9)
{
DeviceInfo.StartSector=0;
}
else
{
//////////////////////////////////
DeviceInfo.StartSector=SwapINT32(pMBR->StartSector);
}
///////////////////////////////////////////////////////
DelayUs(5);
pBPB=(pBPB_BLOCK)FATBUF;
if(!SDReadFat(DeviceInfo.StartSector))
return 0;
SendUart(FATBUF, 512); // debug
DeviceInfo.BPB_BytesPerSec=WordSwap(pBPB->BPB_BytesPerSec);
DeviceInfo.BPB_SecPerClus=pBPB->BPB_SecPerClus;
DeviceInfo.BPB_NumFATs=pBPB->BPB_NumFATs;
DeviceInfo.BPB_RootEntCnt=WordSwap(pBPB->BPB_RootEntCnt);
DeviceInfo.BPB_TotSec16=WordSwap(pBPB->BPB_TotSec16);
DeviceInfo.BPB_FATSz16=WordSwap(pBPB->BPB_FATSz16);
DeviceInfo.BPB_FATSz32=WordSwap(pBPB32->BPB_FATSz32);
DeviceInfo.BPB_TotSec32=SwapINT32(pBPB->BPB_TotSec32);
DeviceInfo.FatStartSector=DeviceInfo.StartSector+WordSwap(pBPB->BPB_RsvdSecCnt);
DeviceInfo.RootStartSector=DeviceInfo.FatStartSector+2*DeviceInfo.BPB_FATSz16;
DeviceInfo.FirstDataSector=DeviceInfo.RootStartSector+0x20;
///////////////////////////////////////////////////////
// ThisFile.bFileOpen=0;
//Judge the FAT type
if(DeviceInfo.BPB_FATSz16 != 0)
FATSz = DeviceInfo.BPB_FATSz16;
else
FATSz = DeviceInfo.BPB_FATSz32;
if(DeviceInfo.BPB_TotSec16 != 0)
TotSec = DeviceInfo.BPB_TotSec16;
else
TotSec = DeviceInfo.BPB_TotSec32;
RootDirSectors = ((DeviceInfo.BPB_RootEntCnt * 32) + (DeviceInfo.BPB_BytesPerSec - 1)) / DeviceInfo.BPB_BytesPerSec;
DataSec = TotSec - (WordSwap(pBPB->BPB_RsvdSecCnt) + (DeviceInfo.BPB_NumFATs * FATSz) + RootDirSectors);
CountofClusters = DataSec / DeviceInfo.BPB_SecPerClus;
if(CountofClusters < 4085)
{
DeviceInfo.bFatType = 1; //fat12
}
else if(CountofClusters < 65525)
{
DeviceInfo.bFatType = 2; //fat16
}
else
{
DeviceInfo.bFatType = 3; //fat32
DeviceInfo.TotCluster =
(DeviceInfo.BPB_TotSec32-DeviceInfo.FirstDataSector+1)/DeviceInfo.BPB_SecPerClus+1;
}
//End Judge the FAT type
}
//######################################################
unsigned char SDCommand(unsigned char command, unsigned char *pAddr)
//######################################################
{
unsigned char i, addr[4];
for (i=0;i<4;i++)
{
addr[i] = *pAddr;
pAddr++;
}
SPI_WRITE(0xFF); //Dummy write
SPI_WRITE(command);
SPI_WRITE(addr[0]); //MSB of address
SPI_WRITE(addr[1]);
SPI_WRITE(addr[2]);
SPI_WRITE(addr[3]); //LSB of address
SPI_WRITE(0xFF); //dummy checksum
// SPI_WRITE(0xFF);
return (1);
}
//
unsigned char SDMp3Read(unsigned long sector)
//######################################################
{
unsigned int i;
unsigned long startadr;
// SPI_CTL1 = SPI_3M; // set high speed
// if(sector>=maxsect) return 0; //sectornumber too big
BufRst = 0x3; // reset peripheral fifo
BufRst = 0x0;
//calculate startadress of the sector
startadr=sector * (unsigned long)BYTE_PER_SEC;
SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);
do
{
SPI_WRITE(0xFF);
}while(!(SPI_STA0 & SPI_RRDY)); // wait for card response
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA != 0x0); // wait for response token
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA & 0x1); // wait for data start
for(i=0; i<BYTE_PER_SEC; i++)
{
SPI_WRITE(0xFF); // shift out a byte into SPI_DATA
BufAddr=SPI_DATA; // store byte in buffer
}
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WRITE(0xFF);
// SPI_CTL1 = SPI_1P5M; // set high speed
return 1;
}
//######################################################
unsigned char SDReadSector(unsigned long sector)
//######################################################
{
unsigned int i;
unsigned long startadr;
if(sector>=maxsect) return 1; //sectornumber too big
//calculate startadress of the sector
startadr=sector * (unsigned long)BYTE_PER_SEC;
//SendUart((unsigned char *)&startadr, 4);
SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);
do
{
SPI_WRITE(0xFF);
}while(!(SPI_STA0 & SPI_RRDY)); // wait for card response
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA != 0x0); // wait for response token
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA & 0x1); // wait for data start
for(i=0; i<BYTE_PER_SEC; i++)
{
SPI_WRITE(0xFF); // shift out a byte into SPI_DATA
DBUF[i]=SPI_DATA; // store byte in buffer
}
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WRITE(0xFF);
return 1;
}
//######################################################
unsigned char SDReadFat(unsigned long sector)
//######################################################
{
unsigned int i;
unsigned long startadr;
if(sector>=maxsect) return 1; //sectornumber too big
//calculate startadress of the sector
startadr=sector * (unsigned long)BYTE_PER_SEC;
//SendUart((unsigned char *)&startadr, 4);
SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);
do
{
SPI_WRITE(0xFF);
}while(!(SPI_STA0 & SPI_RRDY)); // wait for card response
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA != 0x0); // wait for response token
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA & 0x1); // wait for data start
for(i=0; i<BYTE_PER_SEC; i++)
{
SPI_WRITE(0xFF); // shift out a byte into SPI_DATA
FATBUF[i]=SPI_DATA; // store byte in buffer
}
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WRITE(0xFF);
return 1;
}
unsigned char SDReadRdir(unsigned long sector)
//######################################################
{
unsigned int i;
unsigned long startadr;
if(sector>=maxsect) return 1; //sectornumber too big
//calculate startadress of the sector
startadr=sector * (unsigned long)BYTE_PER_SEC;
//SendUart((unsigned char *)&startadr, 4);
SDCommand(SD_READ_BLOCK, (unsigned char *)&startadr);
do
{
SPI_WRITE(0xFF);
}while(!(SPI_STA0 & SPI_RRDY)); // wait for card response
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA != 0x0); // wait for response token
do
{
SPI_WRITE(0xFF);
}while (SPI_DATA & 0x1); // wait for data start
for(i=0; i<BYTE_PER_SEC; i++)
{
SPI_WRITE(0xFF); // shift out a byte into SPI_DATA
RDIRBUF[i]=SPI_DATA; // store byte in buffer
}
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WRITE(0xFF);
return 1;
}
//######################################################
unsigned char SDWriteSector(unsigned long sector, unsigned char *pDBUF)
//######################################################
{
unsigned int i;
unsigned char by;
unsigned long startadr;
if(sector>=maxsect) return 1; //sectornumber too big
//calculate startadress
// startadr=sector * (unsigned long)BYTE_PER_SEC;
startadr=sector<<9;
SDCommand(SD_WRITE_BLOCK,(unsigned char *)&startadr);
SPI_WRITE(0xFF); // do we need this TWO dummy writes ?
SPI_WRITE(0xFF);
SPI_WRITE(0xFE); // start block token
for(i=0; i<BYTE_PER_SEC; i++)
{
SPI_WRITE(*pDBUF++);
}
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WRITE(0xFF);
SPI_WRITE(0xFF); // read response
by=SPI_DATA & 0x1F;
if(by != 0x05) // data block accepted ?
{
return 1;
}
do
{
SPI_WRITE(0xFF);
}while(SPI_DATA !=0xFF); // wait til busy is gone
return 0;
}
//######################################################
unsigned char SDIdentify(void)
//######################################################
{
unsigned char by;
unsigned int i;
unsigned long addr;
// pCSD_BLOCK pCSD;
// SPI_CTL0
// SPI_LSB=0 Send MSB first
// SPI_CPOL=1 SCK high if IDLE
// SPI_CPHA=1 SPI Mode 1
// SPI_MST=1 I am the master
// SPI_TIE=0 No SPI TX Interrupt
// SPI_RIE=0 No SPI RX Interrupt
// SPI_EN=1 SPI Enable
// SPI_SSOEN=0 Output enable for select
SPI_CTL0 = 0x4E;
// SPI_CTL1
SPI_CTL1 = SPI_750K; // set speed
for(i=0; i<10; i++) SPI_WRITE(0xFF); // give min 74 clock pulses before
// sending commands
//send CMD0 for RESET
SPI_WRITE(SD_RESET); //command code CMD0
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95); // CMD0 needs a checksum !
SPI_WRITE(0xFF); // get 16 bit response high
while(!(SPI_STA0&SPI_RRDY));
respBuf[0]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[1]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[2]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[3]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[4]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[5]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[6]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[7]=SPI_DATA;
SPI_WRITE(0xFF);
SendUart(respBuf, 8);
DelayUs(100);
addr = 0;
//repeat CMD1 til result=0
do
{
SDCommand(SD_INIT,(unsigned char *) &addr);
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
respBuf[0]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[1]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[2]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[3]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[4]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[5]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[6]=SPI_DATA;
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY));
respBuf[7]=SPI_DATA;
SPI_WRITE(0xFF);
SendUart(respBuf, 8);
// DelayUs(50);
// SendUart(respBuf, 8); // send back response
}while(respBuf[2]!=0);
// flush out any garbage
// for(i=0; i<10; i++) SPI_WRITE(0xFF);
DelayUs(100);
//read CID
// SDCommand(SD_READ_CID,0); // nothing really interesting here
//read CSD Card Specific Data
SDCommand(SD_READ_CSD,(unsigned char *) &addr);
// SPI_WRITE(0xFF); // ignore response 0xFE
do
{
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
}while (SPI_DATA != 0); // wait for response token
do
{
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
}while (SPI_DATA & 0x1); // wait for data start
SDResp(18);
SendUart(respBuf,18);
//pCSD = (pCSD_BLOCK) respBuf;
// FIXME: lets test if this data structure is OK
//c_size=pCSD->CSD_DevSize;
//read_bl_len=pCSD->CSD_RdBlkLen;
//c_size_mult=pCSD->CSD_DevSizeMult;
//
c_size=respBuf[6] & 0x03; //bits 1..0
c_size<<=10;
c_size+=(unsigned int)respBuf[7]<<2;
c_size+=respBuf[8]>>6;
by= respBuf[5] & 0x0F;
read_bl_len=1;
read_bl_len<<=by;
by=respBuf[9] & 0x03;
by<<=1;
by+=respBuf[10] >> 7;
c_size_mult=1;
c_size_mult<<=(2+by);
//
drive_size=(unsigned long)(c_size+1) * (unsigned long)c_size_mult * (unsigned long)read_bl_len;
maxsect= drive_size / BYTE_PER_SEC;
SendUart((unsigned char *)&drive_size,4);
SendUart((unsigned char *)&maxsect,4);
DelayUs(50);
addr = 512;
SDCommand(SD_SET_BLOCKLEN,(unsigned char *) &addr);
do
{
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
}while (SPI_DATA != 0); // wait for response token
addr = 0;
SDCommand(SD_SEND_STATUS,(unsigned char *) &addr);
do
{
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
}while (SPI_DATA != 0); // wait for response token
do
{
SPI_WRITE(0xFF);
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
}while (SPI_DATA & 0x1); // wait for data start
SDResp(2);
SendUart(respBuf,2);
return 0;
}
unsigned char SDResp(unsigned char respLen)
{
unsigned char i;
for (i=0;i<respLen;i++)
{
SPI_DATA = 0xff;
while(!(SPI_STA0&SPI_RRDY)); //wait last byte rcv
respBuf[i] = SPI_DATA;
}
return(1);
}
unsigned char UartWaitCmd()
{
unsigned char uCmd;
unsigned char uArg;
unsigned char skipSong;
while (!(SCON & SCON_RXINT));
SCON = SCON_FAST;
uCmd = SBUF;
while (!(SCON & SCON_RXINT));
SCON = SCON_FAST;
uArg = SBUF;
// SendUart(&uCmd,1);
// SendUart(&uArg,1);
if (!(uCmd ^ 0x1))
{
Volume = uArg;
uCmd = Volume;
SendUart(&uCmd, 1);
}
else if (!(uCmd ^ 0x2))
{
Mode = uArg;
uCmd = Mode;
SendUart(&uCmd, 1);
}
else if (!(uCmd ^ 0x3))
{
skipSong = uArg;
uCmd = skipSong;
SendUart(&uCmd, 1);
}
else
{
uCmd = 0xAA;
SendUart(&uCmd, 1);
return (0);
}
return (1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -