|
From: Erik M. <er...@us...> - 2001-10-15 21:52:12
|
Update of /cvsroot/blob/blob/src/blob
In directory usw-pr-cvs1:/tmp/cvs-serv19896/src/blob
Modified Files:
flash.c
Log Message:
First cleanup of the flash code
Index: flash.c
===================================================================
RCS file: /cvsroot/blob/blob/src/blob/flash.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- flash.c 2001/10/14 20:24:32 1.3
+++ flash.c 2001/10/15 21:52:09 1.4
@@ -43,107 +43,185 @@
#include <blob/serial.h>
#include <blob/flash.h>
-/* define for advanced flash functionality (not that it works) -- Erik */
-/* #define ADVANCED_FLASH 1 */
+#include <blob/init.h>
+#include <blob/command.h>
+/* this is enough for a 16MB flash with 128kB blocks */
+#define NEW_NUM_FLASH_BLOCKS (128)
-/* Static function defs */
-static u32 EraseOne(const char *whichOne);
-#ifdef ADVANCED_FLASH
-static void GetBlockOrder(tBlkInfo *blocksInfo, u8 which,
- u8 blockOrder[NUM_FLASH_BLOCKS]);
-#endif
+typedef struct {
+ u32 start;
+ u32 size;
+ int lockable;
+} flash_block_t;
+
+static flash_block_t flash_blocks[NEW_NUM_FLASH_BLOCKS];
+static int num_flash_blocks;
-#ifdef ADVANCED_FLASH
-void ScanFlash(tBlkInfo *blocksInfo)
+/* initialise the flash blocks table */
+static void init_flash(void)
{
-/* Scans the flash for headers in the main blocks. Maybe in the future we will
- put the headers in one of the parameter blocks. */
- int i,j;
+ int i = 0;
+ int j;
+ u32 start = 0;
- j = 0;
- for(i = 0; i < NUM_FLASH_BLOCKS; i++) {
- MyMemCpy((u32 *) &(blocksInfo->headers[i]),
- FLASH_BLOCK_BASE + i * FLASH_BLOCK_SIZE,
- sizeof(tBlkHdr) / 4);
- /* Is this a 'first' block ? */
- if(BLOCK_IN_USE(blocksInfo->headers[i])
- && (blocksInfo->headers[i].seqNum == 0))
- blocksInfo->firstBlockIndex[j++] = i;
+ num_flash_blocks = 0;
+
+ while(flash_descriptors[i].size != 0) {
+#ifdef BLOB_DEBUG
+ SerialOutputDec(flash_descriptors[i].num);
+ SerialOutputString("x 0x");
+ SerialOutputHex(flash_descriptors[i].size);
+ SerialOutputString(", ");
+
+ if(!flash_descriptors[i].lockable)
+ SerialOutputString("not ");
+
+ SerialOutputString("lockable\n");
+#endif
+
+ for(j = 0; j < flash_descriptors[i].num; j++) {
+ flash_blocks[num_flash_blocks].start = start;
+ flash_blocks[num_flash_blocks].size =
+ flash_descriptors[i].size;
+ flash_blocks[num_flash_blocks].lockable =
+ flash_descriptors[i].lockable;
+
+ start += flash_descriptors[i].size;
+
+ num_flash_blocks++;
+
+ if(num_flash_blocks >= NEW_NUM_FLASH_BLOCKS) {
+ printerrprefix();
+ SerialOutputString("not enough flash_blocks\n");
+ break;
+ }
+ }
+
+ i++;
}
-
- for(; j < NUM_FLASH_BLOCKS; j++)
- blocksInfo->firstBlockIndex[j] = NO_BLOCK;
-} /* ScanFlash */
-#endif
+#ifdef BLOB_DEBUG
+ SerialOutputString("Flash map:\n");
+ for(i = 0; i < num_flash_blocks; i++) {
+ SerialOutputString(" 0x");
+ SerialOutputHex(flash_blocks[i].size);
+ SerialOutputString(" @ 0x");
+ SerialOutputHex(flash_blocks[i].start);
+ SerialOutputString(" (");
+ SerialOutputDec(flash_blocks[i].size / 1024);
+ SerialOutputString(" kB), ");
+ if(!flash_blocks[i].lockable)
+ SerialOutputString("not ");
+
+ SerialOutputString("lockable\n");
+ }
+#endif
+}
-#ifdef ADVANCED_FLASH
-void LoadBlocksToMem(tBlkInfo *blocksInfo, u8 which, u32 *baseAddr)
+__initlist(init_flash, INIT_LEVEL_OTHER_STUFF);
+
+
+int flash_erase_region(u32 *start, u32 nwords)
{
-/* Load a series of blocks to memory */
- u8 blockOrder[NUM_FLASH_BLOCKS];
- int numBlocks = blocksInfo->headers[which].totSeq;
- int i;
- u32 *srcAddr, *dstAddr = baseAddr;
-
- /* If the block isn't in use, fail silently. */
- if(!BLOCK_IN_USE(blocksInfo->headers[which]))
- return;
-
- GetBlockOrder(blocksInfo, which, blockOrder);
-
- for(i = 0; i < numBlocks; i++) {
- srcAddr = FLASH_BLOCK_BASE +
- blockOrder[i] * FLASH_BLOCK_SIZE + sizeof(tBlkHdr);
- MyMemCpy(dstAddr, srcAddr, blocksInfo->headers[i].bytesInBlock / 4);
- dstAddr += blocksInfo->headers[i].bytesInBlock / 4;
+ u32 *cur;
+ u32 *end;
+ int rv;
+
+ cur = start;
+ end = start + nwords;
+
+ while(cur < end) {
+ if(*cur != 0xffffffff) {
+
+#ifdef BLOB_DEBUG
+ SerialOutputString(__FUNCTION__ "(): erasing dirty block at 0x");
+ SerialOutputHex((u32)cur);
+ SerialOutputByte('\n');
+#endif
+ /* dirty block */
+ rv = erase_flash(cur);
+
+ if(rv < 0) {
+ printerrprefix();
+ SerialOutputString("flash erase error at 0x");
+ SerialOutputHex((u32)cur);
+ SerialOutputByte('\n');
+ return rv;
+ }
+
+ continue;
+ }
+ cur ++;
}
-} /* LoadBlocksToMem */
+
+ return 0;
+}
+
+
+
+int flash_write_region(u32 *dst, const u32 *src, u32 nwords)
+{
+ u32 *cur;
+ u32 *end;
+ int rv;
+
+ cur = dst;
+ end = dst + nwords;
+
+#ifdef BLOB_DEBUG
+ SerialOutputString(__FUNCTION__ "(): flashing 0x");
+ SerialOutputHex(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 = write_flash(cur, src);
+ if(rv < 0) {
+ printerrprefix();
+ SerialOutputString("flash write error at 0x");
+ SerialOutputHex((u32)cur);
+ SerialOutputByte('\n');
+ return rv;
+ }
-/* The spooky functions that write to the same flash that we're executing from */
+ cur ++;
+ src ++;
+ }
-u32 data_from_flash(u32 what);
-u32 data_to_flash(u32 what);
+ return 0;
+}
-#if defined SHANNON || defined NESA
-#define READ_ARRAY 0x00F000F0
-#define UNLOCK1 0x00AA00AA
-#define UNLOCK2 0x00550055
-#define ERASE_SETUP 0x00800080
-#define ERASE_CONFIRM 0x00300030
-#define PGM_SETUP 0x00A000A0
-#define UNLOCK_BYPASS 0x00200020
-#define FLASH_ADDR1 (0x00000555 << 2)
-#define FLASH_ADDR2 (0x000002AA << 2)
-#define ERASE_DONE 0x00800080
-#define RDY_MASK 0x00800080
-#define STATUS_PGM_ERR 0x00200020
-#define STATUS_ERASE_ERR 0x00000001
-#else
-#define READ_ARRAY 0x00FF00FF
-#define ERASE_SETUP 0x00200020
-#define ERASE_CONFIRM 0x00D000D0
-#define PGM_SETUP 0x00400040
-#define STATUS_READ 0x00700070
-#define STATUS_CLEAR 0x00500050
-#define STATUS_BUSY 0x00800080
-#define STATUS_ERASE_ERR 0x00200020
-#define STATUS_PGM_ERR 0x00100010
-#endif
+
+/* -------- OLD ---------------------------------------------------- */
+
+
+
+
+/* Static function defs */
+static u32 EraseOne(const char *whichOne);
+
+
+
void EraseBlocks(tBlockType which)
{
@@ -181,7 +259,7 @@
for(i = 0; i < numBlocks; i++, thisBlock += MAIN_BLOCK_SIZE) {
SerialOutputByte('.');
led_toggle();
- if((EraseOne(thisBlock) & STATUS_ERASE_ERR) != 0) {
+ if(EraseOne(thisBlock) != 0) {
printerrprefix();
SerialOutputString("erase error at address 0x");
SerialOutputHex((u32)thisBlock);
@@ -196,14 +274,8 @@
void WriteBlocksFromMem(tBlockType type, const u32 *source, int length)
{
- volatile u32 *flashBase;
- u32 result;
- int maxLength, i;
-#if defined SHANNON || defined NESA
-#define READY 1
-#define ERR 2
- int chip1, chip2;
-#endif
+ u32 *flashBase;
+ int maxLength;
if((u32)source & 0x03) {
printerror(EALIGN, NULL);
@@ -247,169 +319,37 @@
/* 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(" bytes from 0x");
+ SerialOutputString(" words from 0x");
SerialOutputHex((u32)source);
SerialOutputString(" to 0x");
SerialOutputHex((u32)flashBase);
SerialOutputByte('\n');
#endif
-
-#if defined SHANNON || defined NESA
- *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1);
- *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2);
- *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK_BYPASS);
-#endif
-
- for(i = 0; i < length; i+= 4, flashBase++, source++) {
- if((i % MAIN_BLOCK_SIZE) == 0) {
- SerialOutputByte('.');
- led_toggle();
- }
-
- *flashBase = data_to_flash(PGM_SETUP);
- *flashBase = *source;
-
-#if defined SHANNON || defined NESA
-
- /* This is a pretty similar situation to the erasing status below
- * Bit 7 is ~(data bit 7) until the flash is complete. If bit 5
- * gets set before this happens, there is an error, but this could
- * happen near the clock edge, and bit 5 could be the actual data
- * before bit 7 changes, so we have to read again.
- */
- chip1 = chip2 = 0;
- do {
- result = data_from_flash(*flashBase);
- if (!chip1 && ((result & 0x80) == (*source & 0x80))) chip1 = READY;
- if (!chip1 && ((result & 0xFFFF) & STATUS_PGM_ERR)) {
- result = data_from_flash(*flashBase);
- if ((result & 0x80) == (*source & 0x80)) chip1 = READY;
- else chip1 = ERR;
- }
- if (!chip2 && ((result & (0x80 << 16)) == (*source & (0x80 << 16)))) chip2 = READY;
- if (!chip2 && ((result >> 16) & STATUS_PGM_ERR)) {
- result = data_from_flash(*flashBase);
- if ((result & (0x80 << 16)) == (*source & (0x80 << 16))) chip2 = READY;
- else chip2 = ERR;
- }
-
- } while (!chip1 || !chip2);
-
- if (chip1 == ERR || chip2 == ERR || *flashBase != *source) {
-#else
- do {
- *flashBase = data_to_flash(STATUS_READ);
- result = data_from_flash(*flashBase);
- } while((~result & STATUS_BUSY) != 0);
-
- *flashBase = data_to_flash(READ_ARRAY);
-
- if((result & STATUS_PGM_ERR) != 0 || *flashBase != *source) {
-#endif
- printerrprefix();
- SerialOutputString("Write error at address 0x");
- SerialOutputHex((u32)flashBase);
- SerialOutputByte('\n');
- return;
- }
- }
-
-#if defined SHANNON || defined NESA
- *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY);
-#endif
+ flash_write_region(flashBase, source, length);
} /* WriteBlocksFromMem */
+
static u32 EraseOne(const char *whichOne)
{
-/* Routine to erase one block of flash */
-
- volatile u32 *writeMe = (u32 *)whichOne;
- u32 result;
-
-#if defined SHANNON || defined NESA
- int chip1, chip2;
-#endif
+ int rv;
-#ifdef BLOB_DEBUG
- SerialOutputString(__FUNCTION__ "(): erasing block at address 0x");
- SerialOutputHex((u32)whichOne);
- SerialOutputByte('\n');
-#endif
-
-#if defined SHANNON || defined NESA
- *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1);
- *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2);
- *(u32 *)FLASH_ADDR1 = data_to_flash(ERASE_SETUP);
- *(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1);
- *(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2);
- *writeMe = data_to_flash(ERASE_CONFIRM);
-
- /* I just can't find clean ways of dealing with this flash...
- * The error bit is a *set* bit, so if its read, and bit 7 is 0,
- * but bit 5 is 1, its an error, however, after these status reads
- * are done, erased flash goes to 0xff...sooo...each chip has to
- * be caught where the bits are the status bits */
- chip1 = chip2 = 0;
- do {
- result = data_from_flash(*writeMe);
- if (!chip1 && (result & 0xFFFF) & ERASE_DONE) chip1 = READY;
- if (!chip1 && (result & 0xFFFF) & STATUS_PGM_ERR) chip1 = ERR;
- if (!chip2 && (result >> 16) & ERASE_DONE) chip2 = READY;
- if (!chip2 && (result >> 16) & STATUS_PGM_ERR) chip2 = ERR;
-
- } while(!chip1 || !chip2);
-
- *(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY);
-
- if (chip1 == ERR || chip2 == ERR) return 1;
- return 0;
-#else
+ rv = flash_erase_region((u32 *)whichOne, MAIN_BLOCK_SIZE / 4);
- *writeMe = data_to_flash(ERASE_SETUP);
- *writeMe = data_to_flash(ERASE_CONFIRM);
-
- do {
- *writeMe = data_to_flash(STATUS_READ);
- result = data_from_flash(*writeMe);
- } while((~result & STATUS_BUSY) != 0);
-
- *writeMe = data_to_flash(READ_ARRAY);
- return result;
-#endif
+ if(rv < 0)
+ return 1;
+ else
+ return 0;
} /* EraseOne */
-
-
-
-#ifdef ADVANCED_FLASH
-static void GetBlockOrder(tBlkInfo *blocksInfo, u8 which,
- u8 blockOrder[NUM_FLASH_BLOCKS])
-{
-
- tBlockType type = blocksInfo->headers[which].type;
- char *name = blocksInfo->headers[which].name;
- int i;
-
- /* If the block isn't in use, fail silently. */
- if(!BLOCK_IN_USE(blocksInfo->headers[which]))
- return;
-
- for(i = 0; i < NUM_FLASH_BLOCKS; i++) {
- if(BLOCK_IN_USE(blocksInfo->headers[i]) &&
- (blocksInfo->headers[i].type == type) &&
- !MyStrNCmp(blocksInfo->headers[i].name, name, BLOCK_NAME_LEN)) {
-
- blockOrder[blocksInfo->headers[i].seqNum] = i;
- }
- }
-} /* GetBlockOrder */
-#endif
|