cfi_cmdset_0001.c: Excessive erase suspends

Anders Grafström grfstrm at users.sourceforge.net
Sat Apr 19 09:47:24 EDT 2008


Joakim Tjernlund wrote:
> Don't you need to check that the chip is suspended before you do any
> new operation?

You're right.

Here's the improved version;

static void erase_suspend(unsigned int loops)
{
	volatile unsigned int *flash = (unsigned int *)0x41040000;
	unsigned int i;
	unsigned int suspends = 0;
	unsigned int words = 2;
	unsigned int timeout;

	/* Make sure there's something to erase */
	for (i = 0; i < 0x10000; i++) {
		if (flash[i] == 0xffffffff) {
			flash[i] = 0x00400040;
			flash[i] = 0;
			while ((flash[i] & 0x00800080) != 0x00800080);
		}
	}

	/* Clear status */
	flash[0] = 0x00500050;

	/* Erase */
	flash[0] = 0x00200020;
	flash[0] = 0x00d000d0;

	while (1) {
		/* Suspend */
		flash[0] = 0x00b000b0;
		flash[0] = 0x00700070;
		timeout = 100000;
		while ((flash[0] & 0x00800080) != 0x00800080 && --timeout);
		if (!timeout)
			printf("suspend timeout\n");
		suspends++;

		/* Short delay */
		for (i = 0; i < 1000; i++);

		/* Resume */
		flash[0] = 0x00d000d0;
		flash[0] = 0x00700070;

		/* Erase done ? */
		if ((flash[0] & 0x00800080) == 0x00800080) {
			printf("\nstatus %08x\n", flash[0]);
			break;
		}

		/* Short delay */
		for (i = 0; i < loops; i++);
	}

	/* Read array */
	flash[0] = 0x00ff00ff;

	/* Show the first 2 failed words */
	for (i = 0; i < 0x10000; i++) {
		if (flash[i] != 0xffffffff) {
			printf("%08x\n", flash[i]);
			if (--words == 0)
				break;
		}
	}

	printf("%d suspends\n", suspends);
}

void test_flash_erase_suspend(void)
{
	unsigned int loops;

	for (loops = 6000; loops > 2000; loops -= 500) {
		printf("\n%d loops", loops);
		erase_suspend(loops);
	}
}


It produced this output at one occasion:

6000 loops
status 00800080
ffff0000
ffff0000
4783 suspends

5500 loops
status 00800080
5508 suspends

5000 loops
status 008000a0
6394 suspends

4500 loops
status 00a000a0
fffffeff
fffffffe
5169 suspends

4000 loops
status 00a000a0
fffffeff
fffffeff
5378 suspends

3500 loops
status 00a000a0
aaaaaaaa
aaaaaaaa
5715 suspends

3000 loops
status 00a000a0
55555555
55555555
6142 suspends

2500 loops
status 00a000a0
00000000
00000000
6929 suspends

It locks up when I drop it down to 2000 or less iterations in the loop between resume and suspend.
I think I need to do more testing with properly timed delays.

Is there anything else that I have missed?

/Anders




More information about the linux-mtd mailing list