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

📄 mci.c

📁 IARSOURCECODE是基于LPC2478嵌入式软件IAR EWARM V4.42的应用实例代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	MCI_CLEAR = MCI_DATA_CRC_FAIL;
  }
  if ( MCIStatus &  MCI_DATA_TIMEOUT )
  {
	DataTimeoutErrCount++;
	MCI_CLEAR =  MCI_DATA_TIMEOUT;
  }
  /* Underrun or overrun */
  if ( MCIStatus &  MCI_TX_UNDERRUN )
  {
	DataTxUnderrunErrCount++;
	MCI_CLEAR = MCI_TX_UNDERRUN;
  }
  if ( MCIStatus &  MCI_RX_OVERRUN )
  {
	DataRxOverrunErrCount++;
	MCI_CLEAR =  MCI_RX_OVERRUN;
  }
  /* Start bit error on data signal */
  if ( MCIStatus &  MCI_START_BIT_ERR )
  {
	DataStartbitErrCount++;
	MCI_CLEAR =  MCI_START_BIT_ERR;
  }
  return;
}

/******************************************************************************
** Function name:		MCI_DATA_END_InterruptService
**
** Descriptions:		Called by MCI interrupt handler
**						This is the last interrupt module processing
**                      the block write and	read to and from the MM card.
**					
**                      FIFO interrupts are also used when DMA is disabled
**						This routine simply clears the
**                      MCI_Block_End_Flag, and increments counters for debug
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
void MCI_DATA_END_InterruptService( void )
{
  DWORD MCIStatus;

  MCIStatus = MCI_STATUS;
  if ( MCIStatus &  MCI_DATA_END )		/* Data end, and Data block end  */
  {
	DataEndCount++;
	MCI_CLEAR = MCI_DATA_END;
	return;
  }
  if ( MCIStatus &  MCI_DATA_BLK_END )
  {
	DataBlockEndCount++;
	MCI_CLEAR =  MCI_DATA_BLK_END;
	MCI_TXDisable();
	MCI_Block_End_Flag = 0;
	return;
  }
	
  /* Tx active  */
  if ( MCIStatus & MCI_TX_ACTIVE )
  {
	DataTxActiveCount++;
  }
  /* Rx active  */
  if ( MCIStatus & MCI_RX_ACTIVE )
  {
	DataRxActiveCount++;
  }
  return;
}

/******************************************************************************
** Function name:	MCI_FIFOInterruptService
**
** Descriptions:	Called by MCI interrupt handler when using FIFO
**					interrupts and DMA is disabled
**						
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
void MCI_FIFOInterruptService( void )
{
#if !MCI_DMA_ENABLED
  DWORD MCIStatus;

  MCIStatus = MCI_STATUS;
  if ( MCIStatus & (FIFO_TX_INT_MASK ) )
  {
	DataTxFIFOCount++;			 /* if using TX_HALF_EMPTY remove one WriteFifo below */
	if ( MCIStatus & MCI_TX_HALF_EMPTY ) /* empty is multiple of 512 block size */
	{
	  MCI_WriteFifo((DWORD *)&WriteBlock[TXBlockCounter]); /* write 8 words to fifo */
	  TXBlockCounter += 32;
	}
	if (TXBlockCounter == BLOCK_LENGTH)	/* block complete */
	{
	  TXBlockCounter = 0;
	  MCI_MASK0 &= ~(FIFO_TX_INT_MASK);  /* disable FIFO int until next block write */
	  MCI_MASK1 &= ~(FIFO_TX_INT_MASK);
	  /* wait for SD card to complete sending data i.e MCI_DATA_BLK_END interrupt */
	}
  }
  else if ( MCIStatus & (FIFO_RX_INT_MASK) )
  {
	DataRxFIFOCount++;
	if ( MCIStatus & MCI_RX_HALF_FULL )	/* if using RX_HALF_FULL remove one ReadFIFO below */
	{
	  MCI_ReadFifo((DWORD *)&ReadBlock[RXBlockCounter]); /* read 8 words from fifo */
	  RXBlockCounter += 32;
	}
	if (RXBlockCounter == BLOCK_LENGTH)	/* block complete */
	{
	  RXBlockCounter = 0;
	}
  }
#endif
  DataFIFOCount++;
  return;
}

/******************************************************************************
** Function name:		MCI_IRQHandler
**
** Descriptions:		MCI interrupt handler
**						The handler to handle the block data write and read
**						not for the commands.
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
__irq __arm void MCI_IRQHandler (void)
{
  DWORD MCI_Status;
  MCI_Status = MCI_STATUS;
  IntStatusBuffer[IntIndex++] = MCI_Status;	
  /* handle MCI_STATUS interrupt */
  if ( MCI_Status & DATA_ERR_INT_MASK )
  {
	MCI_DataErrorProcess();
	MCI_DataErrorProcess_count++;
	VICVectAddr = 0;		/* Acknowledge Interrupt */
	return;
  }
  if ( MCI_Status & DATA_END_INT_MASK )
  {
	MCI_DATA_END_InterruptService();
	MCI_DATA_END_InterruptService_count++;
	VICVectAddr = 0;		/* Acknowledge Interrupt */
	return;
  }
  else if ( MCI_Status & FIFO_INT_MASK )
  {
	MCI_FIFOInterruptService();
	MCI_FIFOInterruptService_count++;
	VICVectAddr = 0;		/* Acknowledge Interrupt */
	return;
  }
  else if ( MCI_Status & CMD_INT_MASK )
  {
	MCI_CmdProcess();
	MCI_CmdProcess_count++;
	VICVectAddr = 0;		/* Acknowledge Interrupt */
	return;
  }
  VICVectAddr = 0;		/* Acknowledge Interrupt */
}

/******************************************************************************
** Function name:		MCI_Set_MCIClock
**
** Descriptions:		Set MCI clock rate, during initialization phase < 400K
**						during data phase < 20Mhz. 		
**
** parameters:			Clock rate to be set			
** Returned value:		None
**
******************************************************************************/
void MCI_Set_MCIClock( DWORD ClockRate )
{
  DWORD i, ClkValue = 0;

  if ( ClockRate == SLOW_RATE )
	ClkValue |= MCLKDIV_SLOW;	/* slow clock */
  else if ( ClockRate == NORMAL_RATE )
	ClkValue |= MCLKDIV_NORMAL;/* normal clock */

  MCI_CLOCK &= ~(0xFF); /* clear clock divider */
  MCI_CLOCK |= (1 << 8)  |ClkValue;
  for ( i = 0; i < 0x10; i++ );	/* delay 3MCLK + 2PCLK before next write */
  return;
}

/******************************************************************************
** Function name:		SD_Set_BusWidth
**
** Descriptions:		1-bit bus or 4-bit bus.
**
** parameters:			bus width			
** Returned value:		TRUE or FALSE
**
******************************************************************************/
DWORD SD_Set_BusWidth( DWORD width )
{
  DWORD i;

  for ( i = 0; i < 0x10; i++ );	/* delay 3MCLK + 2PCLK  */
  if ( width == SD_1_BIT )
  {
	MCI_CLOCK &=  ~(1 << 11);	/* 1 bit bus */
  }
  else if ( width == SD_4_BIT )
  {
	MCI_CLOCK |=  (1 << 11);/* 4 bit bus */
  }
	
  if ( MCI_Send_ACMD_Bus_Width( BUS_WIDTH_4BITS ) == FALSE )
  {
	return( FALSE );
  }
  return TRUE;
}

/******************************************************************************
** Function name:		MCI_Init
**
** Descriptions:		Set MCI clock and power registers, setup VIC for
**						data interrupt.		
**
** parameters:			None
** Returned value:		true or fase, if VIC table is full, return false
**
******************************************************************************/
DWORD MCI_Init( void )
{
  DWORD i;

  PCONP |= ( 1 << 28 );			/* Enable clock to the MCI block */

  if ( MCI_CLOCK & (1 << 8) )
  {
	MCI_CLOCK &= ~(1 << 8);
  }
  if ( MCI_POWER & 0x02 )
  {
	MCI_POWER = 0x00;
  }
  for ( i = 0; i < 0x1000; i++ );

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

  /* Due to reversed H/W logic in the MCB2300 board, the MCI power pin
  needs to be configured as GPIO pin that I need to set it active low manually,
  once it's set as MCI power pin, it will be active high. */
  /*connect MCI signals to P0.19-P0.22, and P2.11-P2.13*/

#if MCB2300_VERSION_0
  SCS &= ~0x08;
#if 0
  PINSEL1 = 0x2280;
  PINSEL4 = 0x0A800000;
  IODIR0 = 1 << 21;		/* MCI_PWR as GPIO output */
  IOCLR0 = 1 << 21;
#endif
#elif LINPO_BOARD_V0
  PINSEL2 = 0x280A8A0;
  PINSEL4 = 0x800000;
  SCS &= ~0x08;
#else
  SCS &= ~0x08;
#if 0
  PINSEL1 = 0x2A80;
  PINSEL4 = 0x0A800000;
#endif
#endif

  /*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. */	
  MCI_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( MCI_INT, (void *)MCI_IRQHandler, HIGHEST_PRIORITY ) == FALSE )
  {
	return ( FALSE );
  }

  /* 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.
**
******************************************************************************/

⌨️ 快捷键说明

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