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

📄 lpc177x_8x_mci.c

📁 LPC1788的USBHOST的FATFS移植
💻 C
📖 第 1 页 / 共 4 页
字号:
/**********************************************************************
* $Id$		lpc177x_8x_mci.c			2011-06-02
*//**
* @file		lpc177x_8x_mci.c
* @brief	Contains all functions support for MCI firmware library
*			on LPC177x_8x
* @version	1.0
* @date		02. June. 2011
* @author	NXP MCU SW Application Team
* 
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
*
***********************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**********************************************************************/

#include "lpc177x_8x.h"
#include "lpc_types.h"
#include "lpc177x_8x_mci.h"
#include "lpc177x_8x_gpdma.h"
#include "lpc177x_8x_clkpwr.h"
#include "debug_frmwrk.h"

#define DMA_MCI_SIZE				BLOCK_LENGTH

#define MCI_DMA_WRITE_CHANNEL		(0)
#define MCI_DMA_READ_CHANNEL		(1)

#define _SHIFT(x)						(1 << x)
#define _XSHIFT(x, y)					(x << y)

#define _SHIFT_(x)						(1 >> x)
#define _XSHIFT_(x, y)					(x >> y)


#define MCI_CARDSTATUS_READYFORDATA_P0S		(8)

#define MCI_CARDSTATUS_CURRENTSTATE_POS		(9)
#define MCI_CARDSTATUS_CURRENTSTATE_BMASK	(0x0F)

#define CARDSTATEOF(x)		(_XSHIFT(x, MCI_CARDSTATUS_CURRENTSTATE_POS) & MCI_CARDSTATUS_CURRENTSTATE_BMASK)

#define MCI_CMD8_VOLTAGESUPPLIED_POS		(8)
#define MCI_CMD8_VOLTAGESUPPLIED_BMASK		(0xFF)

#define MCI_CMD8_CHECKPATTERN_POS			(0)
#define MCI_CMD8_CHECKPATTERN_BMASK			(0xFF)

#define MCI_ACMD41_HCS_POS		(30)

#define MCI_OUTPUT_MODE_PUSHPULL		(0)
#define MCI_OUTPUT_MODE_OPENDRAIN		(1)

#define MCI_PWRCTRL_OPENDRAIN_POS		(6)
#define MCI_PWRCTRL_OPENDRAIN_NUMBIT	(1)
#define MCI_PWRCTRL_OPENDRAIN_BMASK		(0x01)

#define MCI_CID_MANUFACTURER_ID_WPOS		(24)	//in word 0
#define MCI_CID_MANUFACTURER_ID_WBMASK		(0xFF)

#define MCI_CID_OEMAPPLICATION_ID_WPOS		(8)		//in word 0
#define MCI_CID_OEMAPPLICATION_ID_WBMASK	(0xFFFF)

#define MCI_CID_PRODUCTNAME_ID_H_WPOS		(0)		//in word 0
#define MCI_CID_PRODUCTNAME_ID_H_WBMASK		(0xFF)

#define MCI_CID_PRODUCTNAME_ID_L_WPOS		(0)		//in word 1
#define MCI_CID_PRODUCTNAME_ID_L_WBMASK		(0xFFFFFFFF)

#define MCI_CID_PRODUCTREVISION_ID_WPOS		(24)	//in word 2
#define MCI_CID_PRODUCTREVISION_ID_WBMASK	(0xFF)

#define MCI_CID_PRODUCTSERIALNUM_ID_H_WPOS		(0)	//in word 2
#define MCI_CID_PRODUCTSERIALNUM_ID_H_WBMASK	(0x00FFFFFF)
#define MCI_CID_PRODUCTSERIALNUM_ID_L_WPOS		(24)	//in word 3
#define MCI_CID_PRODUCTSERIALNUM_ID_L_WBMASK	(0xFF)
#define MCI_CID_PRODUCTSERIALNUM_ID_WBMASK		(0xFFFFFFFF)

#define MCI_CID_RESERVED_ID_WPOS			(20)	//in word 3
#define MCI_CID_RESERVED_ID_WBMASK			(0x1F)

#define MCI_CID_MANUFACTURINGDATE_ID_WPOS	(8)	//in word 3
#define MCI_CID_MANUFACTURINGDATE_ID_WBMASK	(0x0FFF)

#define MCI_CID_CHECKSUM_ID_WPOS			(1)	//in word 3
#define MCI_CID_CHECKSUM_ID_WBMASK			(0x7F)

#define MCI_CID_UNUSED_ID_WPOS				(0)	//in word 3
#define MCI_CID_UNUSED_ID_WBMASK			(0x01)


volatile uint32_t MCI_Block_End_Flag = 0;

volatile uint32_t CardRCA;

volatile en_Mci_CardType MCI_CardType;

// Terminal Counter flag, Error Counter flag for Channel 0
uint32_t dmaWrCh_TermianalCnt, dmaWrCh_ErrorCnt;
uint32_t dmaRdCh_TermianalCnt, dmaRdCh_ErrorCnt;

uint32_t MCI_ReadFifo(uint32_t * dest);
uint32_t MCI_WriteFifo(uint32_t * src);


volatile uint8_t* dataSrcBlock;
volatile uint8_t* dataDestBlock;

volatile uint32_t txBlockCnt=0, rxBlockCnt=0;

/******************************************************************************
** Function name:		MCI_ReadFifo related
**
** Descriptions:
**
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
uint32_t MCI_ReadFifo(uint32_t * dest)
{
	//copy 8 words (32 bytes) from FIFO
	memcpy(dest, LPC_MCI->FIFO, 32);

	return 0;
}

/******************************************************************************
** Function name:		MCI_WriteFifo related
**
** Descriptions:
**
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
uint32_t MCI_WriteFifo(uint32_t * src)
{
	//copy 8 words (32 bytes) from FIFO
	memcpy(LPC_MCI->FIFO, src, 32);

	return 0;
}


/******************************************************************************
** Function name:		MCI_Interrupt related
**
** Descriptions:		MCI interrupt handler and related APIs
**
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
void MCI_TXEnable( void )
{
#if MCI_DMA_ENABLED
	LPC_MCI->MASK0 |= ((DATA_END_INT_MASK)|(ERR_TX_INT_MASK));	/* Enable TX interrupts only */
#else
	LPC_MCI->MASK0 |= ((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK));	/* FIFO TX interrupts only */
#endif

	return;
}
/*****************************************************************/

void MCI_TXDisable( void )
{
#if MCI_DMA_ENABLED
	LPC_MCI->MASK0 &= ~((DATA_END_INT_MASK)|(ERR_TX_INT_MASK));	/* Enable TX interrupts only */
#else
	LPC_MCI->MASK0 &= ~((FIFO_TX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_TX_INT_MASK));	/* FIFO TX interrupts only */
#endif

	return;
}

/*****************************************************************/
void MCI_RXEnable( void )
{
#if MCI_DMA_ENABLED
	LPC_MCI->MASK0 |= ((DATA_END_INT_MASK)|(ERR_RX_INT_MASK));	/* Enable RX interrupts only */
#else
	LPC_MCI->MASK0 |= ((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK));	/* FIFO RX interrupts only */
#endif

	return;
}

/*****************************************************************/

void MCI_RXDisable( void )
{
#if MCI_DMA_ENABLED
	LPC_MCI->MASK0 &= ~((DATA_END_INT_MASK)|(ERR_RX_INT_MASK));	/* Enable TX interrupts only */
#else
	LPC_MCI->MASK0 &= ~((FIFO_RX_INT_MASK)|(DATA_END_INT_MASK)|(ERR_RX_INT_MASK));	/* FIFO TX interrupts only */
#endif

	return;
}

/******************************************************************************
** Function name:		MCI_CheckStatus
**
** Descriptions:		MCI Check status before and after the block read and
**						write. Right after the block read and write, this routine
**						is important that, even the FIFO is empty, complete
**						block has been sent, but, data is still being written
**						to the card, this routine is to ensure that the data
**						has been written based on the state of the card, not
**						by the length being set.
**
** parameters:			None
** Returned value:		TRUE or FALSE
**
******************************************************************************/
uint32_t MCI_CheckStatus(void)
{
	uint32_t respValue, retval = MCI_FUNC_FAILED;

	while (1)
	{
		if (MCI_GetCardStatus(&respValue) != MCI_FUNC_OK)
		{
			break;
		}
		else
		{
			/* The only valid state is TRANS per MMC and SD state diagram.
			RCV state may be seen, but, it happens only when TX_ACTIVE or
			RX_ACTIVE occurs before the WRITE_BLOCK and READ_BLOCK cmds are
			being sent, which is not a valid sequence. */
			if(!(respValue & _SHIFT(MCI_CARDSTATUS_READYFORDATA_P0S)))
			{
				retval = MCI_FUNC_NOT_READY;
			}
			else if(CARDSTATEOF(respValue) != MCI_CARDSTATE_TRAN)
			{
				/* Should be in STANDBY state now and ready */
				retval = MCI_FUNC_ERR_STATE;
			}
			else
			{
				return MCI_FUNC_OK;
			}
		}
	}

	return retval;
}

/******************************************************************************
** Function name:		MCI_CmdProcess
**
** Descriptions:		Called by MCI interrupt handler
**						To simplify the process, for card initialization, the
**						CMD interrupts are disabled.
**
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
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;
}

/******************************************************************************
** Function name:		MCI_DataErrorProcess
**
** Descriptions:		Called by MCI interrupt handler
**						Process data error.
**
** parameters:			None
** Returned value:		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;
	}

	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 )
{
	uint32_t MCIStatus;

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

		return;
	}

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

		MCI_TXDisable();

		MCI_Block_End_Flag = 0;

		return;
	}

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

	}

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

	}

	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
	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 */
		{
			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)
		{
			rxBlockCnt = 0;
		}
	}
#endif

	return;
}

/*********************************************************************//**
 * @brief		GPDMA interrupt handler sub-routine
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void DMA_IRQHandler (void)
{
	// check GPDMA interrupt on channel 0
	if (GPDMA_IntGetStatus(GPDMA_STAT_INT, MCI_DMA_WRITE_CHANNEL))
	{
		//check interrupt status on channel 0
		// Check counter terminal status
		if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, MCI_DMA_WRITE_CHANNEL))
		{
			// Clear terminate counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, MCI_DMA_WRITE_CHANNEL);

			dmaWrCh_TermianalCnt++;
		}
		if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, MCI_DMA_WRITE_CHANNEL))
		{
			// Clear error counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, MCI_DMA_WRITE_CHANNEL);

			dmaWrCh_ErrorCnt++;
		}
	}
	else if (GPDMA_IntGetStatus(GPDMA_STAT_INT, MCI_DMA_READ_CHANNEL))
	{
		//check interrupt status on channel 0
		// Check counter terminal status
		if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, MCI_DMA_READ_CHANNEL))
		{
			// Clear terminate counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, MCI_DMA_READ_CHANNEL);

			dmaRdCh_TermianalCnt++;
		}
		if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, MCI_DMA_READ_CHANNEL))
		{
			// Clear error counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, MCI_DMA_READ_CHANNEL);

			dmaRdCh_ErrorCnt++;
		}
	}
}


/******************************************************************************
** Function name:		SDMMC_IRQHandler
**
** Descriptions:		MCI interrupt handler
**						The handler to handle the block data write and read
**						not for the commands.
**
** parameters:			None
** Returned value:		None
**
******************************************************************************/
void MCI_IRQHandler (void)
{
	uint32_t MCI_Status;

	MCI_Status = LPC_MCI->STATUS;

	/* handle MCI_STATUS interrupt */

⌨️ 快捷键说明

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