⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eepromp.c

📁 TDK 6521 SOC 芯片 DEMO程序
💻 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 + -