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

📄 flash.c

📁 嵌入式ARM的一些源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			info->protect[i] = 0;
		} else if (flag & FLAG_PROTECT_SET) {
			info->protect[i] = 1;
		}
		if (info->protect[i]) {
			rc = 1;
		}
	}
	return (rc);
}


/*-----------------------------------------------------------------------
 */
void
flash_print_info(flash_info_t *info)
{
	int i;

	if (info->flash_id == FLASH_UNKNOWN) {
		printf ("missing or unknown FLASH type\n");
		return;
	}

	switch (info->flash_id & FLASH_VENDMASK) {
	case FLASH_MAN_INTEL:	printf ("INTEL ");		break;
	default:		printf ("Unknown Vendor ");	break;
	}

	switch (info->flash_id & FLASH_TYPEMASK) {
	case FLASH_28F008S5:	printf ("28F008S5\n");
				break;
	default:		printf ("Unknown Chip Type\n");
				break;
	}

	printf ("  Size: %ld MB in %d Sectors\n",
		info->size >> 20, info->sector_count);

	printf ("  Sector Start Addresses:");
	for (i=0; i<info->sector_count; ++i) {
		if ((i % 4) == 0)
			printf ("\n   ");
		printf (" %2d - %08lX%s", i,
			info->start[i],
			info->protect[i] ? " (RO)" : "     "
		);
	}
	printf ("\n");
}

/*-----------------------------------------------------------------------
 */


/*-----------------------------------------------------------------------
 */

/*
 * The following code cannot be run from FLASH!
 */

void
flash_erase(flash_info_t *info, int s_first, int s_last)
{
	int prot, sect, haderr;
	ulong start, now, last;
	void (*erase_init)(flash_info_t *, int);
	int (*erase_poll)(flash_info_t *, int);
	void (*reset)(flash_info_t *, int);

#ifdef FLASH_DEBUG
	printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
		"  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
		(info - flash_info) + 1);
	flash_print_info(info);
#endif

	if ((s_first < 0) || (s_first > s_last)) {
		if (info->flash_id == FLASH_UNKNOWN) {
			printf ("- missing\n");
		} else {
			printf ("- no sectors to erase\n");
		}
		return;
	}

	switch (info->flash_id) {

#if defined(CONFIG_CMA302)
	case FLASH_MAN_INTEL|FLASH_28F008S5:
		erase_init = c302f_erase_init;
		erase_poll = c302f_erase_poll;
		reset = c302f_reset;
		break;
#endif

#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
	case FLASH_MAN_INTEL|FLASH_28F800_B:
	case FLASH_MAN_AMD|FLASH_AM29F800B:
		/* not yet ...
		erase_init = cmbf_erase_init;
		erase_poll = cmbf_erase_poll;
		reset = cmbf_reset;
		break;
		*/
#endif

	default:
		printf ("Flash type %08lx not supported - aborted\n",
			info->flash_id);
		return;
	}

	prot = 0;
	for (sect=s_first; sect<=s_last; ++sect) {
		if (info->protect[sect]) {
			prot++;
		}
	}

	if (prot) {
		printf("- Warning: %d protected sector%s will not be erased!\n",
			prot, (prot > 1 ? "s" : ""));
	}

	start = get_timer (0);
	last = 0;
	haderr = 0;

	for (sect = s_first; sect <= s_last; sect++) {
		if (info->protect[sect] == 0) {	/* not protected */
			ulong estart;
			int sectdone;

			(*erase_init)(info, sect);

			/* wait at least 80us - let's wait 1 ms */
			udelay (1000);

			estart = get_timer(start);

			do {
				now = get_timer(start);

				if (now - estart > CFG_FLASH_ERASE_TOUT) {
					printf ("Timeout (sect %d)\n", sect);
					haderr = 1;
					break;
				}

#ifndef FLASH_DEBUG
				/* show that we're waiting */
				if ((now - last) > 1000) { /* every second */
					putc ('.');
					last = now;
				}
#endif

				sectdone = (*erase_poll)(info, sect);

				if (sectdone < 0) {
					haderr = 1;
					break;
				}

			} while (!sectdone);

			if (haderr)
				break;
		}
	}

	if (haderr > 0)
		printf (" failed\n");
	else
		printf (" done\n");

	/* reset to read mode */
	for (sect = s_first; sect <= s_last; sect++) {
		if (info->protect[sect] == 0) {	/* not protected */
			(*reset)(info, sect);
		}
	}
}

/*-----------------------------------------------------------------------
 */

flash_info_t *
addr2info(ulong addr)
{
	flash_info_t *info;
	int i;

	for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
		if ((addr >= info->start[0]) &&
		    (addr < (info->start[0] + info->size)) ) {
			return (info);
		}
	}

	return (NULL);
}

/*-----------------------------------------------------------------------
 * Copy memory to flash.
 * Make sure all target addresses are within Flash bounds,
 * and no protected sectors are hit.
 * Returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 * 4 - target range includes protected sectors
 * 8 - target address not in Flash memory
 */
int
flash_write (uchar *src, ulong addr, ulong cnt)
{
	int i;
	ulong         end        = addr + cnt - 1;
	flash_info_t *info_first = addr2info (addr);
	flash_info_t *info_last  = addr2info (end );
	flash_info_t *info;

	if (cnt == 0) {
		return (0);
	}

	if (!info_first || !info_last) {
		return (8);
	}

	for (info = info_first; info <= info_last; ++info) {
		ulong b_end = info->start[0] + info->size;	/* bank end addr */
		short s_end = info->sector_count - 1;
		for (i=0; i<info->sector_count; ++i) {
			ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];

			if ((end >= info->start[i]) && (addr < e_addr) &&
			    (info->protect[i] != 0) ) {
				return (4);
			}
		}
	}

	/* finally write data to flash */
	for (info = info_first; info <= info_last && cnt>0; ++info) {
		ulong len;
		
		len = info->start[0] + info->size - addr;
		if (len > cnt)
			len = cnt;
		if ((i = write_buff(info, src, addr, len)) != 0) {
			return (i);
		}
		cnt  -= len;
		addr += len;
		src  += len;
	}
	return (0);
}

/*-----------------------------------------------------------------------
 * Copy memory to flash, returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 * 3 - write error
 */

static int
write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
	ulong cp, wp, data;
	int i, l, rc;
	ulong start, now, last;

	wp = (addr & ~3);	/* get lower word aligned address */

	/*
	 * handle unaligned start bytes
	 */
	if ((l = addr - wp) != 0) {
		data = 0;
		for (i=0, cp=wp; i<l; ++i, ++cp) {
			data = (data << 8) | (*(uchar *)cp);
		}
		for (; i<4 && cnt>0; ++i) {
			data = (data << 8) | *src++;
			--cnt;
			++cp;
		}
		for (; cnt==0 && i<4; ++i, ++cp) {
			data = (data << 8) | (*(uchar *)cp);
		}

		if ((rc = write_word(info, wp, data)) != 0) {
			return (rc);
		}
		wp += 4;
	}

	/*
	 * handle word aligned part
	 */
	start = get_timer (0);
	last = 0;
	while (cnt >= 4) {
		data = 0;
		for (i=0; i<4; ++i) {
			data = (data << 8) | *src++;
		}
		if ((rc = write_word(info, wp, data)) != 0) {
			return (rc);
		}
		wp  += 4;
		cnt -= 4;

		/* show that we're waiting */
		now = get_timer(start);
		if ((now - last) > 1000) {	/* every second */
			putc ('.');
			last = now;
		}
	}

	if (cnt == 0) {
		return (0);
	}

	/*
	 * handle unaligned tail bytes
	 */
	data = 0;
	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
		data = (data << 8) | *src++;
		--cnt;
	}
	for (; i<4; ++i, ++cp) {
		data = (data << 8) | (*(uchar *)cp);
	}
	
	return (write_word(info, wp, data));
}

/*-----------------------------------------------------------------------
 * Write a word to Flash, returns:
 * 0 - OK
 * 1 - write timeout
 * 2 - Flash not erased
 * 3 - write error
 */
static int
write_word(flash_info_t *info, ulong dest, ulong data)
{
	int retval;

	/* Check if Flash is (sufficiently) erased */
	if ((*(ulong *)dest & data) != data) {
		return (2);
	}

	switch (info->flash_id) {

#if defined(CONFIG_CMA302)
	case FLASH_MAN_INTEL|FLASH_28F008S5:
		retval = c302f_write_word((c302f_addr_t)dest, (c302f_word_t)data);
		break;
#endif

#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
	case FLASH_MAN_INTEL|FLASH_28F800_B:
	case FLASH_MAN_AMD|FLASH_AM29F800B:
		/* not yet ...
		retval = cmbf_write_word(info,
			(cmbf_addr_t)dest, (cmbf_word_t)data);
		*/
		retval = 3;
		break;
#endif

	default:
		printf ("Flash type %08lx not supported - aborted\n",
			info->flash_id);
		retval = 3;
		break;
	}

	return (retval);
}

/*-----------------------------------------------------------------------
 */

⌨️ 快捷键说明

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