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

📄 hs1_mmc.c

📁 samsung 最新芯片2450 的测试程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (rHM1_RSPREG0&(0x1<<31))
		{
			if(rHM1_RSPREG0 & (1<<7))
				printf("\nVoltage range : 1.65V ~ 1.95V");
			if(rHM1_RSPREG0 & (1<<21))
				printf("\nVoltage range: 2.7V ~ 3.4V\n\n");	
			else if(rHM1_RSPREG0 & (1<<20))
				printf("\nVoltage range: 2.7V ~ 3.3V\n\n");	
			else if(rHM1_RSPREG0 & (1<<21))
				printf("\nVoltage range: 2.7V ~ 3.4V\n\n");
			else if(rHM1_RSPREG0 & (1<<23))
				printf("\nVoltage range: 2.7V ~ 3.6V\n\n");

			if(rHM1_RSPREG0&(0x1<<30))
				{
				printf("\nHigh Capacity Card\n");
				SectorMode_ch1 = 1;
				}
			
			ThisIsMmc_ch1 = 0;
			return 1;
		}
		Delay(10);
	}
	// The current card is MMC card, then there's time out error, need to be cleared.
	ClearErrInterruptStatus_CH1();
	return 0;
}

int SetMMCOCR_CH1(void)
{
	U32 i, OCR;
	for (i=0; i<250; i++)
	{
		IssueCommand_CH1(1, 0x0, 0);
		OCR = rHM1_RSPREG0 | (1<<30);	

		IssueCommand_CH1(1, OCR, 0); // (Ocr:2.7V~3.6V)

		if (rHM1_RSPREG0&(0x1<<31))
		{			
			if(rHM1_RSPREG0 & (1<<7))
				printf("\nVoltage range : 1.65V ~ 1.95V");
			if(rHM1_RSPREG0 & (1<<21))
				printf("\nVoltage range: 2.7V ~ 3.4V\n");	
			else if(rHM1_RSPREG0 & (1<<20))
				printf("\nVoltage range: 2.7V ~ 3.3V\n");	
			else if(rHM1_RSPREG0 & (1<<19))
				printf("\nVoltage range: 2.7V ~ 3.2V\n");	
			else if(rHM1_RSPREG0 & (1<<18))
				printf("\nVoltage range: 2.7V ~ 3.1V\n");	

			if(rHM1_RSPREG0 & (1<<30))
				{
				printf("\nHigh Capacity Sector Mode Operation\n");
				SectorMode_ch1 = 1;
				}
			ThisIsMmc_ch1=1;
			printf("\nrHM_RSPREG0 = %x\n",rHM1_RSPREG0);
			return 1;
		}
	}
	ClearErrInterruptStatus_CH1();
	return 0;
}

void SetCommandReg_CH1(U16 uCmd,U32 uIsAcmd)
{
	U16 usSfr = 0;
	
	if (!uIsAcmd)//No ACMD
	{
		/* R2: 136-bits Resp.*/
		if ((uCmd==2||uCmd==9||uCmd==10))
			usSfr=(uCmd<<8)|(0<<4)|(1<<3)|(1<<0);

		/* R1,R6,R5: 48-bits Resp. */
		else if (uCmd==3||uCmd==8||uCmd==13||uCmd==16||uCmd==27||uCmd==30||uCmd==32||uCmd==33||uCmd==35||uCmd==36||uCmd==42||uCmd==55||uCmd==56)
			usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(2<<0);

		else if (uCmd==11||uCmd==14||uCmd==17||uCmd==18||uCmd==19||uCmd==20||uCmd==24||uCmd==25)
			usSfr=(uCmd<<8)|(1<<5)|(1<<4)|(1<<3)|(2<<0);

		/* R1b,R5b: 48-bits Resp. */
		else if (uCmd==6||uCmd==7||uCmd==12||uCmd==28||uCmd==29||uCmd==38)
		{
			if (uCmd==12)
				usSfr=(uCmd<<8)|(3<<6)|(1<<4)|(1<<3)|(3<<0);
			else if (uCmd==6)
			{
				if(!ThisIsMmc_ch1)	// SD card
					usSfr=(uCmd<<8)|(1<<5)|(1<<4)|(1<<3)|(2<<0);
				else			// MMC card
					usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(3<<0);
			}
			else
				usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(3<<0);
		}

		/* R3,R4: 48-bits Resp.  */
		else if (uCmd==1)
			usSfr=(uCmd<<8)|(0<<4)|(0<<3)|(2<<0);

		/* No-Resp. */
		else
			usSfr=(uCmd<<8)|(0<<4)|(0<<3)|(0<<0);
	}
	else//ACMD
	{
		if (uCmd==6||uCmd==22||uCmd==23)		// R1
			usSfr=(uCmd<<8)|(1<<4)|(1<<3)|(2<<0);
		else if (uCmd==13||uCmd==51)
			usSfr=(uCmd<<8)|(1<<5)|(1<<4)|(1<<3)|(2<<0);
		else
			usSfr=(uCmd<<8)|(0<<4)|(0<<3)|(2<<0);
	}
	rHM1_CMDREG = usSfr;
}


void setmmcspeedmode_CH1(U32 eSDSpeedMode)
{
	U8  ucSpeedMode;
	U32 uArg=0;
	ucSpeedMode = (eSDSpeedMode == HIGH_CH1) ? 1 : 0;
	uArg=(3<<24)|(185<<16)|(ucSpeedMode<<8); // Change to the high-speed mode
	while(!IssueCommand_CH1(6, uArg, 0));	
}


void SetSDSpeedMode_CH1(U32 eSDSpeedMode)
{
	U32 uSfr;
	U32 uArg = 0;
	U8  ucSpeedMode;
	int i;
	
	ucSpeedMode = (eSDSpeedMode == HIGH_CH1) ? 1 : 0;

	if (!IssueCommand_CH1(16, 64, 0)) // CMD16
		printf("CMD16 fail\n");
	else
	{
		SetBlockSizeReg_CH1(7, 64);
		SetBlockCountReg_CH1(1);
		SetArgumentReg_CH1(0*64);

		SetTransferModeReg_CH1(0, 1, 0, 0, 0);

		uArg = (0x1<<31)|(0xffff<<8)|(ucSpeedMode<<0);

		if (!IssueCommand_CH1(6, uArg, 0))
			printf("CMD6 fail\n");
		else
		{
			WaitForBufferReadReady_CH1();
			ClearBufferReadReadyStatus_CH1();
			
			for(i=0; i<16; i++)
			{
				uSfr = rHM1_BDATA	;			
			}			

			WaitForTransferComplete_CH1();
			ClearTransferCompleteStatus_CH1();
		}
	}	
}


void SetClock_CH1(U32 ClkSrc, U16 Divisor)
{

	rHM1_CONTROL2 = (rHM1_CONTROL2 & ~(0xffffffff)) | (0x1<<15)|(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
	//rHM_CONTROL2 = (rHM_CONTROL2 & ~(0xffffffff)) |(0x1<<14)|(0x1<<8)|(ClkSrc<<4);
	//rHM1_CONTROL3 = (0<<31) | (1<<23) | (0<<15) | (1<<7);//SD OK
	rHM1_CONTROL3 = (1<<31) | (1<<23) | (1<<15) | (1<<7);

	// SDCLK Value Setting + Internal Clock Enable	
	rHM1_CLKCON = (rHM1_CLKCON & ~((0xff<<8)|(0x1))) | (Divisor<<8)|(1<<0);

	// CheckInternalClockStable
	while (!(rHM1_CLKCON&0x2));
	ClockOnOff_CH1(1);
}

int IssueCommand_CH1( U16 uCmd, U32 uArg, U32 uIsAcmd)
{
	U32 uSfr;

	while ((rHM1_PRNSTS&0x1)); // Check CommandInhibit_CMD
	//while ((rHM1_PRNSTS&0x2)); // Check dataInhibit_CMD

	if (!uIsAcmd)//R1b type commands have to check CommandInhibit_DAT bit
	{
		if((uCmd==6&&ThisIsMmc_ch1)||uCmd==7||uCmd==12||uCmd==28||uCmd==29||uCmd==38||((uCmd==42||uCmd==56)&&(!ThisIsMmc_ch1)))
		{
			do	{
				uSfr = rHM1_PRNSTS;
			} while((uSfr&0x2)); // Check CommandInhibit_DAT
		}
	}
	// Argument Setting
	if (!uIsAcmd)// <------------------- Normal Command (CMD)
	{
		if(uCmd==3||uCmd==4||uCmd==7||uCmd==9||uCmd==10||uCmd==13||uCmd==15||uCmd==55)
			rHM1_ARGUMENT = uArg<<16;
		else
			rHM1_ARGUMENT = uArg;
	}
	else// <--------------------------- APP.Commnad (ACMD)
		rHM1_ARGUMENT = uArg;

	SetCommandReg_CH1(uCmd,uIsAcmd);

	if (!WaitForCommandComplete_CH1())
		{
			printf(("Command NOT Complete\n"));
		}
	else
		ClearCommandCompleteStatus_CH1();	

	if (!(rHM1_NORINTSTS&0x8000))
	{
		if(((rHM1_CMDREG>>8) == 0x8) &&(ThisIsMmc_ch1 !=1))
			{
			printf("\nCMD8 Support");
			SDSpecVer_ch1 = 2;
			}
		return 1;
	}
	else
	{
		if(OCRcheck_ch1 == 1)
			return 0;
		else
			{
			printf("Command = %d, Error Stat = %x\n",(rHM1_CMDREG>>8),rHM1_ERRINTSTS);
			rHM1_ERRINTSTS = rHM1_ERRINTSTS;
			rHM1_NORINTSTS =rHM1_NORINTSTS;
			if((rHM1_CMDREG>>8) == 0x8)
				{
				printf("\nThis Card version is NOT SD 2.0\n");
				}
			return 0;								
			}
	}

}

void GetResponseData_CH1(U32 uCmd)
{
	U32 uSfr0,uSfr1,uSfr2,uSfr3;

	uSfr0 = rHM1_RSPREG0;
	uSfr1 = rHM1_RSPREG1;
	uSfr2 = rHM1_RSPREG2;
	uSfr3 = rHM1_RSPREG3;

	if(uCmd==3)
	{
 		if(!ThisIsMmc_ch1)
 		{
			m_uRca_ch1 = (uSfr0>>16)&0xFFFF;			
			printf("=>  RCA=%d\n", m_uRca_ch1);
 		}
	}
	else if (uCmd==9)
	{
		if(ThisIsMmc_ch1)
		{
			m_ucMMCSpecVer_ch1=(rHM1_RSPREG3>>18)& 0xF;
			printf("=>  m_ucMMCSpecVer_ch1=%d\n", m_ucMMCSpecVer_ch1);
		}
	}
}

int GetSdSCR_CH1()
{
	U32  uSCR1, uSCR2;

	if (!IssueCommand_CH1(16, 8, 0))
		return 0;
	else
	{
		SetBlockSizeReg_CH1(7, 8);
		SetBlockCountReg_CH1(1);
		SetArgumentReg_CH1(0*8);

		SetTransferModeReg_CH1(0, 1, 0, 0, 0);
		if (!IssueCommand_CH1(55, m_uRca_ch1, 0))		// CMD55 (For ACMD)
			return 0;
		else
		{
			if (!IssueCommand_CH1(51, 0, 1))			// Acmd51
				return 0;
			else
			{
				WaitForBufferReadReady_CH1();
				ClearBufferReadReadyStatus_CH1();

				uSCR1 = rHM1_BDATA;
				uSCR2 = rHM1_BDATA;

				WaitForTransferComplete_CH1();
				ClearTransferCompleteStatus_CH1();

				if ((uSCR1&0xf) == 0x0)
					SDSpecVer_ch1 = 0; // Version 1.0 ~ 1.01
				else if ((uSCR1&0xf) == 0x1)
					SDSpecVer_ch1 = 1; // Version 1.10, support cmd6
				else if((uSCR1&0xf) == 0x2)
					SDSpecVer_ch1 = 2; // Version 2.0 support cmd6 and cmd8

				printf("SDSpecVer_ch1=%d\n", SDSpecVer_ch1);
				return 1;
			}
		}
	}
}

int IsCardInProgrammingState_CH1(void)
{
	// check the card status.
	U32  uSfr;

	if (!IssueCommand_CH1(13, m_uRca_ch1, 0))
		{
		printf("Card status = %x",((rHM1_RSPREG0>>9)&0xf));
		return 0;
		}
	else
	{
		if(((rHM1_RSPREG0>>9)&0xf) == 4)
			{
			printf("Card is transfer status\n");
			return 1;
			}
		return 0;
	}
}

void HostCtrlSpeedMode_CH1(U8 SpeedMode)
{
	U8  ucSpeedMode;
	ucSpeedMode = (SpeedMode == HIGH_CH1) ? 1 : 0;
	rHM1_HOSTCTL &= ~(0x1<<2);
	rHM1_HOSTCTL |= ucSpeedMode<<2;	
}

void ClockConfig_CH1(U32 Clksrc, U32 Divisior)
{
	U32 SrcFreq, WorkingFreq;
	U32 RealDivisor;
	
	if (Clksrc == SD_HCLK_CH1)
		SrcFreq = HCLK;
	else if (Clksrc == SD_EPLL_CH1)//Epll Out 48MHz
		SrcFreq = 100000000;
	else
		Clksrc = HCLK;

	if (Divisior !=0)
		{
		WorkingFreq = SrcFreq/(Divisior*2);
		printf("HCLK = %d, SD WorkingFreq = %dMHz\n",HCLK,WorkingFreq/(1000000));
		}
	else
		{
		WorkingFreq = SrcFreq;	
		printf("WorkingFreq = %dMHz\n",WorkingFreq/(1000000));
		}

	if (ThisIsMmc_ch1)
	{
		if (m_ucMMCSpecVer_ch1==4)
		{
			if (WorkingFreq>20000000)// It is necessary to enable the high speed mode in the card before changing the clock freq to a freq higher than 20MHz.
			{
				setmmcspeedmode_CH1(HIGH_CH1);					
				printf("\nSet MMC High speed mode OK!!\n");
			}
			else
			{
				setmmcspeedmode_CH1(NORMAL_CH1);	
				printf("\nSet MMC Normal speed mode OK!!\n");
			}
		}
		else // old version
			printf("Old version MMC card can not support working frequency higher than 25MHz");
	}
	else
	{
		GetSdSCR_CH1();
		if (SDSpecVer_ch1==1||SDSpecVer_ch1==2 )
		{
			if (WorkingFreq>25000000)
			{
				SetSDSpeedMode_CH1(HIGH_CH1);//Higher than 25MHz, should use high speed mode. Max 50MHz and 25MB/sec
				printf("\nSet SD High speed mode OK!!\n");
			}
			else
			{
				SetSDSpeedMode_CH1(NORMAL_CH1);
				printf("\nSet SD Normal speed mode OK!!\n");
			}
		}
		else 
			printf("Old version SD card can not support working frequency higher than 25MHz");
	}

	if (WorkingFreq>25000000)// Higher than 25MHz, it is necessary to enable high speed mode of the host controller.
	{
		HostCtrlSpeedMode_CH1(HIGH_CH1);
	}
	else
	{
		HostCtrlSpeedMode_CH1(NORMAL_CH1);
	}

	ClockOnOff_CH1(0); // when change the sd clock frequency, need to stop sd clock.
	SetClock_CH1(Clksrc, Divisior); 
}

void HS_MMC_Irq_CH1(void)
{
	pISR_SDI_1 = (int)HS_CARD_DETECT_INT_CH1;	// Set interrupt service routine.	
	rINTMSK &= ~(BIT_SDI1);
}

void HS_MMC_Reset_CH1(void)
{
	rHM1_SWRST = 0x3;
}

void HS_MMC_SETGPIO_CH1(void)
{
	//SD1
	rGPLCON = rGPLCON & ~(0xfffff) | (0xaaaaa);
	rGPJCON = rGPJCON & ~(0x3f<<26) | (0x2a<<26);
	rGPJCON &= ~(0x3<<30) | (1<<30);
	rGPJDAT |=(1<<15);

	//SD0
	rGPECON = (rGPECON& ~(0x3ffc00))|(0x1<<21)|(0x1<<19)|(0x1<<17)|(0x1<<15)|(0x1<<13)|(0x1<<11);
}

void SetTransferModeReg_CH1(U32 MultiBlk,U32 DataDirection, U32 AutoCmd12En,U32 BlockCntEn,U32 DmaEn)
{
	rHM1_TRNMOD = (rHM1_TRNMOD & ~(0xffff)) | (MultiBlk<<5)|(DataDirection<<4)|(AutoCmd12En<<2)|(BlockCntEn<<1)|(DmaEn<<0);
}

void SetArgumentReg_CH1(U32 uArg)
{
	rHM1_ARGUMENT = uArg;
}

void SetBlockCountReg_CH1(U16 uBlkCnt)
{
	rHM1_BLKCNT = uBlkCnt;
}

void SetSystemAddressReg_CH1(U32 SysAddr)
{
	rHM1_SYSAD = SysAddr;
}

void SetBlockSizeReg_CH1(U16 uDmaBufBoundary, U16 uBlkSize)
{
	rHM1_BLKSIZE = (uDmaBufBoundary<<12)|(uBlkSize);
}

void ClockOnOff_CH1(int OnOff)
{
	if (OnOff == 0)
	{
		rHM1_CLKCON &=~(0x1<<2);
	}
		
	else
	{
		rHM1_CLKCON|=(0x1<<2);		
		while (1)
		{
			if (rHM1_CLKCON&(0x1<<3)) // SD_CLKSRC is Stable
				break;
		}
	}
}

void ClearCommandCompleteStatus_CH1(void)
{
	rHM1_NORINTSTS=(1<<0);
	while (rHM1_NORINTSTS&0x1)
		{
			rHM1_NORINTSTS=(1<<0);
		}	
}

void ClearTransferCompleteStatus_CH1(void)
{

	rHM1_NORINTSTS = (1<<1);
	while (rHM1_NORINTSTS&0x2)
		{
			rHM1_NORINTSTS = (1<<1);
		}
}

void ClearBufferWriteReadyStatus_CH1(void)
{
	rHM1_NORINTSTS = (1<<4);
	while (rHM1_NORINTSTS & 0x10)
		rHM1_NORINTSTS = (1<<4);
}

void ClearBufferReadReadyStatus_CH1(void)
{
	rHM1_NORINTSTS = (1<<5);
	while (rHM1_NORINTSTS & 0x20)
		rHM1_NORINTSTS = (1<<5);
}


void ClearErrInterruptStatus_CH1(void)
{
	while (rHM1_NORINTSTS&(0x1<<15))
	{
		rHM1_NORINTSTS =rHM1_NORINTSTS;
		rHM1_ERRINTSTS =rHM1_ERRINTSTS;
	}

⌨️ 快捷键说明

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