diff --git a/TommyPROM/PromDevice27.cpp b/TommyPROM/PromDevice27.cpp index 0960e67..0d638cd 100644 --- a/TommyPROM/PromDevice27.cpp +++ b/TommyPROM/PromDevice27.cpp @@ -22,12 +22,13 @@ static void disableWrite() { digitalWrite(WE, HIGH);} PromDevice27::PromDevice27(uint32_t size, E27C_PGM pgmType, unsigned long pulseWidthUsec, - unsigned writeAttempts, unsigned overwriteMultiplier) + unsigned writeAttempts, unsigned overwriteMultiplier, bool verify) : PromDevice(size, 0, 0, false), mPgmType(pgmType), mPulseWidthUsec(pulseWidthUsec), mWriteAttempts(writeAttempts), - mOverwriteMultiplier(overwriteMultiplier) + mOverwriteMultiplier(overwriteMultiplier), + mVerifyByte(verify) { } @@ -99,14 +100,12 @@ bool PromDevice27::burnByteWE(byte value, uint32_t address) bool status = false; unsigned writeCount = 0; - byte data = 0; disableOutput(); disableWrite(); enableChip(); setAddress(address); - while (!status && (writeCount < mWriteAttempts)) - { + while (!status && (writeCount < mWriteAttempts)) { setDataBusMode(OUTPUT); writeDataBus(value); delayMicroseconds(1); @@ -115,15 +114,17 @@ bool PromDevice27::burnByteWE(byte value, uint32_t address) disableWrite(); ++writeCount; - setDataBusMode(INPUT); - enableOutput(); - data = readDataBus(); - disableOutput(); - status = (readDataBus() == value); + if (mVerifyByte) { + setDataBusMode(INPUT); + enableOutput(); + status = readDataBus() == value; + disableOutput(); + } else { + status = true; + } } - if (status && (mOverwriteMultiplier > 0)) - { + if (status && (mOverwriteMultiplier > 0)) { setDataBusMode(OUTPUT); writeDataBus(value); delayMicroseconds(1); @@ -132,8 +133,8 @@ bool PromDevice27::burnByteWE(byte value, uint32_t address) disableWrite(); } + setDataBusMode(INPUT); disableChip(); - return status; } @@ -151,14 +152,12 @@ 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)) - { + while (!status && (writeCount < mWriteAttempts)) { setDataBusMode(OUTPUT); writeDataBus(value); delayMicroseconds(2); @@ -168,24 +167,24 @@ bool PromDevice27::burnByteCE(byte value, uint32_t address) delayMicroseconds(2); ++writeCount; - setDataBusMode(INPUT); - enableOutput(); - data = readDataBus(); - disableOutput(); - status = (readDataBus() == value); + if (mVerifyByte) { + setDataBusMode(INPUT); + enableOutput(); + status = readDataBus() == value; + disableOutput(); + } } + setDataBusMode(INPUT); + disableChip(); return status; } ERET PromDevice27::erase(uint32_t start, uint32_t end) { - if (mPgmType != E27C_PGM_CE) return RET_NOT_SUPPORT; + ERET status = RET_FAIL; - // 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); @@ -193,30 +192,46 @@ ERET PromDevice27::erase(uint32_t start, uint32_t end) 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); + if (mPgmType == E27C_PGM_WE) { + // Erase code for the SST27C0x0. The Vpp and A9 pins are held at 12V for the + // erase cycle. This erases the entire chip, so the start and end address + // parameters are ignored. There is no erase verification for this chip. + enableChip(); + delayMicroseconds(1); + enableWrite(); + delayMicroseconds(100); // Hard coded for SST27F020 + disableWrite(); + disableChip(); + setDataBusMode(INPUT); + status = RET_OK; + } else { + // 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. + unsigned writeCount = 0; + 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; - } + // 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; } @@ -224,15 +239,12 @@ ERET PromDevice27::erase(uint32_t start, uint32_t end) void PromDevice27::myDelay(unsigned int us) { - if (us > 16000) - { + if (us > 16000) { // The delayMicroseconds code can't do delays longer than 16ms, so use the // ms delay code for larger values. This rounds down to the nearest ms, so // it is not possible to delay for 40.5 ms, for example. delay(us / 1000); - } - else - { + } else { delayMicroseconds((unsigned int) us); } } diff --git a/TommyPROM/PromDevice27.h b/TommyPROM/PromDevice27.h index cb9a8b1..873f3a2 100644 --- a/TommyPROM/PromDevice27.h +++ b/TommyPROM/PromDevice27.h @@ -36,7 +36,7 @@ class PromDevice27 : public PromDevice { public: PromDevice27(uint32_t size, E27C_PGM pgmType, unsigned long pulseWidthUsec, - unsigned writeAttempts, unsigned overwriteMultiplier); + unsigned writeAttempts, unsigned overwriteMultiplier, bool verify=true); void begin(); const char * getName() { return "27 series EPROM"; } ERET erase(uint32_t start, uint32_t end); @@ -54,6 +54,7 @@ class PromDevice27 : public PromDevice unsigned long mPulseWidthUsec; unsigned mWriteAttempts; unsigned mOverwriteMultiplier; + bool mVerifyByte; }; #endif // #define INCLUDE_PROM_DEVICE_27_H diff --git a/TommyPROM/PromDevice28C.cpp b/TommyPROM/PromDevice28C.cpp index 47938ea..af7c786 100644 --- a/TommyPROM/PromDevice28C.cpp +++ b/TommyPROM/PromDevice28C.cpp @@ -189,7 +189,7 @@ bool PromDevice28C::waitForWriteCycleEnd(byte lastValue) byte b1=0, b2=0; setDataBusMode(INPUT); delayMicroseconds(1); - for (int readCount = 1; (readCount < (mMaxWriteTime * 100)); readCount++) + for (unsigned readCount = 1; (readCount < (mMaxWriteTime * 100)); readCount++) { enableChip(); enableOutput(); diff --git a/TommyPROM/TommyPROM.ino b/TommyPROM/TommyPROM.ino index 95b15f3..ba9c782 100644 --- a/TommyPROM/TommyPROM.ino +++ b/TommyPROM/TommyPROM.ino @@ -19,7 +19,7 @@ #include "XModem.h" -static const char * MY_VERSION = "3.2"; +static const char * MY_VERSION = "3.3"; // Global status @@ -44,11 +44,13 @@ PromDevice28C prom(32 * 1024L, 64, 10, true); // 1000us (1ms) write pulse // 15 write attempts // 4x overwrite pulse +// (true) verify data byte after writing //PromDevice27 prom(8 * 1024L, E27C_PGM_WE, 1000L, 15, 4); // 2764 with SEEQ intelligent programming //PromDevice27 prom(32 * 1024L, E27C_PGM_WE, 1000L, 25, 3); // 27C256 with SEEQ intelligent programming //PromDevice27 prom(2 * 1024L, E27C_PGM_WE, 50000L, 1, 0); // 2716 with single 50ms write -//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 +//PromDevice27 prom(512 * 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 +PromDevice27 prom(256 * 1024L, E27C_PGM_WE, 20L, 1, 0, false); // SST27SF020 with single 20us write, no verify #elif defined(PROM_IS_SST39SF) // Define a device for anSST39SF Flash with the following parameters: diff --git a/docs/prom-families.md b/docs/prom-families.md index 016a291..d52a63f 100644 --- a/docs/prom-families.md +++ b/docs/prom-families.md @@ -161,7 +161,8 @@ The 8755 build of TommyPROM also has a circuit to control the 25V programming pu |:--- |:--- |:--- |:--- |:--- | |AT28C256 |Atmel, others|EEPROM |28C |Fully supported| |SST39SF040|Microchip |Flash |SST39SF|All SST39SF0x0 supported| -|SST28SF040|SST |Flash | |All SST28SF0x0 supported| +|SST28SF040|SST |Flash |SST39SF|All SST28SF0x0 supported| +|SST27SF020|SST |Flash |27 |12V continuous for pgm/erase| |WE27C257 |Winbond |EEPROM |27 |Continual 12V or 14V for program/erase| |AT29C010 |Atmel |Flash |28C |Only with 128 byte or less sector size| |8755A |Intel |EPROM |8755A |Requires 25V pulses to program| @@ -195,6 +196,18 @@ This is an earlier version of the SST39SF series chips. They are pin compatible flash chips support software data protection. The _Lock_ and _Unlock_ commands can be used to enable and disable SDP from the command line. +#### SST27SF020 + +The Silicon Storage SST27SF0x0 are programmed similarly to the 27C257 in that a constant +voltage is applied for program and erase operations. Unlike the 27C257, these have a +dedicated WE pin that controls programming and erasing. Another difference is that they +do not have a verify operation to read back the programmed data. + +These Flash chips have a _VPP_ pin that needs a constant 12V during programming. Unlike +the newer 28C EEPROMs, these chips do not automatically erase before writing to a +location. Instead, the entire chip is erased by applying 12V to _VPP_ and _A9_ and then +pulsing _WE_. + #### 27C257 The Winbond WE27C257 and WE27E257 appear to be identical 32Kx8 EEPROMs. The 27C version @@ -228,4 +241,3 @@ for chips with the 256 byte buffer. |Model |Manufacturer |Type |Module |Notes| |:--- |:--- |:--- |:--- |:--- | |M27C4001 |ST Micro |EEPROM | |VCC=6.5V, VPP=12.75V to pgm| -|SST27SF020|SST |Flash | |12V continuous for pgm/erase|