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

📄 spi_flash.c

📁 最新版的u-boot,2008-10-18发布
💻 C
📖 第 1 页 / 共 2 页
字号:
 *		 The malloc engine is ready and we can move our buffers to *		 normal RAM *  return:      --- */void spi_init_r(void){#if defined(CONFIG_POST) && (CONFIG_POST & CFG_POST_SPI)	/* Our testing strategy here is pretty basic:	 *  - fill src memory with an 8-bit pattern	 *  - write the src memory to the SPI flash	 *  - read the SPI flash into the dst memory	 *  - compare src and dst memory regions	 *  - repeat a few times	 * The variations we test for:	 *  - change the 8-bit pattern a bit	 *  - change the read/write block size so we know:	 *    - writes smaller/equal/larger than the buffer work	 *    - writes smaller/equal/larger than the sector work	 *  - change the SPI offsets so we know:	 *    - writing partial sectors works	 */	uint8_t *mem_src, *mem_dst;	size_t i, c, l, o;	size_t test_count, errors;	uint8_t pattern;	SPI_INIT();	if (spi_detect_part())		goto out;	eeprom_info();	ulong lengths[] = {		flash.write_length,		flash.write_length * 2,		flash.write_length / 2,		flash.sector_size,		flash.sector_size * 2,		flash.sector_size / 2	};	ulong offsets[] = {		0,		flash.write_length,		flash.write_length * 2,		flash.write_length / 2,		flash.write_length / 4,		flash.sector_size,		flash.sector_size * 2,		flash.sector_size / 2,		flash.sector_size / 4,	};	/* the exact addresses are arbitrary ... they just need to not overlap */	mem_src = (void *)(0);	mem_dst = (void *)(max(flash.write_length, flash.sector_size) * 2);	test_count = 0;	errors = 0;	pattern = 0x00;	for (i = 0; i < 16; ++i) {	/* 16 = 8 bits * 2 iterations */		for (l = 0; l < ARRAY_SIZE(lengths); ++l) {			for (o = 0; o < ARRAY_SIZE(offsets); ++o) {				ulong len = lengths[l];				ulong off = offsets[o];				printf("Testing pattern 0x%02X of length %5lu and offset %5lu: ", pattern, len, off);				/* setup the source memory region */				memset(mem_src, pattern, len);				test_count += 4;				for (c = 0; c < 4; ++c) {	/* 4 is just a random repeat count */					if (ctrlc()) {						puts("\nAbort\n");						goto out;					}					/* make sure background fill pattern != pattern */					memset(mem_dst, pattern ^ 0xFF, len);					/* write out the source memory and then read it back and compare */					eeprom_write(0, off, mem_src, len);					eeprom_read(0, off, mem_dst, len);					if (memcmp(mem_src, mem_dst, len)) {						for (c = 0; c < len; ++c)							if (mem_src[c] != mem_dst[c])								break;						printf(" FAIL @ offset %u, skipping repeats ", c);						++errors;						break;					}					/* XXX: should shrink write region here to test with					 * leading/trailing canaries so we know surrounding					 * bytes don't get screwed.					 */				}				puts("\n");			}		}		/* invert the pattern every other run and shift out bits slowly */		pattern ^= 0xFF;		if (i % 2)			pattern = (pattern | 0x01) << 1;	}	if (errors)		printf("SPI FAIL: Out of %i tests, there were %i errors ;(\n", test_count, errors);	else		printf("SPI PASS: %i tests worked!\n", test_count); out:	SPI_DEINIT();#endif}static void transmit_address(uint32_t addr){	/* Send the highest byte of the 24 bit address at first */	spi_write_read_byte(addr >> 16);	/* Send the middle byte of the 24 bit address  at second */	spi_write_read_byte(addr >> 8);	/* Send the lowest byte of the 24 bit address finally */	spi_write_read_byte(addr);}/* * Read a value from flash for verify purpose * Inputs:	unsigned long ulStart - holds the SPI start address *			int pnData - pointer to store value read from flash *			long lCount - number of elements to read */static int read_flash(unsigned long address, long count, uchar *buffer){	size_t i;	/* Send the read command to SPI device */	SPI_ON();	spi_write_read_byte(flash.ops->read);	transmit_address(address);#ifndef CONFIG_SPI_FLASH_SLOW_READ	/* Send dummy byte when doing SPI fast reads */	spi_write_read_byte(0);#endif	/* After the SPI device address has been placed on the MOSI pin the data can be */	/* received on the MISO pin. */	for (i = 1; i <= count; ++i) {		*buffer++ = spi_write_read_byte(0);		if (i % flash.sector_size == 0)			puts(".");	}	SPI_OFF();	return 0;}static int enable_writing(void){	ulong start;	if (flash.manufacturer_id == JED_MANU_ATMEL)		return 0;	/* A write enable instruction must previously have been executed */	SPI_ON();	spi_write_read_byte(0x06);	SPI_OFF();	/* The status register will be polled to check the write enable latch "WREN" */	start = get_timer(0);	while (get_timer(0) - start < TIMEOUT) {		if (read_status_register() & 0x02)			return 0;		if (ctrlc()) {			puts("\nAbort\n");			return -1;		}	}	puts("Timeout\n");	return -1;}static long address_to_sector(unsigned long address){	if (address > (flash.num_sectors * flash.sector_size) - 1)		return -1;	return address / flash.sector_size;}static int erase_sector(int address){	/* sector gets checked in higher function, so assume it's valid	 * here and figure out the offset of the sector in flash	 */	if (enable_writing())		return -1;	/*	 * Send the erase block command to the flash followed by the 24 address	 * to point to the start of a sector	 */	SPI_ON();	spi_write_read_byte(flash.ops->erase);	transmit_address(address);	SPI_OFF();	return wait_for_ready_status();}/* Write [count] bytes out of [buffer] into the given SPI [address] */static long write_flash(unsigned long address, long count, uchar *buffer){	long i, write_buffer_size;	if (enable_writing())		return -1;	/* Send write command followed by the 24 bit address */	SPI_ON();	spi_write_read_byte(flash.ops->write);	transmit_address(address);	/* Shoot out a single write buffer */	write_buffer_size = min(count, flash.write_length);	for (i = 0; i < write_buffer_size; ++i)		spi_write_read_byte(buffer[i]);	SPI_OFF();	/* Wait for the flash to do its thing */	if (wait_for_ready_status()) {		puts("SPI Program Time out! ");		return -1;	}	return i;}/* Write [count] bytes out of [buffer] into the given SPI [address] */static int write_sector(unsigned long address, long count, uchar *buffer){	long write_cnt;	while (count != 0) {		write_cnt = write_flash(address, count, buffer);		if (write_cnt == -1)			return -1;		/* Now that we've sent some bytes out to the flash, update		 * our counters a bit		 */		count -= write_cnt;		address += write_cnt;		buffer += write_cnt;	}	/* return the appropriate error code */	return 0;}/* * Function:    spi_write */ssize_t spi_write(uchar *addr, int alen, uchar *buffer, int len){	unsigned long offset;	int start_sector, end_sector;	int start_byte, end_byte;	uchar *temp = NULL;	int num, ret = 0;	SPI_INIT();	if (spi_detect_part())		goto out;	offset = addr[0] << 16 | addr[1] << 8 | addr[2];	/* Get the start block number */	start_sector = address_to_sector(offset);	if (start_sector == -1) {		puts("Invalid sector! ");		goto out;	}	end_sector = address_to_sector(offset + len - 1);	if (end_sector == -1) {		puts("Invalid sector! ");		goto out;	}	/* Since flashes operate in sector units but the eeprom command	 * operates as a continuous stream of bytes, we need to emulate	 * the eeprom behavior.  So here we read in the sector, overlay	 * any bytes we're actually modifying, erase the sector, and	 * then write back out the new sector.	 */	temp = malloc(flash.sector_size);	if (!temp) {		puts("Malloc for sector failed! ");		goto out;	}	for (num = start_sector; num <= end_sector; num++) {		unsigned long address = num * flash.sector_size;		/* XXX: should add an optimization when spanning sectors:		 * No point in reading in a sector if we're going to be		 * clobbering the whole thing.  Need to also add a test		 * case to make sure the optimization is correct.		 */		if (read_flash(address, flash.sector_size, temp)) {			puts("Read sector failed! ");			len = 0;			break;		}		start_byte = max(address, offset);		end_byte = address + flash.sector_size - 1;		if (end_byte > (offset + len))			end_byte = (offset + len - 1);		memcpy(temp + start_byte - address,			buffer + start_byte - offset,			end_byte - start_byte + 1);		if (erase_sector(address)) {			puts("Erase sector failed! ");			goto out;		}		if (write_sector(address, flash.sector_size, temp)) {			puts("Write sector failed! ");			goto out;		}		puts(".");	}	ret = len; out:	free(temp);	SPI_DEINIT();	return ret;}/* * Function: spi_read */ssize_t spi_read(uchar *addr, int alen, uchar *buffer, int len){	unsigned long offset;	SPI_INIT();	if (spi_detect_part())		len = 0;	else {		offset = addr[0] << 16 | addr[1] << 8 | addr[2];		read_flash(offset, len, buffer);	}	SPI_DEINIT();	return len;}/* *	Spit out some useful information about the SPI eeprom */int eeprom_info(void){	int ret = 0;	SPI_INIT();	if (spi_detect_part())		ret = 1;	else		printf("SPI Device: %s 0x%02X (%s) 0x%02X 0x%02X\n"			"Parameters: num sectors = %i, sector size = %i, write size = %i\n"			"Flash Size: %i mbit (%i mbyte)\n"			"Status: 0x%02X\n",			flash.flash->name, flash.manufacturer_id, flash.manufacturer->name,			flash.device_id1, flash.device_id2, flash.num_sectors,			flash.sector_size, flash.write_length,			(flash.num_sectors * flash.sector_size) >> 17,			(flash.num_sectors * flash.sector_size) >> 20,			read_status_register());	SPI_DEINIT();	return ret;}#endif

⌨️ 快捷键说明

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