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

📄 mmc.c

📁 MMC driver for LPC21
💻 C
📖 第 1 页 / 共 4 页
字号:
	{
		i = mmc_send_cmd(MMC_GO_IDLE_STATE, 0, 40);

		SPI_8(0xff);

		if (i >= 0)
		{
			if (i == MMC_R1_IDLE_STATE) return mmc_ok;		// success!

			#ifdef mmc_debug
			mmc_show_r1("mmc error:", i);
			if (i == 0) WriteStr_uart0("mmc error: non-idle state\r\n");
			#endif
		}
		else
		{
			#ifdef mmc_debug
			WriteStr_uart0("mmc_idle_state_error\r\n");
			#endif
		}
	}

	// timeout/error

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

static int mmc_ready_state(void)
{	// put the MMC in ready state
	//
	// apparently this can take 100's of milliseconds! .. this is not our experience though

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;

	int i = mmc_send_cmd2(MMC_SEND_OP_COND, 0, mmc_info->spi_sclk_speed >> 10, true);

	#ifdef mmc_debug
	if (i < 0) WriteStr_uart0("mmc_ready_state_error\r\n");
	#endif

	return i;
}

static int mmc_set_crc(bool Enable)
{	// turn off/on CRC checking
	//
	// note: it's OFF by default

	int i;

	if (!Enable)
		i = mmc_send_cmd2(MMC_CRC_ON_OFF, 0, 5, true);
	else
		i = mmc_send_cmd2(MMC_CRC_ON_OFF, 1, 5, true);

	#ifdef mmc_debug
	if (i < 0) WriteStr_uart0("mmc_set_crc_error\r\n");
	#endif

	return i;
}

static int mmc_get_cid(void)
{	// read the MMC CID register

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int			i;
	_u8			b;
	_u8			*buf;
	_u8			buffer[16];
	#ifdef mmc_debug1
	char			s[48];
	#endif

	i = mmc_read_data(MMC_SEND_CID, 0, buffer, sizeof(buffer));
	if (i < 0)
	{	// time-out/error
		#ifdef mmc_debug
		WriteStr_uart0("mmc_get_cid_error 1\r\n");
		#endif

		return i;
	}

	#ifdef mmc_use_crc
	i = CheckCRC7(&buffer, sizeof(buffer));	// check the crc in the packet
	if (i < 0)
	{
		#ifdef mmc_debug
		WriteStr_uart0("mmc_get_cid_error 2\r\n");
		#endif

		return i;								// crc error
	}
	#endif

	// *******************************
	// extract the info from the data

	buf = (_u8*)&buffer;

	mmc_info->mid = *buf++;

	mmc_info->oid = *buf++;
	mmc_info->oid = (mmc_info->oid << 8) | *buf++;

	memcpy(mmc_info->pnm, buf, 7);
	mmc_info->pnm[7] = 0;
	buf += 7;

	b = *buf++;
	mmc_info->prv_ms = b >> 4;
	mmc_info->prv_ls = b & 0x0f;

	mmc_info->psn = *buf++;
	mmc_info->psn = (mmc_info->psn << 8) | *buf++;
	mmc_info->psn = (mmc_info->psn << 8) | *buf++;

	b = *buf++;
	mmc_info->mdt_month = b >> 4;
	mmc_info->mdt_year = b & 0x0f;

	b = *buf++;										// crc7

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

	#ifdef mmc_debug1

	WriteStr_uart0("\r\n");

	sprintf(s, "mmc manufacture id: %u\r\n", mmc_info->mid);
	WriteStr_uart0(s);

	sprintf(s, "mmc oem/application id: %u\r\n", mmc_info->oid);
	WriteStr_uart0(s);

	WriteStr_uart0("mmc product name: ");
	WriteStr_uart0(mmc_info->pnm);
	WriteStr_uart0("\r\n");

	sprintf(s, "mmc product revision: %u.%u\r\n", mmc_info->prv_ms, mmc_info->prv_ls);
	WriteStr_uart0(s);

	sprintf(s, "mmc serial number: %u\r\n", mmc_info->psn);
	WriteStr_uart0(s);

	sprintf(s, "mmc manufacture month-year: %u-%u\r\n", mmc_info->mdt_month, 1997 + mmc_info->mdt_year);
	WriteStr_uart0(s);

	#endif

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

	return mmc_ok;
}

static int mmc_get_csd(void)
{	// read the MMC CSD register

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int			i;
	_u8			b;
	_u8			*buf;
	_u8			buffer[16];
	#ifdef mmc_debug1
	char	s[48];
	#endif

	i = mmc_read_data(MMC_SEND_CSD, 0, buffer, sizeof(buffer));
	if (i < 0)
	{
		#ifdef mmc_debug
		WriteStr_uart0("mmc_get_csd_error 1\r\n");
		#endif

		return i;
	}

	#ifdef mmc_use_crc
	i = CheckCRC7(&buffer, sizeof(buffer));	// check the crc in the packet
	if (i < 0)
	{
		#ifdef mmc_debug
		WriteStr_uart0("mmc_get_csd_error 2\r\n");
		#endif

		return i;								// crc error
	}
	#endif

	// *******************************
	// extract the info from the data

	buf = (_u8*)&buffer;

	b = *buf++;
	mmc_info->csd_structure = b >> 6;
	mmc_info->prot = (b >> 2) & 0x0f;
	mmc_info->taac = *buf++;
	mmc_info->nsac = *buf++;
	mmc_info->tran_speed = *buf++;
	mmc_info->ccc = *buf++;
	b = *buf++;
	mmc_info->ccc = (mmc_info->ccc << 4) | (b >> 4);
	mmc_info->read_bl_len = b & 0x0f;
	b = *buf++;
	mmc_info->read_bl_partial = (b >> 7) & 0x01;
	mmc_info->write_blk_misalign = (b >> 6) & 0x01;
	mmc_info->read_blk_misalign = (b >> 5) & 0x01;
	mmc_info->dsr_imp = (b >> 4) & 0x01;
	mmc_info->c_size = b & 0x03;
   mmc_info->c_size = (mmc_info->c_size << 8) | *buf++;
	b = *buf++;
   mmc_info->c_size = (mmc_info->c_size << 2) | (b >> 6);
   mmc_info->vdd_r_curr_min = (b >> 3) & 0x07;
   mmc_info->vdd_r_curr_max = b & 0x07;
	b = *buf++;
   mmc_info->vdd_w_curr_min = (b >> 5) & 0x07;
   mmc_info->vdd_w_curr_max = (b >> 2) & 0x07;
   mmc_info->c_size_mult = b & 0x03;
	b = *buf++;
   mmc_info->c_size_mult = (mmc_info->c_size_mult << 1) | (b >> 7);
   mmc_info->erase_sector_size = (b >> 2) & 0x1f;
   mmc_info->erase_grp_size = b & 0x03;
	b = *buf++;
	mmc_info->erase_grp_size = (mmc_info->erase_grp_size << 3) | (b >> 5);
   mmc_info->wp_grp_size = b & 0x1f;
	b = *buf++;
   mmc_info->wp_grp_enable = (b >> 7);
   mmc_info->default_ecc = (b >> 5) & 0x03;
   mmc_info->r2w_factor = (b >> 2) & 0x07;
   mmc_info->write_bl_len = b & 0x03;
	b = *buf++;
	mmc_info->write_bl_len = (mmc_info->write_bl_len << 2) | (b >> 6);
	mmc_info->write_bl_partial = (b >> 5) & 0x01;
	b = *buf++;
	mmc_info->copy = (b >> 6) & 0x01;
	mmc_info->perm_write_protect = (b >> 5) & 0x01;
	mmc_info->tmp_write_protect = (b >> 4) & 0x01;
	mmc_info->eec = b & 0x03;
	b = *buf++;				// crc7

	// ************************************************************
	// calculate the size of the MMC ..
	//   card sectors
	//   card sector size (in bytes)
	//   card size (in bytes)

	mmc_info->size_sector = 1L << mmc_info->read_bl_len;

	mmc_info->size_bytes = mmc_info->c_size + 1;
	mmc_info->size_bytes <<= mmc_info->c_size_mult + 2;
	mmc_info->size_sectors = mmc_info->size_bytes;
	mmc_info->size_bytes <<= mmc_info->read_bl_len;

	// ************************************************************
	// calculate the maximum transfer speed (bits/s) (spi/ssp sclk speed) we can use for this MMC

	mmc_info->max_transfer_speed = (_u32)mmc_calc_mantissa((mmc_info->tran_speed >> 3) & 0x0f);	// mantissa
	if (mmc_info->max_transfer_speed > 0)
	{
		b = mmc_info->tran_speed & 0x07;			// exponent
		switch (b)
		{
			case 0	:	mmc_info->max_transfer_speed *= 10000;
							break;
			case 1	:	mmc_info->max_transfer_speed *= 100000;
							break;
			case 2	:	mmc_info->max_transfer_speed *= 1000000;
							break;
			case 3	:	mmc_info->max_transfer_speed *= 10000000;
							break;
			default	:	mmc_info->max_transfer_speed = 0;
							break;
		}
	}

	// ************************************************************
	// calculate the 'maximum' time-out values (in micro-seconds)

	mmc_info->max_read_timeout_us = (_u32)mmc_calc_mantissa((mmc_info->taac >> 3) & 0x0f);	// mantissa
	if (mmc_info->max_read_timeout_us > 0)
	{
		b = mmc_info->taac & 0x07;			// exponent
		switch (b)
		{
			case 0	:	mmc_info->max_read_timeout_us = 1;
							break;
			case 1	:	mmc_info->max_read_timeout_us = 1;
							break;
			case 2	:	mmc_info->max_read_timeout_us = 1;
							break;
			case 3	:	//	mmc_info->max_read_timeout_us *= 1;
							break;
			case 4	:	mmc_info->max_read_timeout_us *= 10;
							break;
			case 5	:	mmc_info->max_read_timeout_us *= 100;
							break;
			case 6	:	mmc_info->max_read_timeout_us *= 1000;
							break;
			case 7	:	mmc_info->max_read_timeout_us *= 10000;
							break;
			default	:	mmc_info->max_read_timeout_us = 0;
							break;
		}
	}

	if (mmc_info->max_read_timeout_us < 1) mmc_info->max_read_timeout_us = 100000;	// default to 100ms

	if (mmc_info->r2w_factor <= 5)
		mmc_info->max_write_timeout_us = mmc_info->max_read_timeout_us << mmc_info->r2w_factor;
	else
		mmc_info->max_write_timeout_us = mmc_info->max_read_timeout_us << 5;

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

	#ifdef mmc_debug1

	WriteStr_uart0("\r\n");

	sprintf(s, "mmc_csd_structure: %u\r\n", mmc_info->csd_structure);
	WriteStr_uart0(s);

	sprintf(s, "mmc_prot: %u\r\n", mmc_info->prot);
	WriteStr_uart0(s);

	sprintf(s, "mmc_taac: %0.2X (%u %u)\r\n", mmc_info->taac, (mmc_info->taac >> 3) & 0x0f, mmc_info->taac & 0x07);
	WriteStr_uart0(s);

	sprintf(s, "mmc_nsac: %u (%u)\r\n", mmc_info->nsac, mmc_info->nsac * 100);
	WriteStr_uart0(s);

	sprintf(s, "mmc_tran_speed: %0.2X (%u %u) (%u)\r\n", mmc_info->tran_speed, (mmc_info->tran_speed >> 3) & 0x0f, mmc_info->tran_speed & 0x07, b = mmc_info->tran_speed);
	WriteStr_uart0(s);

	sprintf(s, "mmc_ccc: %0.4X\r\n", mmc_info->ccc);
	WriteStr_uart0(s);

	sprintf(s, "mmc_read_bl_len: %u (%u)\r\n", mmc_info->read_bl_len, 1L << mmc_info->read_bl_len);
	WriteStr_uart0(s);

	sprintf(s, "mmc_read_bl_partial: %u\r\n", mmc_info->read_bl_partial);
	WriteStr_uart0(s);

	sprintf(s, "mmc_write_blk_misalign: %u\r\n", mmc_info->write_blk_misalign);
	WriteStr_uart0(s);

	sprintf(s, "mmc_read_blk_misalign: %u\r\n", mmc_info->read_blk_misalign);
	WriteStr_uart0(s);

	sprintf(s, "mmc_dsr_imp: %u\r\n", mmc_info->dsr_imp);
	WriteStr_uart0(s);

	sprintf(s, "mmc_c_size: %u\r\n", mmc_info->c_size);
	WriteStr_uart0(s);

	sprintf(s, "mmc_vdd_r_curr_min: %u\r\n", mmc_info->vdd_r_curr_min);
	WriteStr_uart0(s);

	sprintf(s, "mmc_vdd_r_curr_max: %u\r\n", mmc_info->vdd_r_curr_max);
	WriteStr_uart0(s);

	sprintf(s, "mmc_vdd_w_curr_min: %u\r\n", mmc_info->vdd_w_curr_min);
	WriteStr_uart0(s);

	sprintf(s, "mmc_vdd_w_curr_max: %u\r\n", mmc_info->vdd_w_curr_max);
	WriteStr_uart0(s);

	sprintf(s, "mmc_c_size_mult: %u (%u)\r\n", mmc_info->c_size_mult, 1L << mmc_info->c_size_mult);
	WriteStr_uart0(s);

	sprintf(s, "mmc_erase_sector_size: %u (%u)\r\n", mmc_info->erase_sector_size, mmc_info->erase_sector_size + 1);
	WriteStr_uart0(s);

	sprintf(s, "mmc_erase_grp_size: %u (%u)\r\n", mmc_info->erase_grp_size, mmc_info->erase_grp_size + 1);
	WriteStr_uart0(s);

	sprintf(s, "mmc_wp_grp_size: %u (%u)\r\n", mmc_info->wp_grp_size, mmc_info->wp_grp_size + 1);
	WriteStr_uart0(s);

	sprintf(s, "mmc_wp_grp_enable: %u\r\n", mmc_info->wp_grp_enable);
	WriteStr_uart0(s);

	sprintf(s, "mmc_default_ecc: %u\r\n", mmc_info->default_ecc);
	WriteStr_uart0(s);

	sprintf(s, "mmc_r2w_factor: %u (%u)\r\n", mmc_info->r2w_factor, 1L << mmc_info->r2w_factor);
	WriteStr_uart0(s);

	sprintf(s, "mmc_write_bl_len: %u (%u)\r\n", mmc_info->write_bl_len, 1L << mmc_info->write_bl_len);
	WriteStr_uart0(s);

	sprintf(s, "mmc_write_bl_partial: %u\r\n", mmc_info->write_bl_partial);
	WriteStr_uart0(s);

	sprintf(s, "mmc_copy: %u\r\n", mmc_info->copy);
	WriteStr_uart0(s);

	sprintf(s, "mmc_perm_write_protect: %u\r\n", mmc_info->perm_write_protect);
	WriteStr_uart0(s);

	sprintf(s, "mmc_tmp_write_protect: %u\r\n", mmc_info->tmp_write_protect);
	WriteStr_uart0(s);

	sprintf(s, "mmc_eec: %u\r\n", mmc_info->eec);
	WriteStr_uart0(s);

	WriteStr_uart0("\r\n");

	sprintf(s, "mmc_size_bytes: %u\r\n", mmc_info->size_bytes);
	WriteStr_uart0(s);
	sprintf(s, "mmc_size_sector: %u\r\n", mmc_info->size_sector);
	WriteStr_uart0(s);
	sprintf(s, "mmc_size_sectors: %u\r\n", mmc_info->size_sectors);
	WriteStr_uart0(s);
	sprintf(s, "mmc_max_transfer_speed: %ubps\r\n", mmc_info->max_transfer_speed);
	WriteStr_uart0(s);
	sprintf(s, "mmc_max_read_timeout: %uus (%uus typical)\r\n", mmc_info->max_read_timeout_us, mmc_info->max_read_timeout_us / 10);
	WriteStr_uart0(s);
	sprintf(s, "mmc_max_write_timeout: %uus (%uus typical)\r\n", mmc_info->max_write_timeout_us, mmc_info->max_write_timeout_us / 10);
	WriteStr_uart0(s);

	#endif

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

	return mmc_ok;
}

static int mmc_get_ocr(void)
{	// read the MMC OCR register
	//
	// note: not all MMC/SD's support this command when in SPI mode (but some do) .. worth a go though!

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int			i;
	_u8			b;
	#ifdef mmc_debug1
	char			s[48];
	#endif

	i = mmc_send_cmd2(MMC_READ_OCR, 0, 5, false);	// send command
	if (i < 0)
	{
		#ifdef mmc_debug
		WriteStr_uart0("mmc_get_ocr_error\r\n");
		#endif

		return i;
	}

	#ifdef mmc_debug1
	WriteStr_uart0("mmc_ocr:");
	#endif

	mmc_info->ocr = 0;

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

		b = SPI_8(0xff);										// read data byte
		mmc_info->ocr = (mmc_info->ocr << 8) | b;		// save data byte

		#ifdef mmc_debug1
		sprintf(s, " %0.2X", b);
		WriteStr_uart0(s);
		#endif
	}

	SPI_8(0xff);

	#ifdef mmc_debug1
	WriteStr_uart0("\r\n");

	if (mmc_info->ocr & Bit31) WriteStr_uart0("mmc ocr: BUSY\r\n");
	if (mmc_info->ocr & Bit23) WriteStr_uart0("mmc ocr: 3.5V - 3.6V\r\n");
	if (mmc_info->ocr & Bit22) WriteStr_uart0("mmc ocr: 3.4V - 3.5V\r\n");
	if (mmc_info->ocr & Bit21) WriteStr_uart0("mmc ocr: 3.3V - 3.4V\r\n");
	if (mmc_info->ocr & Bit20) WriteStr_uart0("mmc ocr: 3.2V - 3.3V\r\n");
	if (mmc_info->ocr & Bit19) WriteStr_uart0("mmc ocr: 3.1V - 3.2V\r\n");
	if (mmc_info->ocr & Bit18) WriteStr_uart0("mmc ocr: 3.0V - 3.1V\r\n");
	if (mmc_info->ocr & Bit17) WriteStr_uart0("mmc ocr: 2.9V - 3.0V\r\n");
	if (mmc_info->ocr & Bit16) WriteStr_uart0("mmc ocr: 2.8V - 2.9V\r\n");
	if (mmc_info->ocr & Bit15) WriteStr_uart0("mmc ocr: 2.7V - 2.8V\r\n");
	if (mmc_info->ocr & Bit14) WriteStr_uart0("mmc ocr: 2.6V - 2.7V\r\n");
	if (mmc_info->ocr & Bit13) WriteStr_uart0("mmc ocr: 2.5V - 2.6V\r\n");
	if (mmc_info->ocr & Bit12) WriteStr_uart0("mmc ocr: 2.4V - 2.5V\r\n");
	if (mmc_info->ocr & Bit11) WriteStr_uart0("mmc ocr: 2.3V - 2.4V\r\n");
	if (mmc_info->ocr & Bit10) WriteStr_uart0("mmc ocr: 2.2V - 2.3V\r\n");
	if (mmc_info->ocr & Bit9) WriteStr_uart0("mmc ocr: 2.1V - 2.2V\r\n");
	if (mmc_info->ocr & Bit8) WriteStr_uart0("mmc ocr: 2.0V - 2.1V\r\n");

	#endif

	return mmc_ok;
}

static int mmc_set_blocklen(_u32 size_bytes)
{	// set the data block length (used when reading/writing sector(s)

	T_MMC_Info	*mmc_info = (T_MMC_Info*)&MMC_Info;
	int			i;

	i = mmc_send_cmd2(MMC_SET_BLOCKLEN, size_bytes, 5, true);	// send command
	if (i < 0) return i;														// error

	mmc_info->last_block_len = size_bytes;								// remember what we have set the block length too - saves doing it again if no change

	return mmc_ok;
}

// *********************************************
// public routines

bool mmc_inserted(void)
{	// test the card slot switch state ..
	//
	// a physical switch on the MMC card slot that makes/breaks depending on whether card is inserted or not
	//
	// return TRUE if the MMC appears to be inserted, elese return FALSE

	#ifdef mmc_use_switch

	if (MMC_SWITCH_PIN & MMC_SWITCH_BIT)
		return false;								// card not inserted (switch is not pulling the pin down to gnd)
	else
		return true;								// card inserted

	#else

	return true;									// not monitoring the card slot switch

	#endif
}

void mmc_deselect(void)
{	// de-chip-select the MMC

	register _u8	b = 0xff;
	register int	i;
	#ifdef mmc_debug1
	char				s[24];
	#endif

	#ifdef mmc_debug1
	WriteStr_uart0("\r\nmmc_send:");
	#endif

	for (i = 10; i > 0; i--)
	{
		if (!mmc_inserted()) break;			// MMC not inserted

		SPI_8(b);

		#ifdef mmc_debug1
		sprintf(s, " %0.2X", b);
		WriteStr_uart0(s);
		#endif
	}

⌨️ 快捷键说明

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