Eclipse开发调试ARM裸机程序(七)sd卡读写

发布者:玉立风华最新更新时间:2016-06-06 来源: eefocus关键字:Eclipse  开发调试  ARM裸机程序  sd卡读写 手机看文章 扫描二维码
随时随地手机看文章
     主要用到了sd card官网上的几个文档,《SD Specifications Part 1 Physical Layer Simplified Specification Version 4.10 January 22, 2013》里边讲了SD卡内部的寄存器,一般的时序。还有《SD Specifications Part A1 Advanced Security SD Extension Simplified Specification Version 2.00 May 18, 2010》和《SD Specifications Part A2 SD Host Controller Simplified Specification Version 3.00 February 25, 2011》都提供了一些信息。另外一个《SD Specifications Part E1 SDIO Simplified Specification Version 3.00 February 25, 2011》是说SDIO的,是以SDIO为接口的衍生品,包括SDIO wifi等等。这些文档都可以在
Eclipse开发调试ARM裸机程序(七)sd卡读写
 
 
         每个寄存器都有特定的含义,我这里真分析的CSD寄存器,并用一个小程序算出每个参数的值。
先用Android手机或者开发板下载一个应用 “sd tools”,这样可以显示出SD卡的CSD,然后根据手册《SD Specifications Part 1 Physical Layer Simplified Specification Version 4.10 January 22, 2013》。测试的SD卡的CSD码值如图所示:
          Eclipse开发调试ARM裸机程序(七)sd卡读写
         小程序如下:
#include 
#include 

typedef unsigned int u_size;

int main()
{
	u_size a = 0, b = 0, c = 0, d = 0;

	//CSD = 003e00325b5a83c5e597ffff12800000
	a = 0x003e0032; //[127:96]
	b = 0x5b5a83c5; //[95 :64]
	c = 0xe597ffff; //[63 :32]
	d = 0x12800000; //[31 :0 ]


	u_size CSD_STRUCTURE      = a / (u_size)pow(2,30) & 0x3;    // [127:126 - 96]

	u_size TAAC               = a/(u_size)pow(2,16) & 0xff; // [119:112]
	u_size NSAC               = a/(u_size)pow(2,8)  & 0xff; // [111:104]
	u_size TRAN_SPEED         = a/(u_size)pow(2,0)  & 0xff;                              // [103:96  - 96]
	u_size CCC                = b/(u_size)pow(2,20) & 0xfff;
	u_size READ_BL_LEN        = b/(u_size)pow(2,16) & 0xf;  // [83:80-64]
	u_size READ_BL_PARTIA     = b/(u_size)pow(2,15) & 0x1;
	u_size WRITE_BLK_MISALIGN = b/(u_size)pow(2,14) & 0x1;
	u_size READ_BLK_MISALIGN  = b/(u_size)pow(2,13) & 0x1;
	u_size DSR_IMP            = b/(u_size)pow(2,12) & 0x1;

	u_size C_SIZE             = (b & 0x3ff)*(u_size)pow(2,2) \
									+ ((c /(u_size)pow(2,30)) & 0x3);                // [73:62]
	u_size VDD_R_CURR_MIN     = c/(u_size)pow(2,27) & 0x7;
	u_size VDD_R_CURR_MAX     = c/(u_size)pow(2,24) & 0x7;
	u_size VDD_W_CURR_MIN     = c/(u_size)pow(2,21) & 0x7;
	u_size VDD_W_CURR_MAX     = c/(u_size)pow(2,18) & 0x7;
	u_size C_SIZE_MULT        = c/(u_size)pow(2,15) & 0x7;  // [49:47]
	u_size ERASE_BLK_EN       = d/(u_size)pow(2,14) & 0x1;
	u_size SECTOR_SIZE        = d/(u_size)pow(2,7)  & 0xef;
	u_size WP_GRP_SIZE        = c/(u_size)pow(2,0)  & 0xef;
	u_size WP_GRP_ENABLE      = d/(u_size)pow(2,31) & 0x1;

	u_size R2W_FACTOR         = d/(u_size)pow(2,26) & 0x7;
	u_size WRITE_BL_LEN       = d/(u_size)pow(2,22) & 0xf;
	u_size WRITE_BL_PARTIAL   = d/(u_size)pow(2,21) & 0x1;
	u_size TMP_WRITE_PROTECT  = d/(u_size)pow(2,12) & 0x1;
	u_size FILE_FORMAT        = d/(u_size)pow(2,10) & 0x3;
	u_size CRC                = d/(u_size)pow(2,1)  & 0xff;

	long C                    = (C_SIZE + 1) * pow(2, (C_SIZE_MULT+2)) * pow(2, READ_BL_LEN);
//       C                    = (3863 + 1) * 512 * 1024


	printf(" 1. CSD_STRUCTURE       = 0x%x\n", CSD_STRUCTURE);
	printf(" 3. TAAC                = 0x%x\n", TAAC);
	printf(" 4. NSAC                = 0x%x\n", NSAC);
	printf(" 5. TRAN_SPEED          = 0x%x (0x32==>25MHz;0x5a==>50MHz)\n", TRAN_SPEED);
	printf(" 6. CCC                 = 0x%x\n", CCC);
	printf(" 7. READ_BL_LEN         = %d\n", READ_BL_LEN);
	printf(" 8. READ_BL_PARTIA      = %d\n", READ_BL_PARTIA);
	printf(" 9. WRITE_BLK_MISALIGN  = %d\n", WRITE_BLK_MISALIGN);
	printf("10. READ_BLK_MISALIGN   = %d\n", READ_BLK_MISALIGN);
	printf("11. DSR_IMP             = %d\n", DSR_IMP);
	printf("12.            / *No Use* /\n");
	printf("13. C_SIZE              = %d\n", C_SIZE);
	printf("14. VDD_R_CURR_MIN      = %d\n", VDD_R_CURR_MIN);
	printf("15. VDD_R_CURR_MAX      = %d\n", VDD_R_CURR_MAX);
	printf("16. VDD_W_CURR_MIN      = %d\n", VDD_W_CURR_MIN);
	printf("17. VDD_W_CURR_MAX      = %d\n", VDD_W_CURR_MAX);
	printf("18. C_SIZE_MULT         = %d\t""(本SD卡容量 = %f G)\n", C_SIZE_MULT, (float)C/1073741824);
	printf("19. ERASE_BLK_EN        = 0x%x\n", ERASE_BLK_EN);
	printf("20. SECTOR_SIZE         = 0x%x\n", SECTOR_SIZE);
	printf("21. WP_GRP_SIZE         = 0x%x\n", WP_GRP_SIZE);
	printf("22. WP_GRP_ENABLE       = 0x%x\n", WP_GRP_ENABLE);
	printf("23.            / *No Use* /\n");
	printf("24. R2W_FACTOR          = 0x%x\n", R2W_FACTOR);
	printf("25. WRITE_BL_LEN        = 0x%x\n", WRITE_BL_LEN);
	printf("26. WRITE_BL_PARTIAL    = 0x%x\n", WRITE_BL_PARTIAL);


	printf("31. TMP_WRITE_PROTECT   = 0x%x\n", TMP_WRITE_PROTECT);

	printf("32. FILE_FORMAT         = 0x%x\n", FILE_FORMAT);
	printf("34. CRC                 = 0x%x\t", CRC);


    return 0;
}
         运行结果如下:
         Eclipse开发调试ARM裸机程序(七)sd卡读写
 
 
          S3C2440上的寄存器就多了,有几个难以理解的写下来:SDICCON的后7位是发送命令值。但是真正填写的时候并不是命令值而是&上了一个值(0x64),这个还没有找出原因所在。例如如果发送命令2,SDICCON的后7位应该是这样的:(0x40 | 2)。
 
四、文件系统
           
         如果只是简单的放一个数据,没有文件系统会显示无力,就无法在PC直接上查看。SD卡应该有一个文件系统如常用的fat32。这个u-boot中有实现,这里就先不做了。
 
五、代码
 
            完整代码这里下载:http://download.csdn.net/detail/kangear/5303482
            这里贴出sdi.c:
/
 * @file     sdi.c
 * @brief    sd卡 读写
 * @details  本程序实现了,读SD卡的CSD寄存器;读写SD卡,并用LED显示。
 *           程序正常:led1首先点亮,然后是0-15的二进制显示
 *           程序出错:led2首先点亮,然后是乱无序的二进制显示
 *           目前只能读写2G以下的SD卡
 *           (启动代码是适用于mini2440 nand 256M的开发板)
 *           读写SD有三种模式:中断,DMA中断,查询。本程序使用的是查询
 * @author   kangear
 * @date     2013-4-26
 * @version  A001
 * @par Copyright (c):
 *           XXX公司
 * @par History:
 *   version: author, date, desc\n
 *
 * docs    1.SD Specifications Part 1 Physical Layer Simplified Specification Version 4.10 January 22, 2013.pdf
 *         2.SD Specifications Part A1 Advanced Security SD Extension Simplified Specification Version 2.00 May 18, 2010.pdf
 *         3.SD Specifications Part A2 SD Host Controller Simplified Specification Version 3.00 February 25, 2011.pdf
 *         4.SD Specifications Part E1 SDIO Simplified Specification Version 3.00 February 25, 2011.pdf
 *
 * download addr:https://www.sdcard.org/downloads/pls/simplified_specs/
 */


//#include 
//#include 
#include "def.h"
//#include "option.h"
//#include "2440addr.h"
#include "s3c24xx.h"
//#include "2440lib.h"
#include "sdi.h"

/*
 * 用在SDICCON中的[7:0] 现在没有搞懂它的实际意义
 * CMD1 = MAGIC_NUMBER | 1
 */
#define	MAGIC_NUMBER 64

#define INICLK	300000
#define SDCLK	24000000	//PCLK=49.392MHz

#define POL	0
#define INT	1
#define DMA	2

int CMD13(void);    // Send card status
int CMD9(void);


unsigned int *Tx_buffer;	//128[word]*16[blk]=8192[byte]
unsigned int *Rx_buffer;	//128[word]*16[blk]=8192[byte]
volatile unsigned int rd_cnt;
volatile unsigned int wt_cnt;
volatile unsigned int block;
volatile unsigned int TR_end=0;

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

int  Maker_ID;
char Product_Name[7]; 
int  Serial_Num;

int PCLK = 50000000;

volatile int RCA;

void Test_SDI(void)
{
	U32 save_rGPEUP, save_rGPECON;
	
	RCA=0;
	MMC=0;
	block=3072;   //3072Blocks=1.5MByte, ((2Block=1024Byte)*1024Block=1MByte)

	save_rGPEUP=GPEUP;
	save_rGPECON=GPECON;
	
	GPEUP  = 0xf83f;     // SDCMD, SDDAT[3:0] => PU En.
	GPECON = 0xaaaaaaaa;	//SDCMD, SDDAT[3:0]


	//Uart_Printf("\nSDI Card Write and Read Test\n");

	if(!SD_card_init())
		return;

	TR_Buf_new();

	Wt_Block();
	
	Rd_Block();
	View_Rx_buf();

	Card_sel_desel(0);	// Card deselect

	if(!CMD9())
	//Uart_Printf("Get CSD fail!!!\n");
	SDIDCON=0;//tark???
	SDICSTA=0xffff;
	GPEUP=save_rGPEUP;
	GPECON=save_rGPECON;
}

void TR_Buf_new(void)
{
    //-- Tx & Rx Buffer initialize
	int i, j;

	Tx_buffer=(unsigned int *)0x31000000;

	j=0;
	for(i=0;i<2048;i++)	//128[word]*16[blk]=8192[byte]
		*(Tx_buffer+i)=i+j;
	Flush_Rx_buf();

}

void Flush_Rx_buf(void)
{
    //-- Flushing Rx buffer 
	int i;

	Rx_buffer=(unsigned int *)0x31800000;

	for(i=0;i<2048;i++)	//128[word]*16[blk]=8192[byte]
		*(Rx_buffer+i)=0;
	//Uart_Printf("End Rx buffer flush\n");
}

void View_Rx_buf()
{
    //-- Display Rx buffer 
	int i,error=0;

	Tx_buffer=(unsigned int *)0x31000000;
	Rx_buffer=(unsigned int *)0x31800000;

	//Uart_Printf("Check Rx data\n");

	for(i=0;i<128*block;i++)
	{
		if(Rx_buffer[i] != Tx_buffer[i])
		{
			//Uart_Printf("\nTx/Rx error\n");
			//Uart_Printf("%d:Tx-0x%08x, Rx-0x%08x\n",i,Tx_buffer[i], Rx_buffer[i]);
			error=1;
			break;
		}
		////Uart_Printf(".");
	}
    
	if(!error)
	{
		//Uart_Printf("\nThe Tx_buffer is same to Rx_buffer!\n");
		//Uart_Printf("SD CARD Write and Read test is OK!\n");
	}
}

void View_Tx_buf(void)
{

}


int SD_card_init(void)
{
//-- SD controller & card initialize 
	int i;

	/* Important notice for MMC test condition */
	/* Cmd & Data lines must be enabled by pull up resister */

	SDIPRE=PCLK/(INICLK)-1;	// 400KHz
	//Uart_Printf("Init. Frequency is %dHz\n",(PCLK/(SDIPRE+1)));
    
	SDICON=(1<<4)|1;	// Type B, clk enable
	SDIFSTA=SDIFSTA|(1<<16);	//YH 040223 FIFO reset
	SDIBSIZE=0x200;		// 512byte(128word)
	SDIDTIMER=0x7fffff;		// Set timeout count

	for(i=0;i<0x1000;i++);  // Wait 74SDCLK for MMC card

	CMD0();
	//Uart_Printf("In idle\n");

	//-- Check SD card OCR
	if(!Chk_SD_OCR())
	{
		// fail
		GPBDAT = (~(2<<5));	 	// 点亮LED2
		//Uart_Printf("Initialize fail\nNo Card assertion\n");
		return 0;
	}

//	Uart_Printf("In SD ready\n");
	GPBDAT = (~(1<<5));	 	// 点亮LED1

	do
	{
		//-- Check attaced cards, it makes card identification state
		SDICARG = 0x0; // CMD2(stuff bit)
		SDICCON = (0x1 << 10) | (0x1 << 9) | (0x1 << 8) | (MAGIC_NUMBER | 2); //lng_resp, wait_resp, start, CMD2

		//-- Check end of CMD2
	} while (!Chk_CMDend(2, 1));

	SDICSTA=0xa00;	// Clear cmd_end(with rsp)

	//Uart_Printf("End id\n");

	do
	{
		//--Send RCA
		SDICARG = MMC << 16; // CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
		SDICCON = (0x1 << 9) | (0x1 << 8) | (MAGIC_NUMBER | 3); // sht_resp, wait_resp, start, CMD3

		//-- Check end of CMD3
		if (!Chk_CMDend(3, 1))
			continue;
		SDICSTA = 0xa00; // Clear cmd_end(with rsp)

		//--Publish RCA
		RCA = (SDIRSP0 & 0xffff0000) >> 16;
		//Uart_Printf("RCA=0x%x\n",RCA);
		SDIPRE = PCLK / (SDCLK) - 1; // Normal clock=25MHz
		//Uart_Printf("SD Frequency is %dHz\n",(PCLK/(SDIPRE+1)));

		//--State(stand-by) check
		if (SDIRSP0 & 0x1e00 != 0x600) // CURRENT_STATE check
			continue;

	} while (0);
    
	//Uart_Printf("In stand-by\n");
    
	Card_sel_desel(1);	// Select

	Set_4bit_bus();

	return 1;
}

void Card_sel_desel(char sel_desel)
{
    //-- Card select or deselect
	if(sel_desel)
	{
		do
		{
			SDICARG = RCA << 16; // CMD7(RCA,stuff bit)
			SDICCON = (0x1 << 9) | (0x1 << 8) | (MAGIC_NUMBER | 7); // sht_resp, wait_resp, start, CMD7

			//-- Check end of CMD7
			if (!Chk_CMDend(7, 1))
				continue;
			SDICSTA = 0xa00; // Clear cmd_end(with rsp)

			//--State(transfer) check
			if (SDIRSP0 & 0x1e00 != 0x800)
				continue;
		} while (0);

	}
	else
	{
		do
		{
			SDICARG = 0 << 16; //CMD7(RCA,stuff bit)
			SDICCON = (0x1 << 8) | (MAGIC_NUMBER | 7); //no_resp, start, CMD7

			//-- Check end of CMD7
			if (!Chk_CMDend(7, 0))
				continue;
		} while (0);

		SDICSTA=0x800;	// Clear cmd_end(no rsp)
	}
}

//void __irq Rd_Int(void)
//{
//	U32 i,status;
//
//	status=SDIFSTA;
//	if( (status&0x200) == 0x200 )	// Check Last interrupt?
//	{
//		for(i=(status & 0x7f)/4;i>0;i--)
//		{
//			*Rx_buffer++=SDIDAT;
//			rd_cnt++;
//		}
//		SDIFSTA=SDIFSTA&0x200;	//Clear Rx FIFO Last data Ready, YH 040221
//	}
//	else if( (status&0x80) == 0x80 )	// Check Half interrupt?
//	{
//		for(i=0;i<8;i++)
//		{
//			*Rx_buffer++=SDIDAT;
//			rd_cnt++;
//		}
//	}
//
//	ClearPending(BIT_SDI);
//}

//void __irq Wt_Int(void)
//{
//	ClearPending(BIT_SDI);
//
//	SDIDAT=*Tx_buffer++;
//	wt_cnt++;
//
//	if(wt_cnt==128*block)
//	{
//		rINTMSK |= BIT_SDI;
//		SDIDAT=*Tx_buffer;
//		TR_end=1;
//	}
//}
//
//void __irq DMA_end(void)
//{
//	ClearPending(BIT_DMA0);
//
//	TR_end=1;
//}

void Rd_Block(void)
{
	U32 mode;
	int status;

	rd_cnt=0;    
	//Uart_Printf("Block read test[ Polling read ]\n");


	mode = 0 ;

	SDIFSTA=SDIFSTA|(1<<16);	// FIFO reset

	if(mode!=2)
		SDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<14)|(2<<12)|(block<<0);	//YH 040220

	SDICARG=0x0;	// CMD17/18(addr)

RERDCMD:
	switch(mode)
	{
		case POL:
			if(block<2)	// SINGLE_READ
			{
				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 17);    // sht_resp, wait_resp, dat, start, CMD17
				if(!Chk_CMDend(17, 1))	//-- Check end of CMD17
					goto RERDCMD;	    
			}
			else	// MULTI_READ
			{
				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 18);    // sht_resp, wait_resp, dat, start, CMD18
				if(!Chk_CMDend(18, 1))	//-- Check end of CMD18 
					goto RERDCMD;
			}

			SDICSTA=0xa00;	// Clear cmd_end(with rsp)

			while(rd_cnt<128*block)	// 512*block bytes
			{
				if((SDIDSTA&0x20)==0x20) // Check timeout
				{
					SDIDSTA=(0x1<<0x5);  // Clear timeout flag
					break;
				}
				status=SDIFSTA;
				if((status&0x1000)==0x1000)	// Is Rx data?
				{
					*Rx_buffer++=SDIDAT;
					rd_cnt++;
				}
			}
			break;

//		case INT:
//			pISR_SDI=(unsigned)Rd_Int;
//			rINTMSK = ~(BIT_SDI);
//
//			rSDIIMSK=5;	// Last & Rx FIFO half int.
//
//			if(block<2)	// SINGLE_READ
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 17);    // sht_resp, wait_resp, dat, start, CMD17
//				if(!Chk_CMDend(17, 1))	//-- Check end of CMD17
//					goto RERDCMD;
//			}
//			else	// MULTI_READ
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 18);    // sht_resp, wait_resp, dat, start, CMD18
//				if(!Chk_CMDend(18, 1))	//-- Check end of CMD18
//				goto RERDCMD;
//			}
//
//			SDICSTA=0xa00;	// Clear cmd_end(with rsp)
//
//			while(rd_cnt<128*block);
//
//			rINTMSK |= (BIT_SDI);
//			rSDIIMSK=0;	// All mask
//			break;
//
//		case DMA:
//			pISR_DMA0=(unsigned)DMA_end;
//			rINTMSK = ~(BIT_DMA0);
//			SDIDCON=SDIDCON|(1<<24); //YH 040227, Burst4 Enable
//
//			rDISRC0=(int)(SDIDAT);	// SDIDAT
//			rDISRCC0=(1<<1)+(1<<0);	// APB, fix
//			rDIDST0=(U32)(Rx_buffer);	// Rx_buffer
//			rDIDSTC0=(0<<1)+(0<<0);	// AHB, inc
//			rDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;
//
//			rDMASKTRIG0=(0<<2)+(1<<1)+0;    //no-stop, DMA2 channel on, no-sw trigger
//
//			SDIDCON=(2<<22)|(1<<19)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(2<<12)|(block<<0);
//			if(block<2)	// SINGLE_READ
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 17);    // sht_resp, wait_resp, dat, start, CMD17
//				if(!Chk_CMDend(17, 1))	//-- Check end of CMD17
//				goto RERDCMD;
//			}
//			else	// MULTI_READ
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 18);    // sht_resp, wait_resp, dat, start, CMD18
//				if(!Chk_CMDend(18, 1))	//-- Check end of CMD18
//					goto RERDCMD;
//			}
//
//			SDICSTA=0xa00;	// Clear cmd_end(with rsp)
//			while(!TR_end);
//			////Uart_Printf("SDIFSTA=0x%x\n",SDIFSTA);
//			rINTMSK |= (BIT_DMA0);
//			TR_end=0;
//			rDMASKTRIG0=(1<<2);	//DMA0 stop
//			break;

		default:
			break;
	}
    //-- Check end of DATA
	if(!Chk_DATend()) 
		//Uart_Printf("dat error\n");

	SDIDCON=SDIDCON&~(7<<12);
	SDIFSTA=SDIFSTA&0x200;	//Clear Rx FIFO Last data Ready, YH 040221
	SDIDSTA=0x10;	// Clear data Tx/Rx end detect

	if(block>1)
	{
RERCMD12:    
		//--Stop cmd(CMD12)
		SDICARG=0x0;	    //CMD12(stuff bit)
		SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 12);//sht_resp, wait_resp, start, CMD12

		//-- Check end of CMD12
		if(!Chk_CMDend(12, 1)) 
			goto RERCMD12;
		SDICSTA=0xa00;	// Clear cmd_end(with rsp)
	}
}

void Wt_Block(void)
{
	U32 mode;
	int status;

	wt_cnt=0;    
	//Uart_Printf("Block write test[ Polling write ]\n");


	
	mode = 0 ;

	SDIFSTA=SDIFSTA|(1<<16);	//YH 040223 FIFO reset

	if(mode!=2)
		SDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<14)|(3<<12)|(block<<0);	//YH 040220


	SDICARG=0x0;	    // CMD24/25(addr)

REWTCMD:
	switch(mode)
	{
		case POL:
			if(block<2)	// SINGLE_WRITE
			{
				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 24);	//sht_resp, wait_resp, dat, start, CMD24
				if(!Chk_CMDend(24, 1))	//-- Check end of CMD24
					goto REWTCMD;
			}
			else	// MULTI_WRITE
			{
				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 25);	//sht_resp, wait_resp, dat, start, CMD25
				if(!Chk_CMDend(25, 1))	//-- Check end of CMD25
				goto REWTCMD;		
			}

			SDICSTA=0xa00;	// Clear cmd_end(with rsp)
	    
			while(wt_cnt<128*block)
			{
				status=SDIFSTA;
				if((status&0x2000)==0x2000) 
				{
					SDIDAT=*Tx_buffer++;
					wt_cnt++;
					////Uart_Printf("Block No.=%d, wt_cnt=%d\n",block,wt_cnt);
				}
			}
			break;

//		case INT:
//			pISR_SDI=(unsigned)Wt_Int;
//			rINTMSK = ~(BIT_SDI);
//
//			rSDIIMSK=0x10;  // Tx FIFO half int.
//
//			if(block<2)	    // SINGLE_WRITE
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 24);    //sht_resp, wait_resp, dat, start, CMD24
//				if(!Chk_CMDend(24, 1))	//-- Check end of CMD24
//				goto REWTCMD;
//			}
//			else	    // MULTI_WRITE
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 25);    //sht_resp, wait_resp, dat, start, CMD25
//				if(!Chk_CMDend(25, 1))	//-- Check end of CMD25
//					goto REWTCMD;
//			}
//
//			SDICSTA=0xa00;	// Clear cmd_end(with rsp)
//
//			while(!TR_end);
//			//while(wt_cnt<128);
//
//			rINTMSK |= (BIT_SDI);
//			TR_end=0;
//			rSDIIMSK=0;	// All mask
//			break;
//
//		case DMA:
//			pISR_DMA0=(unsigned)DMA_end;
//			rINTMSK = ~(BIT_DMA0);
//			SDIDCON=SDIDCON|(1<<24); //YH 040227, Burst4 Enable
//
//			rDISRC0=(int)(Tx_buffer);	// Tx_buffer
//			rDISRCC0=(0<<1)+(0<<0);	// AHB, inc
//			rDIDST0=(U32)(SDIDAT);	// SDIDAT
//			rDIDSTC0=(1<<1)+(1<<0);	// APB, fix
//			rDCON0=(1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(2<<24)+(1<<23)+(1<<22)+(2<<20)+128*block;
//			//handshake, sync PCLK, TC int, single tx, single service, SDI, H/W request,
//			//auto-reload off, word, 128blk*num
//			rDMASKTRIG0=(0<<2)+(1<<1)+0;    //no-stop, DMA0 channel on, no-sw trigger
//
//			SDIDCON=(2<<22)|(1<<20)|(1<<17)|(Wide<<16)|(1<<15)|(1<<14)|(3<<12)|(block<<0);	//YH 040220
//
//			// Word Tx, Tx after rsp, blk, 4bit bus, dma enable, Tx start, blk num
//			if(block<2)	    // SINGLE_WRITE
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 24);    //sht_resp, wait_resp, dat, start, CMD24
//				if(!Chk_CMDend(24, 1))	//-- Check end of CMD24
//				goto REWTCMD;
//			}
//			else	    // MULTI_WRITE
//			{
//				SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 25);    //sht_resp, wait_resp, dat, start, CMD25
//				if(!Chk_CMDend(25, 1))	//-- Check end of CMD25
//					goto REWTCMD;
//			}
//
//			SDICSTA=0xa00;	// Clear cmd_end(with rsp)
//
//			while(!TR_end);
//
//			rINTMSK |= (BIT_DMA0);
//			TR_end=0;
//			rDMASKTRIG0=(1<<2);	//DMA0 stop
//
//			break;

		default:
			break;
	}
    
	//-- Check end of DATA
	if(!Chk_DATend()) 
		//Uart_Printf("dat error\n");

	SDIDCON=SDIDCON&~(7<<12);		//YH 040220, Clear Data Transfer mode => no operation, Cleata Data Transfer start
	SDIDSTA=0x10;	// Clear data Tx/Rx end

	if(block>1)
	{
		//--Stop cmd(CMD12)
REWCMD12:    
		SDIDCON=(1<<18)|(1<<17)|(0<<16)|(1<<14)|(1<<12)|(block<<0); 	//YH  040220

	
		SDICARG=0x0;	    //CMD12(stuff bit)
		SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 12);    //sht_resp, wait_resp, start, CMD12

		//-- Check end of CMD12
		if(!Chk_CMDend(12, 1)) 
			goto REWCMD12;
		SDICSTA=0xa00;	// Clear cmd_end(with rsp)

		//-- Check end of DATA(with busy state)
		if(!Chk_BUSYend()) 
			//Uart_Printf("error\n");
		SDIDSTA=0x08;	//! Should be cleared by writing '1'.
	}
}

void  Delay(volatile unsigned long dly)
{
	for(; dly > 0; dly--);
}

int Chk_CMDend(int cmd, int be_resp)
//0: Timeout
{
	int finish0;

	if(!be_resp)    // No response
	{
		finish0=SDICSTA;
		while((finish0&0x800)!=0x800)	// Check cmd end
		finish0=SDICSTA;

		SDICSTA=finish0;// Clear cmd end state

		return 1;
	}
	else	// With response
	{
		finish0=SDICSTA;
		while( !( ((finish0&0x200)==0x200) | ((finish0&0x400)==0x400) ))    // Check cmd/rsp end


		finish0=SDICSTA;

		if(cmd==1 | cmd==41)	// CRC no check, CMD9 is a long Resp. command.
		{
			if( (finish0&0xf00) != 0xa00 )  // Check error
			{
				SDICSTA=finish0;   // Clear error state

				if(((finish0&0x400)==0x400))
				return 0;	// Timeout error
			}
			SDICSTA=finish0;	// Clear cmd & rsp end state
		}
		else	// CRC check
		{
			if( (finish0&0x1f00) != 0xa00 )	// Check error
			{
				//Uart_Printf("CMD%d:SDICSTA=0x%x, SDIRSP0=0x%x\n",cmd, SDICSTA, SDIRSP0);
				SDICSTA=finish0;   // Clear error state

				if(((finish0&0x400)==0x400))
					return 0;	// Timeout error
			}
			SDICSTA=finish0;
		}
		return 1;
	}
}

int Chk_DATend(void)
{
	int finish;

	finish=SDIDSTA;
	while( !( ((finish&0x10)==0x10) | ((finish&0x20)==0x20) ))	
		// Chek timeout or data end
		finish=SDIDSTA;

	if( (finish&0xfc) != 0x10 )
	{
		//Uart_Printf("DATA:finish=0x%x\n", finish);
		SDIDSTA=0xec;  // Clear error state
		return 0;
	}
	return 1;
}

int Chk_BUSYend(void)
{
	int finish;

	finish=SDIDSTA;
	while( !( ((finish&0x08)==0x08) | ((finish&0x20)==0x20) ))
		finish=SDIDSTA;

	if( (finish&0xfc) != 0x08 )
	{
		//Uart_Printf("DATA:finish=0x%x\n", finish);
		SDIDSTA=0xf4;  //clear error state
		return 0;
	}
	return 1;
}

void CMD0(void)
{
	//-- Make card idle state 
	SDICARG=0x0;	    // CMD0(stuff bit)
	SDICCON=(1<<8)|(MAGIC_NUMBER | 0);   // No_resp, start, CMD0

	//-- Check end of CMD0
	Chk_CMDend(0, 0);
	SDICSTA=0x800;	    // Clear cmd_end(no rsp)
}

int Chk_SD_OCR(void)
{
	int i;

	//-- Negotiate operating condition for SD, it makes card ready state
	for(i=0;i<50;i++)	//If this time is short, init. can be fail.
	{
		CMD55();    // Make ACMD

		SDICARG=0xff8000;	//ACMD41(SD OCR:2.7V~3.6V)

		SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 41);//sht_resp, wait_resp, start, ACMD41

		//-- Check end of ACMD41
		if( Chk_CMDend(41, 1) & SDIRSP0==0x80ff8000 )
		{
			SDICSTA=0xa00;	// Clear cmd_end(with rsp)

			return 1;	// Success	    
		}
		Delay(20000); // Wait Card power up status 1Sec
		//Delay(200); // Wait Card power up status
	}
	////Uart_Printf("SDIRSP0=0x%x\n",SDIRSP0);
	SDICSTA=0xa00;	// Clear cmd_end(with rsp)
	return 0;		// Fail
}

int CMD55(void)
{
	//--Make ACMD
	SDICARG=RCA<<16;			//CMD7(RCA,stuff bit)
	SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 55);	//sht_resp, wait_resp, start, CMD55

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

	SDICSTA=0xa00;	// Clear cmd_end(with rsp)
	return 1;
}

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

	SDICARG=RCA<<16;			// CMD13(RCA,stuff bit)
	SDICCON=(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 13);	// sht_resp, wait_resp, start, CMD13

	//-- Check end of CMD13
	if(!Chk_CMDend(13, 1)) 
		return 0;
	////Uart_Printf("SDIRSP0=0x%x\n", SDIRSP0);
	if(SDIRSP0&0x100)
		////Uart_Printf("Ready for Data\n");
	//else 
		////Uart_Printf("Not Ready\n");
	response0=SDIRSP0;
	response0 &= 0x3c00;
	response0 = response0 >> 9;
	////Uart_Printf("Current Status=%d\n", response0);
	if(response0==6)
		Test_SDI();

	SDICSTA=0xa00;	// Clear cmd_end(with rsp)
	return 1;
}

int CMD9(void)//SEND_CSD
{
	SDICARG=RCA<<16;				// CMD9(RCA,stuff bit)
	SDICCON=(0x1<<10)|(0x1<<9)|(0x1<<8)|(MAGIC_NUMBER | 9);	// long_resp, wait_resp, start, CMD9

	//Uart_Printf("\nCSD register :\n");
	//-- Check end of CMD9
	if(!Chk_CMDend(9, 1)) 
		return 0;

	//Uart_Printf("SDIRSP0=0x%x\nSDIRSP1=0x%x\nSDIRSP2=0x%x\nSDIRSP3=0x%x\n", SDIRSP0,rSDIRSP1,rSDIRSP2,rSDIRSP3);
	return 1;
}

void Set_4bit_bus(void)
{
	Wide=1;
	SetBus();
	////Uart_Printf("\n4bit bus\n");
}

void SetBus(void)
{
	do
	{
		CMD55(); // Make ACMD
		//-- CMD6 implement
		SDICARG = Wide << 1; //Wide 0: 1bit, 1: 4bit
		SDICCON = (0x1 << 9) | (0x1 << 8) | (MAGIC_NUMBER | 6); //sht_resp, wait_resp, start, CMD55

		if (!Chk_CMDend(6, 1)) // ACMD6
			continue;

		SDICSTA = 0xa00; // Clear cmd_end(with rsp)
	} while (0);
}

void Set_Prt(void)
{
	//-- Set protection addr.0 ~ 262144(32*16*512) 
	//Uart_Printf("[Set protection(addr.0 ~ 262144) test]\n");
	do
	{
		//--Make ACMD
		SDICARG = 0; // CMD28(addr)
		SDICCON = (0x1 << 9) | (0x1 << 8) | (MAGIC_NUMBER | 28); //sht_resp, wait_resp, start, CMD28

		//-- Check end of CMD28
		if (!Chk_CMDend(28, 1))
			continue;

		SDICSTA = 0xa00; // Clear cmd_end(with rsp)
	} while (0);
}

void Clr_Prt(void)
{
	//-- Clear protection addr.0 ~ 262144(32*16*512) 
	////Uart_Printf("[Clear protection(addr.0 ~ 262144) test]\n");
	do
	{
		//--Make ACMD
		SDICARG = 0; // CMD29(addr)
		SDICCON = (0x1 << 9) | (0x1 << 8) | (MAGIC_NUMBER | 29); //sht_resp, wait_resp, start, CMD29

		//-- Check end of CMD29
		if (!Chk_CMDend(29, 1))
			continue;

		SDICSTA = 0xa00; // Clear cmd_end(with rsp)
	} while (0);
}
 

 

      总结:调试和运行还是用很在的差别的,eclipse调试没有问题的,运行就会有点小问题,eclipse可以确定程序的框架,运行可以细节地显示问题,那个延时Delay(200)没有问题,到运行时候调整为Delay(2000)才可以正常。jlink的速率什么的都会影响,并不能代码整个实时的运行效果。在线调试和下载运行调试相接合才是王道。

关键字:Eclipse  开发调试  ARM裸机程序  sd卡读写 引用地址:Eclipse开发调试ARM裸机程序(七)sd卡读写

上一篇:TQ2440之定时器中断0——volatile关键字的重要作用
下一篇:Eclipse开发调试ARM裸机程序(七)LCD

推荐阅读最新更新时间:2024-03-16 14:56

AT89C52单片机的SD卡读写电路与程序设计
设计方案   应用AT89C52读写SD卡有两点需要注意。首先,需要寻找一个实现AT89C52 单片机 与SD卡通讯的解决方案;其次,SD卡所能接受的逻辑电平与AT89C52提供的逻辑电平不匹配,需要解决电平匹配问题。   通讯模式   SD卡有两个可选的通讯协议:SD模式和SPI模式。SD模式是SD卡标准的读写方式,但是在选用SD模式时,往往需要选择带有SD卡控制器接口的MCU,或者必须加入额外的SD卡控制单元以支持SD卡的读写。然而,AT89C52单片机没有集成SD卡控制器接口,若选用SD模式通讯就无形中增加了产品的硬件成本。在SD卡数据读写时间要求不是很严格的情况下,选用SPI模式可以说是一种最佳的解决方案。因为在SPI模式
[单片机]
stm32f4基于spi用fatfs读写SD卡的实现
stm32f4之中其实有SDIO这个接口,但是我用封装是100引脚的,有些功能分不开,没办法,只能用SPI来读写SD卡。 这里用加了FATFS文件系统,用的是官方的09版本,这种文件中包括6个文件,分别如下 ff.c ff.h diskio.c diskio.h integer.h ffconf.h 其中需要写的是diskio.c中的函数,这个文件中要写的函数有6个,如下 disk_initialize( ) disk_status( ) disk_read( ) disk_write( ) disk_ioctl( ) disk_fattime( ) 这些函数却又
[单片机]
总结下开发调试MSP430系列的一些另类问题
原始级 问题,一般是刚开始入门的哥们姐们要遇到的问题 1, 接上仿真器,发现不能下载,这个问题想必大家都有遇到过,IAR提示找不到目标!?? 可能的原因: A 并口驱动能力不足,在电脑的BIOS界面下设置成ECP或者 ECP+EPP模式 B JTAG线太长,一般超过20CM不推荐,而且这个线最好不要交叉缠绕,会影响实时在线调试 C 你的负载太大,一般功耗相对比较大,电流超过20MA以上的板子,建议用外接电源,要不光靠并口那点驱动能力,那MCU的电压就要被拉低到不能写FLASH了,呵呵 2, 程序下载到一半,突然告警并报错,说某某地址写不进去!??倒~~我开始也以为是FL
[单片机]
Keil MDK STM32系列(九) 基于HAL和FatFs的FAT格式SD卡TF卡读写
前言 功能: 通过SPI读写SD卡/TF卡上的文件系统 支持FAT16, FAT32, exFAT, 即FatFs所支持的文件格式. 支持存储卡容量512MB至64GB, 更高容量未测试 实现基于 STM32CubeMX, STM32F4 v1.26.2 FatFs, R0.12C(STM32CubeMX内建版本) 大部分参考自STM32Cube配置SPI读sd卡 https://controllerstech.com/sd-card-using-spi-in-stm32/ 视频 https://www.youtube.com/watch?v=spVIZO-jbxE 项目代码 https://github.co
[单片机]
Keil MDK STM32系列(九) 基于HAL和FatFs的FAT格式<font color='red'>SD卡</font>TF卡<font color='red'>读写</font>
MSP432开发板串口调试
拿到MSP432P401R评估板v1.0(这个请注意一下,目前在德州仪器官网上找到的硬件原理图是v2.0,v1.0的串口所在的引脚是RXD,TXD引脚),先将串口调试好,便于下一步工作的展开。首先,查看TI提供的代码例子,这个例子就在TI的MSPWare代码包内。注释如下: //****************************************************************************** // MSP432P401 Demo - eUSCI_A0 UART echo at 9600 baud using BRCLK = 12MHz // // Description:
[单片机]
ARM裸机程序——跑马灯
最近看了一些启动代码的分析,还有很多不懂的地方,打算后面再写关于启动代码的分析。先跑了一些无操作系统裸机程序,来熟悉硬件。开发板用的是FL2440。 先看这样一段C代码 #define GPBCON (*(volatile unsigned long *)0x56000010) //这是寄存器的定义,由于GPB引脚在硬件上连接到了LED上,所以 用到GPB引脚,那么就要定义相关寄存器,该寄存器定义了GPB相关引脚的工作方式。 #define GPBDAT (*(volatile unsigned long *)0x56000014) //该寄存器用来给引脚上的数据。 int main() { GPBCON=0x0000
[单片机]
STM32的简单的SD卡读写
SD卡一般支持两种读写模式,SPI和SDIO模式,SD卡的引脚排序如下图所示。 SPI模式下有几个重要的操作命令,分别是: SD卡R1回应的格式如下 SPI模式下的典型初始化过程如下: 1、初始化硬件配置,SPI配置,IO配置等。 2、上电延时。( 74CLK) 3、复位卡。(CMD0) 4、激活卡,内部初始化并获取卡的类型。 5、查询OCR,获取供电情况。 6、是否使用CRC(CMD59)。 7、设置读写块数据长度(CMD16)。 8、读取CSD,获取存储卡的其他信息(CMD9) 9、发送8CLK后,禁止片选。 SPI模式下的典型读取数据的过程如下,这里采用CMD17来实现。 1、发送CMD17。 2、接收
[单片机]
STM32的简单的<font color='red'>SD卡</font><font color='red'>读写</font>
arm-linux-gcc 裸机程序开发(二)
NANDFLASH启动与标准库问题 把u-boot的start.S移植到我的程序上,这样程序可以用supervivi的D功能下载到内存中运行了,但是还不够。因为程序在内存里,如果掉电程序就没有了,所以我们得将程序固化在flash里面。这里我们要固化在NandFlash里,这就要求程序可以能够NandFlash启动。这里我参考了mini2440的nandlfash读写程序nand.c,里面有一个函数CopyProgramFromNand就是将Nandflash里的程序复制到内存里。在这之前我一直用u-boot默认的下载地址0x33f80000,这个是为了u-boot引导内核方便而定的,因为内核要下载到前面的内存中,既然我的程序没
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved