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

📄 mci.c

📁 nxp的LPC2888处理器的示例代码.
💻 C
📖 第 1 页 / 共 3 页
字号:
  {
	MCI_POWER = 0x00;
  }
  for ( i = 0; i < 0x1000; i++ );

  /* Disable all interrupts for now */
  MCI_MASK0 = 0;
  MCI_MASK1 = MCI_MASK0;

  /*set up clocking default mode, clear any registers as needed */
  MCI_COMMAND = 0;
  MCI_DATA_CTRL = 0;			
  MCI_CLEAR = 0x7FF;		/* clear all pending interrupts */

  MCI_POWER = 0x02;		/* power up */
  while ( !(MCI_POWER & 0x02) );
  for ( i = 0; i < 0x100; i++ );

  /* During identification phase, the clock should be less than
  400Khz. Once we pass this phase, the normal clock can be set up
  to 25Mhz on SD card and 20Mhz on MMC card. */	
  Set_MCIClock( SLOW_RATE );
  MCI_POWER |= 0x01;		/* bit 1 is set already, from power up to power on */
	
  for ( i = 0; i < 0x2000; i++ );
	
  if ( install_IRQ(10, 1, MCI_Handler ) == FALSE )
  {
	return( FALSE );
  }
  INT_REQ10=(1<<28)|(1<<27)|(1<<26)|(1<<16)|0x1;
  INT_VECTOR0=IRQ_TABLE_BASE & MASK_INDEX;
    
  /* During the initialization phase, to simplify the process, the CMD related 
  interrupts are disabled. The DATA related interrupts are enabled when
  the FIFOs are used and just before WRITE_BLOCK READ_BLOCK cmds are issues, and 
  disabled after the data block has been written and read. Please also note,
  before WRITE_BLOCK only TX related data interrupts are enabled, and before
  READ_BLOCK only RX related data interrupts are enabled. */   
  return (TRUE);
}

/******************************************************************************
** Function name:		MCI_SendCmd
**
** Descriptions:		The routine is used to send a CMD to the card		
**
** parameters:			CmdIndex, Argument, ExpectResp Flag, AllowTimeout flag
** Returned value:		None
** 
******************************************************************************/
void MCI_SendCmd( DWORD CmdIndex, DWORD Argument, DWORD ExpectResp, DWORD AllowTimeout )
{
  DWORD i, CmdData = 0;
  DWORD CmdStatus;
	
  /* the command engine must be disabled when we modify the argument
  or the peripheral resends */
  while ( (CmdStatus = MCI_STATUS) & MCI_CMD_ACTIVE )	/* Command in progress. */
  {
	MCI_COMMAND = 0;
	MCI_CLEAR = CmdStatus | MCI_CMD_ACTIVE;
  }
  for ( i = 0; i < 0x100; i++ );	

  /*set the command details, the CmdIndex should 0 through 0x3F only */
  CmdData |= (CmdIndex & 0x3F);	/* bit 0 through 5 only */
  if ( ExpectResp == EXPECT_NO_RESP )			/* no response */
  {
	CmdData &= ~((1 << 6) | (1 << 7));		/* Clear long response bit as well */
  }
  else if ( ExpectResp == EXPECT_SHORT_RESP )	/* expect short response */
  {
	CmdData |= (1 << 6);
  }
  else if ( ExpectResp == EXPECT_LONG_RESP )	/* expect long response */
  {
	CmdData |= (1 << 6) | (1 << 7);
  }

  if ( AllowTimeout )			/* allow timeout or not */
  {
	CmdData |= (1 << 8);
  }
  else
  {
	CmdData &= ~(1 << 8);
  }

  /*send the command*/
  CmdData |= (1 << 10);		/* This bit needs to be set last. */
  MCI_ARGUMENT = Argument;	/* Set the argument first, finally command */
  MCI_COMMAND = CmdData;
  return;
}

/******************************************************************************
** Function name:		MCI_GetCmdResp
**
** Descriptions:		Get response from the card. This module is always used
**						in pair with MCI_SendCmd()		
**
** parameters:			Expected cmd data, expect response flag, pointer to the 
**						response
**						Expected cmd data should be the same as that in SendCmd()
**						expect response flag could be	EXPECT_NO_RESP
**														EXPECT_SHORT_RESP
**														EXPECT_LONG_RESP
**						if GetCmdResp() is 0, check the pointer to the response
**						field to get the response value, if GetCmdResp() returns 
**						non-zero, no need to check the response field, just resend
**						command or bailout. 
** Returned value:		Response status, 0 is valid response. 
** 
******************************************************************************/
DWORD MCI_GetCmdResp( DWORD ExpectCmdData, DWORD ExpectResp, DWORD *CmdResp )
{
  DWORD CmdRespStatus = 0;
  DWORD LastCmdIndex;

  if ( ExpectResp == EXPECT_NO_RESP )
  {
	return ( 0 );
  }

  while ( 1 )
  {
	CmdRespStatus = MCI_STATUS;	
	if ( CmdRespStatus & (MCI_CMD_TIMEOUT) )
	{
	  MCI_CLEAR = CmdRespStatus | MCI_CMD_TIMEOUT;
	  MCI_COMMAND = 0;
	  MCI_ARGUMENT = 0xFFFFFFFF;
	  return ( CmdRespStatus );
	}
	if (  CmdRespStatus & MCI_CMD_CRC_FAIL )
	{
	  MCI_CLEAR = CmdRespStatus | MCI_CMD_CRC_FAIL;
	  LastCmdIndex = MCI_COMMAND & 0x003F;
	  if ( (LastCmdIndex == SEND_OP_COND) || (LastCmdIndex == SEND_APP_OP_COND) 
					|| (LastCmdIndex == STOP_TRANSMISSION) )
	  {
		MCI_COMMAND = 0;
		MCI_ARGUMENT = 0xFFFFFFFF;	 
		break;			/* ignore CRC error if it's a resp for SEND_OP_COND 
						or STOP_TRANSMISSION. */
	  }
	  else
	  { 
		return ( CmdRespStatus );
	  }
	}
	else if ( CmdRespStatus & MCI_CMD_RESP_END )
	{
	  MCI_CLEAR = CmdRespStatus | MCI_CMD_RESP_END;
	  break;	/* cmd response is received, expecting response */
	}
  }
	
  if ( (MCI_RESP_CMD & 0x3F) != ExpectCmdData )
  {
	/* If the response is not R1, in the response field, the Expected Cmd data
	won't be the same as the CMD data in SendCmd(). Below four cmds have
	R2 or R3 response. We don't need to check if MCI_RESP_CMD is the same
	as the Expected or not. */
	if ( (ExpectCmdData != SEND_OP_COND) && (ExpectCmdData != SEND_APP_OP_COND) 
			&& (ExpectCmdData != ALL_SEND_CID) && (ExpectCmdData != SEND_CSD) )
	{
	  CmdRespStatus = INVALID_RESPONSE;	/* Reuse error status */
	  return ( INVALID_RESPONSE );
	}
  }

  if ( ExpectResp == EXPECT_SHORT_RESP )
  {
	*CmdResp = MCI_RESP0;
  }
  else if ( ExpectResp == EXPECT_LONG_RESP )
  {
	*CmdResp = MCI_RESP0;
	*(CmdResp+1) = MCI_RESP1;
	*(CmdResp+2) = MCI_RESP2;
	*(CmdResp+3) = MCI_RESP3;
  }
  return ( 0 );	/* Read MCI_RESP0 register assuming it's not long response. */
}

/******************************************************************************
** Function name:		MCI_Go_Idle_State
**
** Descriptions:		CMD0, the very first command to be sent to initialize
**						either MMC or SD card.		
**
** parameters:			None
** Returned value:		true or false, true if card has been initialized.
** 
******************************************************************************/
DWORD MCI_Go_Idle_State( void )
{
  DWORD retryCount;
  DWORD respStatus;
  DWORD respValue[4];

  retryCount = 0x20;
  while ( retryCount > 0 )
  {
	/* Send CMD0 command repeatedly until the response is back correctly */
    MCI_SendCmd( GO_IDLE_STATE, 0x00000000, EXPECT_NO_RESP, 0 );
	respStatus = MCI_GetCmdResp( GO_IDLE_STATE, EXPECT_NO_RESP, (DWORD *)respValue );
	if ( respStatus == 0 )
	{
	  break;
	}
	retryCount--;
  }
	
  if ( respStatus != 0 )		/* timeout, give up */
  {
	return ( FALSE );
  }
  return( TRUE );
}

/******************************************************************************
** Function name:		MCI_Send_OP_Cond
**
** Descriptions:		CMD1 for MMC		
**
** parameters:			None
** Returned value:		true or false, true if card has response back before
**						timeout, false is timeout on the command.
** 
******************************************************************************/
DWORD MCI_Send_OP_Cond( void )
{
  DWORD i, retryCount;
  DWORD respStatus;
  DWORD respValue[4];

  retryCount = 0x200;			/* reset retry counter */
  while ( retryCount > 0 )
  {
	/* Send CMD1 command repeatedly until the response is back correctly */
	MCI_SendCmd( SEND_OP_COND, OCR_INDEX, EXPECT_SHORT_RESP, 0 );
	respStatus = MCI_GetCmdResp( SEND_OP_COND, EXPECT_SHORT_RESP, (DWORD *)&respValue[0] );
	/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
	if ( !(respStatus & MCI_CMD_TIMEOUT) && (respValue[0] & 0x80000000) )
	{
	  return ( TRUE );	/* response is back and correct. */
	}
	for ( i = 0; i < 0x20; i++ );
	retryCount--;
  }
  return( FALSE );
}

/******************************************************************************
** Function name:		MCI_Send_ACMD
**
** Descriptions:		CMD55, before sending an ACMD, call this routine first  		
**
** parameters:			None
** Returned value:		true or false, true if card has responded before timeout.
**						false is timeout.
** 
******************************************************************************/
DWORD MCI_Send_ACMD( void )
{
  DWORD i, retryCount;
  DWORD CmdArgument;
  DWORD respStatus;
  DWORD respValue[4];

  if ( CardType == SD_CARD )
  {
	CmdArgument = CardRCA;	/* Use the address from SET_RELATIVE_ADDR cmd */
  }
  else			/* if MMC or unknown card type, use 0x0. */
  {
	CmdArgument = 0x00000000;
  }

  retryCount = 20;
  while ( retryCount > 0 )
  {
	/* Send CMD55 command followed by an ACMD */
	MCI_SendCmd( APP_CMD, CmdArgument, EXPECT_SHORT_RESP, 0 );
	respStatus = MCI_GetCmdResp( APP_CMD, EXPECT_SHORT_RESP, (DWORD *)&respValue[0] );
	/* Check if APP_CMD enabled */
	if ( !respStatus && (respValue[0] & CARD_STATUS_ACMD_ENABLE) )	/* Check if APP_CMD enabled */
	{
	  return( TRUE );
	}
	for ( i = 0; i < 0x20; i++ );
	retryCount--;
  }
  return( FALSE );
}

/******************************************************************************
** Function name:		MCI_Send_ACMD_OP_Cond
**
** Descriptions:		If Send_OP_Cond is timeout, it's not a MMC card, try 
**						this combination to see if we can communicate with 
**						a SD card. 		
**
** parameters:			None
** Returned value:		true or false, true if card has been initialized.
** 
******************************************************************************/
DWORD MCI_Send_ACMD_OP_Cond( void )
{
  DWORD i, retryCount;
  DWORD respStatus;
  DWORD respValue[4];

  /* timeout on SEND_OP_COND command on MMC, now, try SEND_APP_OP_COND 
  command to SD */
  retryCount = 0x200;			/* reset retry counter */
  while ( retryCount > 0 )
  {
	MCI_POWER &= ~(1 << 6 );	/* Clear Open Drain output control for SD */
	for ( i = 0; i < 0x3000; i++ );

	if ( MCI_Send_ACMD() == FALSE )
	{
	  continue;
	}		
	/* Send ACMD41 command repeatedly until the response is back correctly */
	MCI_SendCmd( SEND_APP_OP_COND, OCR_INDEX, EXPECT_SHORT_RESP, 0 );
	respStatus = MCI_GetCmdResp( SEND_APP_OP_COND, EXPECT_SHORT_RESP, (DWORD *)&respValue[0] );
	if ( !(respStatus & MCI_CMD_TIMEOUT) && (respValue[0] & 0x80000000) )
	{
	  return ( TRUE );	/* response is back and correct. */
	}
	for ( i = 0; i < 0x20; i++ );
	retryCount--;
  }
  return( FALSE );
}

/******************************************************************************
** Function name:		MCI_CardInit
**
** Descriptions:		Try CMD1 first for MMC, if it's timeout, try CMD55 
**						and CMD41 for SD, if both failed, initialization faliure, 
**						bailout with unknown card type. Otherwise, return the
**						card type, either MMC or SD.		
**
** parameters:			None
** Returned value:		Card type.
** 
******************************************************************************/
DWORD MCI_CardInit( void )
{
  DWORD i, CardType;

  if ( MCI_Go_Idle_State() == FALSE )
  {
	return( CARD_UNKNOWN );
  }

  MCI_POWER |= (1 << 6 );		/* Set Open Drain output control for MMC */
  for ( i = 0; i < 0x3000; i++ );

  /* Try CMD1 first for MMC, if it's timeout, try CMD55 and CMD41 for SD,
  if both failed, initialization faliure, bailout. */
  if ( MCI_Send_OP_Cond() == TRUE )	
  {
	CardType = MMC_CARD;
	return ( CardType );	/* Found the card, it's a MMC */
  }
  else if ( MCI_Send_ACMD_OP_Cond() == TRUE )
  {
	CardType = SD_CARD;
	return ( CardType );	/* Found the card, it's a SD */
  }	
  /* tried both MMC and SD card, give up */
  return ( CARD_UNKNOWN );
}

/******************************************************************************
** Function name:		MCI_Check_CID
**
** Descriptions:		Send CMD2, ALL_SEND_CID		
**
** parameters:			None
** Returned value:		If not timeout, return true.
** 
******************************************************************************/
DWORD MCI_Check_CID( void )
{
  DWORD i, retryCount;
  DWORD respStatus;
  DWORD respValue[4];

  /* This command is normally after CMD1(MMC) or ACMD41(SD). */
  retryCount = 0x20;			/* reset retry counter */
  while ( retryCount > 0 )
  {
	/* Send CMD2 command repeatedly until the response is back correctly */
	MCI_SendCmd( ALL_SEND_CID, 0, EXPECT_LONG_RESP, 0 );
	respStatus = MCI_GetCmdResp( ALL_SEND_CID, EXPECT_LONG_RESP, (DWORD *)&respValue[0] );
	/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
	if ( !(respStatus & MCI_CMD_TIMEOUT) )
	{
	  return ( TRUE );	/* response is back and correct. */
	}
	for ( i = 0; i < 0x20; i++ );
	retryCount--;
  }
  return ( FALSE );
}

/******************************************************************************
** Function name:		MCI_Set_Address
**
** Descriptions:		Send CMD3, STE_RELATIVE_ADDR, should after CMD2		
**
** parameters:			None
** Returned value:		TRUE if response is back before timeout.
** 
******************************************************************************/
DWORD MCI_Set_Address( void )
{
  DWORD i, retryCount;
  DWORD respStatus;
  DWORD respValue[4];
  DWORD CmdArgument;

  /* If it's a SD card, SET_RELATIVE_ADDR is to get the address
  from the card and use this value in RCA, if it's a MMC, set default
  RCA addr. 0x00010000. */ 
  if ( CardType == SD_CARD )
  {
	CmdArgument = 0;
  }
  else			/* If it's unknown or MMC_CARD, fix the RCA address */
  {
	CmdArgument = 0x00010000;
  }

  retryCount = 0x20;			/* reset retry counter */
  while ( retryCount > 0 )

⌨️ 快捷键说明

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