harktrip
驱动小牛
驱动小牛
  • 注册日期2003-11-30
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分51分
  • 威望457点
  • 贡献值0点
  • 好评度170点
  • 原创分0分
  • 专家分2分
阅读:2979回复:4

WINCE4.2+2440 SD卡驱动目前进度:可读,但写入有问题(附源码)

楼主#
更多 发布于:2008-08-01 10:24


前阵子忙着AP,现在回头搞SD卡驱动
(各位兄弟,先别急着笑话:现在还在搞WINCE4.2)

如标题,插入SD卡,不管如何读OK的啦
可是写入会出问题,从U盘COPY些档案到SD卡,
整着COPY过程,WINCE照跑,就看着剩余多久多久完成

但COPY完后,只有目录,完全没档案,
拜求各位兄弟帮忙看看…


#include <atamain.h>

#include "DataType.h"

#define MAX_INITS    5


#define SDCLK_DV1    120
#define SDCLK_DV2    2

//跟硬件相关的操作放在本文件中
PRIVATE volatile IOPreg *v_pIOPregs;
PRIVATE volatile MMCreg *v_pSDMMCregs;

BOOL g_bSDMMCIsExist;
volatile int RCA;
//U32 SDMMC_total_block;

#define MMC_CMD_OUTPUT()    \
    v_pIOPregs->rGPECON&= ~((0x3<<12));    \
    v_pIOPregs->rGPECON|=((0x01<<12))

#define MMC_CMD_INPUT()        \
    v_pIOPregs->rGPECON&= ~((0x3<<12))

#define MMC_DAT_OUTPUT()    \
    v_pIOPregs->rGPECON&= ~((0x3<<14));    \
    v_pIOPregs->rGPECON|=((0x01<<14))
    
#define MMC_DAT_INPUT()        \
    v_pIOPregs->rGPECON&= ~((0x3<<14))

#define MMC_CLK_LOW()        \
    v_pIOPregs->rGPEDAT&= ~((0x01<<5))
    
#define MMC_CLK_HIGH()        \
    v_pIOPregs->rGPEDAT|=((0x01<<5))

#define MMC_CMD_LOW()        \
    v_pIOPregs->rGPEDAT&= ~((0x01<<6))
    
#define MMC_CMD_HIGH()        \
    v_pIOPregs->rGPEDAT|=((0x01<<6))

#define MMC_DAT_LOW()        \
    v_pIOPregs->rGPEDAT&= ~((0x01<<7))
    
#define MMC_DAT_HIGH()        \
    v_pIOPregs->rGPEDAT|=((0x01<<7))

#define MMC_DAT_READ()        \
    ((v_pIOPregs->rGPEDAT&(0x01<<7))>>7)

int Wide=0;     //0:1bit,1:4bit
int gMMC=0;      //0:SD,1:MMC

BOOL mmc_card_init(void);
U8 mmc_read_sector(U8 *buf,U32 secaddrno);
U8 mmc_write_sector(U8 *buf,U32 secaddrno);


void Set_1bit_bus(void);
void Set_4bit_bus(void);
void SetBus(void);
void Set_Prt(void);
void Clr_Prt(void);

BOOL SDMMC_InitializeAddresses(VOID)
{
    //初始化IO 地址
    BOOL RetValue=TRUE;

    //IO Register Allocation
    v_pIOPregs=NULL;
    v_pSDMMCregs=NULL;

    v_pIOPregs=(volatile IOPreg *)VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE,PAGE_NOACCESS);
    if(v_pIOPregs==NULL)
    {
        RETAILMSG(1,(TEXT("For IOPregs:VirtualAlloc failed!\r\n")));
        RetValue=FALSE;
    }
    else
    {
        if(!VirtualCopy((PVOID)v_pIOPregs,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE|PAGE_NOCACHE))
        {
            RETAILMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n")));
            RetValue=FALSE;
        }
    }
    if(!RetValue)
    {
        if(v_pIOPregs)
        {
            VirtualFree((PVOID) v_pIOPregs,0,MEM_RELEASE);
        }

        v_pIOPregs=NULL;
    }
    else
    {
        v_pSDMMCregs=(volatile MMCreg *)VirtualAlloc(0,sizeof(MMCreg),MEM_RESERVE,PAGE_NOACCESS);
        if(v_pSDMMCregs==NULL)
        {
            RETAILMSG(1,(TEXT("For MMCreg:VirtualAlloc failed!\r\n")));
            RetValue=FALSE;
        }
        else
        {
            if(!VirtualCopy((PVOID)v_pSDMMCregs,(PVOID)(MMC_BACE),sizeof(MMCreg),PAGE_READWRITE|PAGE_NOCACHE))
            {
                RETAILMSG(1,(TEXT("For MMCreg: VirtualCopy failed!\r\n")));
                RetValue=FALSE;
            }
        }
        
        if(!RetValue)
        {
            if(v_pSDMMCregs)
            {
                VirtualFree((PVOID) v_pSDMMCregs,0,MEM_RELEASE);
            }

            v_pSDMMCregs=NULL;
        }
        else
            RETAILMSG(1,(TEXT("SDMMC_InitializeAddresses - Success\r\n")));
    }

    return (RetValue);
}


int Chk_CMDend(int cmd,int be_resp)
{
    int status;



    if(!be_resp)                        //No response
    {
        status=v_pSDMMCregs->rSDICMDSTA;
        while((status&0x800)!=0x800)    //Check cmd end
            status=v_pSDMMCregs->rSDICMDSTA;
        v_pSDMMCregs->rSDICMDSTA=status;//Clear cmd end state

        return 1;
    }
    else                                //With response
    {
        status=v_pSDMMCregs->rSDICMDSTA;
        
        
    while(!(((status&0x200)==0x200)|((status&0x400)==0x400)))    //Check cmd/rsp end
          status=v_pSDMMCregs->rSDICMDSTA;
            
         //   RETAILMSG(1,(TEXT("GO Chk_CMD %d \r\n",cmd)));

        if(cmd==1||cmd==41)        //CRC no check
        {
                if((status&0xf00)!=0xa00)      //Check error
                {
                v_pSDMMCregs->rSDICMDSTA=status;       //Clear error state

                if(((status&0x400)==0x400))
                    return 0;            //Timeout error
                    }              
                v_pSDMMCregs->rSDICMDSTA=status;            //Clear cmd&rsp end state
        }
        else                            //CRC check
        {
                if((status&0x1f00)!=0xa00)    //Check error
                {
                v_pSDMMCregs->rSDICMDSTA=status;       //Clear error state
                RETAILMSG(1,(TEXT("++STATUS=%x \r\n",status)));
                
                if(status&0x400)
                    return 0;            //Timeout error
                    }
                v_pSDMMCregs->rSDICMDSTA=status;
        }
        return 1;
    }
}

















int Chk_DATend(void)
{

    int finish;

    finish=v_pSDMMCregs->rSDIDATSTA;
    while(!((finish&0x10)|(finish&0x20)))
    {
    finish=v_pSDMMCregs->rSDIDATSTA;
    }
    if(!finish&0x10)
    {
    RETAILMSG(1,(TEXT("\nDATA:finish=0x%x.\n"),finish));
    v_pSDMMCregs->rSDIDATSTA=0xf4;  //Clear error state
    return 0;
    }
    return 1;
}





int Chk_BUSYend(void)
{
    int finish;

    finish=v_pSDMMCregs->rSDIDATSTA;
    while( !( (finish&0x08) | (finish&0x20 )))
    finish=v_pSDMMCregs->rSDIDATSTA;

    if( !finish&0x08 )
    {
    RETAILMSG(1,(TEXT("I'm not BUSY:%d.\n"),finish));
    v_pSDMMCregs->rSDIDATSTA=0xf4;  
    return 0;
    }
    return 1;
}















void Card_sel_desel(char sel_desel)
{
    //Card select or deselect
    if(v_pSDMMCregs==NULL)
        return;

    if(sel_desel)
    {
    RECMDS7:    
        v_pSDMMCregs->rSDICMDARG=RCA<<16;                    //CMD7(RCA,stuff bit)
        v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x47;       //sht_resp,wait_resp,start,CMD7

        Sleep(1);
        //Check end of CMD7
        if(!Chk_CMDend(7,1))
            goto RECMDS7;
        Sleep(1);
        
        v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
        
        if(v_pSDMMCregs->rSDIRSP0&0x1e00!=0x800)
            goto RECMDS7;
        v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    }
    else
    {
    RECMDD7:
        v_pSDMMCregs->rSDICMDARG=0<<16;            //CMD7(RCA,stuff bit)
        v_pSDMMCregs->rSDICMDCON=(0x1<<8)|0x47;    //no_resp,start,CMD7

        Sleep(1);
        //Check end of CMD7
        if(!Chk_CMDend(7,0))
            goto RECMDD7;

        Sleep(1);
        v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    }
}



void CMD0(void)
{
    int nError;

    if(v_pSDMMCregs==NULL)
    return;
    //Make card idle state
    v_pSDMMCregs->rSDICMDARG=0x0;            //CMD0(stuff bit)
    v_pSDMMCregs->rSDICMDCON=(1<<8)|0x40;   //No_resp,start,CMD0

    Sleep(1);
    //Check end of CMD0
    nError=Chk_CMDend(0,0);
    v_pSDMMCregs->rSDICMDSTA=0x800;        // Clear cmd_end(no rsp)
    RETAILMSG(1,(TEXT("\nCMD0 Chk_CMDend:%d.\n"),nError));
}

void CMD2()    // get sd id
{

}

int CMD9(void)//SEND_CSD
{
    if(v_pSDMMCregs==NULL)
    return 0;

    v_pSDMMCregs->rSDICMDARG=RCA<<16;                // CMD9(RCA,stuff bit)
    v_pSDMMCregs->rSDICMDCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x49;    // long_resp, wait_resp, start, CMD9

    //-- Check end of CMD9
    if(!Chk_CMDend(9, 1))
    return 0;

    RETAILMSG(1,(TEXT(" SDIRSP0=0x%x\n SDIRSP1=0x%x\n SDIRSP2=0x%x\n SDIRSP3=0x%x\n"), v_pSDMMCregs->rSDIRSP0,v_pSDMMCregs->rSDIRSP1,v_pSDMMCregs->rSDIRSP2,v_pSDMMCregs->rSDIRSP3));
    return 1;
}

int CMD13(void)//SEND_STATUS
{
    int response0;

    v_pSDMMCregs->rSDICMDARG=RCA<<16;            // CMD13(RCA,stuff bit)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x4d;    // sht_resp, wait_resp, start, CMD13


    if(!Chk_CMDend(13, 1))
    return 0;
    ;
    response0=v_pSDMMCregs->rSDIRSP0;
    response0 &= 0x3c00;
    response0 = response0 >> 9;
    if(response0==5||response0==6)
    return 0;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    return 1;
}

int CMD16()
{
    int response0;

    v_pSDMMCregs->rSDICMDARG=0x200;            // block size
    v_pSDMMCregs->rSDICMDCON=(1<<11)|(0x1<<9)|(0x1<<8)|0x50;    // sht_resp, wait_resp, start, CMD16

    if(!Chk_CMDend(16, 1))
    return 0;
    response0=v_pSDMMCregs->rSDIRSP0;
    response0 &= 0x3c00;
    response0 = response0 >> 9;
    if(response0==5||response0==6)
    return 0;

    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    return 1;
}

int CMD55(void)
{
    if(v_pSDMMCregs==NULL)
    return 0;
    //Make ACMD
    v_pSDMMCregs->rSDICMDARG=RCA<<16;            //CMD7(RCA,stuff bit)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x77;    //sht_resp,wait_resp,start,CMD55

    //Check end of CMD55
    if(!Chk_CMDend(55,1))
    {
    return 0;
    }

    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    return 1;
}


void Set_Prt(void)
{
    if(v_pSDMMCregs==NULL)
    return;
    //-- Set protection addr.0 ~ 262144(32*16*512)
    //   Uart_Printf("[Set protection(addr.0 ~ 262144) test]\n");

    RECMD28:
    //--Make ACMD
    v_pSDMMCregs->rSDICMDARG=0;        // CMD28(addr)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x5c;    //sht_resp, wait_resp, start, CMD28

    //-- Check end of CMD28
    if(!Chk_CMDend(28, 1))
    goto RECMD28;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
}

void Clr_Prt(void)
{
    if(v_pSDMMCregs==NULL)
    return;
    //-- Clear protection addr.0 ~ 262144(32*16*512)
    //Uart_Printf("[Clear protection(addr.0 ~ 262144) test]\n");

    RECMD29:
    //--Make ACMD
    v_pSDMMCregs->rSDICMDARG=0;        // CMD29(addr)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x5d;    //sht_resp, wait_resp, start, CMD29

    //-- Check end of CMD29
    if(!Chk_CMDend(29, 1))
    goto RECMD29;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
}


void Enable_SDIclk()
{
    if(v_pSDMMCregs==NULL)
        return;
    v_pSDMMCregs->rSDICON |=1;
}

void Disable_SDIclk()
{
    if(v_pSDMMCregs==NULL)
        return;
    v_pSDMMCregs->rSDICON &= (~0x01);
}



int Chk_SD_OCR(void)
{
    int i;
    for(i=0;i<10;i++)
    {
    CMD55();                //Make ACMD        

    v_pSDMMCregs->rSDICMDARG=0xff8000;    //ACMD41(OCR:2.7V~3.6V)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x69;//sht_resp, wait_resp, start, ACMD41

    if(Chk_CMDend(41,1)& (v_pSDMMCregs->rSDIRSP0==0x80ff8000))     //OCR最高位为0表示正在POWER UP
    {
    return 1;    //Success        
    }
    //    for(j=0;j<500;j++);    //Wait Card power up status
    Sleep(300);
    }

    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    return 0;            //Fail
}

int Chk_MMC_OCR(void)
{
    int i;

    if(v_pSDMMCregs==NULL)
    return 0;

    //Negotiate operating condition for MMC,it makes card ready state
    for(i=0;i<15;i++)
    {
    v_pSDMMCregs->rSDICMDARG=0xff8000;                    //CMD1(OCR:2.7V~3.6V)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x41;    //sht_resp,wait_resp,start,CMD1

    //Check end of CMD1
    RETAILMSG(1,(TEXT("Chk_MMC_OCR\r\n")));
    if(Chk_CMDend(1,1)&&(v_pSDMMCregs->rSDIRSP0==0x80ff8000))//    if(Chk_CMDend(1,1)&&(v_pSDMMCregs->rSDIRSP0)>>16==0x80ff)
    {
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    return 1;    //Success
    }
    }
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
    return 0;            //Failed
}

U8 InitSDMMC(void)
{
    //成功返回1

    g_bSDMMCIsExist=FALSE;
    if(v_pIOPregs==NULL)
        return 0;
    if(v_pSDMMCregs==NULL)
        return 0;


    v_pIOPregs->rGPEUP &= ~(0x3f<<5);    //The pull up
    v_pIOPregs->rGPECON &= ~(0xfff<<10);
    v_pIOPregs->rGPECON |= (0xaaa<<10);


    v_pSDMMCregs->rSDIDATSTA = 0xffff;
    v_pSDMMCregs->rSDIDATCON = 0;
    v_pSDMMCregs->rSDICMDSTA = 0x1e00;//0xffff;
    v_pSDMMCregs->rSDICMDCON = 0;    


    v_pSDMMCregs->rSDIPRE=SDCLK_DV1;//400KHz

    v_pSDMMCregs->rSDICON=(1<<1)|1;            //Type A,clk enable

    v_pSDMMCregs->rSDIFSTA |= (1<<16);             //FIFO reset,

    v_pSDMMCregs->rSDIBSIZE=0x200;            //512byte(128word)
    v_pSDMMCregs->rSDIDTIMER=0x7fffff;        //Set timeout count



    Sleep(2);

        CMD0();
    RETAILMSG(1,(TEXT("\nIn idle.\n")));
    
    //Check MMC card OCR
    if(Chk_MMC_OCR())
    {
        RETAILMSG(1,(TEXT("\nIn MMC ready.\n")));
        gMMC=1;
        goto RECMD2;
    }

    if(Chk_SD_OCR())
        RETAILMSG(1,(TEXT("\nIn SD ready.\n")));
    else
    {
        RETAILMSG(1,(TEXT("\nInitialize fail\nNo Card assertion.\n")));
        return 0;
    }        

RECMD2:
    //Check attaced cards,it makes card identification state
    v_pSDMMCregs->rSDICMDARG=0x0;                               //CMD2(stuff bit)
    v_pSDMMCregs->rSDICMDCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|0x42;     //lng_resp,wait_resp,start,CMD2

    //Check end of CMD2
    if(!Chk_CMDend(2,1))
        {
        goto RECMD2;
    }
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)

    RETAILMSG(1,(TEXT("\nEnd id.\n")));

RECMD3:
    //Send RCA
    v_pSDMMCregs->rSDICMDARG=gMMC<<16;                    //CMD3(MMC:Set RCA,SD:Ask RCA-->SBZ)
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x43;    //sht_resp,wait_resp,start,CMD3

    //Check end of CMD3
    if(!Chk_CMDend(3,1))
        goto RECMD3;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)

    //Publish RCA
    if(gMMC)
        RCA=1;
    else
        RCA=(v_pSDMMCregs->rSDIRSP0&0xffff0000)>>16;

    RETAILMSG(1,(TEXT("\nRCA=0x%x\n"),RCA));

    //State(stand-by) check
    if(v_pSDMMCregs->rSDIRSP0&0x1e00!=0x600)    //CURRENT_STATE check
        goto RECMD3;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)

    RETAILMSG(1,(TEXT("\nIn stand-by\n")));
    
    v_pSDMMCregs->rSDIPRE=SDCLK_DV2;//PCLK/(2*NORCLK)-1;    //Normal clock=25MHz

    Card_sel_desel(1);            //Select

    if(!gMMC)
        Set_4bit_bus();
    else
        Set_1bit_bus();            


    if(mmc_card_init())
    {
        g_bSDMMCIsExist=TRUE;
        RETAILMSG(1,(TEXT("mmc_card_init OK.\n")));
        return 1;
    }
    else
    {
        g_bSDMMCIsExist=FALSE;
        RETAILMSG(1,(TEXT("mmc_card_init ERROR.\n")));
        return 0;
    }
}

unsigned char Del_SDMMC()
{
    if(v_pSDMMCregs==NULL)
        return 0;

    Disable_SDIclk();
    return 1;

}


void mmc_spi_cs_low()
{
    //mmc_cs=0
    v_pIOPregs->rGPEDAT&= ~((0x01<<10));
}

void mmc_spi_cs_high()
{
    //mmc_cs=1
    v_pIOPregs->rGPEDAT|=((0x01<<10));
}

U8 mmc_spi_io(U8 data_out)
{
    //从MSB开始,把data_out从CMD线发送,并返回DAT线的内容
    U8 i,input=0;
    //从CMD线发送数据
    MMC_CMD_OUTPUT();
    //从DAT线读数据
    MMC_DAT_INPUT();

    //从MSB开始发送  
    for(i=8;i>0;i--)
    {
    //lower CLOCK
    MMC_CLK_LOW();
    //put DATA on CMD line
    if((data_out>>(i-1))&0x01)
    MMC_CMD_HIGH();
    else
    MMC_CMD_LOW();
    //raise CLOCK
    MMC_CLK_HIGH();
    //从DAT线读数据
    input<<=1;
    input|=MMC_DAT_READ();
    }
    //最后把CMD设高
    MMC_CMD_HIGH();
    return input;    
}

UINT16 calculateCRC7(UCHAR *dBuff,UINT16 offset,UINT16 dLength)
{
    UINT16 ibyte,ibit;
    UINT16 rreg,crc_byte,dtmp;

    crc_byte=0x09;

    rreg=0;
    for(ibyte=offset;ibyte<dLength;ibyte++)
    {
    dtmp=(UINT16)(dBuff[ibyte]);
    for(ibit=0;ibit<8;ibit++)
    {
    rreg<<=1;
    dtmp&=0xFF;
    rreg^=(((dtmp^rreg)&0x80)?crc_byte:0);
    dtmp<<=1;
    }
    }

    return (rreg&0xFF);
}

void mmc_send_command(U8 cmdindex,U32 para)
{
    t_MMC_COMMAND Command;
    U8 i=0;

    memset((U8*)&Command,0,6);
    Command.b1TransmissionBit=1;
    Command.b6CommandIndex=cmdindex;
    Command.Argument.dwArgument[0]=(U8)((para&0xff000000)>>24);
    Command.Argument.dwArgument[1]=(U8)((para&0x00ff0000)>>16);
    Command.Argument.dwArgument[2]=(U8)((para&0x0000ff00)>>8);
    Command.Argument.dwArgument[3]=(U8)(para&0x000000ff);

    Command.b7CRC7=calculateCRC7((U8*)&Command,0,5);
    Command.b1EndBit=1;

    for(i=0;i<6;i++)
        mmc_spi_io(((U8*)&Command));
}


BOOL mmc_card_init(void)
{
    return 1;
}

void mmc_parse_csd(U8 *buf,t_MMC_CSD* pCSD)
{
    RETAILMSG(1,(TEXT("csd :%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x .\r\n"),
        buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],
        buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15]));

    pCSD->b2CSDStructure=(buf[0]&0xc0)>>6;
    pCSD->b4SpecVers=(buf[0]&0x3c)>>2;
    pCSD->b2Reserved1=buf[0]&0x03;

    pCSD->byTAAC=buf[1];
    pCSD->byNSAC=buf[2];
    pCSD->byTranSpeed=buf[3];
    
    pCSD->b12CCC=buf[4];
    pCSD->b12CCC<<=4;
    pCSD->b12CCC|=((buf[5]&0xf0)>>4);

    pCSD->b4ReadBLLen=(buf[5]&0x0f);
    
    pCSD->b1ReadBLPartial=((buf[6]&0x80)>>7);
    pCSD->b1WriteBlkMisalign=((buf[6]&0x40)>>6);
    pCSD->b1ReadBlkMisalign=((buf[6]&0x20)>>5);
    pCSD->b1DSRImp=((buf[6]&0x10)>>4);

    pCSD->b2Reserved2=((buf[6]&0x0c)>>2);
    
    pCSD->b12CSize=(buf[6]&0x03);
    pCSD->b12CSize<<=8;
    pCSD->b12CSize|=buf[7];
    pCSD->b12CSize<<=2;
    pCSD->b12CSize|=((buf[8]&0xc0)>>6);

    pCSD->b3VDDRCurrMin=((buf[8]&0x38)>>3);
    pCSD->b3VDDRCurrMax=(buf[8]&0x07);

    pCSD->b3VDDWCurrMin=((buf[9]&0xe0)>>5);
    pCSD->b3VDDWCurrMax=((buf[9]&0x1c)>>2);
    
    pCSD->b3CSizeMult=(buf[9]&0x03);
    pCSD->b3CSizeMult<<=2;
    pCSD->b3CSizeMult|=((buf[10]&0x80)>>7);

    pCSD->b5EraseGrpSize=((buf[10]&0x7c)>>2);
    pCSD->b5EraseGrpMult=(buf[10]&0x03);
    pCSD->b5EraseGrpMult<<=3;
    pCSD->b5EraseGrpMult|=((buf[11]&0xe0)>>5);
    pCSD->b5WPGrpSize=(buf[11]&0x1f);
    
    pCSD->b1WPGrpEnable=((buf[12]&0x80)>>7);
    pCSD->b2DefaultECC=((buf[12]&0x60)>>5);
    pCSD->b3R2WFactor=((buf[12]&0x1c)>>2);
    
    pCSD->b4WriteBLLen=(buf[12]&0x03);
    pCSD->b4WriteBLLen<<=2;
    pCSD->b4WriteBLLen|=((buf[13]&0xc0)>>6);

    pCSD->b1WriteBLPartial=((buf[13]&0x20)>>5);
    pCSD->b4Reserved3=((buf[13]&0x1e)>>1);
    pCSD->b1ContentProtAPP=(buf[13]&0x01);

    pCSD->b1FileFormatGrp=((buf[14]&0x80)>>7);
    pCSD->b1Copy=((buf[14]&0x40)>>6);
    pCSD->b1PermWriteProtect=((buf[14]&0x20)>>5);
    pCSD->b1TmpWriteProtect=((buf[14]&0x10)>>4);

    pCSD->b2FileFormat=((buf[14]&0x0c)>>2);
    pCSD->b2ECC=(buf[14]&0x03);

    pCSD->b7CRC=((buf[15]&0xfe)>>1);
    pCSD->b1NouUsed=buf[15]&0x01;
}

BOOL mmc_send_csd(DISK_INFO *pDiskInfo)
{
    //获取分区表信息

    U8 buf[16];
    U32 m_Size,rate;
    t_MMC_CSD m_CSD;

    memset((U8*)&m_CSD,0,sizeof(t_MMC_CSD));
    
    Card_sel_desel(0);    // Card deselect

        if(!CMD9())
        RETAILMSG(1,(TEXT("\nmmc_send_csd::cmd9 error\n")));

    buf[0] = ((v_pSDMMCregs->rSDIRSP0)>>24)&0xff;
    buf[1] = ((v_pSDMMCregs->rSDIRSP0)>>16)&0xff;
    buf[2] = ((v_pSDMMCregs->rSDIRSP0)>>8)&0xff;
    buf[3] = (v_pSDMMCregs->rSDIRSP0)&0xff;
    
    buf[4] = ((v_pSDMMCregs->rSDIRSP1)>>24)&0xff;
    buf[5] = ((v_pSDMMCregs->rSDIRSP1)>>16)&0xff;
    buf[6] = ((v_pSDMMCregs->rSDIRSP1)>>8)&0xff;
    buf[7] = (v_pSDMMCregs->rSDIRSP1)&0xff;
    
    buf[8] = ((v_pSDMMCregs->rSDIRSP2)>>24)&0xff;
    buf[9] = ((v_pSDMMCregs->rSDIRSP2)>>16)&0xff;
    buf[10] = ((v_pSDMMCregs->rSDIRSP2)>>8)&0xff;
    buf[11] = (v_pSDMMCregs->rSDIRSP2)&0xff;
    
    buf[12] = ((v_pSDMMCregs->rSDIRSP3)>>24)&0xff;
    buf[13] = ((v_pSDMMCregs->rSDIRSP3)>>16)&0xff;
    buf[14] = ((v_pSDMMCregs->rSDIRSP3)>>8)&0xff;
    buf[15] = (v_pSDMMCregs->rSDIRSP3)&0xff;

    Card_sel_desel(1);    // Card deselect
    
    //分析CSD
    mmc_parse_csd((U8 *)buf,&m_CSD);

    RETAILMSG(1,(TEXT("---------------------------------\r\n")));
    RETAILMSG(1,(TEXT("b2CSDStructure=%d.\r\n"),m_CSD.b2CSDStructure));
    RETAILMSG(1,(TEXT("b4SpecVers=%d.\r\n"),m_CSD.b4SpecVers));
    RETAILMSG(1,(TEXT("b2Reserved1=%d.\r\n"),m_CSD.b2Reserved1));
    RETAILMSG(1,(TEXT("byTAAC=%d.\r\n"),m_CSD.byTAAC));
    RETAILMSG(1,(TEXT("byNSAC=%d.\r\n"),m_CSD.byNSAC));
    RETAILMSG(1,(TEXT("byTranSpeed=%d.\r\n"),m_CSD.byTranSpeed));
    RETAILMSG(1,(TEXT("b12CCC=%d.\r\n"),m_CSD.b12CCC));
    RETAILMSG(1,(TEXT("b4ReadBLLen=%d.\r\n"),m_CSD.b4ReadBLLen));
                    
    RETAILMSG(1,(TEXT("b1ReadBLPartial=%d.\r\n"),m_CSD.b1ReadBLPartial));
    RETAILMSG(1,(TEXT("b1WriteBlkMisalign=%d.\r\n"),m_CSD.b1WriteBlkMisalign));
    RETAILMSG(1,(TEXT("b1ReadBlkMisalign=%d.\r\n"),m_CSD.b1ReadBlkMisalign));
    RETAILMSG(1,(TEXT("b1DSRImp=%d.\r\n"),m_CSD.b1DSRImp));
    RETAILMSG(1,(TEXT("b12CSize=%d.\r\n"),m_CSD.b12CSize));
                    
    RETAILMSG(1,(TEXT("b3VDDRCurrMin=%d.\r\n"),m_CSD.b3VDDRCurrMin));
    RETAILMSG(1,(TEXT("b3VDDRCurrMax=%d.\r\n"),m_CSD.b3VDDRCurrMax));
    RETAILMSG(1,(TEXT("b3VDDWCurrMin=%d.\r\n"),m_CSD.b3VDDWCurrMin));
    RETAILMSG(1,(TEXT("b3VDDWCurrMax=%d.\r\n"),m_CSD.b3VDDWCurrMax));
                    
    RETAILMSG(1,(TEXT("b3CSizeMult=%d.\r\n"),m_CSD.b3CSizeMult));
    RETAILMSG(1,(TEXT("b5EraseGrpSize=%d.\r\n"),m_CSD.b5EraseGrpSize));
    RETAILMSG(1,(TEXT("b5EraseGrpMult=%d.\r\n"),m_CSD.b5EraseGrpMult));
    RETAILMSG(1,(TEXT("b5WPGrpSize=%d.\r\n"),m_CSD.b5WPGrpSize));
                    
    RETAILMSG(1,(TEXT("b1WPGrpEnable=%d.\r\n"),m_CSD.b1WPGrpEnable));
    RETAILMSG(1,(TEXT("b2DefaultECC=%d.\r\n"),m_CSD.b2DefaultECC));
    RETAILMSG(1,(TEXT("b3R2WFactor=%d.\r\n"),m_CSD.b3R2WFactor));
    RETAILMSG(1,(TEXT("b4WriteBLLen=%d.\r\n"),m_CSD.b4WriteBLLen));

    RETAILMSG(1,(TEXT("b1WriteBLPartial=%d.\r\n"),m_CSD.b1WriteBLPartial));
    RETAILMSG(1,(TEXT("b4Reserved3=%d.\r\n"),m_CSD.b4Reserved3));
    RETAILMSG(1,(TEXT("b1ContentProtAPP=%d.\r\n"),m_CSD.b1ContentProtAPP));

    RETAILMSG(1,(TEXT("b1FileFormatGrp=%d.\r\n"),m_CSD.b1FileFormatGrp));
    RETAILMSG(1,(TEXT("b1Copy=%d.\n"),m_CSD.b1Copy));
    RETAILMSG(1,(TEXT("b1PermWriteProtect=%d.\r\n"),m_CSD.b1PermWriteProtect));
    RETAILMSG(1,(TEXT("b1TmpWriteProtect=%d.\r\n"),m_CSD.b1TmpWriteProtect));
    RETAILMSG(1,(TEXT("b2FileFormat=%d.\r\n"),m_CSD.b2FileFormat));
    RETAILMSG(1,(TEXT("b2ECC=%d.\r\n"),m_CSD.b2ECC));
    RETAILMSG(1,(TEXT("b7CRC=%d.\r\n"),m_CSD.b7CRC));
    RETAILMSG(1,(TEXT("b1NouUsed=%d.\r\n"),m_CSD.b1NouUsed));
    RETAILMSG(1,(TEXT("---------------------------------\r\n")));

    pDiskInfo->di_bytes_per_sect=MMC_SECTOR_SIZE;    //Start with 512,then go with SetInfo changes
    pDiskInfo->di_cylinders=1;
    pDiskInfo->di_heads=1;
    pDiskInfo->di_sectors=32;
    

    m_Size=(m_CSD.b12CSize+1)*(pow(2,m_CSD.b3CSizeMult+2))*(pow(2,m_CSD.b4ReadBLLen))/512;

    
    pDiskInfo->di_total_sectors=m_Size;
    pDiskInfo->di_flags=DISK_INFO_FLAG_MBR;

    
    return TRUE;
}


void SDMMC_Identify(DISK_INFO *pDiskInfo)
{
    //获取MMC卡的信息
    RETAILMSG(1,(TEXT("SDMMC_Identify\r\n")));
    if(g_bSDMMCIsExist==FALSE)
        return;
    RETAILMSG(1,(TEXT("SDMMC_Identify in...\r\n")));
    if(mmc_send_csd(pDiskInfo))
    {
        RETAILMSG(1,(TEXT("di_bytes_per_sect=%d.\r\n"),pDiskInfo->di_bytes_per_sect));
        RETAILMSG(1,(TEXT("di_cylinders=%d.\r\n"),pDiskInfo->di_cylinders));
        RETAILMSG(1,(TEXT("di_heads=%d.\r\n"),pDiskInfo->di_heads));
        RETAILMSG(1,(TEXT("di_sectors=%d.\r\n"),pDiskInfo->di_sectors));
        RETAILMSG(1,(TEXT("di_total_sectors=%d.\r\n"),pDiskInfo->di_total_sectors));

        RETAILMSG(1,(TEXT("mmc_send_csd OK.\r\n")));
    }
    else
    {
        RETAILMSG(1,(TEXT("mmc_send_csd ERROR.\r\n")));
    }
}


U8 mmc_read_sector(U8 *buf,U32 secaddrno)
{
    U32 addr;
    U32 rd_data;
    int status;
    int rd_cnt=0;
    unsigned int cnt = 0;

    
    if(v_pSDMMCregs==NULL)
        return 0;

    if(secaddrno>MMC_MAX_SECTOR*4)
        return 0;
    
    addr = secaddrno*MMC_SECTOR_SIZE;


    v_pSDMMCregs->rSDIFSTA |= (1<<16);    //FIFO reset
    v_pSDMMCregs->rSDIFSTA &= 0xc000; // clear error status
    v_pSDMMCregs->rSDICMDSTA = 0x1E00; // clear any pending status flags
    v_pSDMMCregs->rSDIDATCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)|(2<<12)|(1<<0);    //YH 040220
        v_pSDMMCregs->rSDICMDARG=addr;                    //CMD17/18(addr)

RERDCMD:
    v_pSDMMCregs->rSDICMDCON=(0x1<<11)|(0x1<<9)|(0x1<<8)|0x51;    //sht_resp,wait_resp,dat,start,CMD17
    cnt ++;
    if(cnt > 4000)
        {
        RETAILMSG(1,(TEXT("\ncmd read sector 17 1 while sector = %d , CMDSTATE = 0x%x\n"),secaddrno,v_pSDMMCregs->rSDICMDSTA));
        return 0;
        }
    Sleep(1);
    if(!Chk_CMDend(17,1))    //Check end of CMD17
        goto RERDCMD;

    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)    
    v_pSDMMCregs->rSDIDATSTA=0x20;      //Clear timeout flag    



    while(rd_cnt<128)    //512 bytes
    {
    status=v_pSDMMCregs->rSDIDATSTA;
    if(status&0x20)     //Check timeout
    {
    RETAILMSG(1,(TEXT("\nRd_Block timeout:%d!\n"),secaddrno));
    v_pSDMMCregs->rSDIDATSTA=0x20;      //Clear timeout flag
    return 0;
    }
    status=v_pSDMMCregs->rSDIFSTA;


    if((status&0x1000)==0x1000)    //Is Rx data?
    {
    rd_data=v_pSDMMCregs->rSDIDAT;

    buf[rd_cnt*4]  =(rd_data>>0 &0xff);
    buf[rd_cnt*4+1]=(rd_data>>8 &0xff);
    buf[rd_cnt*4+2]=(rd_data>>16&0xff);
    buf[rd_cnt*4+3]=(rd_data>>24&0xff);

    rd_cnt++;

    }

    }






    

    //Check end of DATA
    if(!Chk_DATend())
        {
        RETAILMSG(1,(TEXT("\nread check dat end error sector = %d\n"),secaddrno));
            return 0;
        }


    v_pSDMMCregs->rSDIDATCON = (v_pSDMMCregs->rSDIDATCON)&~(7<<12);        //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
    v_pSDMMCregs->rSDIFSTA &= 0x200;    //Clear Rx FIFO Last data Ready, YH 040221
        v_pSDMMCregs->rSDIDATSTA = 0x10;    //Clear data Tx/Rx end

    v_pSDMMCregs->rSDIPRE=SDCLK_DV2;

    return 1;
}


U8 mmc_write_sector(U8 *buf,U32 secaddrno)
{
    int status;
    int wt_cnt=0;
    U32 addr;
    U32 *wdata=(U32 *)buf;
   unsigned int cnt = 0;



    if(v_pSDMMCregs==NULL)
        return 0;

    if(secaddrno>MMC_MAX_SECTOR)    
        return 0;
    addr=secaddrno*MMC_SECTOR_SIZE;


    v_pSDMMCregs->rSDIFSTA |= (1<<16);    //FIFO reset
    v_pSDMMCregs->rSDICMDSTA = 0x1E00; // clear any pending status flags    
    v_pSDMMCregs->rSDIDATCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|(1<<0);    //YH 040220
    v_pSDMMCregs->rSDICMDARG=addr;                //CMD24/25(addr)

REWTCMD:
    v_pSDMMCregs->rSDICMDCON=(0x1<<11)|(0x1<<9)|(0x1<<8)|0x58;    //sht_resp,wait_resp,dat,start,CMD24
    cnt ++;
    if(cnt > 1000)
        {
        RETAILMSG(1,(TEXT("\ncmd write sector 24 1 while sector = %d , CMDSTATE = 0x%x\n"),secaddrno,v_pSDMMCregs->rSDICMDSTA));
        return 0;
        }
    
    if(!Chk_CMDend(24,1))                //Check end of CMD24
        goto REWTCMD;
    
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)

    while(wt_cnt<128)
    {
        status=v_pSDMMCregs->rSDIFSTA;
        if((status&0x2000)==0x2000)
        {
            v_pSDMMCregs->rSDIDAT= *wdata++;
            wt_cnt++;
        }
    }
    
    //Check end of DATA
   Sleep(10);
    if(!Chk_DATend())
        {

        }


        
    v_pSDMMCregs->rSDIDATCON = v_pSDMMCregs->rSDIDATCON&~(7<<12);        //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
    v_pSDMMCregs->rSDIDATSTA=0x10;    //Clear data Tx/Rx end
    v_pSDMMCregs->rSDIPRE=SDCLK_DV2;



    return 1;
}


unsigned char sector_busy = 0;
void ReadSector(PBYTE pBuffer,DWORD dwStartSector)
{
    while(sector_busy);

    sector_busy = 1;
    mmc_read_sector(pBuffer,dwStartSector);
    sector_busy = 0;
}

void WriteSector(PBYTE pBuffer,DWORD dwStartSector)
{
    while(sector_busy);

    sector_busy = 1;
    mmc_write_sector(pBuffer,dwStartSector);
    sector_busy = 0;
}

void Set_1bit_bus(void)
{
    Wide=0;
    if(!gMMC)
    SetBus();
}

void Set_4bit_bus(void)
{
    Wide=1;
    SetBus();
}

void SetBus(void)
{
SET_BUS:
    CMD55();    //Make ACMD
    //CMD6 implement
    v_pSDMMCregs->rSDICMDARG=Wide<<1;                    //Wide 0: 1bit,1: 4bit
    v_pSDMMCregs->rSDICMDCON=(0x1<<9)|(0x1<<8)|0x46;    //sht_resp,wait_resp,start,CMD55

    if(!Chk_CMDend(6,1))   //ACMD6
        goto SET_BUS;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)
}

harktrip
驱动小牛
驱动小牛
  • 注册日期2003-11-30
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分51分
  • 威望457点
  • 贡献值0点
  • 好评度170点
  • 原创分0分
  • 专家分2分
沙发#
发布于:2008-08-01 11:47
使用MMC卡,COPY一整个目录(約30MB),可以复制过去到MMC卡.
但部分MMC卡上的档案结构会被破坏,导致在PC上无法读取
harktrip
驱动小牛
驱动小牛
  • 注册日期2003-11-30
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分51分
  • 威望457点
  • 贡献值0点
  • 好评度170点
  • 原创分0分
  • 专家分2分
板凳#
发布于:2008-08-01 15:29
U8 mmc_write_sector(U8 *buf,U32 secaddrno)
{
    int status;
    int wt_cnt=0;
    U32 addr;
    U32 *wdata=(U32 *)buf;
   unsigned int cnt = 0;



    if(v_pSDMMCregs==NULL)
        return 0;


    addr=secaddrno*MMC_SECTOR_SIZE;


    v_pSDMMCregs->rSDIFSTA |= (1<<16);    //FIFO reset
    v_pSDMMCregs->rSDIFSTA &= 0xc000; // clear error status
    v_pSDMMCregs->rSDICMDSTA = 0x1E00; // clear any pending status flags    
    v_pSDMMCregs->rSDIDATCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|(1<<0);    //YH 040220
    v_pSDMMCregs->rSDICMDARG=addr;                //CMD24/25(addr)

REWTCMD:
    v_pSDMMCregs->rSDICMDCON=(0x1<<11)|(0x1<<9)|(0x1<<8)|0x58;    //sht_resp,wait_resp,dat,start,CMD24
    cnt ++;
    if(cnt > 1000)
        {
        RETAILMSG(1,(TEXT("\ncmd write sector 24 1 while sector = %d , CMDSTATE = 0x%x\n"),secaddrno,v_pSDMMCregs->rSDICMDSTA));
        return 0;
        }
    
    if(!Chk_CMDend(24,1))                //Check end of CMD24
        goto REWTCMD;
    v_pSDMMCregs->rSDICMDSTA=0xa00;    // Clear cmd_end(with rsp)    
    v_pSDMMCregs->rSDIDATSTA=0x20;      //Clear timeout flag    


    while(wt_cnt<128)
    {
        status=v_pSDMMCregs->rSDIFSTA;
        if((status&0x2000)==0x2000)
        {
            v_pSDMMCregs->rSDIDAT= *wdata++;
            wt_cnt++;
        }
    }
    

    //Check end of DATA
    if(!Chk_DATend())
        {
        RETAILMSG(1,(TEXT("\nread check dat end error sector = %d\n"),secaddrno));
            return 0;
        }


    v_pSDMMCregs->rSDIDATCON = (v_pSDMMCregs->rSDIDATCON)&~(7<<12);        //YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
    v_pSDMMCregs->rSDIFSTA &= 0x200;    //Clear Rx FIFO Last data Ready, YH 040221
  v_pSDMMCregs->rSDIDATSTA = 0x10;    //Clear data Tx/Rx end

    v_pSDMMCregs->rSDIPRE=SDCLK_DV2;

    return 1;
}


unsigned char sector_busy = 0;
void ReadSector(PBYTE pBuffer,DWORD dwStartSector)
{
    while(sector_busy);

    sector_busy = 1;
    mmc_read_sector(pBuffer,dwStartSector);
    sector_busy = 0;
}

void WriteSector(PBYTE pBuffer,DWORD dwStartSector)
{
    while(sector_busy);

    sector_busy = 1;
    mmc_write_sector(pBuffer,dwStartSector);
    sector_busy = 0;
}


改這樣後,可以寫入檔案了,不過....
似乎某些檔案寫入後,該檔結構不完整有問題,而無法讀取或寫入~~~
gooogleman
驱动牛犊
驱动牛犊
  • 注册日期2007-03-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望179点
  • 贡献值0点
  • 好评度18点
  • 原创分0分
  • 专家分0分
地板#
发布于:2008-10-10 12:02
楼主,不错。我直接用微软自带的了
WINCEqq 群39063007
lStoneCN
驱动牛犊
驱动牛犊
  • 注册日期2004-08-11
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分334分
  • 威望321点
  • 贡献值1点
  • 好评度28点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-10-12 11:25
太长了,做个记号以后看。
寻zigbee/CC2430高手合作!
游客

返回顶部