📄 flash.c
字号:
/***************************************************************************
* This code and information is provided "as is" without warranty of any *
* kind, either expressed or implied, including but not limited to the *
* implied warranties of merchantability and/or fitness for a particular *
* purpose. *
* *
* Copyright (C) 2005 Teridian Semiconductor Corp. All Rights Reserved. *
***************************************************************************/
//**************************************************************************
// DESCRIPTION: 71M652x POWER METER - Flash Routines.
//
// AUTHOR: MTF
//
// HISTORY: See end of file.
//**************************************************************************
// File: FLASH.C
//
#include "options.h"
#if FLASH
#include "IRQ.H"
#include "library.h"
#include "flash.h"
/*** External functions used within this module ***/
// Compare FLASH.
/*** External variables used within this module ***/
// None.
/*** Public functions/variables declared within this module ***/
// see flash.h
/*** Private functions declared within this module ***/
// Erase FLASH before write to it.
static void memcpy_rxe (uint8r_t *dst, uint8x_t *src, uint16_t len) small reentrant;
// Just write to FLASH.
static void memcpy_rx_ (uint8r_t *dst, uint8x_t *src, uint16_t len) small reentrant;
#define memset_r(d, s) memcpy_rx_(d, s, 1)
static bool flash_write_ok (uint8r_t *dst, uint8x_t *src, uint16_t len) small reentrant;
static bool flash_bad_cmp (uint8r_t *rsrc, uint8x_t *xsrc, uint16_t len) small reentrant;
static bool flash_not_erased (uint8r_t *rsrc, uint16_t len) small reentrant;
/*** Private variables declared within this module ***/
// None.
//--------------------------------------//
// FLASH API
#if FLASH || (CAL_SAVE && (NV_SELECT == NV_FLASH))
#pragma save
#pragma NOAREGS
bool memcpy_rx (uint8r_t *dst, uint8x_t *src, uint16_t len) small reentrant
{
if (!flash_write_ok (dst, src, len))
return (FALSE);
memcpy_rxe (dst, src, len); // Only erase if full page write.
return (0 == memcmp_rx (dst, src, len));
} // Verify write.
// Note: FPAGE contains page address in 7 MSbs (i.e. PAGE ADDR is 2 x PAGE).
#define NEXT_PAGE 0x02
static void memcpy_rxe (uint8r_t *dst, uint8x_t *src, uint16_t len) small reentrant
{
uint16_t tlen;
int8_t page;
IRQ_DEFINES;
page = (uint16_t) dst >> 8; // Extract page number x 2.
if ((uint16_t) dst & FPAGE_MASK)
{ // Not starting at page boundary.
tlen = min (FPAGE_SIZE - ((uint16_t) dst & FPAGE_MASK), len);
if (flash_bad_cmp (dst, src, tlen))
{ // Need to erase page first.
IRQ_DISABLE(); // ALL interrupt OFF.
FPAGE = page; // Set Flash Page Erase Enable.
ERASE = PAGE_ERASE_; // Initiate page erase, MPU halted.
IRQ_ENABLE(); // Turn interrupts back ON.
}
memcpy_rx_ (dst, src, tlen); // Just write partial page.
dst += tlen;
src += tlen;
len -= tlen;
}
// Starting at page boundary.
while (len)
{
if (len >= FPAGE_SIZE)
{
IRQ_DISABLE(); // ALL interrupt OFF.
FPAGE = page; // Set Flash Page Erase Enable.
ERASE = PAGE_ERASE_; // Initiate page erase, MPU halted.
IRQ_ENABLE(); // Turn interrupts back ON.
}
memcpy_rx_ (dst, src, min (len, FPAGE_SIZE));
dst += FPAGE_SIZE; // Update pointers.
src += FPAGE_SIZE;
len -= min (len, FPAGE_SIZE);
page += NEXT_PAGE; // Next page.
}
}
static void memcpy_rx_ (uint8r_t *Dst, uint8x_t *src, uint16_t len) small reentrant
{
IRQ_DEFINES;
uint8x_t *dst = (uint8x_t *) Dst;
while (len--)
{
IRQ_DISABLE(); // ALL interrupt OFF.
FCTRL |= PWE_; // MOVX @DPTR,A writes single byte to FLASH.
*dst = *src;
FCTRL = 0; // Disable further writing to flash.
IRQ_ENABLE(); // Turn interrupts back ON.
dst++; src++;
}
}
static bool flash_write_ok (uint8r_t *dst, uint8x_t *src, uint16_t len) small reentrant
{
uint16_t tlen;
if ((uint16_t) dst & FPAGE_MASK)
{ // Not starting at page boundary.
tlen = min (FPAGE_SIZE - ((uint16_t) dst & FPAGE_MASK), len);
// First, just check overlayed portion of first page.
if (flash_bad_cmp (dst, src, tlen))
{ // May need to erase this page.
if (flash_not_erased ((uint8r_t *) ((uint16_t) dst & ~FPAGE_MASK), (uint16_t) dst & FPAGE_MASK))
{ // Do not do write.
return (FALSE); // Needed to read/erase/modify/write.
}
}
dst += tlen;
src += tlen;
len -= tlen;
}
// Next, check overlayed portion of last page.
tlen = len & ~FPAGE_MASK; // Compute distance to final page.
if (flash_bad_cmp (dst + tlen, src + tlen, len - tlen))
{
if (flash_not_erased (dst + len, FPAGE_SIZE - (((uint16_t) dst + len) & FPAGE_MASK)))
{ // Do not do write.
return (FALSE); // Needed to read/erase/modify/write.
}
}
return (TRUE);
}
static bool flash_bad_cmp (uint8r_t *rsrc, uint8x_t *xsrc, uint16_t len) small reentrant
{
while (len--)
{
if ((*rsrc & *xsrc) != *xsrc) break;
rsrc++; xsrc++;
}
return (len + 1);
}
static bool flash_not_erased (uint8r_t *src, uint16_t len) small reentrant
{
while (len--)
{
if (0xFF != *src) break;
src++;
}
return (len + 1);
}
// The standard 16-bit CRC polynomial specified in ISO/IEC 3309 is used.
// 16 12 5
// Which is: x + x + x + 1
//
#if EXTRAS
bool CRC_Calc (uint8r_t *ptr, uint16_t len, int8_t set) small reentrant
{
IRQ_DEFINES;
int8_t d, Ok;
uint16_t CRC;
static uint8_t xdata src;
if (set)
len -= 2; // Do not include CRC in calculation.
CRC = 0xFFFF;
do
{
d = *ptr++ ^ (CRC & 0xFF); // Compute combined value.
d ^= d << 4;
CRC = (d << 3) ^ (d << 8) ^ (CRC >> 8) ^ (d >> 4);
} while (--len);
if (set)
{ // Store complement of CRC.
CRC ^= 0xFFFF; // Complement CRC.
d = CRC & 0xFF;
src = d;
memset_r (ptr, &src);
ptr++;
d = CRC >> 8;
src = d;
memset_r (ptr, &src);
Ok = (CRC >> 8) == (*(ptr + 1));
Ok &= (CRC & 0xFF) == (*(ptr ));
return (Ok);
}
else
{
Ok = CRC == 0xF0B8;
return (Ok);
}
}
#endif
#pragma restore
#endif
#if (CLI && !CAL_SAVE) || (CAL_SAVE && NV_SELECT == NV_FLASH)
bool memcpy_rce (int32r_t *dst, int32x_t *src, uint8_t len)
{ // Never any overlapped data.
uint8x_t *pDst;
uint8x_t *pSrc;
int8_t page;
CE_XFER_DEFINES;
pDst = (uint8x_t *) dst;
pSrc = (uint8x_t *) src;
page = (uint16_t) dst >> 8; // Extract page number x 2.
IRQ_DISABLE(); // Turn OFF all interrupts.
FPAGE = page; // Set Flash Page Erase Enable.
ERASE = PAGE_ERASE_; // Initiate page erase, MPU halted.
IRQ_ENABLE(); // Restore interrupt state.
do
{
BEGIN_CE_CRITICAL_SECTION; // this actually disables interrupts
CLK_STRETCH; // Change stretch to '6'
FCTRL |= PWE_; *pDst = *pSrc;
FCTRL = 0; // Disable further writing to flash.
CLK_RELAX; // Back to default value
pDst++; pSrc++;
FCTRL |= PWE_; *pDst = *pSrc; FCTRL = 0; pDst++; pSrc++;
FCTRL |= PWE_; *pDst = *pSrc; FCTRL = 0; pDst++; pSrc++;
FCTRL |= PWE_; *pDst = *pSrc; FCTRL = 0;
END_CE_CRITICAL_SECTION;
pDst++; pSrc++;
} while (--len);
return (TRUE);
}
#endif
#if M6520
#pragma save
#pragma NOAREGS
void fwcol_isr (void) small reentrant interrupt FWCOL_IV
{
if (IE_FWCOL0)
CLR_IE_FWCOL0();
if (IE_FWCOL1)
CLR_IE_FWCOL1();
}
#pragma restore
#endif
#endif // flash
/***************************************************************************
* History:
* $Log: flash.c,v $
* Revision 1.25 2006/09/09 01:15:14 gmikef
* *** empty log message ***
*
* Revision 1.24 2006/06/29 00:58:43 tvander
* Added NOAREGs to reentrant code.
*
* Revision 1.23 2006/06/06 05:15:56 tvander
* clean build
*
* Revision 1.22 2006/04/14 20:21:58 tvander
* Integrated with phased calibration
*
* Revision 1.21 2006/04/12 00:30:40 tvander
* Added code for phased calibration, 6513 compiled with equations 3 and 4.
*
* Revision 1.20 2006/03/08 00:10:53 tvander
* Clean build
*
* Revision 1.19 2006/03/06 03:42:09 Michael T. Fischer
* More 6530 prep.
*
* Revision 1.18 2006/03/03 11:31:15 Michael T. Fischer
* Prep for 6530 LCD, etc.
*
* Revision 1.17 2006/01/16 20:11:31 tvander
* Clean Keil build, all versions
*
* Revision 1.16 2006/01/10 04:11:35 gmikef
* Added PDATA support for CE Outputs.
*
* Revision 1.15 2006/01/04 04:47:55 gmikef
* Switched RMS and VA calculations to use floating point. (and Calibration).
*
* Revision 1.14 2005/12/23 01:28:22 tvander
* Fixed compile errors
*
* Revision 1.12 2005/12/21 01:37:09 tvander
* 6513
*
* Revision 1.11 2005/12/08 03:09:10 gmikef
* Manually clear PWE (disable flash writes) after each write.
*
* Revision 1.10 2005/10/15 02:21:24 tvander
* Improved critical sections to use the official macros.
* Also improved the compilation flags.
*
* Revision 1.9 2005/10/12 23:00:07 tvander
* Includes demonstratable mission mode, brownout, LCD and sleep modes
*
* Revision 1.8 2005/09/22 23:45:26 tvander
* Clean build all models and unit tests, updated copyright to be fore Teridian
*
* Revision 1.7 2005/09/11 00:34:08 tvander
* Clean compiles
*
* Revision 1.6 2005/09/01 04:25:28 gmikef
* *** empty log message ***
*
* Revision 1.5 2005/08/31 05:58:03 gmikef
* First version w/ LAPIE interface.
*
* Revision 1.4 2005/08/30 18:22:56 gmikef
* *** empty log message ***
*
* Revision 1.3 2005/08/12 06:03:07 gmikef
* Added MPU temperature compensation for GAIN_ADJ.
* Added changes to support new CE 6521 code.
*
* Revision 1.2 2005/08/11 18:10:25 tvander
* *** empty log message ***
*
* Revision 1.1 2005/08/10 02:07:05 gmikef
* *** empty log message ***
*
* Revision 1.10 2005/07/15 01:20:06 gmikef
* *** empty log message ***
*
* Copyright (C) 2005 Teridian Semiconductor Corp. All Rights Reserved. *
* this program is fully protected by the United States copyright *
* laws and is the property of Teridian Semiconductor Corporation. *
***************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -