📄 sdhc.c
字号:
#include "sdhc.h"
#include "sdhcmap.h"
#include "sdhcbase.h"
//#include "hw.h"
#include "utils.h"
#define debug myprintf
static int isSDHCInitialized=0;
//SDHC_T* theSDHCHandle;
int g_theblklen;//block length
int g_thewidth;//width: 1 or 4 data wire
char g_isAUTOCMD12; //if AUTOCMD12 is used, no need to send abort after transfer
unsigned short g_rca; //similar to an address
//#define debug(fmt,arg...) printk(fmt, ##arg)
DEVICE_OP sdhc_dev_op={
read: sdhc_dev_read,
write: sdhc_dev_write,
};
void initSDHC()
{
// CSD_T theCSD;// CID_T theCID;// SCR_T theSCR;// unsigned long theCardType; unsigned long status;
int dividerCode;
isSDHCInitialized=1;
// printk("init SDHC********************\n");/*// theSDHCHandle=(SDHC_T*)SDHC_MODULE_BASE;//mapping to register printk("theSDHCHandle=0x%X\n",theSDHCHandle);
printk("u32DMAAdr :0x%x\n",&theSDHCHandle->u32DMAAddr); printk("u16BlkSize :0x%x\n",&theSDHCHandle->u16BlkSize); printk("u16BlkCount :0x%x\n",&theSDHCHandle->u16BlkCount); printk("u32Arg :0x%x\n",&theSDHCHandle->u32Arg); printk("u16TrnsfrMode :0x%x\n",&theSDHCHandle->u16TrnsfrMode); printk("u16Cmd :0x%x\n",&theSDHCHandle->u16Cmd); printk("a32Rsp :0x%x\n",theSDHCHandle->a32Rsp); printk("u8DataPort :0x%x\n",&theSDHCHandle->u8DataPort); printk("a8Rsvd1 :0x%x\n",theSDHCHandle->a8Rsvd1); printk("u32PrsntState :0x%x\n",&theSDHCHandle->u32PrsntState); printk("u8HstCntl :0x%x\n",&theSDHCHandle->u8HstCntl); printk("u8PwrCntl :0x%x\n",&theSDHCHandle->u8PwrCntl); printk("u8BlkGapCntl :0x%x\n",&theSDHCHandle->u8BlkGapCntl); printk("u8WkupCntl :0x%x\n",&theSDHCHandle->u8WkupCntl); printk("u8ClkCntl :0x%x\n",&theSDHCHandle->u8ClkCntl); printk("u8ClkDiv :0x%x\n",&theSDHCHandle->u8ClkDiv); printk("u8ToutCntl :0x%x\n",&theSDHCHandle->u8ToutCntl); printk("u8SwReset :0x%x\n",&theSDHCHandle->u8SwReset); printk("u16NrmIntrStatus :0x%x\n",&theSDHCHandle->u16NrmIntrStatus); printk("u16ErrIntrStatus :0x%x\n",&theSDHCHandle->u16ErrIntrStatus); printk("u16NrmIntrStatusEn:0x%x\n",&theSDHCHandle->u16NrmIntrStatusEn); printk("u16ErrIntrStatusEn:0x%x\n",&theSDHCHandle->u16ErrIntrStatusEn); printk("u16NrmIntrSignalEn:0x%x\n",&theSDHCHandle->u16NrmIntrSignalEn); printk("u16ErrIntrSignalEn:0x%x\n",&theSDHCHandle->u16ErrIntrSignalEn); printk("u16ACMD12ErrStatus:0x%x\n",&theSDHCHandle->u16ACMD12ErrStatus); printk("u16Rsvd2 :0x%x\n",&theSDHCHandle->u16Rsvd2); printk("u32Capabilities :0x%x\n",&theSDHCHandle->u32Capabilities); printk("u32CapRsvd :0x%x\n",&theSDHCHandle->u32CapRsvd); printk("u32MaxCurrCap :0x%x\n",&theSDHCHandle->u32MaxCurrCap); printk("u32MaxCurrCapRsvd :0x%x\n",&theSDHCHandle->u32MaxCurrCapRsvd); printk("u32Rsvd3 :0x%x\n",theSDHCHandle->u32Rsvd3); printk("u16SlotIntrStatus :0x%x\n",&theSDHCHandle->u16SlotIntrStatus); printk("u16HCVer :0x%x\n",&theSDHCHandle->u16HCVer);*/ g_theblklen=512; //block size = 512 byte
g_thewidth=1;//g_thewidth=4; //4 wire or 1 wire [only 1 wire for MMC] g_isAUTOCMD12=1;//use AUTOCMD12 as default instead of send abort at the end of transfer
sdhc_init(&g_rca);
sdhc_set_buswidth(g_thewidth);
sdhc_set_blklen(g_theblklen);
dividerCode=0x1; //printk("Divider Code=%X\n",dividerCode); clock_cntl (0x4,dividerCode,1); decode_r1(status);
}
#define checkInitialized() { if(!isSDHCInitialized) { initSDHC(); } }
int sdhc_set_block_length(unsigned long blklen)
{
checkInitialized();
g_theblklen=blklen; //block size = 512 byte
return sdhc_set_blklen(g_theblklen);}
int sdhc_get_block_length()
{
return g_theblklen;
}
unsigned long sdhc_get_card_type()
{
return _sdhc_get_card_type();
}
unsigned long sdhc_get_card_capacity()
{
return _sdhc_get_card_capacity();
}
int sdhc_dma_read_single(unsigned long SDByteAddr, unsigned char *blkbuf)
{
checkInitialized();
int nblk=1;//0:single block transfer
int flag=(RWF_DMA) |(g_isAUTOCMD12? RWF_AUTOCMD12:0);
INT32 memOffset=ssd_mem_malloc(g_theblklen); if(memOffset>=0) { int i,error; error=sdhc_read_ex (SDByteAddr, memOffset, g_theblklen, nblk,flag, 0); for(i=0;i<g_theblklen;i++) { blkbuf[i]=SSD_MEMRB(memOffset+i); } ssd_mem_free(memOffset); return error; } else { return -1;//error }}
int sdhc_dma_read_multiple(unsigned long SDByteAddr, unsigned char *blkbuf, int nblk)
{
checkInitialized();
//myprintf("SDByteAddress = 0x%x.\n\r", SDByteAddr); int flag=(RWF_DMA) |(g_isAUTOCMD12? RWF_AUTOCMD12:0);
INT32 memOffset=ssd_mem_malloc(g_theblklen); //myprintf("Memory offset = 0x%x.\n\r", memOffset); if(memOffset>=0) { int i,error; int blkIndex=0; error=0; for(blkIndex=0;blkIndex<nblk && !error; blkIndex++) { int bufOffset=blkIndex*g_theblklen; error=sdhc_read_ex (SDByteAddr+bufOffset, memOffset, g_theblklen, 1,flag, 0);//1 block each time for(i=0;i<g_theblklen;i++) { blkbuf[i+bufOffset]=SSD_MEMRB(memOffset+i); } } ssd_mem_free(memOffset); return error; } else { return -1; } //return sdhc_read(theSDHCHandle,SDByteAddr,blkbuf,g_theblklen,nblk,flag,0);}
int sdhc_dma_read_multiple_to_memory(unsigned long SDByteAddr, int memOffset, int nblk)
{
checkInitialized();
int flag=(RWF_DMA) |(g_isAUTOCMD12? RWF_AUTOCMD12:0)| RWF_NOREAD;
return sdhc_read_ex (SDByteAddr, memOffset, g_theblklen, nblk,flag, 0);}
int sdhc_dma_write_single(unsigned long SDByteAddr, unsigned char *blkbuf)
{
checkInitialized();
int nblk=1;//0: single block transfer
int flag=(RWF_DMA) |(g_isAUTOCMD12? RWF_AUTOCMD12:0);
INT32 memOffset=ssd_mem_malloc(g_theblklen); if(memOffset>=0) { int i,error; int blkIndex=0; error=0; for(i=0;i<g_theblklen;i++) { SSD_MEMWB(memOffset+i,blkbuf[i]); } error=sdhc_write_ex (SDByteAddr, memOffset, g_theblklen, 1,flag, 0);//1 block each time ssd_mem_free(memOffset); return error; } else { return -1; } //return sdhc_write (theSDHCHandle,SDByteAddr,blkbuf, g_theblklen,nblk, flag,0);}
int sdhc_dma_write_multiple(unsigned long SDByteAddr, unsigned char *blkbuf, int nblk)
{
checkInitialized();
int flag=(RWF_DMA) |(g_isAUTOCMD12? RWF_AUTOCMD12:0);
INT32 memOffset=ssd_mem_malloc(g_theblklen); if(memOffset>=0) { int i,error; int blkIndex=0; error=0; for(blkIndex=0;blkIndex<nblk && !error; blkIndex++) { int bufOffset=blkIndex*g_theblklen; for(i=0;i<g_theblklen;i++) { SSD_MEMWB(memOffset+i,blkbuf[i+bufOffset]); } error=sdhc_write_ex (SDByteAddr+bufOffset, memOffset, g_theblklen, 1,flag, 0);//1 block each time } ssd_mem_free(memOffset); return error; } else { return -1; } //return sdhc_write (theSDHCHandle,SDByteAddr,blkbuf, g_theblklen,nblk, flag,0);}
int sdhc_dma_write_multiple_from_memory(unsigned long SDByteAddr, int memOffset, int nblk)
{
checkInitialized();
int flag=(RWF_DMA) |(g_isAUTOCMD12? RWF_AUTOCMD12:0)|RWF_NOFILL;
return sdhc_write_ex (SDByteAddr,memOffset, g_theblklen,nblk, flag,0);}
int sdhc_pio_read_single(unsigned long SDByteAddr, unsigned char *blkbuf)
{
checkInitialized();
int nblk=1;//0:single block transfer
int flag=(g_isAUTOCMD12? RWF_AUTOCMD12:0 );
//return sdhc_read(theSDHCHandle,SDByteAddr,blkbuf,g_theblklen,nblk,flag,0);}
int sdhc_pio_read_multiple(unsigned long SDByteAddr, unsigned char *blkbuf, int nblk)
{
checkInitialized();
int flag=(g_isAUTOCMD12? RWF_AUTOCMD12:0 );
//return sdhc_read(theSDHCHandle,SDByteAddr,blkbuf,g_theblklen,nblk,flag,0);}
int sdhc_pio_write_single(unsigned long SDByteAddr, unsigned char *blkbuf)
{
checkInitialized();
int nblk=1;
int flag=(g_isAUTOCMD12? RWF_AUTOCMD12:0);
//return sdhc_write (theSDHCHandle,SDByteAddr,blkbuf, g_theblklen,nblk, flag,0);}
int sdhc_pio_write_multiple(unsigned long SDByteAddr, unsigned char *blkbuf, int nblk)
{
checkInitialized();
int flag=(g_isAUTOCMD12? RWF_AUTOCMD12:0);
//return sdhc_write (theSDHCHandle,SDByteAddr,blkbuf, g_theblklen,nblk, flag,0);}
int sdhc_reset_all ()
{
checkInitialized();
//reset data
//reset cmd
sdhc_reset ( SW_RESET_ALL);}
int sdhc_set_buswidth (int width)
{
checkInitialized();
g_thewidth=width; //4 wire or 1 wire [only 1 wire for MMC]
return sdhc_set_width(g_rca,g_thewidth);}
int sdhc_get_buswidth()
{
return g_thewidth;
}
int sdhc_set_autocmd12(int isOn)
{
checkInitialized();
g_isAUTOCMD12=isOn;//use AUTOCMD12 as default instead of send abort at the end of transfer
return 0;
}
UINT32 sdhc_dev_read_with_mcu_address(UINT32 SDOffset, UINT8 *buffer, UINT32 byteSize)
{
int blockLen=sdhc_get_block_length();
int numOfFullBlock=byteSize/blockLen;
int residualSize=byteSize;
int retCode=0;
INT32 memOffset=ssd_mem_malloc(blockLen);
if(memOffset<0)
{
debug("memory not enough\n");
return 0;
}
int DataStartInsideBlock=SDOffset%blockLen;
int SDOffsetToRead=SDOffset-DataStartInsideBlock;
int bufferIndex=0;
while(residualSize>0)
{
int i;
if(retCode=sdhc_dma_read_multiple_to_memory(SDOffsetToRead, memOffset, 1))
{
break;
}
for(i=0;i<blockLen && residualSize;i++)
{
buffer[bufferIndex++]=*(unsigned char*)(SSD_MAP_MEM+memOffset+DataStartInsideBlock+i);
residualSize--;
}
SDOffsetToRead+=blockLen;
DataStartInsideBlock=0;
}
ssd_mem_free(memOffset);
if(retCode)
return 0;
else
return byteSize;
}
UINT32 sdhc_dev_read_with_1923_address(UINT32 SDOffset, UINT8 *buffer, UINT32 byteSize)
{
int blockLen=sdhc_get_block_length();
int numOfFullBlock=byteSize/blockLen;
int residualSize=byteSize;
int retCode=0;
int memOffset=(int)buffer;
memOffset-=SSD_MAP_MEM;
if(numOfFullBlock>0)
{
retCode=sdhc_dma_read_multiple_to_memory(SDOffset, memOffset, numOfFullBlock);
residualSize-=numOfFullBlock*blockLen;
}
if(!retCode && residualSize>0)
{
int i;
INT32 tempMem=ssd_mem_malloc(512);//one block
if(tempMem<0)
{
return -1;
}
retCode=sdhc_dma_read_multiple_to_memory(SDOffset+numOfFullBlock*blockLen, tempMem, 1);
int tempMemBase=SSD_MAP_MEM+tempMem;
for(i=0;i<residualSize;i++)
{
buffer[numOfFullBlock*blockLen+i]=*(unsigned char*)(tempMemBase+i);
}
ssd_mem_free(tempMem);
}
if(retCode)
return 0;
else
return byteSize;
}
UINT32 sdhc_dev_write_with_mcu_address(UINT32 SDOffset, UINT8 *buffer, UINT32 byteSize)
{
int i;
int blockLen=sdhc_get_block_length();
int numOfFullBlock=byteSize/blockLen;
int residualSize=byteSize;
int retCode=0;
INT32 memOffset=ssd_mem_malloc(blockLen);
if(memOffset<0)
{
debug("memory not enough\n");
return 0;
}
int DataStartInsideBlock=SDOffset%blockLen;
int SDOffsetToRead=SDOffset-DataStartInsideBlock;
int bufferIndex=0;
while(residualSize>0)
{
int i;
//1.if the data is start inside a block or the data is not a full block
//read out the data block first
if(DataStartInsideBlock || residualSize<blockLen)
{
debug("read out the data\n");
if(retCode=sdhc_dma_read_multiple_to_memory(SDOffsetToRead, memOffset, 1))
{
break;
}
}
//2. modified the data block
for(i=DataStartInsideBlock;i<blockLen && residualSize;i++)
{
*(unsigned char*)(SSD_MAP_MEM+memOffset+i)=buffer[bufferIndex++];
residualSize--;
}
//3. write back the data block
if(retCode=sdhc_dma_write_multiple_from_memory(SDOffsetToRead, memOffset, 1))
{
debug("sdhc_dma_write_multiple_from_memory() error =%d\n",retCode);
break;
}
SDOffsetToRead+=blockLen;
DataStartInsideBlock=0;
}
ssd_mem_free(memOffset);
if(retCode)
return 0;
else
return byteSize;
}
UINT32 sdhc_dev_write_with_1923_address(UINT32 SDOffset, UINT8 *buffer, UINT32 byteSize)
{
int blockLen=sdhc_get_block_length();
int numOfFullBlock=byteSize/blockLen;
int residualSize=byteSize%blockLen;
int retCode=0;
int memOffset=(int)buffer;
memOffset-=SSD_MAP_MEM;
if(byteSize>0)
{
retCode=sdhc_dma_write_multiple_from_memory(SDOffset, memOffset, numOfFullBlock+residualSize?1:0);
}
/*
if(!retCode && residualSize>0)
{
int i;
INT32 tempMem=ssd_mem_malloc(512);//one block
if(tempMem<0)
{
return -1;
}
//1. read back
retCode=sdhc_dma_read_multiple_to_memory(SDOffset+numOfFullBlock*blockLen,tempMem,1);
if(!retCode)
{
int tempMemBase=SSD_MAP_MEM+tempMem;
//2. modified the data
for(i=blockLen-residualSize;i<blockLen;i++)
{
buffer[numOfFullBlock*blockLen+i]=*(unsigned char*)(tempMemBase+i);
}
//3.write back to SD card
retCode=sdhc_dma_write_multiple_from_memory(SDOffset+numOfFullBlock*blockLen, tempMem, 1);
}
ssd_mem_free(tempMem);
}
*/
if(retCode)
return 0;
else
return byteSize;
}
UINT32 sdhc_dev_read(UINT32 SDOffset, UINT8 *buffer, UINT32 byteSize)
{
int blockLen=sdhc_get_block_length();
int retCount=0;
if(buffer<SSD_MAP_MEM || buffer>SSD_MAP_MEM+512*1024 || (int)buffer%512 || SDOffset%blockLen)
{
retCount= sdhc_dev_read_with_mcu_address(SDOffset,buffer,byteSize);
}
else
{
retCount= sdhc_dev_read_with_1923_address(SDOffset,buffer,byteSize);
}
return retCount;
}
UINT32 sdhc_dev_write(UINT32 SDOffset, UINT8 *buffer, UINT32 byteSize)
{
int blockLen=sdhc_get_block_length();
int retCount=0;
if(buffer<SSD_MAP_MEM || buffer>SSD_MAP_MEM+512*1024 || (int)buffer%512 || SDOffset%blockLen)
{
retCount= sdhc_dev_write_with_mcu_address(SDOffset,buffer,byteSize);
}
else
{
retCount= sdhc_dev_write_with_1923_address(SDOffset,buffer,byteSize);
}
return retCount;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -