pic24_flash.c

Go to the documentation of this file.
00001 /*
00002  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
00003  * All rights reserved.
00004  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
00005  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
00006  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
00007  *
00008  * Permission to use, copy, modify, and distribute this software and its
00009  * documentation for any purpose, without fee, and without written agreement is
00010  * hereby granted, provided that the above copyright notice, the following
00011  * two paragraphs and the authors appear in all copies of this software.
00012  *
00013  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
00014  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00015  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
00016  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00017  *
00018  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00019  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00020  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00021  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
00022  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
00023  *
00024  * Please maintain this header in its entirety when copying/modifying
00025  * these files.
00026  *
00027  *
00028  */
00029 // Documentation for this file. If the \file tag isn't present,
00030 // this file won't be documented.
00036 #include "pic24_all.h"
00037 #include <stdio.h>   //for NULL definition
00038 
00046 //doWriteLatch ;W0=TBLPAG,W1=Wn,W2=WordHi,W3=WordLo - no return values
00047 void doWriteLatchFlash(uint16 u16_addrhi, uint16 u16_addrlo, uint16 u16_wordhi, uint16 u16_wordlo) {
00048   TBLPAG = u16_addrhi;
00049   __builtin_tblwtl(u16_addrlo,u16_wordlo); //equivalent to asm("        tblwtl W3,[W1]")
00050   __builtin_tblwth(u16_addrlo,u16_wordhi); //equivalent to asm("        tblwth W2,[W1]")
00051 }
00052 
00059 //_ReadLatch: ;W0=TBLPAG,W1=Wn - data in W1:W0
00060 uint32 doReadLatchFlash(uint16 u16_addrhi, uint16 u16_addrlo) {
00061   union32 u32_a;
00062   TBLPAG = u16_addrhi;
00063   u32_a.u16.ls16 = __builtin_tblrdl(u16_addrlo);   //equivalent to asm("        tblrdl [W1],W0")
00064   u32_a.u16.ms16 = __builtin_tblrdh(u16_addrlo);   //equivalent to asm("        tblrdl [W1],W1")
00065   return(u32_a.u32);
00066 }
00067 
00068 
00074 void doErasePageFlash (uint16 u16_addrhi, uint16 u16_addrlo) {
00075   uint16 u16_save_SR, u16_save_TBLPAG;
00076 
00077 // preserve the SR and TBLPAG registers
00078   u16_save_SR = SR;
00079   u16_save_TBLPAG = TBLPAG;
00080 //disable interrupts
00081   SR = SR | 0xE0;
00082 // NVCON = flash write + erase + page erase
00083   NVMCON = 0x4042;
00084   TBLPAG = u16_addrhi; // select page
00085 //select row
00086 //equivalant to "tblwtl W1,[W1]"
00087   asm("tblwtl  %0,[%0]"::"r"(u16_addrlo));
00088 //start erase
00089   __builtin_write_NVM();
00090 //reenable interrupts
00091   SR  = u16_save_SR;
00092 //wait for end of erase
00093   while (NVMCON & 0x8000)
00094     doHeartbeat();
00095 // restore TBLPAG
00096   TBLPAG = u16_save_TBLPAG;
00097 }
00098 
00103 void doWriteRowFlash() {
00104   uint16 u16_save_SR;
00105   // save SR
00106   u16_save_SR = SR;
00107   // disable interrupts
00108   SR = SR | 0xE0;
00109   // flash write + row op
00110   NVMCON = 0x4001;
00111 //start write
00112   __builtin_write_NVM();
00113 //reenable interrupts
00114   SR = u16_save_SR;
00115 //wait for end of write
00116   while (NVMCON & 0x8000)
00117     doHeartbeat();
00118 }
00119 
00129 void doWritePageFlash(union32 u32_pmemAddress, uint8* pu8_data, uint16 u16_len) {
00130   uint16 u16_byteCnt;
00131   union32 u32_a;
00132   uint16 u16_ICnt, u16_numInstructions;
00133 
00134   ASSERT(u16_len <= FLASH_PAGEBYTES);
00135   doErasePageFlash(u32_pmemAddress.u16.ms16, u32_pmemAddress.u16.ls16);  //erase page
00136   //write the bytes
00137   //round up to nearest row boundary
00138   u16_numInstructions = u16_len/3;
00139   if (u16_len % 3 != 0) u16_numInstructions++;
00140   u16_numInstructions += (u16_numInstructions%64);
00141   for (u16_ICnt = 0, u16_byteCnt=0;u16_ICnt<u16_numInstructions; u16_ICnt += 1,u16_byteCnt += 3) {
00142     u32_a.u8[0] = pu8_data[u16_byteCnt];
00143     u32_a.u8[1] = pu8_data[u16_byteCnt+1];
00144     u32_a.u8[2] = pu8_data[u16_byteCnt+2];
00145     u32_a.u8[3] = 0;
00146     doWriteLatchFlash(u32_pmemAddress.u16.ms16, u32_pmemAddress.u16.ls16,u32_a.u16.ms16,u32_a.u16.ls16);
00147     if ((u16_ICnt+1)%64 == 0) {
00148       //row boundary, write it.
00149       doWriteRowFlash();
00150     }
00151     u32_pmemAddress.u32 += 2;  //program memory address increments by 2
00152   }
00153 }
00154 
00162 void doReadPageFlash(union32 u32_pmemAddress, uint8* pu8_data, uint16 u16_len) {
00163   uint16 u16_byteCnt;
00164   union32 u32_a;
00165 
00166   ASSERT(u16_len <= FLASH_PAGEBYTES);
00167   for (u16_byteCnt=0;u16_byteCnt<u16_len;u16_byteCnt += 3) {
00168     u32_a = (union32) doReadLatchFlash(u32_pmemAddress.u16.ms16, u32_pmemAddress.u16.ls16);
00169     pu8_data[u16_byteCnt] = u32_a.u8[0];
00170     pu8_data[u16_byteCnt+1] = u32_a.u8[1];
00171     pu8_data[u16_byteCnt+2] = u32_a.u8[2];
00172     u32_pmemAddress.u32 += 2;
00173   }
00174 }

Generated on Mon Oct 18 07:40:46 2010 for Python-on-a-chip by  doxygen 1.5.9