|
From: Erik M. <er...@us...> - 2001-10-24 12:28:28
|
Update of /cvsroot/blob/blob/src/blob
In directory usw-pr-cvs1:/tmp/cvs-serv13224/src/blob
Modified Files:
flash.c main.c
Log Message:
More flash cleanup. This includes the new flash write algorithm. Next is
static flash partition support.
Index: flash.c
===================================================================
RCS file: /cvsroot/blob/blob/src/blob/flash.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- flash.c 2001/10/21 21:36:15 1.5
+++ flash.c 2001/10/24 12:28:25 1.6
@@ -11,6 +11,7 @@
/*
* flash.c: Flash I/O functions for blob
*
+ * Copyright (C) 2001 Erik Mouw (J.A...@it...)
* Copyright (C) 1999 Jan-Derk Bakker (J.D...@it...)
*
* This program is free software; you can redistribute it and/or modify
@@ -48,7 +49,7 @@
/* this is enough for a 16MB flash with 128kB blocks */
-#define NEW_NUM_FLASH_BLOCKS (128)
+#define NUM_FLASH_BLOCKS (128)
typedef struct {
@@ -58,7 +59,7 @@
} flash_block_t;
-static flash_block_t flash_blocks[NEW_NUM_FLASH_BLOCKS];
+static flash_block_t flash_blocks[NUM_FLASH_BLOCKS];
static int num_flash_blocks;
flash_descriptor_t *flash_descriptors;
@@ -113,7 +114,7 @@
num_flash_blocks++;
- if(num_flash_blocks >= NEW_NUM_FLASH_BLOCKS) {
+ if(num_flash_blocks >= NUM_FLASH_BLOCKS) {
printerrprefix();
SerialOutputString("not enough flash_blocks\n");
break;
@@ -155,14 +156,21 @@
cur = start;
end = start + nwords;
+#if BLOB_DEBUG
+ SerialOutputString(__FUNCTION__ "(): erasing 0x");
+ SerialOutputHex(nwords);
+ SerialOutputString(" (");
+ SerialOutputDec(nwords);
+ SerialOutputString(") words at 0x");
+ SerialOutputHex((u32)start);
+ SerialOutputByte('\n');
+#endif
while(cur < end) {
if(*cur != 0xffffffff) {
-
-#ifdef BLOB_DEBUG
- SerialOutputString(__FUNCTION__ "(): erasing dirty block at 0x");
+ SerialOutputString("erasing dirty block at 0x");
SerialOutputHex((u32)cur);
SerialOutputByte('\n');
-#endif
+
/* dirty block */
rv = flash_driver->flash_erase(cur);
@@ -184,189 +192,107 @@
+
+/* Write a flash region with a minimum number of erase operations.
+ *
+ * Flash chips wear from erase operations (that's why flash lifetime
+ * is specified in erase cycles), so we try to limit the number of
+ * erase operations in this function. Luckily the flash helps us a
+ * little bit with this, because it only allows you to change a '1'
+ * bit into a '0' during a write operation. This means that 0xffff can
+ * be changed into 0x1010, and 0x1010 into 0x0000, but 0x0000 can't be
+ * changed into anything else anymore because there are no '1' bits
+ * left.
+ */
int flash_write_region(u32 *dst, const u32 *src, u32 nwords)
{
- u32 *cur;
- u32 *end;
int rv;
+ u32 nerrors = 0;
+ u32 i = 0;
- cur = dst;
- end = dst + nwords;
+ u32 nerase = 0;
+ u32 nwrite = 0;
+ u32 nscandown = 0;
+ u32 nskip = 0;
-#ifdef BLOB_DEBUG
+#if BLOB_DEBUG
SerialOutputString(__FUNCTION__ "(): flashing 0x");
SerialOutputHex(nwords);
- SerialOutputString(" words from 0x");
+ SerialOutputString(" (");
+ SerialOutputDec(nwords);
+ SerialOutputString(") words from 0x");
SerialOutputHex((u32)src);
SerialOutputString(" to 0x");
SerialOutputHex((u32)dst);
SerialOutputByte('\n');
#endif
-
- while(cur < end) {
- if((u32)cur % (16 * 1024) == 0) {
- SerialOutputByte('.');
- led_toggle();
- }
-
- rv = flash_driver->flash_write(cur, src);
- if(rv < 0) {
- printerrprefix();
- SerialOutputString("flash write error at 0x");
- SerialOutputHex((u32)cur);
- SerialOutputByte('\n');
- return rv;
+ while(i < nwords) {
+ /* nothing to write */
+ if(dst[i] == src[i]) {
+ i++;
+ nskip++;
+ continue;
}
-
- cur ++;
- src ++;
- }
-
- return 0;
-}
-
-
-
-
-/* -------- OLD ---------------------------------------------------- */
-
-
-
-
-/* Static function defs */
-static u32 EraseOne(const char *whichOne);
-
-
+ /* different, so write to this location */
+ rv = flash_driver->flash_write(&dst[i], &src[i]);
+ nwrite++;
+
+ if(rv == 0) {
+ i++;
+ } else {
+ nerrors++;
+
+ SerialOutputString("erasing at 0x");
+ SerialOutputHex((u32)&dst[i]);
+ SerialOutputString("...");
-void EraseBlocks(tBlockType which)
-{
- char *thisBlock;
- int numBlocks, i;
+ /* erase block at current location */
+ rv = flash_driver->flash_erase(&dst[i]);
+ nerase++;
+ if(rv < 0) {
+ /* something is obviously wrong */
+ return rv;
+ }
+
+ SerialOutputString(" scanning down...");
- switch(which) {
- case blBlob:
- thisBlock = (char *)BLOB_START;
- numBlocks = NUM_BLOB_BLOCKS;
- break;
+ /* scan down until we find the first
+ non-erased location and restart writing
+ again from that location */
+ while((i > 0) &&
+ ((dst[i] != src[i]) || (dst[i] == 0xffffffff))) {
+ i--;
+ nscandown++;
+ }
-#ifdef PARAM_START
- case blParam:
- thisBlock = (char *)PARAM_START;
- numBlocks = NUM_PARAM_BLOCKS;
- break;
-#endif
+ SerialOutputString(" resume writing at 0x");
+ SerialOutputHex((u32)&dst[i]);
+ SerialOutputByte('\n');
+ }
- case blKernel:
- thisBlock = (char *)KERNEL_START;
- numBlocks = NUM_KERNEL_BLOCKS;
- break;
-
- case blRamdisk:
- thisBlock = (char *)INITRD_START;
- numBlocks = NUM_INITRD_BLOCKS;
- break;
-
- default:
- /* this should not happen */
- return;
- }
-
- for(i = 0; i < numBlocks; i++, thisBlock += MAIN_BLOCK_SIZE) {
- SerialOutputByte('.');
- led_toggle();
- if(EraseOne(thisBlock) != 0) {
+ /* there is something seriously wrong if this is true */
+ if(nerrors > 2 * nwords) {
printerrprefix();
- SerialOutputString("erase error at address 0x");
- SerialOutputHex((u32)thisBlock);
- SerialOutputByte('\n');
- return;
+ SerialOutputString("too many flash errors, probably hardware error\n");
+ return -EFLASHPGM;
}
}
-} /* EraseBlocks */
-
-
-
-void WriteBlocksFromMem(tBlockType type, const u32 *source, int length)
-{
- u32 *flashBase;
- int maxLength;
-
- if((u32)source & 0x03) {
- printerror(EALIGN, NULL);
#ifdef BLOB_DEBUG
- printerrprefix();
- SerialOutputString("Address = 0x");
- SerialOutputHex((u32)source);
- SerialOutputByte('\n');
-#endif
- return;
- }
-
- if(length & 0x03)
- length += 0x04;
- length &= ~((u32) 0x03);
-
- switch(type) {
- case blBlob:
- flashBase = (u32 *)BLOB_START;
- maxLength = BLOB_LEN;
- break;
-
-#ifdef PARAM_START
- case blParam:
- flashBase = (u32 *)PARAM_START;
- maxLength = PARAM_LEN;
- break;
-#endif
-
- case blKernel:
- flashBase = (u32 *)KERNEL_START;
- maxLength = KERNEL_LEN;
- break;
-
- case blRamdisk:
- flashBase = (u32 *)INITRD_START;
- maxLength = INITRD_LEN;
- break;
-
- default:
- /* this should not happen */
- return;
- }
-
- length = (length + 3) / 4;
- maxLength /= 4;
-
- if(length > maxLength)
- length = maxLength;
-
-#ifdef BLOB_DEBUG
- SerialOutputString(__FUNCTION__ "(): Flashing 0x");
- SerialOutputHex((u32)length);
- SerialOutputString(" words from 0x");
- SerialOutputHex((u32)source);
- SerialOutputString(" to 0x");
- SerialOutputHex((u32)flashBase);
+ SerialOutputDec(nwords);
+ SerialOutputString(" words source image\n");
+ SerialOutputDec(nwrite);
+ SerialOutputString(" words written to flash\n");
+ SerialOutputDec(nskip);
+ SerialOutputString(" words skipped\n");
+ SerialOutputDec(nerase);
+ SerialOutputString(" erase operations\n");
+ SerialOutputDec(nscandown);
+ SerialOutputString(" words scanned down\n");
SerialOutputByte('\n');
#endif
-
- flash_write_region(flashBase, source, length);
-} /* WriteBlocksFromMem */
-
-
-
-static u32 EraseOne(const char *whichOne)
-{
- int rv;
-
- rv = flash_erase_region((u32 *)whichOne, MAIN_BLOCK_SIZE / 4);
-
- if(rv < 0)
- return 1;
- else
- return 0;
-} /* EraseOne */
+ return 0;
+}
Index: main.c
===================================================================
RCS file: /cvsroot/blob/blob/src/blob/main.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- main.c 2001/10/14 20:24:32 1.3
+++ main.c 2001/10/24 12:28:25 1.4
@@ -131,13 +131,7 @@
#ifdef BLOB_DEBUG
/* print some information */
- SerialOutputString("Running from ");
- if(RunningFromInternal())
- SerialOutputString("internal");
- else
- SerialOutputString("external");
-
- SerialOutputString(" flash, blockSize = 0x");
+ SerialOutputString("Flash blockSize = 0x");
SerialOutputHex(blockSize);
SerialOutputByte('\n');
#endif
@@ -271,38 +265,40 @@
static int Flash(int argc, char *argv[])
{
- u32 startAddress = 0;
- tBlockType block;
- int numBytes = 0;
- int maxSize = 0;
+ u32 *src;
+ u32 *dst;
+ u32 numBytes = 0;
+ u32 maxSize = 0;
+ u32 nwords;
block_source_t type = fromFlash;
+
if(argc < 2)
return -ENOPARAMS;
if(strncmp(argv[1], "blob", 4) == 0) {
- startAddress = BLOB_RAM_BASE;
- block = blBlob;
- numBytes = blob_status.blobSize;
+ src = (u32 *)BLOB_RAM_BASE;
+ dst = (u32 *)BLOB_START;
maxSize = BLOB_LEN;
+ numBytes = blob_status.blobSize;
type = blob_status.blobType;
#ifdef PARAM_START
} else if(strncmp(argv[1], "param", 5) == 0) {
- startAddress = PARAM_RAM_BASE;
- block = blParam;
- numBytes = blob_status.paramSize;
+ src = (u32 *)PARAM_RAM_BASE;
+ dst = (u32 *)PARAM_START;
maxSize = PARAM_LEN;
+ numBytes = blob_status.paramSize;
type = blob_status.paramType;
#endif
} else if(strncmp(argv[1], "kernel", 6) == 0) {
- startAddress = KERNEL_RAM_BASE;
- block = blKernel;
+ src = (u32 *)KERNEL_RAM_BASE;
+ dst = (u32 *)KERNEL_START;
numBytes = blob_status.kernelSize;
maxSize = KERNEL_LEN;
type = blob_status.kernelType;
} else if(strncmp(argv[1], "ramdisk", 7) == 0) {
- startAddress = RAMDISK_RAM_BASE;
- block = blRamdisk;
+ src = (u32 *)RAMDISK_RAM_BASE;
+ dst = (u32 *)INITRD_START;
numBytes = blob_status.ramdiskSize;
maxSize = INITRD_LEN;
type = blob_status.ramdiskType;
@@ -312,7 +308,6 @@
}
if(type == fromFlash) {
- /* error */
printerrprefix();
SerialOutputString(argv[1]);
SerialOutputString(" not downloaded\n");
@@ -330,13 +325,14 @@
return -ETOOLONG;
}
+ nwords = (numBytes + sizeof(u32) - 1) / sizeof(u32);
+
SerialOutputString("Saving ");
SerialOutputString(argv[1]);
- SerialOutputString(" to flash ");
- EraseBlocks(block);
- SerialOutputByte(' ');
- WriteBlocksFromMem(block, (u32 *)startAddress, numBytes);
- SerialOutputString(" done\n");
+ SerialOutputString(" to flash\n");
+
+
+ flash_write_region(dst, src, nwords);
return 0;
}
@@ -407,12 +403,6 @@
{
SerialOutputString("Bootloader : " PACKAGE "\n");
SerialOutputString("Version : " VERSION "\n");
-
- SerialOutputString("Running from : ");
- if(RunningFromInternal())
- SerialOutputString("internal");
- else
- SerialOutputString("external");
SerialOutputString(" flash\nBlocksize : 0x");
SerialOutputHex(blob_status.blockSize);
|