//-----------------------------------------------------------------------------
// File: eeprom.c
// Contents: EEPROM update firmware source. (Write only)
//
// indent 3. NO TABS!
//
// Copyright (c) 2002 Cypress Semiconductor
//
// $Workfile: eeprom.c $
// $Date: 3/30/05 2:38p $
// $Revision: 2 $
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "atapi.h"
#include "globals.h"
void EEWaitForStop();
bit EEWaitForAck();
static void EEStartAndAddr();
extern void WaitForEEPROMWrite();
///////////////////////////////////////////////////////////////////////////////////////
// Write the entire EEPROM
bit EEPROMWrite(WORD len, WORD addr)
{
WORD i;
for (addr = 0; addr < len && addr < dataTransferLen; addr += wPacketSize)
{
// Wait for host to send data
while(EP2468STAT & 0x01) ;
// Write the data from the USB buffer to the EEPROM
for (i = 0; i < wPacketSize && addr + i < len; i+= EEPROM_PAGE_SIZE)
{
if (EEPROMWriteBlock(addr+i, EP2FIFOBUF+i, EEPROM_PAGE_SIZE))
return(1);
}
// Give up the buffer
EP2BCL = 0x80;
}
dataTransferLen = 0;
return(0);
}
// Write up to one page of data to the EEPROM.
// Returns 0 on success, 1 on failure
// Normally called within a while() loop so that errors are retried:
// while (EEPROMWriteBlock(....))
// ;
bit EEPROMWriteBlock(WORD addr, BYTE xdata * ptr, BYTE len)
{
// Make sure the i2c interface is idle
EEWaitForStop();
// write the START bit and i2c device address
EEStartAndAddr();
if(EEWaitForAck())
return(1);
// write the eeprom offset
if (addr > 0x100)
{
I2DAT = MSB(addr);
if(EEWaitForAck())
return(1);
}
I2DAT = LSB(addr);
// If the EEPROM doesn't respond, set the STOP bit to idle the bus, then return error
if(EEWaitForAck())
{
I2CS |= 0x40; // Set the STOP bit
EEWaitForStop();
return(1);
}
// Write the data block
for(; len != 0; len--)
{
I2DAT = *ptr++;
if(EEWaitForDone())
return(1);
}
I2CS |= 0x40;
WaitForEEPROMWrite();
return 0;
}
void EEStartAndAddr()
{
I2CS = bmSTART;
I2DAT = eepromAddr << 1;
}
// 0x2e in assembly, less than 0x20 with compiler optimization!!
void WaitForEEPROMWrite()
{
EEWaitForStop();
waitForBusy:
EEStartAndAddr();
EEWaitForDone();
I2CS |= 0x40; // ; Set the STOP bit
EEWaitForStop();
if (!(I2CS & 0x02)) // If no ACK, try again.
goto waitForBusy;
}
void EEWaitForStop() {
// Data should not be written to I2CS or I2DAT until the STOP bit returns low.
while (I2CS & 0x40);
}
// Returns 0 on success, 1 on failure
bit EEPROMRead(WORD addr, WORD length, BYTE xdata*buf) {
BYTE i;
// Make sure the i2c interface is idle
EEWaitForStop();
// write the START bit and i2c device address
EEStartAndAddr();
if(EEWaitForAck())
return(1);
// write the eeprom offset
if (addr > 0x100)
{
I2DAT = MSB(addr);
if(EEWaitForAck())
return(1);
}
I2DAT = LSB(addr);
// If the EEPROM doesn't respond, set the STOP bit to idle the bus, then return error
if(EEWaitForAck())
{
I2CS |= 0x40; // Set the STOP bit
EEWaitForStop();
return(1);
}
I2CS = bmSTART;
// send the read command
I2DAT = (eepromAddr << 1) | 0x01;
if(EEWaitForDone())
return(1);
// read dummy byte
i = I2DAT;
if(EEWaitForDone())
return(1);
for (i=0; i < (length - 1); i++)
{
*(buf+i) = I2DAT;
if(EEWaitForDone())
return(1);
}
I2CS = 0x20; // bmLASTRD
if(EEWaitForDone())
return(1);
*(buf+i) = I2DAT;
if(EEWaitForDone())
return(1);
I2CS = 0x40; // bmSTOP
i = I2DAT;
return(0);
}
// Return 0 for ok, 1 for error
bit EEWaitForDone() {
BYTE i;
while (!((i=I2CS) & 1)); // Poll the done bit
if (i & 0x04) return 1; // bmBERR
return 0;
}
// Return 0 for ok, 1 for error
// Same as wait for done, but checks for ACK as well
bit EEWaitForAck() {
BYTE i;
while (!((i=I2CS) & 1)); // Poll the done bit
if (i & 0x04) return 1; // bmBERR
if (!(i & 0x02)) return 1; // bmACK
return 0;
}
| Vorgefundene Kodierung: ASCII (7 bit) | 2
|