flashWrite.c File Reference

Flash manipulation functions. More...

#include "inc/freeEMS.h"
#include "inc/utils.h"
#include "inc/flashWrite.h"
#include "inc/flashBurn.h"
#include "inc/commsISRs.h"
#include "inc/commsCore.h"
#include <string.h>
Include dependency graph for flashWrite.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define FLASHWRITE_C

Functions

unsigned short eraseSector (unsigned char PPage, unsigned short *flashAddr)
 Erases a sector of flash memory.
unsigned short writeBlock (blockDetails *details, void *buffer)
 Writes a block of memory to flash.
unsigned short writeSector (unsigned char RPage, unsigned short *RAMSourceAddress, unsigned char PPage, unsigned short *flashDestinationAddress)
 Writes a sector from memory to a sector in flash.
unsigned short writeWord (unsigned short *flashDestination, unsigned short data)
 Program Command.

Detailed Description

Flash manipulation functions.

This file contains all functions that operate directly or indirectly and only on flash memory. They are used for erasing data from and reprogramming data to the embedded flash non-volatile storage area.

Author:
Sean Keys, Fred Cooke

Definition in file flashWrite.c.


Define Documentation

#define FLASHWRITE_C

Definition at line 39 of file flashWrite.c.


Function Documentation

unsigned short eraseSector ( unsigned char  PPage,
unsigned short *  flashAddr 
)

Erases a sector of flash memory.

This will erase a 1k sector in flash. Write 0xFFFF to the starting sector to be erased, 0xFFFF will be written regardless. Register the flash sector erase command(0x40) and call StackBurner();. If you try to erase a protected sector you will get PVIOL in the FSTAT register.

Author:
Sean Keys
Warning:
This will erase an entire 1k block starting at flashAddr
Parameters:
PPage the flash page the sector is in
flashAddr the start address of the sector
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 65 of file flashWrite.c.

References ACCERR, addressNotSectorAligned, FCMD, flashSectorSize, FSTAT, PPAGE, PVIOL, SECTOR_ERASE, and StackBurner().

Referenced by decodePacketAndRespond(), initXgate(), and writeSector().

00065                                                                           {
00066 
00067     if (((unsigned short)flashAddr % flashSectorSize) != 0){
00068         return addressNotSectorAligned;
00069     }
00070     unsigned char currentPage = PPAGE;
00071     PPAGE = PPage;
00072     FSTAT = (PVIOL|ACCERR); /* clear any errors */
00073     (*flashAddr) = 0xFFFF;     /* Dummy data to first word of page to be erased it will write FFFF regardless with the erase command*/
00074     PPAGE = currentPage;
00075     FCMD = SECTOR_ERASE;            /* set the flash command register mode to ERASE */
00076     StackBurner();   //PPAGE loaded into Register B, PPAGE is set with Reg B in StackBurn asm file
00077     //TODO add return for accerr and pviol error bits
00078 
00079     // @todo TODO verify the erase, is this necessary or is it taken care of by the hardware??
00080     return 0;
00081 }

Here is the call graph for this function:

unsigned short writeBlock ( blockDetails details,
void *  buffer 
)

Writes a block of memory to flash.

The block size must either be under 1024, or an exact multiple of 1024. Additionally, if under 1024 the destination should be within a single flash sector, and if a multiple of 1024, the destination should be sector aligned.

Because the ram version will be in an arbitrary place we need to base our positioning from the flash location. Firstly we need to ensure that it doesn't cross any sector boundaries. Then we need to find the address of the sector to be burned to. We also need to determine if there are 2 or 3 chunks of memory to be copied to the buffer, three cases exist for that :

| From Flash | From RAM | From flash | | From Flash | From RAM | | From RAM | From Flash |

Warning:
Limited to 63k per write! (obviously)
Author:
Fred Cooke
Parameters:
details contains the RAM address and page to be read from, the flash address and page to be burned to and the size to be read.
buffer is a pointer to a block of RAM at least 1024 bytes long used to allow small chunks to be burned independently.
Returns:
An error code. Zero means success, anything else is a failure.

Definition at line 110 of file flashWrite.c.

References blockDetails::FlashAddress, blockDetails::FlashPage, flashSectorSize, flashSectorSizeInWords, PPAGE, blockDetails::RAMAddress, blockDetails::RAMPage, RPAGE, blockDetails::size, sizeNotMultipleOfSectorSize, sizeOfBlockToBurnIsZero, smallBlockCrossesSectorBoundary, and writeSector().

Referenced by decodePacketAndRespond().

00110                                                               {
00111     unsigned char sectors;
00112     unsigned char RAMPage;
00113     /* FlashPage is always the one provided and is just used as is. */
00114     unsigned short* RAMAddress;
00115     unsigned short* FlashAddress;
00116 
00117     /* Check that the size isn't zero... */
00118     if(details->size == 0){
00119         return sizeOfBlockToBurnIsZero;
00120     }else if(details->size < 1024){
00121         unsigned short chunkFlashAddress = (unsigned short)details->FlashAddress;
00122         /* Get the offset from the start of the sector */
00123         unsigned short offset = chunkFlashAddress % flashSectorSize;
00124 
00125         /* Check for flash sector boundary crossing */
00126         if((offset + details->size) > 1024){
00127             return smallBlockCrossesSectorBoundary;
00128         }
00129 
00130         /* Configure the final burn variables */
00131         sectors = 1; /* By definition if we are in this code there is only one */
00132         RAMPage = RPAGE; /* The buffer is always in linear RAM region */
00133         RAMAddress = buffer; /* Save the buffer start address */
00134         FlashAddress = (unsigned short*)(chunkFlashAddress - offset); /* Get the start of the flash sector */
00135 
00136         /* Possibly three parts to copy to the buffer, copy only what is required */
00137 
00138         /* Save the PPAGE value and set the flash page */
00139         unsigned char oldFlashPage = PPAGE;
00140         PPAGE = details->FlashPage;
00141 
00142         /* If the chunk doesn't start at the beginning of the sector, copy the first area from flash */
00143         if(offset != 0){
00144             memcpy(buffer, FlashAddress, offset);
00145             buffer += offset;
00146         }
00147 
00148         /* Copy the middle section up regardless */
00149         unsigned char oldRAMPage = RPAGE;
00150         RPAGE = details->RAMPage;
00151         memcpy(buffer, details->RAMAddress, details->size);
00152         buffer += details->size;
00153         RPAGE = oldRAMPage;
00154 
00155         /* If the chunk doesn't end at the end of the sector, copy the last are from flash */
00156         if((offset + details->size) < 1024){
00157             void* chunkFlashEndAddress = details->FlashAddress + details->size;
00158             memcpy(buffer, chunkFlashEndAddress, (1024 - (offset + details->size)));
00159         }
00160 
00161         /* Restore the PPAGE value back */
00162         PPAGE = oldFlashPage;
00163     } else {
00164         /* If not smaller than 1024, check size is product of sector size */
00165         if((details->size % flashSectorSize) != 0){
00166             return sizeNotMultipleOfSectorSize;
00167         }
00168 
00169         /* Set the variables to what they would have been before */
00170         sectors = details->size / flashSectorSize;
00171         RAMPage = details->RAMPage;
00172         RAMAddress = (unsigned short*)details->RAMAddress;
00173         FlashAddress = (unsigned short*)details->FlashAddress;
00174     }
00175 
00176     unsigned char i;
00177     for(i=0;i<sectors;i++){
00178         unsigned short errorID = writeSector(RAMPage, RAMAddress, details->FlashPage, FlashAddress);
00179         if(errorID != 0){
00180             return errorID;
00181         }
00182         /* Incrementing a pointer is done by blocks the size of the type, hence 512 per sector here */
00183         RAMAddress += flashSectorSizeInWords;
00184         FlashAddress += flashSectorSizeInWords;
00185     }
00186     // @todo TODO verify the write? necessary??
00187     return 0;
00188 }

Here is the call graph for this function:

unsigned short writeSector ( unsigned char  RPage,
unsigned short *  RAMSourceAddress,
unsigned char  PPage,
unsigned short *  flashDestinationAddress 
)

Writes a sector from memory to a sector in flash.

Uses writeWord to write a 1k block from sourceAddress(RAM) to flashDestinationAddress, one word at a time. Give it the starting memory address and the destination flash address. Both addresses will be incremented by 1 word after a successful writeWord, until the whole 1024 byte sector has been written. Before any writing occurs eraseSector is called to make sure the destination is blank.

Author:
Sean Keys
Parameters:
RPage the page of RAM the RAMSourceAddress is located
RAMSourceAddress the address of the source data
PPage the page of flash where your flashDestinationAddress is located
flashDestinationAddress where your data will be written to in flash
Returns:
an error code. Zero means success, anything else is a failure.

Todo:
TODO Decide if we need to disable interrupts since we are manually setting Flash/RAM pages.

Definition at line 209 of file flashWrite.c.

References addressNotFlashRegion, addressNotSectorAligned, eraseSector(), flashSectorSize, flashSectorSizeInWords, PPAGE, RPAGE, and writeWord().

Referenced by decodePacketAndRespond(), initXgate(), and writeBlock().

00209                                                                                                                                                 {
00210 
00211     if(((unsigned short)flashDestinationAddress % flashSectorSize) != 0){
00212             return addressNotSectorAligned;
00213     }
00214 
00215     if(((unsigned short)flashDestinationAddress) < 0x4000){
00216         return addressNotFlashRegion;
00217     }
00218 
00220     eraseSector((unsigned char)PPage, (unsigned short*)flashDestinationAddress);  /* First Erase our destination block */
00221 
00222     unsigned short wordCount = flashSectorSizeInWords;
00223 
00224     /* Save pages */
00225     unsigned char currentRPage = RPAGE;
00226     unsigned char currentPPage = PPAGE;
00227 
00228     /* Switch pages */
00229     RPAGE = RPage;
00230     PPAGE = PPage;
00231 
00232     while (wordCount > 0)
00233     {
00234         unsigned short sourceData = *RAMSourceAddress; /*Convert the RAMAddr to data(dereference) */
00235         unsigned short errorID = writeWord(flashDestinationAddress, sourceData);
00236         if(errorID != 0){
00237             return errorID;
00238         }
00239         RAMSourceAddress++;
00240         flashDestinationAddress++;
00241         wordCount--; /* Decrement our word counter */
00242     }
00243 
00244     /* Restore pages */
00245     RPAGE = currentRPage;
00246     PPAGE = currentPPage;
00247     // @todo TODO verify the write? necessary??
00248     return 0;
00249 }

Here is the call graph for this function:

unsigned short writeWord ( unsigned short *  flashDestination,
unsigned short  data 
)

Program Command.

This will write 1 word to an empty(0xFFFF) flash address. If you try to write to an address containing data(not 0xFFFF),an error will register at FSTAT. The embedded algorithm works like this, just write to the desired flash address as you would any other writable address. Then register the program command(0x20) at FCDM, the rest is handled by StackBurner();

Author:
Sean Keys
Warning:
Be sure your destination address is not protected or you will flag an error in FSTAT
Parameters:
flashDestination where you want to write your data
data the data you are going to write
Returns:
an error code. Zero means success, anything else is a failure.

Definition at line 269 of file flashWrite.c.

References ACCERR, addressNotWordAligned, FCMD, FSTAT, PVIOL, StackBurner(), and WORD_PROGRAM.

Referenced by writeSector().

00269                                                                                {
00270     if((unsigned short)flashDestination & 0x0001){
00271         return addressNotWordAligned;
00272     }
00273 
00274     FSTAT=(ACCERR | PVIOL);
00275     *flashDestination = data;
00276     FCMD = WORD_PROGRAM;        //Load Flash Command Register With Word_Program mask
00277     StackBurner();
00278 
00279     // @todo TODO verify the write? necessary??
00280     return 0;
00281 }

Here is the call graph for this function:

Generated on Sat Oct 16 21:29:09 2010 for FreeEMS by  doxygen 1.6.3