public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] Flash Programming Example with ecos
@ 2001-09-25 12:27 Jeffrey Jopling
  2001-09-25 23:58 ` Jesper Skov
  0 siblings, 1 reply; 3+ messages in thread
From: Jeffrey Jopling @ 2001-09-25 12:27 UTC (permalink / raw)
  To: ecos-discuss

Does anyone have a simple app or a code snip that I can look at as a sample
of how to write an ecos application that can write and read data from flash?

Any assistance is appreciated.

Cheers,
Jeff Jopling

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [ECOS] Flash Programming Example with ecos
  2001-09-25 12:27 [ECOS] Flash Programming Example with ecos Jeffrey Jopling
@ 2001-09-25 23:58 ` Jesper Skov
  0 siblings, 0 replies; 3+ messages in thread
From: Jesper Skov @ 2001-09-25 23:58 UTC (permalink / raw)
  To: Jeffrey Jopling; +Cc: ecos-discuss

>>>>> "Jeffrey" == Jeffrey Jopling <jeff.jopling@indlogic.com> writes:

Jeffrey> Does anyone have a simple app or a code snip that I can look
Jeffrey> at as a sample of how to write an ecos application that can
Jeffrey> write and read data from flash?

Look at RedBoot. The flash.c file in particular.

Jesper

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [ECOS] Flash Programming Example with ecos
@ 2001-09-26  1:16 Simpkins, Andy
  0 siblings, 0 replies; 3+ messages in thread
From: Simpkins, Andy @ 2001-09-26  1:16 UTC (permalink / raw)
  To: Jeffrey Jopling, ecos-discuss

[-- Attachment #1: Type: text/plain, Size: 465 bytes --]

see attached

> -----Original Message-----
> From: Jeffrey Jopling [ mailto:jeff.jopling@indlogic.com ]
> Sent: 25 September 2001 20:34
> To: ecos-discuss@sources.redhat.com
> Subject: [ECOS] Flash Programming Example with ecos
> 
> 
> Does anyone have a simple app or a code snip that I can look 
> at as a sample
> of how to write an ecos application that can write and read 
> data from flash?
> 
> Any assistance is appreciated.
> 
> Cheers,
> Jeff Jopling
> 


[-- Attachment #2: fileSystem.h --]
[-- Type: text/x-c++, Size: 401 bytes --]

// fileSystem.h
#ifndef __FILESYSTEM_H__
#define __FILESYSTEM_H__


class fileSystem
{
   public:
      virtual bool format(void) = 0;
      virtual bool create(int length, char *data, char *name) = 0;
      virtual bool readAll(char *name, int *length, char *data) = 0;
      virtual bool erase(char *name) = 0;

      bool valid;       // validity of this file system
};


#endif // __FILESYSTEM_H__

[-- Attachment #3: flash.h --]
[-- Type: text/x-c++, Size: 5396 bytes --]

/*-----------------------------------------------------------------------------
 *
 *      (c) Tardis Mobile - 2000
 *
 *      Name: flash.h
 *
 *      Author: A Simpkins
 *
 *      Date: 04 October
 *
 *-----------------------------------------------------------------------------
 *
 *      Description:
 *
 *      Header file to be used with flashTest.C & eventualy a flash libuary 
 *      which flashTest.c will be a part.
 *
 *      Modification history:
 *
 * ---  14/08/2001 002 - converted to eCos
 *      04/10/2000 001 - Initial draft
 * 
 *
 *-----------------------------------------------------------------------------
 */
#ifndef __FLASH_H__
#define __FLASH_H__

// Address of code loaded into RAM (.2ram.flash_query)
#define FLASHCodeInRAM     (0x4100caac)

/* Structures */
/* ~~~~~~~~~~ */

/* Structure array length */
#define flashEscape_maxLength   (0x06) 


struct flashPairStruct
{
   cyg_uint32 pairAddress;
   cyg_uint16 pairData;
};


struct flashEscape
{
   cyg_uint16 length;
   struct flashPairStruct flashpair[flashEscape_maxLength];
};




/* Definitions */
/* ~~~~~~~~~~~ */

/* Memory is 16 bit wide (2 bytes). */
#define memoryWidth (0x002)

#define startAddressFLASH (0x40000000)
#define LengthFLASH (0x00100000)
   
/* flash Commands */
#define flash_eraseSectorCmd    (0x0030)
#define flash_reset             (0x00f0)
#define flash_erraseCmd         (0x0010)
#define flash_blank             (0x00ff)

#if CYGHWR_HAL_ARM_TARDIS3_VERSION == 1
   #define flash_make           (startAddressFLASH + 0x00000000)
   #define flash_deviceID       (startAddressFLASH + 0x00000004)  
   #define flash_erraseAllAddr  (startAddressFLASH + 0x00001554) 
   /* List of the sectors to erase with the above command */
   #define flash_SA00              (0x00000000)
   #define flash_SA01              (0x00002000)
   #define flash_SA02              (0x00003000)
   #define flash_SA03              (0x00004000)
   #define flash_SA04              (0x00008000)
   #define flash_SA05              (0x00010000)
   #define flash_SA06              (0x00018000)
   #define flash_SA07              (0x00020000)
   #define flash_SA08              (0x00028000)
   #define flash_SA09              (0x00030000)
   #define flash_SA10              (0x00038000)
   #define flash_SA11              (0x00040000)
   #define flash_SA12              (0x00048000)
   #define flash_SA13              (0x00050000)
   #define flash_SA14              (0x00058000)
   #define flash_SA15              (0x00060000)
   #define flash_SA16              (0x00068000)
   #define flash_SA17              (0x00070000)
   #define flash_SA18              (0x00078000) 
#else
   #define flash_make           (startAddressFLASH + 0x00000000)
   #define flash_deviceID       (startAddressFLASH + 0x00000002)
   #define flash_erraseAllAddr  (startAddressFLASH + 0x00000555)
   /* List of the sectors to erase with the above command */
   #define flash_SA00              (0x00000000)
   #define flash_SA01              (0x00004000)
   #define flash_SA02              (0x00006000)
   #define flash_SA03              (0x00008000)
   #define flash_SA04              (0x00010000)
   #define flash_SA05              (0x00020000)
   #define flash_SA06              (0x00030000)
   #define flash_SA07              (0x00040000)
   #define flash_SA08              (0x00050000)
   #define flash_SA09              (0x00060000)
   #define flash_SA10              (0x00070000)
   #define flash_SA11              (0x00080000)
   #define flash_SA12              (0x00090000)
   #define flash_SA13              (0x000a0000)
   #define flash_SA14              (0x000b0000)
   #define flash_SA15              (0x000c0000)
   #define flash_SA16              (0x000d0000)
   #define flash_SA17              (0x000e0000)
   #define flash_SA18              (0x000f0000) 
#endif


/* Flash Error Bits */
#define flash_DQ0               (0x0001)
#define flash_DQ1               (0x0002)
#define flash_DQ2               (0x0004)
#define flash_DQ3               (0x0008)
#define flash_DQ4               (0x0010)
#define flash_DQ5               (0x0020)
#define flash_DQ6               (0x0040)
#define flash_DQ7               (0x0080)


/* Function Commands and assocated data structures */
#define flashCmd_Info            (0x0001)
#define flashCmd_Erase           (0x0002)
#define flashCmd_ResumeErase     (0x0003)
#define flashCmd_Write           (0x0004)
#define flashResult_OK           (0x1001)
#define flashResult_badAddress   (0x1002)


class flashcmd
{
   public:
      int flashCommand;
};

class infoFlashCmd : public flashcmd
{
   public: 
      int make;
      int deviceID;
};

class eraseFlashCmd : public flashcmd
{
   public: 
      cyg_uint32 sectorNo;
      bool success;
      bool onHold;
};

class writeFlashCmd : public flashcmd
{
   public: 
      cyg_uint32 writeAddress;
      cyg_uint16 writeData;
      int        result;
};
  
// Bitmap of possible SiRF Interrupts
//#define SiRFIRQ                  (0xa260)  
#define SiRFIRQ                  (0x0000)  
  
// types of FLASH device 
// ~~~~~~~~~~~~~~~~~~~~~

// MAKE 
#define FLASHunknown             (0x0000)
#define AMD                      (0x0001)

// Device ID
#define AMD29LV800BB             (0x225b)
#define AMD29LV800BT             (0x22da)

// function type to call to code in RAM
typedef cyg_uint32 (*RAMfn_type)(cyg_uint32 *); 

#endif  /* __FLASH_H__ */

[-- Attachment #4: FLASHFileSystem.cpp --]
[-- Type: text/x-c, Size: 31302 bytes --]

// These functions should reside below the API and be called only for calls to filesystem 'FLASH0'
// This will only work with AMD AM29LV800BB or AM29LV160BB flash devices!
//
// terminology
//    superblock  - one block of FLASH
//    subblock    - subdevision of a superblock, smallest space that the filesystem can allocate
//    block       - not used to avoid confusion :-)

#include "eCosIvory/FLASHFileSystem.h"   // this file system
#include "eCosIvory/flash.h"             // flash lib
#include <stdlib.h>                      // malloc 
#include <stdio.h>                      /* sprintf */
#include <cyg/hal/t3.h>                 /* LED Control */
#include <cyg/infra/diag.h>             /* diag_printf */
#include "eCosIvory/console.h"          // display
#include "eCosIvory/system.h"           // file system pointer


// Constructor
FLASHfileSystem::FLASHfileSystem()
{ 
   // declare block information     
   // to be populated by hand! 
   subBlockSize = SUBBLOCKSIZE;                   // MUST NOT EXCEED superBlocksize / noSubBlocksPerSuperBlock
   noSubBlocksPerSuperBlock = SUBBLOCKSPERSUPERBLOCK;
 
   CYG_ADDRESS sbt[NUMSUPERBLOCKS] = SUPERBLOCKS;
   memcpy(superBlockTable, sbt, sizeof(sbt));
   
   // build FAT structure in RAM
   noSuperBlocks = NUMSUPERBLOCKS;
   noSubBlocks = NUMSUBBLOCKS; 
      
   // Attempt to read device information 
   infoFlashCmd flashData;
   flashData.flashCommand = flashCmd_Info;
   ((RAMfn_type)(FLASHCodeInRAM))((cyg_uint32 *)&flashData);
     
   // valid devices devices...
   if (flashData.make == AMD && flashData.deviceID == AMD29LV800BB)
   {
      valid = true; 
   } else {
      valid = false;
   }
   
   next = NULL;      // invalid file pointer (no open files)
      
   //## insert code to restore FAT contents from FLASH  
   
   //## insert code to create mutex for file system
}



// destructor
FLASHfileSystem::~FLASHfileSystem()
{ 
   //## insert code to back RAM tables to FLASH
   //## insert code to destry mutex
}



// erase block;
bool FLASHfileSystem::eraseBlock(CYG_ADDRESS superblock)
{
   eraseFlashCmd flashErase;   
   flashErase.flashCommand = flashCmd_Erase;
   flashErase.sectorNo = superblock;
   ((RAMfn_type)(FLASHCodeInRAM))((cyg_uint32 *)&flashErase);      
         
   while (flashErase.onHold)
   {
      cyg_thread_yield();
      flashErase.flashCommand = flashCmd_ResumeErase;
      ((RAMfn_type)(FLASHCodeInRAM))((cyg_uint32 *)&flashErase); 
   }
         
   return flashErase.success;
}



// FLASH Format
bool FLASHfileSystem::format(void)
{
   // Confirm that this is flash we know about...
   if (!valid) return false;
   
   // confirm that there are no files open...
   // i.e. we can not format if there are still files open
   if(next != NULL)
   {  
      #ifdef dbg_FLASH
         diag_printf("format: files are still open - can't format!\r");
      #endif
      return false;
   }
   
   //## lock FLASH mutex
      
   // erase superblocks used in our file system 
   for (int SB = 0; SB < noSuperBlocks; SB++)
      if (!eraseBlock(superBlockTable[SB])) return false;
   
   // Initialise structure 
   for (cyg_uint32 count = 0; count < noSubBlocks; count++)
   {
      subBlockTable[count].state = unused;
      subBlockTable[count].next = FLASHNull;
      subBlockTable[count].prev = FLASHNull;
   }   
   
   freeCount   = noSubBlocks - noSubBlocksPerSuperBlock;  // leave 1 superblock as working space
   usedCount   = 0;
   dirtyCount  = 0;
   subBlockFreePtr = 0;
   subBlockUsedPtr = 0;
   
   for (int FR = 0; FR < MAXFILES; FR++)
   {
      // technicly we need only initialise the name
      strcpy(FAT[FR].name,"\0");    
      FAT[FR].start = FLASHNull;
      FAT[FR].length = 0;
   }
   fileCount   = 0;
   
   //## unlock FLASH mutex
   
   return true;
}  



// write to FLASH   
bool FLASHfileSystem::writeToFlash(cyg_uint16 writeData, cyg_uint32 writeAddress)   
{
   writeFlashCmd flashWrite;
   flashWrite.flashCommand = flashCmd_Write;
   
    
   flashWrite.writeData = writeData;
	flashWrite.writeAddress = writeAddress;
   
   ((RAMfn_type)(FLASHCodeInRAM))((cyg_uint32 *)&flashWrite);
      
   return flashWrite.result;
}



// examine the FAT for a matching name
int FLASHfileSystem::lookUp(char *name)
{
   for (int count = 0; count < MAXFILES; count++)
      if (strcmp(name, FAT[count].name) == 0) return count;
   return FLASHFileNotFound;
}



// Calculate the start Address of the SubBlock
cyg_uint32 FLASHfileSystem::getSubBlockAddress(int subBlockNumber)
{
   int superBlockNo = subBlockNumber / noSubBlocksPerSuperBlock;
   int subBlockOfSuperBlock = subBlockNumber % noSubBlocksPerSuperBlock;
   return (subBlockOfSuperBlock * subBlockSize) + superBlockTable[superBlockNo];
}



// FLASH create file        
bool FLASHfileSystem::create(int length, char *data, char *name)      
{
   #ifdef dbg_FLASH
      diag_printf("checking for valid file system...");
   #endif
   
   // Confirm that this is flash we know about...
   if (!valid) return false;
   

   //## lock FLASH mutex 
   
   // check if we have space for the file
   #ifdef dbg_FLASH
      diag_printf("FS VALID\rCheck for space in FAT...");
   #endif
   if (fileCount == MAXFILES) return false;
   
   #ifdef dbg_FLASH
      diag_printf("Enough space\r");
   #endif
     
   //Limit size of file name
   #ifdef dbg_FLASH
      diag_printf("Limit file name size..."); 
   #endif
   int nameLen = strlen(name);
   if (nameLen > MAXNAMELEN)
   {
      nameLen = MAXNAMELEN; 
   }      
   name[nameLen] = '\0';
   #ifdef dbg_FLASH
      diag_printf("File name limited to %s\r", name);
   #endif
     
   // confirm that the file doesn't already exist
   #ifdef dbg_FLASH
      diag_printf("checking name is unique...");
   #endif
   if (int FileNumber = lookUp(name) != FLASHFileNotFound) return false;     // name exists
   #ifdef dbg_FLASH
      diag_printf("DONE\r");
   #endif
   
   // grab the number of required subBlocks or return false if insufficiant space
   #ifdef dbg_FLASH
      diag_printf("Allocating required number of subBlocks...");
   #endif
   int subBlocksRequired = length / subBlockSize; 
   if ((length % subBlockSize) > 0)  subBlocksRequired += 1;
   if (subBlocksRequired > freeCount) return false;
   freeCount-= subBlocksRequired;
   #ifdef dbg_FLASH
      diag_printf("%d subBlocks allocated\r", subBlocksRequired);
   #endif
    
   // build a table of the sub block numbers
   diag_printf("Building table of subBlocks\r");
   int subBlock[subBlocksRequired];
   for (int selected = 0; selected < subBlocksRequired; selected++)
   {
      #ifdef dbg_FLASH
         diag_printf("Outer Loop Start (selected = 0x%x\r", selected);
      #endif
      do
      {
         subBlock[selected] = subBlockFreePtr;
         subBlockFreePtr++;
         subBlockFreePtr = subBlockFreePtr % noSubBlocks;
      } while (subBlockTable[subBlock[selected]].state != unused);
      subBlockTable[subBlock[selected]].state = inuse;
      #ifdef dbg_FLASH
         diag_printf("Using subBlock 0x%x\r", selected);
      #endif
   }

   // Find an unused entry in the FAT and populate it
   int count = 0;
   #ifdef dbg_FLASH
      diag_printf("Looking for space in FAT...");
   #endif
   while (strcmp(FAT[count].name,"") != 0) count++;
   #ifdef dbg_FLASH
      diag_printf("added entry to FAT record 0x%x\r", count);
   #endif
   strcpy(FAT[count].name,name);
   FAT[count].length = length;
   FAT[count].start = subBlock[0];   
   fileCount++; 
   
   //## unlock FLASH mutex
   
   // populate the data to flash and update each record
   #ifdef dbg_FLASH
      diag_printf("writing data to FLASH...");
   #endif
   cyg_uint32 written = 0;      // how much data we have already written
   cyg_uint32 writeEnd;         // last data element to write in this subBlock
   char *pMem = data;
   for (count = 0; count < subBlocksRequired; count++)
   {
      // update subBlockTable
      //## lock FLASH mutex
      subBlockTable[subBlock[count]].next = (count != subBlocksRequired-1) ? subBlock[count+1] : FLASHNull;
      subBlockTable[subBlock[count]].prev = (count != 0) ? subBlock[count-1] : FLASHNull;
      //## unlock FLASH mutex
      
      // Calculate the start Address of the SubBlock
      cyg_uint32 writeAddress = getSubBlockAddress(subBlock[count]);
      #ifdef dbg_FLASH
         diag_printf("Writing subblock from address 0x%08x to ", writeAddress);
      #endif
      // calculate the amount of data to write
      cyg_uint32 writeLength = length - written;
      if (writeLength > subBlockSize)
      {
         writeEnd = writeAddress + subBlockSize;
         writeLength = subBlockSize;
      } else {
         writeEnd = writeAddress + writeLength;
      }
      #ifdef dbg_FLASH
         diag_printf("0x%08x \r\n", writeEnd);
      #endif
      //write to FLASH
      while (writeAddress < writeEnd)
      {
         cyg_uint16 tmp = *pMem++;                // 1st byte
         cyg_uint16 wdata = (*pMem++ << 8) | tmp; // 2nd byte
//         diag_printf("FLASHfileSystem::create   Writing 0x%x from 0x%x to 0x%x\r\n", flashWrite.writeData, pMem - 2, flashWrite.writeAddress);
         writeToFlash(wdata, writeAddress);
         writeAddress += 2;
      }      
      written += writeLength;        // amount of date written     
      diag_printf("written = 0x%08x \r\n", written);
      
      //## lock FLASH mutex
      subBlockTable[subBlock[count]].state = used;
      usedCount++;
      //## unlock FLASH mutex
   }
   #ifdef dbg_FLASH
      diag_printf("DONE\r\r FILE CREATED\r\r");
   #endif
   
   return true;
}   



// FLASH read file
bool FLASHfileSystem::readAll(char *name, int *length, char *data)
{
   // Confirm that this is flash we know about...
   if (!valid) return false;

   //## lock FLASH mutex
   
   // check that the filename exists
   int fileNumber = lookUp(name);
   if (fileNumber == FLASHFileNotFound) return false;
   
   // get file attributes
   *length = FAT[fileNumber].length;
   int subBlock = FAT[fileNumber].start;
   
   // allocate buffer to read data into
   if ((data = (char *) malloc(*length)) == NULL)
      return false;     // unable to allocate space in which to open the file
   
   
   // read the data from FLASH into RAM   
   int bytesRead = 0;
   char *storeAt = data;
   CYG_ADDRESS readAddress = getSubBlockAddress(subBlock);
   {
      int readLength = (*length - bytesRead <= subBlockSize) ? *length - bytesRead : subBlockSize;
      
      // read from FLASH into the buffer
      memcpy(storeAt, (char *)readAddress, readLength);
      
      // update pointers and counters
      storeAt += readLength;
      bytesRead += readLength;
      subBlock = subBlockTable[subBlock].next;
      readAddress = getSubBlockAddress(subBlock);      
   } while (readAddress != FLASHNull);
   
   //## unlock FLASH mutex
}



// recover 'dirty' areas of FLASH
void FLASHfileSystem::reclaimDirtyFLASH(void)
{
   while (dirtyCount >= noSubBlocksPerSuperBlock)
   {
      // find oldest dirtySubBlock
      int dirtySubBlock;
      do
      {
         dirtySubBlock = subBlockUsedPtr++;
         subBlockUsedPtr = subBlockUsedPtr % noSubBlocks;
      } while (subBlockTable[dirtySubBlock].state != dirty);
      
      // calculate the SuperBlock within which this subBlock resides
      int superBlockNo = dirtySubBlock / noSubBlocksPerSuperBlock;
      int baseSubBlockNo = dirtySubBlock - (dirtySubBlock % noSubBlocksPerSuperBlock);
      
      // re-loacate all used subblocks and update tables
      for (int count = baseSubBlockNo; count < (baseSubBlockNo + noSubBlocksPerSuperBlock); count++)
      {
         switch (subBlockTable[count].state)
         {
            case used:
            {   
               // relocate to another subBlock
               // find a new location to write to
               int newLocation;
               do
               {
                  newLocation = subBlockFreePtr++;
                  subBlockFreePtr = subBlockFreePtr % noSubBlocks;
               } while (subBlockTable[newLocation].state != unused);
               subBlockTable[newLocation].state = used;
               
               // Calculate the start Address of the SubBlock
               cyg_uint32 writeAddress = getSubBlockAddress(newLocation);
               cyg_uint32 writeEnd = writeAddress + subBlockSize ;
               char *pMem = (char *)getSubBlockAddress(count);
               
               //write to FLASH
               while (writeAddress < writeEnd)
               {
                  cyg_uint16 tmp = *pMem++;                // 1st byte
                  cyg_uint16 data = (*pMem++ << 8) | tmp;  // 2nd byte
                  #ifdef dbg_FLASH
                     diag_printf("reclaimDirtyFLASH:   Writing 0x%x from 0x%x to 0x%x\r\n", flashWrite.writeData, pMem - 2, flashWrite.writeAddress);
                  #endif
                  writeToFlash(data, writeAddress);
                  writeAddress += 2;
               }
                              
               // update FAT if required
               if (subBlockTable[count].prev == FLASHNull)
               {
                  // Find Entry in FAT
                  int FR = 0;
                  while (FAT[FR].start != count) FR++;
                  // Update start field
                  FAT[FR].start = newLocation  ;                    
               }
               
               // update linked list
               subBlockTable[newLocation].state = subBlockTable[count].state;
               subBlockTable[newLocation].next = subBlockTable[count].next;
               subBlockTable[newLocation].prev = subBlockTable[count].prev;
               subBlockTable[count].state = unused;
               subBlockTable[count].next = FLASHNull;
               subBlockTable[count].prev = FLASHNull;
               break;
            }
               
            case dirty:
            {
               // change the state to free and update counters
               subBlockTable[count].state = unused;
               subBlockTable[count].next = FLASHNull;
               subBlockTable[count].prev = FLASHNull;
               --dirtyCount;
               freeCount++;
               break;
            }
                   
            default:
               // do not change the subBlockTable entry for this subBlock
               // i.e. if the subBlock is marked as bad it will remain so
               // note however that the DATA in flash related to this 
               // subBlock WILL still be ERASED
               break;            
         }   
      }
      
      // erase the superBlock
      eraseBlock(superBlockTable[superBlockNo]);
   }   
}



// FLASH erase file        
bool FLASHfileSystem::erase(char *name)
{
   // Confirm that this is flash we know about...
   if (!valid) return false;

   //## lock FLASH mutex
   
   // check that the filename exists
   int fileNumber = lookUp(name);
   if (fileNumber == FLASHFileNotFound) return false;
   
   // delete file number and recover the 1st subBlock of the file
   strcpy(FAT[fileNumber].name,"");     // remove entry  
   int count = FAT[fileNumber].start;
   fileCount--; 
   
   do
   {
      subBlockTable[count].state = dirty;
      count = subBlockTable[count].next;
      dirtyCount++;
      --usedCount;
   }
   while (count != FLASHNull); 
   
   // reclaim SuperBlocks if possible
   reclaimDirtyFLASH();
   //## unlock FLASH mutex
}



// diagnostic routine to dump the current file structure to the serial port
void FLASHfileSystem::show(void)
{
   //## Lock FLASH mutex
   
   char buffer[128];
   sprintf(buffer, "File System information:");
   display (buffer);
   sprintf(buffer, "  noSuperBlocks            = 0x%x", noSuperBlocks);
   display (buffer);
   sprintf(buffer, "  subBlocksize             = 0x%x", subBlockSize);
   display (buffer);
   sprintf(buffer, "  noSubBlocksPerSuperBlock = 0x%x", noSubBlocksPerSuperBlock);
   display (buffer);
   sprintf(buffer, "  noSubBlocks              = 0x%x", noSubBlocks);
   display (buffer);
   sprintf(buffer, "  freeCount                = 0x%x", freeCount);
   display (buffer);
   sprintf(buffer, "  usedCount                = 0x%x", usedCount);
   display (buffer);
   sprintf(buffer, "  dirtyCount               = 0x%x", dirtyCount);
   display (buffer);
   sprintf(buffer, "  subBlockFreePtr          = 0x%x", subBlockFreePtr);
   display (buffer);
   sprintf(buffer, "  subBlockUsedPtr          = 0x%x", subBlockUsedPtr);
   display (buffer);
   sprintf(buffer, "  fileCount                = 0x%x", fileCount);
   display (buffer);
   
   sprintf(buffer, "  FAT      name      start     length");
   display (buffer);
   for (int count0 = 0; count0 < MAXFILES; count0++)
   {
      sprintf(buffer, "  FAT[0x%x] = %s, 0x%x, 0x%x", count0, FAT[count0].name, FAT[count0].start, FAT[count0].length);
      display (buffer);
   }
   sprintf(buffer, "  subBlock             state  next    prev    start address");
   display (buffer);
   for (int count1 = 0; count1 < noSubBlocks; count1++)
   {
      sprintf(buffer, "  subBlockTable[0x%04x] = %02d, 0x%04x, 0x%04x, 0x%08x", count1, subBlockTable[count1].state, subBlockTable[count1].next, subBlockTable[count1].prev, getSubBlockAddress(count1));
      display (buffer);
   }
   
   //## unlock FLASH mutex
} 



// show files in file system
void FLASHfileSystem::cat(void)
{
   //## Lock FLASH mutex
   
   char buffer[128];
   int files = 0;
   int used = 0;
   for (int count = 0; count < MAXFILES; count++)
   {
      if (strcmp(FAT[count].name,"") != 0)
      {
         sprintf(buffer, "%s 0x%x", FAT[count].name, FAT[count].length);
         display (buffer);
         files++;
         used += FAT[count].length;
      }
   }
   sprintf(buffer, "%d File(s) 0x%x Bytes\r        0x%x Bytes free\r\n", files, used, (freeCount+dirtyCount)*subBlockSize);
   display (buffer);
   
   //## unlock FLASH mutex
}


// open a file for read/write returning a handle if valid
int FLASHfileSystem::open(char *name, openFile *&handle)
{
   #ifdef dbg_FLASH
      diag_printf("open\r");
   #endif
   // Confirm that this is flash we know about...
   if (!valid) return FLASH_UnsupportedDevice;
   #ifdef dbg_FLASH
      diag_printf(" fileSystem is valid\r");
   #endif
   
   //Limit size of file name
   int nameLen = strlen(name);
   if (nameLen > MAXNAMELEN)
   {
      nameLen = MAXNAMELEN; 
   }      
   name[nameLen] = '\0';
   #ifdef dbg_FLASH
      diag_printf(" name = %s\r", name);
   #endif
   
   //## lock FLASH mutex
   
   // check if the filename exists
   int fileNumber = lookUp(name);
   if (fileNumber == FLASHFileNotFound) 
   {
      // file does not exist
      #ifdef dbg_FLASH
         diag_printf(" File does not exist - creating new file\r");
      #endif
      
      // check if there is space to create a new file
      if (fileCount == MAXFILES) return FLASH_TooManyFiles;
      
      // allocate 1st subBlock to the file (there has to be somewhere for the data!)
      if (freeCount < 1) return FLASH_OutOfSpace;
      freeCount--;
      usedCount++;
      int subBlockSelected;
      do
      {
         subBlockSelected = subBlockFreePtr;
         subBlockFreePtr++;
         subBlockFreePtr = subBlockFreePtr % noSubBlocks;
      } while (subBlockTable[subBlockSelected].state != unused);
      subBlockTable[subBlockSelected].state = inuse;
            
      // find a free entry in the FAT and populate it
      int count = 0;
      while (strcmp(FAT[count].name,"") != 0) count++;
      strcpy(FAT[count].name,name);
      FAT[count].length = 0;
      FAT[count].start = subBlockSelected; 
      fileCount++; 
      fileNumber = count;        
   } else {
      // file does exist
      #ifdef dbg_FLASH
         diag_printf(" Found file\r");
      #endif
      
      // check to see if the file is already open
      openFile *fwd = next;
      while (fwd != NULL)
      {
         if (fwd->fileNumber == fileNumber) return FLASH_FileAlreadyOpen;
         fwd = fwd->next;
      }
   }
   
   #ifdef dbg_FLASH
      diag_printf(" handle originly 0x%x\r", handle);
   #endif
   
   handle = new openFile(next, fileNumber);
   
   #ifdef dbg_FLASH      
      diag_printf(" handle 0x%x\r\n", handle);
   #endif
   
   //## unlock FLASH mutex
   return FLASH_OperationSuccessful;
}



// confirm that the handle given is valid
bool FLASHfileSystem::validateHandle(openFile *handle)
{
   // travers the linked list of open files to confirm that the handle does exist
   #ifdef dbg_FLASH
      diag_printf("validateHandle\r");
      diag_printf(" handle = 0x%x\r", handle);
   #endif
   
   openFile *fwd = next;
   while (fwd != NULL)
   {
      if (fwd == handle) 
      {
         #ifdef dbg_FLASH
            diag_printf(" handle is valid\r");
         #endif
         return true;
      }
      fwd = fwd->next;
   }
   #ifdef dbg_FLASH
      diag_printf(" handle is invalid\r");
   #endif
   return false;
}

   

int FLASHfileSystem::read(openFile *handle, size_t position, size_t *length, void *ptr)
{
   #ifdef dbg_FLASH
      diag_printf("FLASHfileSystem::read\r");
   #endif
   //## lock FLASH mutex
   
   // confirm that the handle is valid
   if (!validateHandle(handle)) return FLASH_InvalidHandle;
   
   size_t readPosition = position;
   size_t toRead = *length;
   *length = 0;
   char *buffer = (char *)ptr;
   char inChar;
   #ifdef dbg_FLASH 
      diag_printf(" reading...\r");
   #endif
   while (toRead > 0)
   {
      #ifdef dbg_FLASH
         diag_printf(" readPosition = 0x%x\r FAT[handle->fileNumber].length = 0x%x\r", readPosition, FAT[handle->fileNumber].length);
      #endif
      // check that the start position is inside the file
      if (readPosition > FAT[handle->fileNumber].length)
      {
         #ifdef dbg_FLASH
            diag_printf("\rFLASHfileSystem::read EOF DONE\r");
         #endif
         return FLASH_EOF;
      }
      
      // determine the subBlock that we are going to start from
      int subBlock = readPosition  / subBlockSize;
      
      // get the address of this subBlock
      int record = FAT[handle->fileNumber].start;
      for (int count = 1; count < subBlock; count++)
      {
         record = subBlockTable[record].next;
      } 
      int subBlockAddress = getSubBlockAddress(subBlock);
      int readAddress = subBlockAddress + (readPosition % subBlockSize);
      
      inChar = (*((char *)(readAddress)));
      #ifdef dbg_FLASH
         diag_printf("%c", inChar);
      #endif
      buffer[readPosition] = inChar;
      toRead-=1;
      *length = (size_t)readPosition++;
      #ifdef dbg_FLASH
         diag_printf(" bytes left to read = 0x%x\r we have read 0x%x bytes so far\r", toRead, length);
      #endif
   }
   
   //## unlock FLASHmutex
   #ifdef dbg_FLASH
      diag_printf("\rFLASHfileSystem::read DONE\r");
   #endif
   return FLASH_OperationSuccessful;
}




int FLASHfileSystem::write(openFile *handle, size_t position, size_t *length, void *ptr)
{
   //## lock FLASH mutex
   #ifdef dbg_FLASH
      diag_printf("write\r\n");
      diag_printf(" handle = 0x%x\r", handle);
      diag_printf(" position = 0x%x\r",position);
      diag_printf(" length = 0x%x\r", *length);
      diag_printf(" ptr = 0x%x\r", ptr);
   #endif
   
   // confirm that the handle is valid
   if (!validateHandle(handle)) return FLASH_InvalidHandle;
   
   // only support append type write
   #ifdef dbg_FLASH
      diag_printf(" FAT[handle->fileNumber].length = 0x%x\r", FAT[handle->fileNumber].length);
      diag_printf(" handle->fileNumber = 0x%x\r", handle->fileNumber);
   #endif
   if (position != FAT[handle->fileNumber].length) return FLASH_OporationNotSupported;
   
   
   size_t writePosition = position;
   size_t toWrite = *length;
   *length = 0;
   char *buffer = (char *)ptr;
   
   #ifdef dbg_FLASH
      diag_printf(" We are going to write 0x%x bytes to file 0x%x starting at position 0x%x\r", toWrite, handle->fileNumber, writePosition);
   #endif
   while (toWrite > 0)
   {      
      // determine the subBlock that we are going to start from
      int subBlock = writePosition  / subBlockSize;
      int record;
      
      #ifdef dbg_FLASH
         diag_printf("\r ---- \r");
      #endif
      
      if ((writePosition % subBlockSize != 0) || writePosition == 0)
      {
         // We are still inside the last subBlock
         #ifdef dbg_FLASH
            diag_printf(" This falls inside the last subBlock of the file\r");
         #endif
         
         // get the address of this subBlock
         record = FAT[handle->fileNumber].start;
         while (subBlockTable[record].next != FLASHNull)
         {
            record = subBlockTable[record].next;
         } 
      } else {
         // We have run out of space to write data.  Attempt to get another subBlock
         #ifdef dbg_FLASH
            diag_printf(" We have run out of space to write data.  Attempt to get another subBlock\r");
         #endif
         
         // Confirm that there is another free subBlock
         if (freeCount == 0) return FLASH_OutOfSpace;
         freeCount--;
         
         // get the last subBlock used by our file
         int lastSubBlock = FAT[handle->fileNumber].start;
         while (subBlockTable[lastSubBlock].next != FLASHNull)
         {
            lastSubBlock = subBlockTable[lastSubBlock].next;
         } 
         
         // obtain the subBlock
         do
         {
            record = subBlockFreePtr++;
            subBlockFreePtr = subBlockFreePtr % noSubBlocks;
         } while (subBlockTable[record].state != unused);
         subBlockTable[record].state = used;
         usedCount++;
         
         // add the new subBlock to the end of the linked list for our file
         subBlockTable[lastSubBlock].next = record;
         subBlockTable[record].prev = lastSubBlock;
         subBlockTable[record].next = FLASHNull;
      }
      
      // get the address to write to
      int subBlockAddress = getSubBlockAddress(record);
      int writeAddress = subBlockAddress + (writePosition % subBlockSize);
      
      #ifdef dbg_FLASH
         diag_printf(" subBlock Record number = 0x%x\r at address 0x%x\r we will write from address 0x%x\r", record, subBlockAddress, writeAddress);
      #endif
      
      // perform actual write operation
      // note that this is a 16 bit oporation but we want to work in bytes!
      if (writeAddress % 2 == 0)
      {
         // even address
         cyg_uint16 data = 0xff00 | *buffer++;              // LSB will be the byte to write MSB will be blank (0xff)
         #ifdef dbg_FLASH
            diag_printf(" even write data = 0x%04x\r", data);
         #endif
         writeToFlash(data, writeAddress);
      } else {
         // odd address
         cyg_uint16 *tmp = (cyg_uint16 *)(writeAddress-1);   // LSB is read from device
         cyg_uint16 rval = *tmp;
         #ifdef dbg_FLASH
            diag_printf(" odd write\r  read 0x%04x\r  rval = 0x%04x\r", *tmp, rval);
         #endif
         rval &= 0x00ff;                                     // just interested in the lower byte
         #ifdef dbg_FLASH
            diag_printf("  after mask 0x%04x\r", rval);
            diag_printf("  *buffer = 0x%x\r", *buffer);
         #endif
         cyg_uint16 wchar = (cyg_uint16)*buffer++;
         #ifdef dbg_FLASH
            diag_printf("  wchr before rotate = 0x%04x\r", wchar);
         #endif
         wchar = wchar << 8;
         #ifdef dbg_FLASH
            diag_printf("  wchr after rotate = 0x%04x\r", wchar);
         #endif
         cyg_uint16 data = wchar | rval;          // MSB is the byte to program
         
         #ifdef dbg_FLASH
            diag_printf("  value to write 0x%04x\r", data);
         #endif
         writeToFlash(data, writeAddress-1);
      }
      
      // update counts
      FAT[handle->fileNumber].length++;   // file length
      toWrite--;                          // number of bytes left to write
      *length++;                          // number of bytes written
      writePosition++;                    // where to write data to next...
   }
      
   return FLASH_OperationSuccessful;
}



// closes an open file.  free's up any available resources.
int FLASHfileSystem::close(openFile *handle)
{
   //## lock FLASH mutex
   
   // confirm that the handle is valid
   if (!validateHandle(handle)) return FLASH_InvalidHandle;
   
   // free up resources if possible
   if (FAT[handle->fileNumber].length == 0)
   {
      subBlockTable[FAT[handle->fileNumber].start].state = unused;   // mark block as free
      freeCount++;                                                   // number of free blocks +1
      usedCount--;                                                   // return used block to free state
      fileCount--;                                                   // count of files -1
      strcpy(FAT[handle->fileNumber].name,"");                       // remove entry from FAT 
   }
   
   delete handle;
   
   //## unlock FLASH mutex
   return FLASH_OperationSuccessful;
}


openFile::openFile(openFile *&fwd, int fileNum)
{
   // add the handle to the linked list of all open files
   #ifdef dbg_FLASH
      diag_printf("openFile::openFile\r");
   #endif
      
   if (fwd == NULL)
   {
      #ifdef dbg_FLASH
         diag_printf(" No files open\r");
      #endif
      fwd = this;
      prev = NULL;
      next = NULL;
   } else {
      #ifdef dbg_FLASH
         diag_printf(" files are open\r");
      #endif
      while (fwd->next != NULL)
      {
         #ifdef dbg_FLASH
            diag_printf(" advaning down the list\r");
         #endif
         fwd = fwd->next;
      } 
      #ifdef dbg_FLASH
         diag_printf(" adding record to the list\r");
      #endif
      fwd->next = this;
      prev = fwd;
      next = NULL;
   }
   
   #ifdef dbg_FLASH
      if (prev == NULL)
      {
         diag_printf(" prev = NULL\r");
      } else {  
         diag_printf(" prev = 0x%x\r", prev);
      }
      
      if (next == NULL)
      {
         diag_printf(" next = NULL\r");
      } else {  
         diag_printf(" next = 0x%x\r", next);
      }
      
      if (sys->fs->next == NULL)
      {
         diag_printf(" sys->fs->next = NULL\r");
      } else {  
         diag_printf(" sys->fs->next = 0x%x\r", sys->fs->next);
      }
      
      
      diag_printf("openFile::openFile DONE\r");
   #endif
      
   fileNumber = fileNum;
   
}


openFile::~openFile()
{
   #ifdef dbg_FLASH
      diag_printf("openFile::~openFile\r");
   #endif
   // remove entry from the linked list of open files
   if (prev != NULL)
   {
      prev->next = next;
   } else {
      sys->fs->next = next;
   }
   if (next != NULL) next->prev = prev;
   
   #ifdef dbg_FLASH
      if (prev == NULL)
      {
         diag_printf(" prev = NULL\r");
      } else {  
         diag_printf(" prev = 0x%x\r", prev);
      }
      
      if (next == NULL)
      {
         diag_printf(" next = NULL\r");
      } else {  
         diag_printf(" next = 0x%x\r", next);
      }
      
      if (sys->fs->next == NULL)
      {
         diag_printf(" sys->fs->next = NULL\r");
      } else {  
         diag_printf(" sys->fs->next = 0x%x\r", sys->fs->next);
      }
      diag_printf("openFile::~openFile DONE\r");
   #endif
}

[-- Attachment #5: FLASHFileSystem.h --]
[-- Type: text/x-c++, Size: 3715 bytes --]

// FLASHFileSystem.h
#ifndef __FLASHFILESYSTEM_H__
#define __FLASHFILESYSTEM_H__

#include <cyg/kernel/kapi.h>            /* All the kernel specific stuff */
#include <cyg/hal/hal_arch.h>           /* CYGNUM_HAL_STACK_SIZE_TYPICAL */
#include "eCosIvory/flash.h"             // flash device primatives
#include "eCosIvory/filesystem.h"

// The following values need to be defined with care
#define  MAXFILES                16
#define  MAXNAMELEN              8
#define  NUMSUPERBLOCKS          4
#define  SUBBLOCKSPERSUPERBLOCK  8
#define  SUBBLOCKSIZE            128
#define  SUPERBLOCKS   {flash_SA15, flash_SA16, flash_SA17, flash_SA18}
                          
// you should not need to make changes past this point
                          
#define  NUMSUBBLOCKS         (SUBBLOCKSPERSUPERBLOCK * NUMSUPERBLOCKS)
#define  FLASHFileNotFound    MAXFILES
#define  FLASHNull            NUMSUBBLOCKS

typedef enum
{
   unallocated = 0,
   unused      = 1,
   inuse       = 2,
   used        = 3,
   dirty       = 4,
   bad         = 5
} subBlockState;



class subBlockRecord
{
   public:
      subBlockState  state;
      int            next;
      int            prev;
//      CYG_ADDRESS    FLASHAddress;
};

class FATRecord
{
   public:
      char        name[MAXNAMELEN + 1];
      int         start;
      cyg_uint32  length;
};
      
class openFile
{
   public:
      openFile(openFile *&fwd, int FileNum);
     ~openFile();
      int fileNumber;   // which file we are dealing with
      openFile *next;   // the next file in the linked list of open files
      openFile *prev;   // the previous file in the linked list of open files
};
      
class FLASHfileSystem : public fileSystem
{
   friend class openFile;
   
   public:
      FLASHfileSystem();      // constructor
     ~FLASHfileSystem();     // destructor
     
      bool format(void);
      bool create(int length, char *data, char *name);
      bool readAll(char *name, int *length, char *data);
      bool erase(char *name);
      void show(void);
      void cat(void);
      int open(char *name, openFile *&handle);
      int read(openFile *handle, size_t position, size_t *length, void *ptr);
      int write(openFile *handle, size_t position, size_t *length, void *ptr);
      int close(openFile *handle);
     
   private: 
   // methods
      bool           eraseBlock(CYG_ADDRESS superblock);
      bool           writeToFlash(cyg_uint16 writeData, cyg_uint32 writeAddress);
      int            lookUp(char *name);
      cyg_uint32     getSubBlockAddress(int subBlockNumber);
      void           reclaimDirtyFLASH(void);
      bool           validateHandle(openFile *handle);

      
   // data
      CYG_ADDRESS    superBlockTable[NUMSUPERBLOCKS];
      subBlockRecord subBlockTable[NUMSUBBLOCKS];
      FATRecord      FAT[MAXFILES];
      int            freeCount;
      int            usedCount;
      int            dirtyCount; 
      int            subBlockFreePtr;
      int            subBlockUsedPtr;
      int            fileCount;     
      openFile       *next;


   // The following are almost constants      
      int            noSuperBlocks;  
      int            subBlockSize;
      int            noSubBlocksPerSuperBlock;
      int            noSubBlocks;
};

#define FLASH_OperationSuccessful       0
#define FLASH_FileNotFound             -1
#define FLASH_OporationNotSupported    -2
#define FLASH_OutOfSpace               -3
#define FLASH_TooManyFiles             -4
#define FLASH_EOF                      -5
#define FLASH_UndefinedError           -6
#define FLASH_UnsupportedDevice        -7
#define FLASH_FileAlreadyOpen          -8
#define FLASH_InvalidHandle            -9

#endif __FLASHFILESYSTEM_H__

[-- Attachment #6: FlashRAM.cpp --]
[-- Type: text/x-c, Size: 10431 bytes --]

/*-----------------------------------------------------------------------------
 *
 *      (c) Tardis Mobile - 2000
 *
 *      Name: flash.c
 *
 *      Author: A Simpkins
 *
 *      Date: 04 October
 *
 *-----------------------------------------------------------------------------
 *
 *      Modification history:
 *
 * ---  14/08/2001 002 - converted to eCos
 *      04/10/2000 001 - Initial functions to test FLASH; flashEraseSegment & 
 *                       flashWrite.
 * 
 *
 *-----------------------------------------------------------------------------
 */

#include <cyg/kernel/kapi.h>            /* All the kernel specific stuff */
#include <cyg/hal/t3.h>    
#include <eCosIvory/flash.h>
#include <cyg/io/eCosSiRF.h>

#if CYGHWR_HAL_ARM_TARDIS3_VERSION == 1
/* FLASH addresses corrected for address line error on hardware */
struct flashEscape flashDeviceInfoSeq =
{  
   0x03,
   { 
      (startAddressFLASH + (0x00001554)), 0x00aa, 
      (startAddressFLASH + (0x00000aaa)), 0x0055,
      (startAddressFLASH + (0x00001554)), 0x0090 
   }
};


struct flashEscape flashEraseSectorSeq =
{
   0x05,
   {
      (startAddressFLASH + 0x00001554), 0x00aa, 
      (startAddressFLASH + 0x00000aaa), 0x0055,
      (startAddressFLASH + 0x00001554), 0x0080,
      (startAddressFLASH + 0x00001554), 0x00aa,
      (startAddressFLASH + 0x00000aaa), 0x0055
   }
};



struct flashEscape flashWriteSeq =
{
   0x03,
   {
      (startAddressFLASH + 0x00001554), 0x00aa, 
      (startAddressFLASH + 0x00000aaa), 0x0055,
      (startAddressFLASH + 0x00001554), 0x00A0
   }
};



struct flashEscape flashEraseAllSeq =
{
   0x06,
   {
      (startAddressFLASH + 0x00001554), 0x00aa, 
      (startAddressFLASH + 0x00000aaa), 0x0055,
      (startAddressFLASH + 0x00001554), 0x0080,
      (startAddressFLASH + 0x00001554), 0x00aa,
      (startAddressFLASH + 0x00000aaa), 0x0055,
      (startAddressFLASH + 0x00001554), 0x0010
   }
};




#else
/* FLASH address values from AMD datasheet 
   NOTE : addresses are for 8-bit access data is for 16-bit access
          all other combinations do not work!
*/

struct flashEscape flashDeviceInfoSeq =
{
   0x03,
   { 
      (startAddressFLASH + 0x00000aaa), 0xaa, 
      (startAddressFLASH + 0x00000555), 0x55,
      (startAddressFLASH + 0x00000aaa), 0x90 
   }
};


struct flashEscape flashEraseSectorSeq =
{
   0x05,
   {
      (startAddressFLASH + 0x00000aaa), 0xaa, 
      (startAddressFLASH + 0x00000555), 0x55,
      (startAddressFLASH + 0x00000aaa), 0x80,
      (startAddressFLASH + 0x00000aaa), 0xaa,
      (startAddressFLASH + 0x00000555), 0x55
   }
};



struct flashEscape flashWriteSeq =
{
   0x03,
   {
      (startAddressFLASH + 0x00000aaa), 0xaa, 
      (startAddressFLASH + 0x00000555), 0x55,
      (startAddressFLASH + 0x00000aaa), 0xA0
   }
};



struct flashEscape flashEraseAllSeq =
{
   0x06,
   {
      (startAddressFLASH + 0x00000aaa), 0xaa, 
      (startAddressFLASH + 0x00000555), 0x55,
      (startAddressFLASH + 0x00000aaa), 0x80,
      (startAddressFLASH + 0x00000aaa), 0xaa,
      (startAddressFLASH + 0x00000555), 0x55,
      (startAddressFLASH + 0x00000aaa), 0x10
   }
};


#endif


void __attribute__ ((section (".2ram.playFlashEscapeSeq"))) playFlashEscapeSeq (struct flashEscape *sequence)
{
   volatile cyg_uint16 *pMem;
   
   for (cyg_uint16 count = 0; count < sequence->length; count++)
   {
      pMem = (cyg_uint16* )sequence->flashpair[count].pairAddress;
      *pMem = sequence->flashpair[count].pairData;
   }
}
 
void __attribute__ ((section (".2ram.flashReset"))) flashReset(void)
{
   volatile cyg_uint16 *pMem;
   
   pMem = (cyg_uint16 *)startAddressFLASH;
   *pMem = flash_reset;
}


cyg_uint32 __attribute__ ((section (".2ram.flash_query"))) flash_query(cyg_uint32 *callAddr)
{
   flashcmd *data = (flashcmd *)callAddr;
   bool cacheOn = false;
   
   switch (data->flashCommand)
   {
      // Read the FLASH device information
      case flashCmd_Info:  
         int old;
         HAL_DISABLE_INTERRUPTS(old);  // disable interrupts 
  
         if (ASIC_CACHE_EN == 0x0001)
         {
            cacheOn = true;
            ASIC_CACHE_EN = 0x0000; // dissable cache
         }
               
         flashReset();
         playFlashEscapeSeq(&flashDeviceInfoSeq);
         volatile cyg_uint16 *pMem;
         pMem =(cyg_uint16 *)flash_make;
         ((infoFlashCmd *)data)->make = *pMem;
         flashReset();
         playFlashEscapeSeq(&flashDeviceInfoSeq);
         pMem =(cyg_uint16 *)flash_deviceID;
         ((infoFlashCmd *)data)->deviceID = *pMem;
         flashReset();
         
         if (cacheOn) ASIC_CACHE_EN = 0x0001;    // re-enable cache
               
         HAL_RESTORE_INTERRUPTS(old);  // re-enable interrupts
         break;
      
      // Erase the specified sector
      // Erasing sectors on a FLASH device may take a while.  Because we can not run code from the 
      // FLASH during this time, we should dissable interrupts.  Whilst we poll the FLASH to see if 
      // the opoeration has compleated we should also poll the interrupt status, is an interrupt has 
      // occured then we should suspend the FLASH oporation, enable (thus handle) interrupts before 
      case flashCmd_Erase:
         {
            int old;
            HAL_DISABLE_INTERRUPTS(old);  // disable interrupts
            
            if (ASIC_CACHE_EN == 0x0001)
            {
               cacheOn = true;
               ASIC_CACHE_EN = 0x0000; // dissable cache
            }
            
            ((eraseFlashCmd *)data)->onHold = false; 
            
            flashReset();
            
            playFlashEscapeSeq(&flashEraseSectorSeq);
            
            volatile cyg_uint16 *pMem;           
            pMem = (cyg_uint16 *)((eraseFlashCmd *)data)->sectorNo;
            *pMem = flash_eraseSectorCmd;
            
                  
            while ((*pMem & flash_DQ7) == 0)
            {
               // ### fix me
               // what about a timeout - i.e. if the FLASH never finishes erasing the sector?
               
               // check to see if an interrupt has occured
               if (ASIC_INTREG & SiRFIRQ != 0)
               {
                  *pMem = 0xB0;                             // Suspend erase
                  ((eraseFlashCmd *)data)->onHold = true;   // flag erase incompleate
                  break;                                    // terminate the while loop
               }
            } 
                        
            if (((eraseFlashCmd *)data)->onHold == true)
            {
               // on hold so not compleated
               ((eraseFlashCmd *)data)->success = false;
            } else {
               // we have compleated signal this and reset FLASH
               ((eraseFlashCmd *)data)->success = true;
               flashReset();
            }
            
            if (cacheOn) ASIC_CACHE_EN = 0x0001;    // re-enable cache
               
            HAL_RESTORE_INTERRUPTS(old);  // re-enable interrupts
            break;
         }
         
         
         
      case flashCmd_ResumeErase:
         {
            int old;
            HAL_DISABLE_INTERRUPTS(old);  // disable interrupts
            
            if (ASIC_CACHE_EN == 0x0001)
            {
               cacheOn = true;
               ASIC_CACHE_EN = 0x0000; // dissable cache
            }
               
            volatile cyg_uint16 *pMem;  
            pMem = (cyg_uint16 *)((eraseFlashCmd *)data)->sectorNo;
            *pMem = 0x30;                 // continue erasing FLASH
            
            ((eraseFlashCmd *)data)->onHold = false;
                    
            while ((*pMem & flash_DQ7) == 0)
            {
               // ### fix me
               // what about a timeout - i.e. if the FLASH never finishes erasing the sector?
               
               
               // check to see if an interrupt has occured
               if (ASIC_INTREG & SiRFIRQ != 0)
               {
                  *pMem = 0xB0;                             // Suspend erase
                  ((eraseFlashCmd *)data)->onHold = true;   // flag suspended
                  break;                        // terminate the while loop
               }
            }  
            
            if (((eraseFlashCmd *)data)->onHold)
            {
               ((eraseFlashCmd *)data)->success = false;
            } else {
               ((eraseFlashCmd *)data)->success = true;
               flashReset();
            }
            
            if (cacheOn) ASIC_CACHE_EN = 0x0001;    // re-enable cache
                      
            HAL_RESTORE_INTERRUPTS(old);  // re-enable interrupts
            
            break;
         }
         
      
      case flashCmd_Write:
         {
            // test for bad address (we can only program 16 bit data at an even address)
            if (((writeFlashCmd *)data)->writeAddress % 2 == 1 )
            {
               ((writeFlashCmd *)data)->result = flashResult_badAddress;
            } else { 
               
               int old;
               HAL_DISABLE_INTERRUPTS(old);  // disable interrupts
               
               if (ASIC_CACHE_EN == 0x0001)
               {
                  cacheOn = true;
                  ASIC_CACHE_EN = 0x0000; // dissable cache
               }
               
               
                             
               flashReset();
               playFlashEscapeSeq(&flashWriteSeq);
               
               volatile cyg_uint16 *pMem; 
               pMem = (cyg_uint16 *)((writeFlashCmd *)data)->writeAddress;               
               cyg_uint16 writeChar = ((writeFlashCmd *)data)->writeData;
               *pMem = writeChar;
                              
               while ( (*pMem & flash_DQ7) != (writeChar & flash_DQ7) )
               {
                  // ### fix me
                  // what about a timeout - i.e. if the FLASH never finishes programming?
               }
                    
               flashReset();                  
               
               if (cacheOn) ASIC_CACHE_EN = 0x0001;    // re-enable cache
               
               HAL_RESTORE_INTERRUPTS(old);  // re-enable interrupts
               ((writeFlashCmd *)data)->result = flashResult_OK;
            
            }   
            break;
         }

                     
      default:
      break;
   }
   return 1;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2001-09-26  1:16 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-09-25 12:27 [ECOS] Flash Programming Example with ecos Jeffrey Jopling
2001-09-25 23:58 ` Jesper Skov
2001-09-26  1:16 Simpkins, Andy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).