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>
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. |
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.
Definition in file flashWrite.c.
#define FLASHWRITE_C |
Definition at line 39 of file flashWrite.c.
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.
PPage | the flash page the sector is in | |
flashAddr | the start address of the sector |
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 }
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 |
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. |
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 }
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.
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 |
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 }
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();
flashDestination | where you want to write your data | |
data | the data you are going to write |
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 }