⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdi2410.c

📁 HFAT32是我依据FAT标准,按照自己的理解写出来的一个FAT文件系统 特性: 1.HFAT32 是一个小型的嵌入式FAT文件系统,可以方便地在nand flash,RAM和SD Card
💻 C
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------------
// Copyright jinhailiao 2008-2010
// E-mail:   jinhailiao@163.com
// Project:			HFAT16/32
// File:			sdi2410.c
// Description:		
//-------------------------------------------------------------
// Reversion Histroy:
//-------------------------------------------------------------
// Version		date		operations				by who
// 1.0.0		2008-09-09  create                  Kingsea
//---------------------------------------------------------------------------------
#include "hfstype.h"
#include "ftdevice.h"
#include "haiclib.h"

#ifdef ADD_S3C2410_SDI

#include "cfg2410.h"
#include "reg2410.h"

//note: only support SD_CARD partition 1 now.

//macro define
//
#define SDT_NO_CARD			0
#define SDT_MMC_CARD		1
#define SDT_SD_CARD			2
#define SDT_SDHC_CARD		3

#define SD_BUSW_1BIT		0x00
#define SD_BUSW_4BIT		0x01
#define SD_BUSW_MASK		0x01
#define SD_WTPROT_NON		0x00
#define SD_WTPROT_YES		0x02
#define SD_WTPROT_MSK		0x02

#define pSD_MBR(p)			(p+0)
#define pSD_MBR_PT1(p)		(p+446)
#define pSD_MBR_PT2(p)		(p+462)
#define pSD_MBR_PT3(p)		(p+478)
#define pSD_MBR_PT4(p)		(p+494)
#define pSD_MBR_SW(p)		(p+510)
#define sSD_MBR				446
#define sSD_MBR_PT			16
#define sSD_MBR_SW			2

#define pSD_PT_BOOTINDIC(p)			(p+0)
#define pSD_PT_STARTHEAD(p)			(p+1)
#define pSD_PT_STARTSECCYL(p)		(p+2)
#define pSD_PT_SYSTEMID(p)			(p+4)
#define pSD_PT_ENDHEAD(p)			(p+5)
#define pSD_PT_ENDSECCYL(p)			(p+6)
#define pSD_PT_RELATIVESEC(p)		(p+8)
#define pSD_PT_TOTALSECTOR(p)		(p+12)
#define sSD_PT_BOOTINDIC			1
#define sSD_PT_STARTHEAD			1
#define sSD_PT_STARTSECCYL			2
#define sSD_PT_SYSTEMID				1
#define sSD_PT_ENDHEAD				1
#define sSD_PT_ENDSECCYL			2
#define sSD_PT_RELATIVESEC			4
#define sSD_PT_TOTALSECTOR			4

#define SDI_INITIALCLK	400000
#define SDI_NORMALCLK	5000000

//command format
//
// 10    9     8           7        6     5...0
//LRSP WTRSP CMDStart startbit:0  host:1  CMDIDX
#define SDICMD_HOST		0x00000040UL//(1<<6)
#define SDICMD_START	0x00000100UL//(1<<8)
#define SDICMD_WTRSP	0x00000200UL//(1<<9)
#define SDICMD_L_RSP	0x00000400UL//(1<<10)
#define SDICMD_NORSP	0x00000000UL//(0<<9)
#define SDICMD_S_RSP	0x00000000UL//(0<<10)

#define SDICMD_IDXMSK	0x0000003FUL

//command class
//
#define SDICMD_GO_IDLE_STATE	0
#define SDICMD_OP_COND			1
#define SDICMD_ALL_SEND_CID		2
#define SDICMD_SEND_REL_ADDR	3
#define SDICMD_SEL_DSEL_CARD	7
#define SDICMD_SEND_CSD			9
#define SDICMD_SEND_CID			10
#define SDICMD_STOP_TRANS		12
#define SDICMD_SEND_STATUS		13
#define SDICMD_SET_BLOCKLEN		16
#define SDICMD_READ_SINGLBLK	17
#define SDICMD_READ_MULTIBLK	18
#define SDICMD_WRITE_SINGLBLK	24
#define SDICMD_WRITE_MULTIBLK	25
#define SDICMD_SEND_WRIT_PROT	30
#define SDICMD_APP_CMD			55

#define SDICMD_SET_BUS_WIDTH	6
#define SDICMD_SD_STATUS		13
#define SDICMD_SD_APP_OP_COND	41

#define SDCARD_BLOCK_LENG_MAX		1024
#define SDCARD_BUFFER_BLOCK_MAX		10
#define SDCARD_FAT_SECTOR_BYTES		512
#define SDCARD_BUFFER_NEEDFLUSH		0x01000000


//assert struct
//
typedef struct tagPartTab
{
	S_BYTE BootIndicator;//active partition:0x80;otherwise:0x00
	S_BYTE StartHead;
	S_WORD StartSecCyl;
	S_BYTE SystemID;//0x01 or 0x04 or 0x06
	S_BYTE EndHead;
	S_WORD EndSecCyl;
	S_DWORD RelativeSec;
	S_DWORD TotalSector;
}
S_PARTTAB, *SP_PARTTAB;

typedef struct tagCID
{
	S_BYTE MID;//binary:0x03
	S_BYTE OID[2];//ASCII:"SD"
	S_BYTE PNM[5];//ASCII:"SD128"
	S_BYTE PRV;//BCD:30
	S_BYTE PSN[4];//binary
	S_BYTE MDT[2];//BCD:yym(offset from 2000)
	S_BYTE CRC;//binary
}
S_CID, *SP_CID;

typedef struct tagCSD
{
	S_BYTE CSDStruct;
//	S_BYTE ReadAccessTime1;
//	S_BYTE ReadAccessTime2;
//	S_BYTE DataTransRate;
//	S_WORD CardCmdClasses;
	S_BYTE ReadBlockLen;
//	S_BYTE ReadBlockPartial;
	S_WORD DeviceSize;
	S_BYTE DeviceSizeMulti;
}
S_CSD, *SP_CSD;

typedef struct tagSDCARD
{
	S_BYTE CardType;
	S_BYTE flag;
	S_WORD BlockLen;
	S_WORD RCA;
	S_CID  CID;
	S_CSD  CSD;
	S_PARTTAB part[4];//only support part[0] now.
}
S_SDCARD, *SP_SDCARD;

static S_SDCARD sdcard;

//function prototype
//
int s3c2410sdiInit(void);
int s3c2410sdiStatus(void);
int s3c2410sdiRead(S_DWORD sector, S_BYTE *OutBuf);
int s3c2410sdiWrite(S_DWORD sector, S_BYTE *InBuf);
int s3c2410sdiCmd(S_DWORD cmd, S_DWORD arg, S_DWORD *OutVal);
int s3c2410sdiFlush(S_DWORD sector, S_BOOL FreeBuffer);

static int sdi_SendCmd(int rCMD, int rARG);
static int sdi_CMD55(S_WORD RCA);
static int sdi_ChkMMCOCR(void);
static int sdi_ChkSDOCR(void);
static int sdi_GetCID(S_WORD RCA, SP_CID pCID);
static int sdi_GetCSD(S_WORD RCA, SP_CSD pCSD);
static int sdi_MakeIdent(void);
static int sdi_MakeStandby(S_WORD *pRCA);
static int sdi_CardSelect(S_WORD RCA);
static int sdi_SetBusWidth(S_WORD RCA, int BUSW);
static int sdi_CheckDATend(void);

static int sdi_SDcardInit(void);
static int sdi_ReadBlock(S_DWORD block, S_BYTE *OutBuf);
static int sdi_WriteBlock(S_DWORD block, S_BYTE *InBuf);

static void sdi_IncUseCount(int BufNo);
static int sdi_FindLeastUseCluster(void);

//assert driver struct
//
const S_FATDEVDRV s3c2410sdiDrv =
{
	"S3C2410_SDI",
	s3c2410sdiInit,
	s3c2410sdiStatus,
	s3c2410sdiRead,
	s3c2410sdiWrite,
	s3c2410sdiCmd,
	s3c2410sdiFlush,
};

//Driver Buffer
//
static S_BYTE  SDCARDBuf[SDCARD_BUFFER_BLOCK_MAX][SDCARD_BLOCK_LENG_MAX];
static S_DWORD SDCARDFlag[SDCARD_BUFFER_BLOCK_MAX];
static S_DWORD SDCARDClst[SDCARD_BUFFER_BLOCK_MAX];


//driver function define
//
int s3c2410sdiInit(void)
{
	int err, try = 3;
	S_BYTE *pPart, *pMBR = SDCARDBuf[0];

	do
	{
		err = sdi_SDcardInit();
	}while (err && try--);
	if (err) return err;

	//read partition
	try = 3;
	do
	{
		err = sdi_ReadBlock(0, pMBR);
	}while (err && try--);
	if (err) return err;

	pPart = pSD_MBR_PT1(pMBR);
	sdcard.part[0].BootIndicator = *pSD_PT_BOOTINDIC(pPart);
	sdcard.part[0].StartHead   = *pSD_PT_STARTHEAD(pPart);
	sdcard.part[0].StartSecCyl = HAI_MAKEWORD(pSD_PT_STARTSECCYL(pPart));
	sdcard.part[0].SystemID    = *pSD_PT_SYSTEMID(pPart);
	sdcard.part[0].EndHead     = *pSD_PT_ENDHEAD(pPart);
	sdcard.part[0].EndSecCyl   = HAI_MAKEWORD(pSD_PT_ENDSECCYL(pPart));
	sdcard.part[0].RelativeSec = HAI_MAKEDWORD(pSD_PT_RELATIVESEC(pPart));
	sdcard.part[0].TotalSector = HAI_MAKEDWORD(pSD_PT_TOTALSECTOR(pPart));
	
	for (try = 0; try < SDCARD_BUFFER_BLOCK_MAX; try++)
		SDCARDFlag[try] = 0;
	for (try = 0; try < SDCARD_BUFFER_BLOCK_MAX; try++)
		SDCARDClst[try] = 0xFFFFFFFF;

	return err;
}

int s3c2410sdiStatus(void)
{
	return 0;//always OK.
}

int s3c2410sdiRead(S_DWORD sector, S_BYTE *OutBuf)
{
	int err, try;
	int i, m = SDCARD_BUFFER_BLOCK_MAX-1;
	S_DWORD cluster, current;

	sector += sdcard.part[0].RelativeSec;
	cluster = sector/(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
	current = sector%(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
	
	//find if in driver buffer
	for (i = 0; i < SDCARD_BUFFER_BLOCK_MAX; i++)
	{
		if (SDCARDClst[i] == 0xFFFFFFFF)
			m = i;
		else if (SDCARDClst[i] == cluster)
			break;
	}
	
	if (i == SDCARD_BUFFER_BLOCK_MAX)// not found out
	{
		if (SDCARDClst[m] != 0xFFFFFFFF) // have not idle cluster, make one idle cluster
		{
			m = sdi_FindLeastUseCluster();
			if ((SDCARDFlag[m]&SDCARD_BUFFER_NEEDFLUSH) == SDCARD_BUFFER_NEEDFLUSH)
			{
				try = 3;
				do
				{
					err = sdi_WriteBlock(SDCARDClst[m], SDCARDBuf[m]);
				}while (err && try--);

				if (err)
					return err;
			}
		}
		SDCARDFlag[m] = 0;
		SDCARDClst[m] = cluster;//ok, have one idle cluster
		try = 3;
		do
		{
			err = sdi_ReadBlock(SDCARDClst[m], SDCARDBuf[m]);
		}while (err && try--);
		if (err)
		{
			SDCARDClst[m] = 0xFFFFFFFF;//Oh, shit! fail on read disk
			return err;
		}
		i = m;//make it as found successful....
	}

	if (SDCARDClst[i] == cluster)//OK, found out
	{
#if 0
		S_BYTE *pDat = &SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
		hai_memcpy(OutBuf, pDat, SDCARD_FAT_SECTOR_BYTES);
#else
		int *pDat = (int *)&SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
		int *pOut = (int *)OutBuf;
		for (try = 0; try < SDCARD_FAT_SECTOR_BYTES/4; try++)
			*pOut++ = *pDat++;
#endif
		sdi_IncUseCount(i);
	}
	
	return 0;	
}

int s3c2410sdiWrite(S_DWORD sector, S_BYTE *InBuf)
{
	int err, try;
	int i, m = SDCARD_BUFFER_BLOCK_MAX-1;
	S_DWORD cluster, current;

	sector += sdcard.part[0].RelativeSec;
	cluster = sector/(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
	current = sector%(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
	
	//find if in driver buffer
	for (i = 0; i < SDCARD_BUFFER_BLOCK_MAX; i++)
	{
		if (SDCARDClst[i] == 0xFFFFFFFF)
			m = i;
		else if (SDCARDClst[i] == cluster)
			break;
	}
	
	if (i == SDCARD_BUFFER_BLOCK_MAX)// not found out
	{
		if (SDCARDClst[m] != 0xFFFFFFFF) // have not idle cluster, make one idle cluster
		{
			m = sdi_FindLeastUseCluster();
			if ((SDCARDFlag[m]&SDCARD_BUFFER_NEEDFLUSH) == SDCARD_BUFFER_NEEDFLUSH)
			{
				try = 3;
				do
				{
					err = sdi_WriteBlock(SDCARDClst[m], SDCARDBuf[m]);
				}while (err && try--);
				if (err)
					return err;
			}
		}
		SDCARDFlag[m] = 0;
		SDCARDClst[m] = cluster;//ok, have one idle cluster
		try = 3;
		do
		{
			err = sdi_ReadBlock(SDCARDClst[m], SDCARDBuf[m]);
		}while (err && try--);
		if (err)
		{
			SDCARDClst[m] = 0xFFFFFFFF;//Oh, shit! fail on read disk
			return err;
		}
		i = m;//make it as found successful....
	}

	if (SDCARDClst[i] == cluster)//OK, found out
	{
#if 0
		S_BYTE *pDat = &SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
		hai_memcpy(pDat, InBuf, SDCARD_FAT_SECTOR_BYTES);
#else
		int *pDat = (int *)&SDCARDBuf[i][current*SDCARD_FAT_SECTOR_BYTES];
		int *pIn  = (int *)InBuf;
		for (try = 0; try < SDCARD_FAT_SECTOR_BYTES/4; try++)
			*pDat++ = *pIn++;
#endif
		SDCARDFlag[i] |= SDCARD_BUFFER_NEEDFLUSH;
		sdi_IncUseCount(i);
	}
		
	return 0;
}

int s3c2410sdiCmd(S_DWORD cmd, S_DWORD arg, S_DWORD *OutVal)
{
	int err = 0;
	switch (cmd)
	{
	case DEVCMD_WRITE_PROTECT:
		*OutVal = (sdcard.flag&SD_WTPROT_MSK)?1:0;
		break;
	case DEVCMD_SECTOR_SIZE:
		*OutVal = SDCARD_FAT_SECTOR_BYTES;//this is a recommand val, otherwise:1024, 2048, 4096.
		break;
	case DEVCMD_TOTAL_SECTOR:
		*OutVal = sdcard.part[0].TotalSector;
		break;
	case DEVCMD_SEC_PER_CLUS:
		*OutVal = 0; //or 1, 2, 4, 8, 16, 32, 64, 128;
		break;
	default:
		*OutVal = 0;
		break;
	}
	return err;
}

int s3c2410sdiFlush(S_DWORD sector, S_BOOL FreeBuffer)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -