flashWrite.c File Reference

Flash manipulation functions. More...

#include "inc/freeEMS.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:

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 38 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 63 of file flashWrite.c.

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

Referenced by decodePacketAndRespond(), and writeSector().

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

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 107 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().

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

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 205 of file flashWrite.c.

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

Referenced by decodePacketAndRespond(), and writeBlock().

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

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 264 of file flashWrite.c.

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

Referenced by writeSector().

00264                                                                                {
00265     if((unsigned short)flashDestination & 0x0001){
00266         return addressNotWordAligned;
00267     }
00268 
00269     FSTAT=(ACCERR | PVIOL);
00270     *flashDestination = data;
00271     FCMD = WORD_PROGRAM;        //Load Flash Command Register With Word_Program mask
00272     StackBurner();
00273 
00274     return 0;
00275 }

Here is the call graph for this function:


Generated on Mon Jan 26 00:16:56 2009 for FreeEMS by  doxygen 1.5.8