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

📄 lpc177x_8x_mci.c

📁 NXPl788上lwip的无操作系统移植,基于Embest开发板
💻 C
📖 第 1 页 / 共 5 页
字号:
				/* Should be in STANDBY state now and ready */
				retval = MCI_FUNC_ERR_STATE;
			}
			else
			{
				return MCI_FUNC_OK;
			}
		}
	}

	return retval;
}


/*********************************************************************//**
 * @brief 		Called by MCI interrupt handler to simplify the command
 *				process.
 *
 * @param		None
 *
 * @return 		None
 *
 * @note		In card initialization, the commnad interrupts are disabled
 *************************************************************************/
void MCI_CmdProcess( void )
{
	uint32_t MCIStatus;

	MCIStatus = LPC_MCI->STATUS;

	if ( MCIStatus &  MCI_CMD_CRC_FAIL )
	{
		LPC_MCI->CLEAR =  MCI_CMD_CRC_FAIL;
	}

	if ( MCIStatus &  MCI_CMD_TIMEOUT )
	{
		LPC_MCI->CLEAR =  MCI_CMD_TIMEOUT;
	}

	/* Cmd Resp End or Cmd Sent */
	if ( MCIStatus &  MCI_CMD_RESP_END )
	{
		LPC_MCI->CLEAR =  MCI_CMD_RESP_END;
	}

	if ( MCIStatus &  MCI_CMD_SENT )
	{
		LPC_MCI->CLEAR =  MCI_CMD_SENT;
	}

	if ( MCIStatus &  MCI_CMD_ACTIVE )
	{
		LPC_MCI->CLEAR =  MCI_CMD_ACTIVE;
	}

	return;
}


/*********************************************************************//**
 * @brief 		Called by MCI interrupt handler to manage error on the bus
 *
 * @param		None
 *
 * @return 		None
 *************************************************************************/
void MCI_DataErrorProcess( void )
{
	uint32_t MCIStatus;

	MCIStatus = LPC_MCI->STATUS;

	if ( MCIStatus &  MCI_DATA_CRC_FAIL )
	{
		LPC_MCI->CLEAR = MCI_DATA_CRC_FAIL;
	}

	if ( MCIStatus &  MCI_DATA_TIMEOUT )
	{
		LPC_MCI->CLEAR =  MCI_DATA_TIMEOUT;
	}

	/* Underrun or overrun */
	if ( MCIStatus &  MCI_TX_UNDERRUN )
	{
		LPC_MCI->CLEAR = MCI_TX_UNDERRUN;
	}

	if ( MCIStatus &  MCI_RX_OVERRUN )
	{
		LPC_MCI->CLEAR =  MCI_RX_OVERRUN;
	}

	/* Start bit error on data signal */
	if ( MCIStatus &  MCI_START_BIT_ERR )
	{
		LPC_MCI->CLEAR =  MCI_START_BIT_ERR;
	}

    Mci_Data_Xfer_End = 0;
    Mci_Data_Xfer_ERR = MCIStatus;
	return;
}


/*********************************************************************//**
 * @brief 		Called by MCI interrupt handler. This is the last interrupt
 *				manipulates the process of the data-block write and read 
 *				to/with card
 *
 * @details		This service is also used with/without DMA support. It simply
 *				clears the flag messages the in-process data-block transfer 
 *				has been done/ended
 *
 * @param		None
 *
 * @return 		None
 *************************************************************************/
void MCI_DATA_END_InterruptService( void )
{
	uint32_t MCIStatus;

	MCIStatus = LPC_MCI->STATUS;
	if ( MCIStatus &  MCI_DATA_END )		/* Data end, and Data block end  */
	{
		LPC_MCI->CLEAR = MCI_DATA_END;

		Mci_Data_Xfer_End = 0;

        Mci_Data_Xfer_ERR = 0;

		MCI_TXDisable();
		
		MCI_RXDisable();

		return;
	}

	if ( MCIStatus &  MCI_DATA_BLK_END )
	{
		LPC_MCI->CLEAR =  MCI_DATA_BLK_END;

		//MCI_TXDisable();

		return;
	}

	/* Tx active  */
	if ( MCIStatus & MCI_TX_ACTIVE )
	{

	}

	/* Rx active  */
	if ( MCIStatus & MCI_RX_ACTIVE )
	{

	}

	return;
}


/*********************************************************************//**
 * @brief 		Called by MCI interrupt handler if requiring to using FIFO
 *				for data transferring. It copy data to/from FIFO register
 *				from/to a data buffer.
 *
 * @param		None
 *
 * @return 		None
 *
 * @note		This function is done without DMA transfer support
 **********************************************************************/
void MCI_FIFOInterruptService( void )
{
#if !MCI_DMA_ENABLED
	uint32_t MCIStatus;

	MCIStatus = LPC_MCI->STATUS;

	if ( MCIStatus & (FIFO_TX_INT_MASK ) )
	{
		/* empty is multiple of 512 block size */
		if ( MCIStatus & MCI_TX_HALF_EMPTY )
		{
			//There's no data, return
			if(dataSrcBlock == NULL)
				return;

			/* write 8 words to fifo */
			MCI_WriteFifo((uint32_t *)&dataSrcBlock[txBlockCnt]);

			txBlockCnt += 32;
		}

		if (txBlockCnt == BLOCK_LENGTH)	/* block complete */
		{
			dataSrcBlock += BLOCK_LENGTH;

			txBlockCnt = 0;

			/* disable FIFO int until next block write */
			//LPC_MCI->MASK0 &= ~(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) )
	{
		/* if using RX_HALF_FULL remove one ReadFIFO below */
		if ( MCIStatus & MCI_RX_HALF_FULL )
		{
			//There's no store data, return
			if(dataDestBlock == NULL)
				return;

			/* read 8 words from fifo */
			MCI_ReadFifo((uint32_t *)&dataDestBlock[rxBlockCnt]);

			rxBlockCnt += 32;
		}

		/* block complete */
		if (rxBlockCnt == BLOCK_LENGTH)
		{
			dataDestBlock += BLOCK_LENGTH;

			rxBlockCnt = 0;
		}
	}
#endif

	return;
}

/*********************************************************************//**
 * @brief 		MCI_IRQHandler is to manage the reasons that cause the 
 *				interrupt.
 *
 * @details		It controls the data-block writing and reading by access 
 *				the FIFO register.
 *				It handle the state changes on the MCI bus...
 *
 * @param		None
 *
 * @return 		None
 **********************************************************************/
void MCI_IRQHandler (void)
{
	uint32_t MCI_Status;

	MCI_Status = LPC_MCI->STATUS;

	/* handle MCI_STATUS interrupt */
	if ( MCI_Status & DATA_ERR_INT_MASK )
	{
		MCI_DataErrorProcess();

		return;
	}

	if ( MCI_Status & DATA_END_INT_MASK )
	{
		MCI_DATA_END_InterruptService();

		return;
	}
	else if ( MCI_Status & FIFO_INT_MASK )
	{
		MCI_FIFOInterruptService();

		return;
	}
	else if ( MCI_Status & CMD_INT_MASK )
	{
		MCI_CmdProcess();

		return;
	}
}


/**
 * @}
 */



/** @addtogroup MCI_Public_Functions
 * @{
 */

/*********************************************************************//**
 * @brief 		Set MCI clock rate, during initialization phase < 400K
 *				during data phase < 20Mhz
 *
 * @param[in]	ClockRate Clock rate to be set
 *
 * @return 		None
 **********************************************************************/
void MCI_Set_MCIClock( uint32_t ClockRate )
{
	uint32_t i, ClkValue = 0;

	if ( ClockRate == MCI_SLOW_RATE )
	{
		/* slow clock */
		ClkValue |= MCLKDIV_SLOW;
	}
	else if (ClockRate == MCI_NORMAL_RATE)
	{
		/* normal clock */
		ClkValue |= MCLKDIV_NORMAL;
	}

	LPC_MCI->CLOCK &= ~(0xFF); /* clear clock divider */

	LPC_MCI->CLOCK |= (1 << 8)  | ClkValue;

	for ( i = 0; i < 0x10; i++ );	/* delay 3MCLK + 2PCLK before next write */

	return;
}


/**********************************************************************//**
 * @brief 		Set the Width to 1-bit Bus or 4-bit Bus
 *
 * @param[in]	width buswidth expected to set
 *
 * @return 		MCI_FUNC_OK in case of success
 *************************************************************************/
int32_t MCI_SetBusWidth( uint32_t width )
{
	uint32_t i;

	for ( i = 0; i < 0x10; i++ );	/* delay 3MCLK + 2PCLK  */

	if ( width == SD_1_BIT )
	{
		LPC_MCI->CLOCK &=  ~(1 << 11);	/* 1 bit bus */
	}
	else if ( width == SD_4_BIT )
	{
		LPC_MCI->CLOCK |=  (1 << 11);/* 4 bit bus */
	}

	if ( MCI_Acmd_SendBusWidth( BUS_WIDTH_4BITS ) != MCI_FUNC_OK )
	{
		return(MCI_FUNC_FAILED);
	}

	return MCI_FUNC_OK;
}


/************************************************************************//**
 * @brief 		Do initialization the MCI block as set its clock, registers,
 *				setup NVIC for interrupts, configure the pins used for MCI 
 *				function, do initialize the card in slot...
 *
 * @param[in]	powerActiveLevel the power level to activate the card in slot
 *
 * @return 		MCI_FUNC_OK in case of success
 ***************************************************************************/
int32_t MCI_Init(uint8_t powerActiveLevel )
{
	uint32_t i;

	MCI_CardType = MCI_CARD_UNKNOWN;

	// Following block of code added to ensure card VCC drops to zero
    // before card is initialized
  
   // Force all MCI control pins to basic I/O mode
   LPC_IOCON->P1_2  &= ~0x1F; /* SD_CLK @ P1.2 */
   LPC_IOCON->P1_3  &= ~0x1F; /* SD_CMD @ P1.3 */
   LPC_IOCON->P1_5  &= ~0x1F; /* SD_PWR @ P1.5 */
   LPC_IOCON->P1_6  &= ~0x1F; /* SD_DAT_0 @ P1.6 */
   LPC_IOCON->P1_7  &= ~0x1F; /* SD_DAT_1 @ P1.7 */
   LPC_IOCON->P1_11 &= ~0x1F; /* SD_DAT_2 @ P1.11 */
   LPC_IOCON->P1_12 &= 0x1F; /* SD_DAT_3 @ P1.12 */

   // Set all MCI pins to outputs
   LPC_GPIO1->DIR |= 0x18EC;
  
   // Force all pins low (except power control pin)
   LPC_GPIO1->CLR = 0x1000;
   LPC_GPIO1->CLR = 0x0800;
   LPC_GPIO1->CLR = 0x0080;
   LPC_GPIO1->CLR = 0x0040;
  
   LPC_GPIO1->SET = 0x0020;
  
   LPC_GPIO1->CLR = 0x0008;
   LPC_GPIO1->CLR = 0x0004;

   // Crude delay of 50ms at 120MHz
   for ( i = 0; i < 0x100000; i++ );

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

	if ( LPC_MCI->CLOCK & (1 << 8) )
	{
		LPC_MCI->CLOCK &= ~(1 << 8);
	}

	if ( LPC_MCI->POWER & 0x02 )
	{
		LPC_MCI->POWER = 0x00;
	}

	for ( i = 0; i < 0x1000; i++ );

	/* Disable all interrupts for now */
	LPC_MCI->MASK0 = 0;

	//SD_CLK
	PINSEL_ConfigPin(1, 2, 2);

	//SD_CMD
	PINSEL_ConfigPin(1, 3, 2);

	//SD_PWR
	PINSEL_ConfigPin(1, 5, 2);

	//SD_DAT_0
	PINSEL_ConfigPin(1, 6, 2);

	//SD_DAT_1
	PINSEL_ConfigPin(1, 7, 2);

	//SD_DAT_2
	PINSEL_ConfigPin(1, 11, 2);

	//SD_DAT_3
	PINSEL_ConfigPin(1, 12, 2);

	// SD_PWR is active high (follows the output of the SD Card interface block).
	if(powerActiveLevel == LOW_LVL)
	{
		LPC_SC->SCS &= ~ 0x08;//Becase on EA board SD_PWR is active low
	}
	else
	{
		LPC_SC->SCS |= 0x08;
	}

	//Setting for timeout problem
	LPC_MCI->DATATMR = 0x1FFFFFFF;

	/*set up clocking default mode, clear any registers as needed */
	LPC_MCI->COMMAND = 0;
	LPC_MCI->DATACTRL = 0;
	LPC_MCI->CLEAR = 0x7FF;		/* clear all pending interrupts */

	LPC_MCI->POWER = 0x02;		/* power up */
	while ( !(LPC_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(MCI_SLOW_RATE );

	LPC_MCI->POWER |= 0x01;		/* bit 1 is set already, from power up to power on */

	for ( i = 0; i < 0x2000; i++ );

	NVIC_EnableIRQ(MCI_IRQn);

	MCI_CardInit();

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

⌨️ 快捷键说明

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