📄 eepromp.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: 71M651x POWER METER - Serial EEPROM Routines.
//
// AUTHOR: RGV
//
// HISTORY: See end of file
//**************************************************************************
// File: eepromp.c
//**************************************************************************
// High speed polling eeprom API for an AT24C1024
// This can use either iicdio.c a fast bit-banging interface, or
// iiceep.c, a slower, less power-hungry interface that uses the
// chip's on-board I2C hardware. Both have the same interface, iic.h
//
#include "options.h"
#if EEPROM && I2C_POLLED
#include "stm.h"
#include "eeprom.h"
#include "iic.h" // polling IIC/I2C interface.
static uint16x_t page_size, time_to_write;
static int16x_t timeout_cnt;
enum EEPROM_RC data eeprom_state;
// timeout routines;
#pragma save
#pragma NOAREGS
void timeout_start (void) small reentrant
{
RESET_WD();
timeout_cnt = 10000;
}
#pragma restore
#pragma save
#pragma NOAREGS
uint8_t timeout_ok (void) small reentrant
{
--timeout_cnt;
if (timeout_cnt < 0)
{
eeprom_state = _ERR_NACK;
timeout_cnt = 0;
return 0;
}
// reset watchdog less often than 1kHz
if ((timeout_cnt & 0x1f) == 0)
RESET_WD();
return 1;
}
#pragma restore
// Initialize the EEPROM interface for polling access
#pragma save
#pragma NOAREGS
void EEProm_Config (uint8_t access, uint16_t spg, uint8_t tWr) small reentrant
{
uint8_t cnt;
eeprom_state = _OK;
if (access)
{
page_size = spg;
time_to_write = tWr;
IICInit(); // initialize the IIC bus
// little dance recommended by AT24C1024 data sheet, pg 6
IICStart();
for (cnt = 0; cnt < 9; ++cnt)
{
if (IICGetBit()) break;
}
IICStart(); // this is probably not right; no change on scope, but it works
IICStop();
}
else
{
EX_EEPROM = FALSE; // Disable EEPROM non-busy interrupt.
#if TRACE10 || M6520
DIO &= ~DIO_EEX; // Disconnect from external EEPROM.
#else
#error unhandled device type
#endif
}
}
#pragma restore
// delay loop
//#define DELAY 20
#ifdef DELAY
static void delay(void)
{
uint_fast8_t cnt0, cnt1, cnt2;
for (cnt0 = DELAY; cnt0 > 0; --cnt0)
{
for (cnt1 = 10; cnt1 > 0; --cnt1)
{
for (cnt2 = 100; cnt2 > 0; --cnt2)
{
}
}
}
}
#endif
// Write EEPROM Data; returns 0 when OK
#pragma save
#pragma NOAREGS
static uint8_t EPWritePage(uint32_t dst, uint8x_t *pchOut,
uint16_t cnt) small reentrant
{
static uint8_t xdata cmd;
static uint16_t xdata xdst;
if (eeprom_state != _OK)
return 1;
// this is supposed to address up to two EEPROMs
cmd = 0xA0 | (6 & (dst >> 15)); // page write command
xdst = (uint16_t)dst;
#ifdef DELAY
delay(); // for debugging
#endif
timeout_start(); // long, but not forever
IICStart();
// while the EEPROM is busy, wait
while(IICWrite(&cmd, 1) && timeout_ok())
{
IICStop();
IICStart();
}
// write the address
if(IICWrite((uint8x_t *)&xdst, 2) || !timeout_ok())
{
IICStop();
eeprom_state = _ERR_NACK;
return 1;
}
// write the rest of the page's data
if(IICWrite(pchOut, cnt) || !timeout_ok())
{
IICStop();
eeprom_state = _ERR_NACK;
return 1;
}
IICStop();
return 0; // no error
}
#pragma restore
#if EXTRAS
// Copy four (4) bytes to eeprom;
enum EEPROM_RC data *memset_pr (uint32_t dst, int32_t src)
{
int32_t xdata xsrc = src;
return (memcpy_prx (dst, (uint8x_t *) &xsrc, 4));
}
#endif
// copy any number of bytes from xdata to eeprom;
#pragma save
#pragma NOAREGS
enum EEPROM_RC data *memcpy_prx(uint32_t dst,
uint8x_t *src, int16_t len) small reentrant
{
int16_t lenInPage;
// figure the number of bytes to the end of the first page
lenInPage = page_size - (dst & (page_size - 1));
// if the number of bytes is zero, then the write
// starts on a page boundary
if (lenInPage != 0)
{
// if the write is less than one page, finish it
if (lenInPage > len)
lenInPage = len;
if(EPWritePage(dst, src, lenInPage))
return &eeprom_state;
src += (int)lenInPage;
dst += (uint32_t)lenInPage;
len -= lenInPage;
}
// write pages as quickly as possible
while (len > PAGE_SIZE)
{
// write pages
if(EPWritePage(dst, src, PAGE_SIZE))
return &eeprom_state;
src += PAGE_SIZE;
dst += PAGE_SIZE;
len -= PAGE_SIZE;
}
// write the last partial page, if any
if (0 != len)
{
// write the last few bytes
if(EPWritePage(dst, src, len))
return &eeprom_state;
}
eeprom_state = _OK;
return &eeprom_state;
}
#pragma restore
#if CLI
// Clear EEPROM Data; returns 0 when OK
static bool EPClearPage(uint32_t dst)
{
uint8_t xdata cmd;
uint16_t xdata xdst;
if (eeprom_state != _OK)
return 1;
// this is supposed to address up to two EEPROMs
cmd = 0xA0 | (6 & (dst >> 15)); // page write command
xdst = (uint16_t)dst;
#ifdef DELAY
delay(); // for debugging
#endif
timeout_start ();
IICStart();
while(IICWrite(&cmd, 1) && timeout_ok()) // while the EEPROM is busy, wait
{
IICStop();
IICStart();
}
if(IICWrite((uint8x_t *)&xdst, 2) || !timeout_ok()) // write the address
{
IICStop();
eeprom_state = _ERR_NACK;
return 1;
}
// write the rest of the page's data
if(IICPad(PAGE_SIZE, 0xFF) || !timeout_ok())
{
IICStop();
eeprom_state = _ERR_NACK;
return 1;
}
IICStop();
eeprom_state = _OK;
return 0; // no error
}
#endif
#if CLI
// clear the ROM;
enum EEPROM_RC data *memclr_pr (void)
{
uint32_t len = EEPROM_SIZE;
uint32_t dst = 0;
// write pages as quickly as possible
while (len > 0)
{
// write pages
if(EPClearPage(dst))
return &eeprom_state;
dst += PAGE_SIZE;
len -= PAGE_SIZE;
}
eeprom_state = _OK;
return &eeprom_state;
}
#endif
#if EXTRAS
// Read four (4) bytes; A return of nonzero is a failure.
enum EEPROM_RC data *memget_pr (int32x_t *dst, uint32_t src)
{
return (memcpy_xpr((uint8x_t *) dst, src, 4));
}
#endif
// read bytes; a return of nonzero is a fail.
#pragma save
#pragma NOAREGS
enum EEPROM_RC data *memcpy_xpr(
uint8x_t *dst,
uint32_t src,
int16_t len
) small reentrant
{
static uint8_t xdata cmd;
static uint16_t xdata xsrc;
if (eeprom_state != _OK)
return &eeprom_state;
// should address up to two EEPROMs
cmd = 0xA0 | (6 & (src >> 15)); // page write command
xsrc = (uint16_t)src;
// do dummy write to load address to chip
timeout_start();
IICStart();
// while there's a write in progress, wait
while(IICWrite(&cmd, 1) && timeout_ok())
{
// retry
IICStop();
IICStart();
}
// write the address
if(IICWrite((uint8x_t *)&xsrc, 2) || !timeout_ok())
{
IICStop();
eeprom_state = _ERR_NACK;
return &eeprom_state;
}
IICStop();
cmd |= 0xA1; // sequential read command, address bits preserved
timeout_start();
IICStart();
while(IICWrite(&cmd, 1) && timeout_ok()) // while there's an error, wait
{
// retry
IICStop();
IICStart();
}
if (!timeout_ok())
{
IICStop();
eeprom_state = _ERR_NACK;
return &eeprom_state;
}
IICRead(dst, (uint16_t)len); // read the rest of the page's data
IICStop();
eeprom_state = _OK;
return &eeprom_state;
}
#pragma restore
#if CAL_SAVE && NV_SELECT == NV_EEPROM
// returns 1 if it worked, 0 if it timed out or failed
#pragma save
#pragma NOAREGS
bool eeprom_ok (enum EEPROM_RC data *pstatus) small reentrant
{
RESET_WD();
return (_OK == *pstatus);
}
#pragma restore
#endif // extras
#endif // EEPROM
/***************************************************************************
* $Log: eepromp.c,v $
* Revision 1.32 2006/10/13 00:47:28 tvander
* Removed compile options for 6530, 6515;
* renamed 6511 and 6513 to trace11 and trace13;
* Binary verified unchanged from previous version.
*
* Revision 1.31 2006/09/27 00:55:02 tvander
* Fix watchdog resets when erasing an EEPROM
*
* Revision 1.30 2006/09/09 01:09:20 gmikef
* *** empty log message ***
*
* Revision 1.29 2006/08/09 00:56:33 tvander
* *** empty log message ***
*
* Revision 1.28 2006/06/15 16:36:55 tvander
* Fixed reentrancy on iiceep.c and eepromp.c
* Made parallel code changes to microwire eeprom drivers.
*
* Revision 1.27 2006/06/06 05:17:24 tvander
* clean build
*
* Revision 1.26 2006/05/25 03:24:11 tvander
* Added timeouts to EEPROMs. Tested all three.
* Newly ported calibration loader, compiles without error.
* RTC setting uses a software timer (less code, also frees tmr1)
*
* Revision 1.25 2006/05/18 23:18:44 tvander
* 16K and 32K
* First cut at new requirements.
* 32K 6521 is grossly tested.
* All others have a clean compile with C51 8.02
*
* Revision 1.24 2006/04/14 20:11:23 tvander
* Fixed, integrated with phased calibration
*
* Revision 1.23 2006/03/08 00:00:56 tvander
* Revised IO so that multiplexed interrupts are centralized in io65xx.c
* Added default interrupts to io65xx.c
* Clean build.
* Tested CE, serial.
* interrupting EEPROM driver fails.
*
* Revision 1.22 2006/03/06 03:30:57 Michael T. Fischer
* More 6530 prep.
*
* Revision 1.21 2006/03/03 11:25:35 Michael T. Fischer
* Prep for 6530 LCD, etc.
*
* Revision 1.20 2006/02/08 22:37:20 gmikef
* *** empty log message ***
*
* Revision 1.19 2006/02/08 03:43:18 tvander
* Made "import" the default power measurement mode, rather than net-metering
*
* Revision 1.18 2006/01/16 20:11:22 tvander
* Clean Keil build, all versions
*
* Revision 1.17 2006/01/10 03:57:19 gmikef
* Added PDATA support for CE Outputs.
*
* Revision 1.15 2005/11/05 02:14:00 tvander
* Fixed build
*
* Revision 1.14 2005/11/05 01:56:26 tvander
* Added EEPROM erase; Note uwreep.c is not working; don't know why.
*
* Revision 1.13 2005/10/31 17:37:59 tvander
* Includes improved EEPROM code with uwire.
* Clean build, all build trees (Thank-you, Mike!)
*
* Revision 1.12 2005/10/20 18:39:40 tvander
* Ported 2-wire EEPROM code from 6511/6513, including interrupting version, polling version for DIO, and polling version using the 2-wire logic.
*
* Revision 1.11 2005/09/22 23:45:04 tvander
* Clean build all models and unit tests, updated copyright to be fore Teridian
*
* Revision 1.10 2005/09/12 07:47:28 tvander
* Power measurement is stable, with no creep.
* VARh measurement is stable, with no creep.
* Pulse sources work.
* Full access to MPU variables.
* Rolled date.
* Clock software works.
*
* Revision 1.9 2005/08/28 02:13:33 gmikef
* *** empty log message ***
*
* Revision 1.8 2005/08/12 21:50:42 tvander
* Added a synchronization and test function.
*
* Revision 1.7 2005/08/10 01:57:53 gmikef
* *** empty log message ***
*
* Revision 1.6 2005/05/13 00:34:41 tvander
* 6511/32k works
* Integrated and debugged self-calibration.
* The build has one unused segment, and no other errors or warnings.
* default LCD and pulse displays appear OK.
* EEPROM, software timers and hardware timers are all integrated.
*
* Revision 1.5 2005/05/03 00:39:43 tvander
* Incorporated event reporting in tmr0,tmr1 and unit tests.
* Retested stm, trm0, tmr1.
* Incorporated untested changes in io651x.h
*
* Revision 1.4 2005/04/21 01:59:08 gmikef
* *** empty log message ***
*
* Revision 1.8 2005/04/09 02:04:24 gmikef
* *** empty log message ***
*
* Revision 1.3 2005/03/12 00:16:58 tvander
* Integrated memory types.
*
* Revision 1.2 2005/03/11 22:57:02 tvander
* Added bool, and 8/16/32 data structures
*
* Revision 1.1 2005/03/11 22:19:14 tvander
* *** empty log message ***
*
* Revision 1.2 2005/02/17 18:32:25 tvander
* Added automatic check-in logging to all source code.
*
* 2004 DECEMBER 22; First Version
*
* Revision 1.1 2005/02/01 20:04:40 tvander
* Reorganization
*
* Revision 1.2 2005/01/26 19:52:35 tvander
* Added update log
*
* 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 + -