flashWrite.c

Go to the documentation of this file.
00001 /*      flashWrite.c
00002 
00003         Copyright 2008 Sean Keys
00004 
00005         This file is part of the FreeEMS project.
00006 
00007         FreeEMS software is free software: you can redistribute it and/or modify
00008         it under the terms of the GNU General Public License as published by
00009         the Free Software Foundation, either version 3 of the License, or
00010         (at your option) any later version.
00011 
00012         FreeEMS software is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU General Public License for more details.
00016 
00017         You should have received a copy of the GNU General Public License
00018         along with any FreeEMS software.  If not, see <http://www.gnu.org/licenses/>.
00019 
00020         We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org
00021 
00022         Thank you for choosing FreeEMS to run your engine! */
00023 
00024 #define FLASHWRITE_C
00025 #include "inc/freeEMS.h"
00026 #include "inc/flashWrite.h"
00027 #include "inc/flashBurn.h"
00028 #include "inc/commsISRs.h"
00029 
00030 
00031 
00032 
00033 /**************************************************************************************************************/
00034 /*      27.4.2.4 Sector Erase Command
00035 
00036         The sector erase operation will erase all addresses in a 1 Kbyte sector of Flash memory using an embedded
00037         algorithm.
00038 
00039         An example flow to execute the sector erase operation is shown in Figure 27-29. The sector erase
00040         command write sequence is as follows:
00041 
00042         1. Write to a Flash block address to start the command write sequence for the sector erase command.
00043         The Flash address written determines the sector to be erased while global address bits [9:0] and the
00044         data written are ignored. Multiple Flash sectors can be simultaneously erased by writing to the
00045         same relative address in each Flash block.
00046 
00047         2. Write the sector erase command, 0x40, to the FCMD register.
00048 
00049         3. Clear the CBEIF flag in the FSTAT register by writing a 1 to CBEIF to launch the sector erase
00050         command.
00051 
00052         If a Flash sector to be erased is in a protected area of the Flash block, the PVIOL flag in the FSTAT register
00053         will set and the sector erase command will not launch. Once the sector erase command has successfully
00054         launched, the CCIF flag in the FSTAT register will set after the sector erase operation has completed unless
00055         a new command write sequence has been buffered. */
00056 unsigned short eraseSector(unsigned char PPage, unsigned short *flashAddr){
00057 
00058         if (((unsigned short)flashAddr % flashSectorSize) != 0){
00059                 return addressNotSectorAligned;
00060         }
00061         unsigned char currentPage = PPAGE;
00062         PPAGE = PPage;
00063         FSTAT = (PVIOL|ACCERR); /* clear any errors */
00064         (*flashAddr) = 0xFFFF;     /* Dummy data to first word of page to be erased it will write FFFF regardless with the erase command*/
00065         PPAGE = currentPage;
00066         FCMD = SECTOR_ERASE;            /* set the flash command register mode to ERASE */
00067         StackBurner();   //PPAGE loaded into Register B, PPAGE is set with Reg B in StackBurn asm file
00068         //TODO add return for accerr and pviol error bits
00069 
00070         return 0;
00071 }
00072 
00073 
00074                                 /* TODO for 0.0.19
00075                                  *
00076                                  * To be called from replace block of flash and ram to flash serial functions :
00077                                  *
00078                                  * create some sort of function to copy the flash sector up into
00079                                  * the serial rx buffer in the high end and then over write with
00080                                  * the small piece defined either from incoming data, or from its
00081                                  * memory location. Then just call burn in the normal way.
00082                                  *
00083                                  * function could take :
00084                                  * pointer to the buffer region (must be 1024 long or more)
00085                                  * rpage, address, length of data to be persisted
00086                                  * ppage, address of the sector to retrieve the rest of the data from
00087                                  * pointer to the details object we want to use for the following call :
00088                                  */
00089 
00090 
00091 /* Pass in anything you like and it will error if it can't handle it. */
00092 /* Note : Limited to 63k per write!! (obviously) */
00093 /* TODO buffer, copy and do smaller regions by supplementing with data read from the block in question. TODO see above ^ */
00094 unsigned short writeBlock(unsigned char RPage, unsigned short* RAMSourceAddress, unsigned char PPage, unsigned short* flashDestinationAddr, unsigned short size){
00095 
00096         if(((size % flashSectorSize) != 0) || (size == 0)){
00097                 return sizeNotMultipleOfSectorSize;
00098         }
00099 
00100         unsigned char sectors = size / flashSectorSize;
00101         unsigned char i;
00102         for(i=0;i<sectors;i++){
00103                 unsigned short errorID = writeSector(RPage, RAMSourceAddress, PPage, flashDestinationAddr);
00104                 if(errorID != 0){
00105                         return errorID;
00106                 }
00107                 /* Incrementing a pointer is done by blocks the size of the type, hence 512 per sector here */
00108                 flashDestinationAddr += flashSectorSizeInWords;
00109                 RAMSourceAddress += flashSectorSizeInWords;
00110         }
00111         return 0;
00112 }
00113 
00114 /*******************************************************************************
00115  *      writeSector will use writeWord to write a 1k block from sourceAddress(RAM) to flashDestinationAddress.
00116  *  Give it the starting memory address and the destination flash address.
00117  *  Both addresses will be incremented by 1 word after a successful writeWord,
00118  *  until the whole 1024 byte sector has been written.  Before any writing occurs
00119  *  eraseSector is called to make sure the destination is blank. */
00120 unsigned short writeSector(unsigned char RPage, unsigned short* RAMSourceAddress, unsigned char PPage , unsigned short* flashDestinationAddress){
00121 
00122         if (((unsigned short)flashDestinationAddress % flashSectorSize) != 0){
00123                         return addressNotSectorAligned;
00124                 }
00125 
00126         if(((unsigned short)flashDestinationAddress) < 0x4000){
00127                 return addressNotFlashRegion;
00128         }
00129 
00130         //TODO Decide if we need to disable interrupts since we are manually setting Flash/RAM pages.
00131         eraseSector((unsigned char)PPage, (unsigned short*)flashDestinationAddress);  /* First Erase our destination block */
00132 
00133         unsigned short wordCount = flashSectorSizeInWords;
00134 
00135         /* Save pages */
00136         unsigned char currentRPage = RPAGE;
00137         unsigned char currentPPage = PPAGE;
00138 
00139         /* Switch pages */
00140         RPAGE = RPage;
00141         PPAGE = PPage;
00142 
00143         while (wordCount > 0)
00144         {
00145         unsigned short sourceData = *RAMSourceAddress; /*Convert the RAMAddr to data(dereference) */
00146         unsigned short errorID = writeWord(flashDestinationAddress, sourceData);
00147         if(errorID != 0){
00148                         return errorID;
00149                 }
00150                 RAMSourceAddress++;
00151                 flashDestinationAddress++;
00152                 wordCount--; /* Decrement our word counter */
00153         }
00154 
00155         /* Restore pages */
00156         RPAGE = currentRPage;
00157         PPAGE = currentPPage;
00158         return 0;
00159 }
00160 /*      27.4.2.3 Program Command
00161 
00162         The program operation will program a previously erased word in the Flash memory using an embedded
00163         algorithm.
00164 
00165         An example flow to execute the program operation is shown in Figure 27-28. The program command write
00166         sequence is as follows:
00167 
00168         1. Write to a Flash block address to start the command write sequence for the program command. The
00169         data written will be programmed to the address written. Multiple Flash blocks can be
00170         simultaneously programmed by writing to the same relative address in each Flash block.
00171 
00172         2. Write the program command, 0x20, to the FCMD register.
00173 
00174         3. Clear the CBEIF flag in the FSTAT register by writing a 1 to CBEIF to launch the program
00175         command.
00176 
00177         If a word to be programmed is in a protected area of the Flash block, the PVIOL flag in the FSTAT register
00178         will set and the program command will not launch. Once the program command has successfully launched,
00179         the CCIF flag in the FSTAT register will set after the program operation has completed unless a new
00180         command write sequence has been buffered. By executing a new program command write sequence on
00181         sequential words after the CBEIF flag in the FSTAT register has been set, up to 55% faster programming
00182         time per word can be effectively achieved than by waiting for the CCIF flag to set after each program
00183         operation.*/
00184 unsigned short writeWord(unsigned short* flashDestination, unsigned short data){
00185         if ((unsigned short)flashDestination & 0x0001){
00186                 return addressNotWordAligned;
00187         }
00188 
00189         FSTAT=(ACCERR | PVIOL);
00190         *flashDestination = data;
00191         FCMD = WORD_PROGRAM;        //Load Flash Command Register With Word_Program mask
00192     StackBurner();
00193 
00194     return 0;
00195 }

Generated on Mon Dec 22 21:29:18 2008 for freeems by  doxygen 1.5.2