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

📄 mmc.c

📁 MMC driver for LPC21
💻 C
📖 第 1 页 / 共 4 页
字号:
		case MMC_SEND_OP_COND				:	WriteStr_uart0("MMC_SEND_OP_COND");
														break;
		case MMC_ALL_SEND_CID				:	WriteStr_uart0("MMC_ALL_SEND_CID");
														break;
		case MMC_SET_RELATIVE_ADDR			:	WriteStr_uart0("MMC_SET_RELATIVE_ADDR");
														break;
		case MMC_SWITCH						:	WriteStr_uart0("MMC_SWITCH");
														break;
		case MMC_SEND_CSD						:	WriteStr_uart0("MMC_SEND_CSD");
														break;
		case MMC_SEND_CID						:	WriteStr_uart0("MMC_SEND_CID");
														break;
		case MMC_READ_DAT_UNTIL_STOP		:	WriteStr_uart0("MMC_READ_DAT_UNTIL_STOP");
														break;
		case MMC_STOP_TRANSMISSION			:	WriteStr_uart0("MMC_STOP_TRANSMISSION");
														break;
		case MMC_SEND_STATUS					:	WriteStr_uart0("MMC_SEND_STATUS");
														break;
		case MMC_GO_INACTIVE_STATE			:	WriteStr_uart0("MMC_GO_INACTIVE_STATE");
														break;
		case MMC_SET_BLOCKLEN				:	WriteStr_uart0("MMC_SET_BLOCKLEN");
														break;
		case MMC_READ_SINGLE_BLOCK			:	WriteStr_uart0("MMC_READ_SINGLE_BLOCK");
														break;
		case MMC_READ_MULTIPLE_BLOCK		:	WriteStr_uart0("MMC_READ_MULTIPLE_BLOCK");
														break;
		case MMC_WRITE_DAT_UNTIL_STOP		:	WriteStr_uart0("MMC_WRITE_DAT_UNTIL_STOP");
														break;
		case MMC_SET_BLOCK_COUNT			:	WriteStr_uart0("MMC_SET_BLOCK_COUNT");
														break;
		case MMC_WRITE_BLOCK					:	WriteStr_uart0("MMC_WRITE_BLOCK");
														break;
		case MMC_WRITE_MULTIPLE_BLOCK		:	WriteStr_uart0("MMC_WRITE_MULTIPLE_BLOCK");
														break;
		case MMC_PROGRAM_CSD					:	WriteStr_uart0("MMC_PROGRAM_CSD");
														break;
		case MMC_SET_WRITE_PROT				:	WriteStr_uart0("MMC_SET_WRITE_PROT");
														break;
		case MMC_CLR_WRITE_PROT				:	WriteStr_uart0("MMC_CLR_WRITE_PROT");
														break;
		case MMC_SEND_WRITE_PROT			:	WriteStr_uart0("MMC_SEND_WRITE_PROT");
														break;
		case MMC_TAG_SECTOR_START			:	WriteStr_uart0("MMC_TAG_SECTOR_START");
														break;
		case MMC_TAG_SECTOR_END				:	WriteStr_uart0("MMC_TAG_SECTOR_END");
														break;
		case MMC_UNTAG_SECTOR				:	WriteStr_uart0("MMC_UNTAG_SECTOR");
														break;
		case MMC_TAG_ERASE_GROUP_START	:	WriteStr_uart0("MMC_TAG_ERASE_GROUP_START");
														break;
		case MMC_TAG_ERARE_GROUP_END		:	WriteStr_uart0("MMC_TAG_ERARE_GROUP_END");
														break;
		case MMC_UNTAG_ERASE_GROUP			:	WriteStr_uart0("MMC_UNTAG_ERASE_GROUP");
														break;
		case MMC_ERASE							:	WriteStr_uart0("MMC_ERASE");
														break;
		case MMC_LOCK_UNLOCK					:	WriteStr_uart0("MMC_LOCK_UNLOCK");
														break;
		case MMC_APP_CMD						:	WriteStr_uart0("MMC_APP_CMD");
														break;
		case MMC_GEN_CMD						:	WriteStr_uart0("MMC_GEN_CMD");
														break;
		case MMC_READ_OCR						:	WriteStr_uart0("MMC_READ_OCR");
														break;
		case MMC_CRC_ON_OFF					:	WriteStr_uart0("MMC_CRC_ON_OFF");
														break;
		default									:	WriteStr_uart0("MMC_UNKNOWN_COMMAND ");
														sprintf(s, "[%u]", cmd);
														WriteStr_uart0(s);
														break;
	}
	WriteStr_uart0(" ..");
	#endif

	#ifdef mmc_use_crc
	crc = 0;																				// initialize the crc
	#endif

//	memset(&cmd_buf, 0, sizeof(cmd_buf));

	cmd_buf[0] = 0x40 | cmd;
	cmd_buf[1] = arg >> 24;
	cmd_buf[2] = arg >> 16;
	cmd_buf[3] = arg >> 8;
	cmd_buf[4] = arg >> 0;

	for (i = 0; i < sizeof(cmd_buf) - 1; i++)
	{
		b = cmd_buf[i];										// get command byte

		SPI_SendByte(b);										// send command byte

		#ifdef mmc_use_crc
		crc = mmc_update_crc7(crc, b);					// calculate the crc while the byte is being sent
		#endif

		b = SPI_WaitForTxGetRx();							// wait for the byte to be sent
	}

	#ifdef mmc_use_crc
	crc = (crc << 1) | 0x01;
	#else
	crc = 0xff;
	if (cmd == MMC_GO_IDLE_STATE) crc = 0x95;
	#endif
	cmd_buf[sizeof(cmd_buf) - 1] = crc;					// the calculated crc byte

	SPI_SendByte(crc);										// send command crc byte

	#ifdef mmc_debug1
	for (i = 0; i < sizeof(cmd_buf); i++)
	{
		sprintf(s, " %02X", cmd_buf[i]);
		WriteStr_uart0(s);
	}
	#endif

	#ifdef mmc_debug
	WriteStr_uart0("\r\n");
	#endif

	b = SPI_WaitForTxGetRx();								// wait for crc byte to be sent

	return mmc_get_response(0xff, false, res_time);	// wait for response (ie, anything but a 0xff)
}

static int mmc_send_cmd2(_u8 cmd, _u32 arg, int attempts, bool stuff_byte)
{
	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int			i, j;
	#ifdef mmc_debug
	char			s[48];
	#endif

	if (attempts < 1) attempts = 1;

	#ifdef mmc_debug
	sprintf(s, "\r\nmax attempts: %u ..\r\n", j);
	WriteStr_uart0(s);
	#endif

	for (j = attempts; j > 0; j--)
	{
		i = mmc_send_cmd(cmd, arg, mmc_info->spi_sclk_speed >> 13);		// send command - monitor next 'nn' bytes for a non 0xff byte
		if (i < 0) continue;									// time-out/error

		if (stuff_byte) SPI_8(0xff);						// stuff byte

		if (i == 0x00) return mmc_ok;						// success!

		if (!stuff_byte) SPI_8(0xff);						// stuff byte

		#ifdef mmc_debug
		mmc_show_r1("mmc error:", i);
		#endif
	}

	// timeout/error

	if (i < 0)
		return i;
	else
		return mmc_err_fail;
}

static int mmc_get_status(void)
{	// read the MMC status register (R1 & R2)

	int	i;
	_u8	r1, r2;
	#ifdef mmc_debug
	char	s[48];
	#endif

	#ifdef mmc_debug
	WriteStr_uart0("\r\n");
	#endif

	i = mmc_send_cmd(MMC_SEND_STATUS, 0, 40);			// send command
	if (i < 0)
	{	// time-out/error
		#ifdef mmc_debug
		WriteStr_uart0("mmc_get_status_error\r\n");
		#endif

		return i;
	}

	r1 = (_u8)i;												// save R1 result
	r2 = SPI_8(0xff);											// read R2 result

	SPI_8(0xff);

	#ifdef mmc_debug1
	sprintf(s, "mmc_res: %0.2X\r\n", r2);
	WriteStr_uart0(s);
	#endif

	#ifdef mmc_debug
	sprintf(s, "mmc status .. R1: %0.2X .. R2: %0.2X\r\n", r1, r2);
	WriteStr_uart0(s);
	mmc_show_r1("mmc status:", r1);
	mmc_show_r2("mmc status:", r2);
	#endif

	return (((int)r2 << 8) | r1);							// return the 2 status bytes as a word
}

static int mmc_write_data(_u8 cmd, _u32 arg, void *buffer, int data_length)
{	// write a block of data to the MMC (registers, sectors etc)

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int	i;
	#ifdef mmc_use_crc
	_u16	crc;
	#endif
	_u16	w;
	_u8	b;
	_u8	*buf;
	#ifdef mmc_debug1
	int	j = 0;
	char	s[48];
	#endif

	if (!mmc_inserted()) return mmc_err_not_inserted;			// mmc not inserted
	if (data_length < 1) return mmc_err_invalid_data_size;	// hmmmm

	// **********************
	// get current status before we attempt the data write - just to check the MMC is in a ready state

	w = mmc_get_status();
	if (w != 0)
	{
		#ifdef mmc_debug
		WriteStr_uart0("mmc_write_data_error 1\r\n");
		#endif

		return mmc_err_invalid_state;
	}

	// **********************
	// send command

	i = mmc_send_cmd2(cmd, arg, 5, false);			// send command
	if (i < 0)
	{	// time-out/error
		#ifdef mmc_debug
		WriteStr_uart0("mmc_write_data_error 2\r\n");
		#endif

		return i;
	}

	// *********************
	// send data token

	#ifdef mmc_debug1
	sprintf(s, "mmc_send: %0.2X (data token)\r\n", MMC_STRT_SINGLE_BLK_WR);
	WriteStr_uart0(s);
	#endif

	b = SPI_8(MMC_STRT_SINGLE_BLK_WR);					// send data token byte

	#ifdef mmc_debug1
	sprintf(s, "mmc_res: %0.2X\r\n", b);
	WriteStr_uart0(s);
	#endif

	// *********************
	// write data to MMC

	#ifdef mmc_use_crc
	crc = 0;														// init our crc
	#endif

	buf = (_u8*)buffer;
	for (i = data_length; i > 0; i--)
	{
//		if (!mmc_inserted()) return mmc_err_not_inserted;	// mmc not inserted

		b = *buf++;												// get data byte

		SPI_SendByte(b);										// send the data byte

		#ifdef mmc_use_crc
		crc = mmc_update_crc16(crc, b);					// calculate our crc while the byte is being sent
		#endif

		#ifdef mmc_debug1
		if (j <= 0)
		{
			WriteStr_uart0("mmc_send:");
			j = 0;
		}
		sprintf(s, " %0.2X", b);
		WriteStr_uart0(s);
		j++;
		if (j >= 32)
		{
			WriteStr_uart0("\r\n");
			j = 0;
		}
		#endif

		b = SPI_WaitForTxGetRx();							// wait for byte to be sent and get rx'ed byte

		if (b != 0xff)
		{	// error ????

		}
	}

	#ifdef mmc_debug1
	if (j > 0)
	{
		WriteStr_uart0("\r\n");
		j = 0;
	}
	#endif

	#ifdef mmc_use_crc
	w = crc;														// proper crc word
	#else
	w = 0xffff;													// blank crc word
	#endif

	#ifdef mmc_debug1
	sprintf(s, "mmc_send: %0.2X %0.2X (crc)\r\n", w >> 8, w & 0x00ff);
	WriteStr_uart0(s);
	#endif

	w = SPI_16(w);												// send crc word

	// *********************
	// get response

   i = mmc_get_response(0xff, false, mmc_info->spi_sclk_speed >> 9);	// wait for a non 0xff byte
																							// wait for upto 15ms
	i = (i >> 1) & 0x07;
	#ifdef mmc_debug
	switch (i)
	{
		case MMC_DR_ACCEPT					:	WriteStr_uart0("(Data accepted)\r\n");
														break;
		case MMC_DR_REJECT_CRC				:	WriteStr_uart0("(Data rejected due to a CRC error)\r\n");
														break;
		case MMC_DR_REJECT_WRITE_ERROR	:	WriteStr_uart0("(Data Rejected due to a Write Error)\r\n");
														break;
		default									:	WriteStr_uart0("(Unknown write data response)\r\n");
														break;
	}
	#endif

	if (i != MMC_DR_ACCEPT)
	{ // error
		SPI_8(0xff);

		#ifdef mmc_debug
		WriteStr_uart0("mmc write data error 3\r\n");
		#endif

		return mmc_err_write;
	}

	// *********************
	// wait until MMC has finished writing the data.
	// we are waiting for the mmc/sd to write the data to it's NAND flash that we sent to it's internal buffer

//   i = mmc_get_response(0x00, false, mmc_info->spi_sclk_speed >> 4);	// wait for a non 0x00 byte
//																							// wait for upto 500ms
   i = mmc_get_response(0x00, false, mmc_info->max_write_timeout_count);	// wait for a non 0x00 byte
	SPI_8(0xff);
	if (i < 0 || i == 0x00)
	{	// time out/card not inserted

		#ifdef mmc_debug
		if (i == 0x00)
			WriteStr_uart0("mmc_write_data_error time-out\r\n");
		else
			WriteStr_uart0("mmc_write_data_error 4\r\n");
		#endif

		return mmc_err_write;
	}

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

	return mmc_ok;
}

static int mmc_read_data(_u8 cmd, _u32 arg, void *buffer, int data_length)
{	// read data from the MMC (registers, sectors etc)

	T_MMC_Info		*mmc_info = (T_MMC_Info*)&MMC_Info;
	register int	i;
	register _u8	b1;
	register _u8	*buf;
	_u16				crc2, w;
	#ifdef mmc_use_crc
	register _u16	crc1;
	#endif
	#ifdef mmc_debug
	char				s[56];
	#ifdef mmc_debug1
	int				j = 0;
	#endif
	#endif


	if (!mmc_inserted()) return mmc_err_not_inserted;				// mmc not inserted
	if (data_length <= 0) return mmc_err_invalid_data_size;		// hmmmm

	// **********************
	// get current status before we start a read off

	w = mmc_get_status();
	if (w != 0)
	{
		#ifdef mmc_debug
		WriteStr_uart0("mmc_read_data_error 1\r\n");
		#endif

		return mmc_err_invalid_state;
	}

	// **********************
	// send command

	i = mmc_send_cmd2(cmd, arg, 5, false);				// send command
	if (i < 0)
	{	// time-out/error
		#ifdef mmc_debug
		WriteStr_uart0("mmc_read_data_error 2\r\n");
		#endif

		return i;
	}

	// **********************
	// wait for data token.
	// we are waiting for the mmc/sd to read the sector data from it's NAND flash into it's own internal buffer.

//   i = mmc_get_response(0xff, false, mmc_info->spi_sclk_speed >> 5);		// wait for a non 0xff byte
//																								// wait for upto 250ms
   i = mmc_get_response(0xff, false, mmc_info->max_read_timeout_count);	// wait for a non 0xff byte
	if (i != MMC_SINGLE_BLK_RD)
	{	// timeout/error

		SPI_8(0xff);

		#ifdef mmc_debug
		if (i >= 0)
		{
			if (i & MMC_DE_MISALIGN) WriteStr_uart0("mmc MISALIGN\r\n");
			if (i & MMC_DE_ADDR_OUT_OF_RANGE) WriteStr_uart0("mmc ADDR OUT-OF_RANGE\r\n");
			if (i & MMC_DE_CARD_EEC_FAIL) WriteStr_uart0("mmc CARD ECC FAIL\r\n");
			if (i & MMC_DE_CARD_ERROR) WriteStr_uart0("mmc CARD ERROR\r\n");
			if (i & MMC_DE_EX_ERROR) WriteStr_uart0("mmc EX ERROR\r\n");
		}
		WriteStr_uart0("mmc_read_data_error 3\r\n");
		#endif

		if (i < 0)
			return i;
		else
			return mmc_err_read;
	}

	// **********************
	// read the data out of the mmc/sd

	#ifdef mmc_use_crc
	crc1 = 0;													// init our crc
	#endif

	buf = (_u8*)buffer;

	SPI_SendByte(0xff);										// send a null byte

	for (i = data_length; i > 0; i--)
	{
//		if (!mmc_inserted()) return mmc_err_not_inserted;	// mmc not inserted

//		while (!(S0SPSR & S0SPSR_SPIF));					// wait for byte to be sent
//		b1 = S0SPDR;											// get the rx'ed byte
		b1 = SPI_WaitForTxGetRx();							// wait for byte to be sent and get rx'ed byte

//		S0SPDR = 0xff;											// send byte
		SPI_SendByte(0xff);									// send a null byte

		*buf++ = b1;											// save rx'ed data byte

		#ifdef mmc_use_crc
		crc1 = mmc_update_crc16(crc1, b1);				// calculate our crc while the byte is being sent
		#endif

		#ifdef mmc_debug1
		if (j <= 0)
		{
			WriteStr_uart0("mmc_read:");
			j = 0;
		}
		sprintf(s, " %0.2X", b1);
		WriteStr_uart0(s);
		j++;
		if (j >= 32)
		{
			WriteStr_uart0("\r\n");
			j = 0;
		}
		#endif
	}

	#ifdef mmc_debug1
	if (j > 0) WriteStr_uart0("\r\n");
	#endif

	crc2 = (_u16)SPI_WaitForTxGetRx() << 8;			// wait for byte to be sent and get rx'ed byte
	crc2 |= (_u16)SPI_8(0xff);							 // send byte, wait for it to be sent and get rx'ed byte

	#ifdef mmc_debug1
	sprintf(s, "mmc_read: %0.2X %0.2X (crc)\r\n", crc2 >> 8, crc2 & 0x00ff);
	WriteStr_uart0(s);
	#endif

	b1 = SPI_8(0xff);

	#ifdef mmc_use_crc
	if (crc1 != crc2)
	{	// crc mismatch

		#ifdef mmc_debug
		sprintf(s, "mmc crc16 error .. our crc: %0.4X   there crc: %0.4X\r\n", crc1, crc2);
		WriteStr_uart0(s);
		#endif

		return mmc_err_crc;
	}
	#endif

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

	return mmc_ok;
}

static int mmc_idle_state(void)
{	// put the MMC in idle state

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int			i, j;
	#ifdef mmc_debug
	char			s[48];
	#endif

	j = mmc_info->spi_sclk_speed >> 11;
	if (j < 1) j = 1;

	#ifdef mmc_debug
	sprintf(s, "\r\nmax attempts: %u\r\n", j);
	WriteStr_uart0(s);
	#endif

	for ( ; j > 0; j--)

⌨️ 快捷键说明

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