mirror of
https://github.com/TomNisbet/TommyPROM.git
synced 2024-11-24 08:31:16 +00:00
device support for 27E257/27C257
This commit is contained in:
parent
fc42ef50e1
commit
c6b91d0768
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
wip/
|
||||||
|
@ -14,6 +14,13 @@
|
|||||||
* Block writes are supported on compatible devices by specifying a blockSize
|
* Block writes are supported on compatible devices by specifying a blockSize
|
||||||
* in the constructor. Use zero for devices that only support byte writes.
|
* in the constructor. Use zero for devices that only support byte writes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum ERET {
|
||||||
|
RET_OK,
|
||||||
|
RET_FAIL,
|
||||||
|
RET_NOT_SUPPORT
|
||||||
|
};
|
||||||
|
|
||||||
class PromDevice
|
class PromDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -25,9 +32,9 @@ class PromDevice
|
|||||||
|
|
||||||
virtual void begin() = 0;
|
virtual void begin() = 0;
|
||||||
virtual const char * getName() = 0;
|
virtual const char * getName() = 0;
|
||||||
virtual void disableSoftwareWriteProtect() {}
|
virtual ERET disableSoftwareWriteProtect() { return RET_NOT_SUPPORT; }
|
||||||
virtual void enableSoftwareWriteProtect() {}
|
virtual ERET enableSoftwareWriteProtect() { return RET_NOT_SUPPORT; }
|
||||||
virtual bool erase(uint32_t start, uint32_t end) { return false; }
|
virtual ERET erase(uint32_t start, uint32_t end) { return RET_NOT_SUPPORT; }
|
||||||
|
|
||||||
uint32_t debugBlockWrites; // Number of block write operations
|
uint32_t debugBlockWrites; // Number of block write operations
|
||||||
uint32_t debugLastAddress; // Last address with an issue
|
uint32_t debugLastAddress; // Last address with an issue
|
||||||
|
@ -21,9 +21,10 @@ static void enableWrite() { digitalWrite(WE, LOW); }
|
|||||||
static void disableWrite() { digitalWrite(WE, HIGH);}
|
static void disableWrite() { digitalWrite(WE, HIGH);}
|
||||||
|
|
||||||
|
|
||||||
PromDevice27::PromDevice27(uint32_t size, unsigned long pulseWidthUsec,
|
PromDevice27::PromDevice27(uint32_t size, E27C_PGM pgmType, unsigned long pulseWidthUsec,
|
||||||
unsigned writeAttempts, unsigned overwriteMultiplier)
|
unsigned writeAttempts, unsigned overwriteMultiplier)
|
||||||
: PromDevice(size, 0, 0, false),
|
: PromDevice(size, 0, 0, false),
|
||||||
|
mPgmType(pgmType),
|
||||||
mPulseWidthUsec(pulseWidthUsec),
|
mPulseWidthUsec(pulseWidthUsec),
|
||||||
mWriteAttempts(writeAttempts),
|
mWriteAttempts(writeAttempts),
|
||||||
mOverwriteMultiplier(overwriteMultiplier)
|
mOverwriteMultiplier(overwriteMultiplier)
|
||||||
@ -81,6 +82,19 @@ byte PromDevice27::readByte(uint32_t address)
|
|||||||
|
|
||||||
// Burn a byte to the chip and verify that it was written.
|
// Burn a byte to the chip and verify that it was written.
|
||||||
bool PromDevice27::burnByte(byte value, uint32_t address)
|
bool PromDevice27::burnByte(byte value, uint32_t address)
|
||||||
|
{
|
||||||
|
switch(mPgmType) {
|
||||||
|
case E27C_PGM_WE: return burnByteWE(value, address); break;
|
||||||
|
case E27C_PGM_CE: return burnByteCE(value, address); break;
|
||||||
|
default: return false; // PGM_D13 not implemented yet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Burn a byte to the chip and verify that it was written.
|
||||||
|
// This uses a dedicated WE or PGM chip that operates on TTL levels and is active LOW.
|
||||||
|
// Overwrite burning is supported.
|
||||||
|
bool PromDevice27::burnByteWE(byte value, uint32_t address)
|
||||||
{
|
{
|
||||||
bool status = false;
|
bool status = false;
|
||||||
unsigned writeCount = 0;
|
unsigned writeCount = 0;
|
||||||
@ -123,6 +137,91 @@ bool PromDevice27::burnByte(byte value, uint32_t address)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Burn a byte to the chip and verify that it was written.
|
||||||
|
// This uses an active LOW program pulse on the CE line and a verify operation with CE
|
||||||
|
// HIGH. Overwrite is not supported, but could be added is a chip is found that needs it.
|
||||||
|
// Chips that use this mode require a programming voltage on the PGM pin and possibly on
|
||||||
|
// other pins as well.
|
||||||
|
//
|
||||||
|
// VCC may also have a non-standard voltage in program mode. Be sure to separate the
|
||||||
|
// PROM's VCC line from system VCC if a non-standard voltage is used.
|
||||||
|
bool PromDevice27::burnByteCE(byte value, uint32_t address)
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
unsigned writeCount = 0;
|
||||||
|
|
||||||
|
byte data = 0;
|
||||||
|
disableOutput();
|
||||||
|
disableWrite();
|
||||||
|
disableChip();
|
||||||
|
setAddress(address);
|
||||||
|
|
||||||
|
while (!status && (writeCount < mWriteAttempts))
|
||||||
|
{
|
||||||
|
setDataBusMode(OUTPUT);
|
||||||
|
writeDataBus(value);
|
||||||
|
delayMicroseconds(2);
|
||||||
|
enableChip();
|
||||||
|
myDelay(mPulseWidthUsec);
|
||||||
|
disableChip();
|
||||||
|
delayMicroseconds(2);
|
||||||
|
++writeCount;
|
||||||
|
|
||||||
|
setDataBusMode(INPUT);
|
||||||
|
enableOutput();
|
||||||
|
data = readDataBus();
|
||||||
|
disableOutput();
|
||||||
|
status = (readDataBus() == value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ERET PromDevice27::erase(uint32_t start, uint32_t end)
|
||||||
|
{
|
||||||
|
if (mPgmType != E27C_PGM_CE) return RET_NOT_SUPPORT;
|
||||||
|
|
||||||
|
// Erase code for the 27E257 and 27C257. The Vpp and A9 pins are held at 14V for the
|
||||||
|
// erase and verify cycle. This erases the entire chip, so the start and end address
|
||||||
|
// parameters are ignored.
|
||||||
|
disableChip();
|
||||||
|
disableOutput();
|
||||||
|
setAddress(0);
|
||||||
|
setDataBusMode(OUTPUT);
|
||||||
|
writeDataBus(0xff);
|
||||||
|
delayMicroseconds(2);
|
||||||
|
|
||||||
|
unsigned writeCount = 0;
|
||||||
|
ERET status = RET_FAIL;
|
||||||
|
while ((status == RET_FAIL) && (writeCount < mWriteAttempts)) {
|
||||||
|
setAddress(0);
|
||||||
|
setDataBusMode(OUTPUT);
|
||||||
|
writeDataBus(0xff);
|
||||||
|
delayMicroseconds(2);
|
||||||
|
enableChip();
|
||||||
|
delay(100);
|
||||||
|
disableChip();
|
||||||
|
delayMicroseconds(2);
|
||||||
|
|
||||||
|
// Read back the data to verify all cells are erased. Note That this is done
|
||||||
|
// while CE is HIGH. This is the erase verify mode.
|
||||||
|
setDataBusMode(INPUT);
|
||||||
|
for (uint32_t address = 0; (address < mSize); address++) {
|
||||||
|
setAddress(address);
|
||||||
|
enableOutput();
|
||||||
|
uint8_t b = readDataBus();
|
||||||
|
disableOutput();
|
||||||
|
if (b != 0xff) break;
|
||||||
|
}
|
||||||
|
status = RET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PromDevice27::myDelay(unsigned int us)
|
void PromDevice27::myDelay(unsigned int us)
|
||||||
{
|
{
|
||||||
if (us > 16000)
|
if (us > 16000)
|
||||||
@ -140,4 +239,3 @@ void PromDevice27::myDelay(unsigned int us)
|
|||||||
|
|
||||||
|
|
||||||
#endif // #if defined(PROM_IS_27)
|
#endif // #if defined(PROM_IS_27)
|
||||||
|
|
||||||
|
@ -25,24 +25,35 @@
|
|||||||
* See the constructor definition for an explanation of the parameters that
|
* See the constructor definition for an explanation of the parameters that
|
||||||
* control programming.
|
* control programming.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum E27C_PGM {
|
||||||
|
E27C_PGM_WE, // Dedicated WE or PGM pin that is active LOW
|
||||||
|
E27C_PGM_CE, // CE is pulsed low to program, CE HIGH for verify
|
||||||
|
E27C_PGM_D13 // Program voltage pulse switched using Arduino D13 pin
|
||||||
|
};
|
||||||
|
|
||||||
class PromDevice27 : public PromDevice
|
class PromDevice27 : public PromDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PromDevice27(uint32_t size, unsigned long mPulseWidthUsec, unsigned writeAttempts, unsigned overwriteMultiplier);
|
PromDevice27(uint32_t size, E27C_PGM pgmType, unsigned long pulseWidthUsec,
|
||||||
|
unsigned writeAttempts, unsigned overwriteMultiplier);
|
||||||
void begin();
|
void begin();
|
||||||
const char * getName() { return "27 series EPROM"; }
|
const char * getName() { return "27 series EPROM"; }
|
||||||
|
ERET erase(uint32_t start, uint32_t end);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setAddress(uint32_t address);
|
void setAddress(uint32_t address);
|
||||||
byte readByte(uint32_t address);
|
byte readByte(uint32_t address);
|
||||||
bool burnByte(byte value, uint32_t address);
|
bool burnByte(byte value, uint32_t address);
|
||||||
|
|
||||||
|
bool burnByteWE(byte value, uint32_t address);
|
||||||
|
bool burnByteCE(byte value, uint32_t address);
|
||||||
void myDelay(unsigned int us);
|
void myDelay(unsigned int us);
|
||||||
|
|
||||||
|
E27C_PGM mPgmType;
|
||||||
unsigned long mPulseWidthUsec;
|
unsigned long mPulseWidthUsec;
|
||||||
unsigned mWriteAttempts;
|
unsigned mWriteAttempts;
|
||||||
unsigned mOverwriteMultiplier;
|
unsigned mOverwriteMultiplier;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #define INCLUDE_PROM_DEVICE_27_H
|
#endif // #define INCLUDE_PROM_DEVICE_27_H
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ void PromDevice28C::begin()
|
|||||||
|
|
||||||
|
|
||||||
// Write the special six-byte code to turn off Software Data Protection.
|
// Write the special six-byte code to turn off Software Data Protection.
|
||||||
void PromDevice28C::disableSoftwareWriteProtect()
|
ERET PromDevice28C::disableSoftwareWriteProtect()
|
||||||
{
|
{
|
||||||
disableOutput();
|
disableOutput();
|
||||||
disableWrite();
|
disableWrite();
|
||||||
@ -61,11 +61,13 @@ void PromDevice28C::disableSoftwareWriteProtect()
|
|||||||
|
|
||||||
setDataBusMode(INPUT);
|
setDataBusMode(INPUT);
|
||||||
disableChip();
|
disableChip();
|
||||||
|
|
||||||
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Write the special three-byte code to turn on Software Data Protection.
|
// Write the special three-byte code to turn on Software Data Protection.
|
||||||
void PromDevice28C::enableSoftwareWriteProtect()
|
ERET PromDevice28C::enableSoftwareWriteProtect()
|
||||||
{
|
{
|
||||||
disableOutput();
|
disableOutput();
|
||||||
disableWrite();
|
disableWrite();
|
||||||
@ -78,6 +80,8 @@ void PromDevice28C::enableSoftwareWriteProtect()
|
|||||||
|
|
||||||
setDataBusMode(INPUT);
|
setDataBusMode(INPUT);
|
||||||
disableChip();
|
disableChip();
|
||||||
|
|
||||||
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ class PromDevice28C : public PromDevice
|
|||||||
PromDevice28C(uint32_t size, word blockSize, unsigned maxWriteTime, bool polling);
|
PromDevice28C(uint32_t size, word blockSize, unsigned maxWriteTime, bool polling);
|
||||||
void begin();
|
void begin();
|
||||||
const char * getName() { return "28C series EEPROM"; }
|
const char * getName() { return "28C series EEPROM"; }
|
||||||
void disableSoftwareWriteProtect();
|
ERET disableSoftwareWriteProtect();
|
||||||
void enableSoftwareWriteProtect();
|
ERET enableSoftwareWriteProtect();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setAddress(uint32_t address);
|
void setAddress(uint32_t address);
|
||||||
@ -34,4 +34,3 @@ class PromDevice28C : public PromDevice
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // #define INCLUDE_PROM_DEVICE_28C_H
|
#endif // #define INCLUDE_PROM_DEVICE_28C_H
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ void PromDeviceSST39SF::begin()
|
|||||||
|
|
||||||
|
|
||||||
// Erase all sectors containing the specified address range.
|
// Erase all sectors containing the specified address range.
|
||||||
bool PromDeviceSST39SF::erase(uint32_t start, uint32_t end)
|
ERET PromDeviceSST39SF::erase(uint32_t start, uint32_t end)
|
||||||
{
|
{
|
||||||
start >>= 12;
|
start >>= 12;
|
||||||
end >>= 12;
|
end >>= 12;
|
||||||
@ -55,7 +55,7 @@ bool PromDeviceSST39SF::erase(uint32_t start, uint32_t end)
|
|||||||
eraseSector(sector << 12);
|
eraseSector(sector << 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return RET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class PromDeviceSST39SF : public PromDevice
|
|||||||
PromDeviceSST39SF(uint32_t size, word unsigned maxWriteTime, bool polling);
|
PromDeviceSST39SF(uint32_t size, word unsigned maxWriteTime, bool polling);
|
||||||
void begin();
|
void begin();
|
||||||
const char * getName() { return "SST39SF series NOR Flash"; }
|
const char * getName() { return "SST39SF series NOR Flash"; }
|
||||||
bool erase(uint32_t start, uint32_t end);
|
ERET erase(uint32_t start, uint32_t end);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "XModem.h"
|
#include "XModem.h"
|
||||||
|
|
||||||
|
|
||||||
static const char * MY_VERSION = "3.0";
|
static const char * MY_VERSION = "3.1";
|
||||||
|
|
||||||
|
|
||||||
// Global status
|
// Global status
|
||||||
@ -35,17 +35,20 @@ CmdStatus cmdStatus;
|
|||||||
// 10ms max write time
|
// 10ms max write time
|
||||||
// Data polling supported
|
// Data polling supported
|
||||||
PromDevice28C prom(32 * 1024L, 64, 10, true);
|
PromDevice28C prom(32 * 1024L, 64, 10, true);
|
||||||
|
//PromDevice28C prom(8 * 1024L, 0, 10, true); // 28C64 with no page writes
|
||||||
|
|
||||||
#elif defined(PROM_IS_27)
|
#elif defined(PROM_IS_27)
|
||||||
// Define a device for a 2764 EPROM with the following parameters:
|
// Define a device for a 2764 EPROM with the following parameters:
|
||||||
// 8K byte device capacity
|
// 8K byte device capacity
|
||||||
|
// PGM pin pulses active LOW
|
||||||
// 1000us (1ms) write pulse
|
// 1000us (1ms) write pulse
|
||||||
// 15 write attempts
|
// 15 write attempts
|
||||||
// 4x overwrite pulse
|
// 4x overwrite pulse
|
||||||
PromDevice27 prom(8 * 1024L, 1000L, 15, 4); // 2764 with SEEQ intelligent programming
|
//PromDevice27 prom(8 * 1024L, E27C_PGM_WE, 1000L, 15, 4); // 2764 with SEEQ intelligent programming
|
||||||
//PromDevice27 prom(32 * 1024L, 1000L, 25, 3); // 27C256 with SEEQ intelligent programming
|
//PromDevice27 prom(32 * 1024L, E27C_PGM_WE, 1000L, 25, 3); // 27C256 with SEEQ intelligent programming
|
||||||
//PromDevice27 prom(2 * 1024L, 50000L, 1, 0); // 2716 with single 50ms write
|
//PromDevice27 prom(2 * 1024L, E27C_PGM_WE, 50000L, 1, 0); // 2716 with single 50ms write
|
||||||
//PromDevice27 prom(64 * 1024L, 100L, 11, 0); // 27C040 with Atmel rapid programming
|
//PromDevice27 prom(64 * 1024L, E27C_PGM_WE, 100L, 11, 0); // 27C040 with Atmel rapid programming
|
||||||
|
PromDevice27 prom(32 * 1024L, E27C_PGM_CE, 100L, 25, 0); // 27C257/27E257 with 100uS program pulse on CE
|
||||||
|
|
||||||
#elif defined(PROM_IS_SST39SF)
|
#elif defined(PROM_IS_SST39SF)
|
||||||
// Define a device for anSST39SF Flash with the following parameters:
|
// Define a device for anSST39SF Flash with the following parameters:
|
||||||
@ -493,7 +496,13 @@ void pokeBytes(char * pCursor)
|
|||||||
cmdStatus.info("Poke successful");
|
cmdStatus.info("Poke successful");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printRetStatus(ERET status)
|
||||||
|
{
|
||||||
|
switch (status) {
|
||||||
|
case RET_FAIL: Serial.println(F("FAILED")); break;
|
||||||
|
case RET_NOT_SUPPORT: Serial.println(F("NOT SUPPORTED")); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DEBUG_COMMANDS
|
#ifdef ENABLE_DEBUG_COMMANDS
|
||||||
/**
|
/**
|
||||||
@ -686,7 +695,7 @@ void loop()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_ERASE:
|
case CMD_ERASE:
|
||||||
prom.erase(start, end);
|
printRetStatus(prom.erase(start, end));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_FILL:
|
case CMD_FILL:
|
||||||
@ -695,8 +704,8 @@ void loop()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_LOCK:
|
case CMD_LOCK:
|
||||||
Serial.println(F("Writing the lock code to enable Software Write Protect mode."));
|
Serial.print(F("Writing the lock code to enable Software Write Protect mode: "));
|
||||||
prom.enableSoftwareWriteProtect();
|
printRetStatus(prom.enableSoftwareWriteProtect());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_POKE:
|
case CMD_POKE:
|
||||||
@ -713,8 +722,8 @@ void loop()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_UNLOCK:
|
case CMD_UNLOCK:
|
||||||
Serial.println(F("Writing the unlock code to disable Software Write Protect mode."));
|
Serial.print(F("Writing the unlock code to disable Software Write Protect mode: "));
|
||||||
prom.disableSoftwareWriteProtect();
|
printRetStatus(prom.disableSoftwareWriteProtect());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_WRITE:
|
case CMD_WRITE:
|
||||||
|
@ -21,11 +21,12 @@ support for programming.
|
|||||||
|
|
||||||
## EEPROM - Electrically Erasable Programmable Read-only Memory
|
## EEPROM - Electrically Erasable Programmable Read-only Memory
|
||||||
|
|
||||||
EEPROMs are the easiest PROMs to use. They usually can be erased and reprogrammed
|
EEPROMs are the easiest PROMs to use. Modern EEPROMs usually can be erased and reprogrammed
|
||||||
electrically at the individual byte level. This makes them appear similar to a slower
|
electrically at the individual byte level. This makes them appear similar to a slower
|
||||||
static RAM. All of the interactive features of TommyPROM work well with EEPROMs. Due
|
static RAM. All of the interactive features of TommyPROM work well with EEPROMs. Due
|
||||||
to their complexity, EEPROMs typically come in smaller sizes than other technologies.
|
to their complexity, EEPROMs typically come in smaller sizes than other technologies.
|
||||||
The largest EEPROM in the 28C family is 32K bytes.
|
The largest EEPROM in the 28C family is 32K bytes. Some older EEPROMs cannot be reprogrammed at the individual byte level and are instead bulk erased before a new write
|
||||||
|
operation. Programming and erasing for these chips usually requires voltages higher than 5V.
|
||||||
|
|
||||||
## Flash ROM
|
## Flash ROM
|
||||||
|
|
||||||
@ -144,3 +145,13 @@ address lines. The Arduino has enough pins to drive all of these directly, with
|
|||||||
need for shift registers to create address lines.
|
need for shift registers to create address lines.
|
||||||
|
|
||||||
The 8755 build of TommyPROM also has a circuit to control the 25V programming pulses.
|
The 8755 build of TommyPROM also has a circuit to control the 25V programming pulses.
|
||||||
|
|
||||||
|
# Verified Chips
|
||||||
|
|
||||||
|
|Model |Manufacturer |Type |Module |Notes|
|
||||||
|
|:--- |:--- |:--- |:--- |:--- |
|
||||||
|
|28C256 |Atmel, others|EEPROM |28C |Fully supported|
|
||||||
|
|SST39SF040|Microchip |Flash |SST39SF|All SST39SF0x0 supported|
|
||||||
|
|27E257 | |EEPROM |27 |Continual 12V or 14V for program/erase|
|
||||||
|
|29C010 | |Flash |28C |Only with 128 byte or less sector size|
|
||||||
|
|8755A |Intel |EPROM |8755A |Requires 25V pulses to program|
|
||||||
|
Loading…
Reference in New Issue
Block a user