?? eeprom.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) 2004 Teridian SemiConductor, Corporation. *
* All Rights Reserved. *
* *
***************************************************************************/
//**************************************************************************
// DESCRIPTION: 71M652x POWER METER - Serial EEPROM Routines.
//
// AUTHOR: MTF
//
// HISTORY: See end of file.
//**************************************************************************
// File: EEPROM.C
//
#include "options.h"
#if EEPROM && I2C_INT
#include "mmath.h"
#include "stm.h"
#include "wd.h"
#include "eeprom.h"
/*** External functions used within this module ***/
// software timers, software watchdog
/*** External variables used within this module ***/
// None.
/*** Public functions declared within this module ***/
// See include file "eeprom.h".
/*** Public variables declared within this module ***/
// See include file "eeprom.h".
/*** Private functions declared within this module ***/
static void issue_START (void) small reentrant;
/*** Private variables declared within this module ***/
//
#define WRITE 0xA0 // EEPROM write to I2C device A0.
#define READ 0xA1 // EEPROM read from I2C device A0.
#define START_DELAY 0x800 // Minimum allowable is 0x6A8.
static volatile void (* xdata eeprom_proc) (void);
// EEPROM interface definitions.
enum STATE_t {
IDLE,
WAIT_STOP,
START_WRITE,
WAIT_WRITE_ACK,
WAIT_MSB_ADDR_ACK,
WAIT_LSB_ADDR_ACK,
WAIT_DATA_ACK,
WAIT_CLEAR_ACK,
START_READ,
WAIT_READ_ACK,
WAIT_DATA
};
static volatile uint8_t mode;
#define READ_MODE 0
#define WRITE_MODE 1
#define CLEAR_MODE 2
static volatile uint16i_t page_fill; // Count of bytes to fill page.
static volatile uint32i_t cnt; // Count of bytes to still send or receive.
static volatile uint8_16_32_t idata addr;
static volatile uint8x_t * idata ptr; // Pointer to string XMT'd/RCV'd to/from EEPROM.
static volatile enum EEPROM_RC data status; // status of TX/RX of EEPROM.
static volatile enum STATE_t data state;
static volatile bool done;
static volatile uint16i_t page_mask;
static volatile uint16i_t write_tick_cnt; // Time to write a page of EEPROM.
static const uint16r_t mask[] = { 0x0000,
0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
void EEProm_Config (bool access, uint16_t page_size, uint8_t msWr)
{ // Enable control pins to access EEPROM, set page size and write time.
if (access)
{
page_mask = mask[ log2 (page_size) ];
write_tick_cnt = milliseconds(msWr); // convert milliseconds to ticks.
EX_EEPROM = FALSE; // Disable EEPROM non-busy interrupt.
done = TRUE;
DIO = (DIO & ~DIO_EEX) | DIO_EEX_2W; // Connect to 2-Wire external EEPROM.
EX_EEPROM = TRUE; // Enable EEPROM non-busy interrupt.
}
else
{
EX_EEPROM = FALSE; // Disable EEPROM non-busy interrupt.
DIO &= ~DIO_EEX; // Disconnect from external EEPROM.
}
}
#pragma save
#pragma NOAREGS
void EEProm_isr (void) small reentrant interrupt EEPROM_IV
{
if (EECTRL & EE_ERROR)
{
status = _ERR_NACK;
state = IDLE;
return;
}
#ifdef WD_EEPROM
wd_reset ( WD_EEPROM );
#endif
switch (state)
{
case IDLE:
break; // Just ignore interrupts.
case START_WRITE: // Start of 'Page Write' or 'Sequential Read'.
EEDATA = (addr.c[ HI_LO ] << 1) | WRITE; // Real or "dummy" write.
EECTRL = EE_TX; // issue_TRANSMIT ();
state = WAIT_WRITE_ACK;
break;
case WAIT_WRITE_ACK:
EEDATA = addr.c[ LO_HI ]; // Send MSB of address.
EECTRL = EE_TX; // issue_TRANSMIT ();
state = WAIT_MSB_ADDR_ACK;
break;
case WAIT_MSB_ADDR_ACK:
EEDATA = addr.c[ LO_LO ]; // Send LSB of address.
EECTRL = EE_TX; // Finish step-up of read/write of next page.
state = WAIT_LSB_ADDR_ACK;
break;
case WAIT_LSB_ADDR_ACK:
switch(mode)
{
case READ_MODE: // Do 'Sequential Read'.
EECTRL = EE_START;
state = START_READ;
break;
case WRITE_MODE: // Do 'Page Write'.
EEDATA = *(ptr++); // Fetch character to send to EEPROM.
EECTRL = EE_TX; // issue_TRANSMIT ();
page_fill = min (PAGE_SIZE - (addr.i[ LO ] & page_mask), cnt);
cnt -= (uint32_t)page_fill;
state = WAIT_DATA_ACK;
break;
case CLEAR_MODE: // Do clear of device.
EEDATA = 0xFF; // Fetch character to send to EEPROM.
EECTRL = EE_TX; // issue_TRANSMIT ();
page_fill = PAGE_SIZE;
cnt -= (uint32_t)page_fill;
state = WAIT_CLEAR_ACK;
break;
}
break;
case WAIT_DATA_ACK:
if (--page_fill)
{
EEDATA = *(ptr++); // Fetch character to send to EEPROM.
EECTRL = EE_TX; // issue_TRANSMIT ();
}
else // Transmit to EEPROM.
{ // Page full.
if (0 == cnt)
status = _OK; // All done.
EECTRL = EE_STOP; // Do STOP.
state = WAIT_STOP;
}
break;
case WAIT_CLEAR_ACK:
if (--page_fill)
{
EEDATA = 0xFF; // Character to send to EEPROM.
EECTRL = EE_TX; // issue_TRANSMIT ();
}
else // Transmit to EEPROM.
{ // Page full.
if (0 == cnt)
status = _OK; // All done.
EECTRL = EE_STOP; // Do STOP.
state = WAIT_STOP;
}
break;
case WAIT_STOP:
if (cnt)
{
uint16x_t *pstm;
// Align on page boundary.
addr.i[ LO ] &= ~page_mask;
addr.l += PAGE_SIZE; // Next page.
state = START_WRITE; // Delay 'msWr' msec before next START.
pstm = stm_start(write_tick_cnt, 0, issue_START);
if (NULL == pstm)
status = _ERR_OVERRUN;
}
else
{
done = TRUE;
status = _OK;
state = IDLE; // Done w/ READ or WRITE.
}
break;
////////////////////////////////////////////////////////////////////////////
case START_READ:
EEDATA = (addr.c[ HI_LO ] << 1) | READ;
EECTRL = EE_TX; // issue_TRANSMIT ();
state = WAIT_READ_ACK;
break;
case WAIT_READ_ACK:
if (1 == cnt)
EECTRL = EE_RCV; // Receive last byte (NO ACK).
else
EECTRL = EE_RCV_ACK; // Receive and ACK byte.
state = WAIT_DATA;
break;
case WAIT_DATA: // ACK has been sent.
*(ptr++) = EEDATA; // Store character received from EEPROM.
if (--cnt)
{
if (1 == cnt)
EECTRL = EE_RCV; // Receive last byte (NO ACK).
else
EECTRL = EE_RCV_ACK; // Receive and ACK byte.
}
else
{
EECTRL = EE_STOP;
state = WAIT_STOP; // Done w/ READ.
}
break;
}
}
#pragma restore
#pragma save
#pragma NOAREGS
static void issue_START (void) small reentrant
{
EECTRL = EE_START;
}
#pragma restore
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -