sketch: implemented read write verify for ATF750C

The implementation is based on Afterburner's fork by Michael D.
https://github.com/nospam2000/afterburner.git
This commit is contained in:
ole00 2024-02-02 08:58:48 +00:00
parent 053c914fae
commit e99494df09
1 changed files with 176 additions and 109 deletions

View File

@ -412,8 +412,8 @@ galinfo_t galinfo __attribute__ ((section (".noinit"))); //preserve data between
// MAXFUSES calculated as the biggest required space to hold the fuse bitmap // MAXFUSES calculated as the biggest required space to hold the fuse bitmap
// MAXFUSES = GAL6002 8330 bits = 8330/8 = 1041.25 bytes rounded up to 1042 bytes // MAXFUSES = GAL6002 8330 bits = 8330/8 = 1041.25 bytes rounded up to 1042 bytes
//#define MAXFUSES 1042 //#define MAXFUSES 1042
//extra space added for sparse fusemap //extra space added for sparse fusemap (just enough to fit erased ATF750C)
#define MAXFUSES 1280 #define MAXFUSES 1332
#define USE_SPARSE_FUSEMAP #define USE_SPARSE_FUSEMAP
#endif #endif
@ -666,7 +666,7 @@ static void copyGalInfo(void) {
memcpy_P(&galinfo, &galInfoList[gal], sizeof(galinfo_t)); memcpy_P(&galinfo, &galInfoList[gal], sizeof(galinfo_t));
// Note: Sparse fuse map is ignored on MCUs with big SRAM // Note: Sparse fuse map is ignored on MCUs with big SRAM
if (gal == ATF750C) { if (gal == ATF750C || gal == ATF22V10C) {
sparseInit(0); sparseInit(0);
} else { } else {
sparseDisable(); sparseDisable();
@ -733,10 +733,14 @@ char handleTerminalCommands() {
return COMMAND_NONE; return COMMAND_NONE;
} }
// Parses decimal integer number typed as 4 digit. // Parses decimal integer number typed as 4 or 5 digits.
// Returns the number value. // Returns the number value.
unsigned short parse4dec(char i) { unsigned short parse45dec(char i, char five) {
unsigned short v = (line[i++] - '0') * 1000; unsigned short v = 0;
if (five) { //containts 5 digits
v = (line[i++] - '0') * 10000;
}
v += (line[i++] - '0') * 1000;
v += (line[i++] - '0') * 100; v += (line[i++] - '0') * 100;
v += (line[i++] - '0') * 10; v += (line[i++] - '0') * 10;
v += line[i] - '0'; v += line[i] - '0';
@ -765,14 +769,19 @@ unsigned short parse2hex(char i) {
// Parses hexdecimal integer number typed as 4 digit. // Parses hexdecimal integer number typed as 4 digit.
// Returns the number value. // Returns the number value.
unsigned short parse4hex(char i) { unsigned short parse4hex(char i) {
unsigned short v;
if (line[i] == '\r' || line[i] == 0 || line[i] == ' ') { if (line[i] == '\r' || line[i] == 0 || line[i] == ' ') {
return -1; return -1;
} }
unsigned short v = ((unsigned short)toHex(line[i++])) << 12; v = toHex(line[i++]);
v |= ((unsigned short)toHex(line[i++])) << 8; v <<= 4;
v |= toHex(line[i++]) << 4; v |= toHex(line[i++]);
return v + toHex(line[i]); v <<= 4;
v |= toHex(line[i++]);
v <<= 4;
v |= toHex(line[i]);
return v ;
} }
// Parses a line fed by the serial connection. // Parses a line fed by the serial connection.
@ -817,8 +826,13 @@ void parseUploadLine() {
case 'f': { case 'f': {
char i = 8; char i = 8;
char j; char j;
unsigned short addr = parse4dec(3); unsigned short addr;
short v; short v;
char fiveDigitAddr = (line[7] != ' ') ? 1 : 0;
addr = parse45dec(3, fiveDigitAddr);
i += fiveDigitAddr;
do { do {
v = parse2hex(i); v = parse2hex(i);
if (v >= 0) { if (v >= 0) {
@ -1608,20 +1622,43 @@ static void readGalFuseMap(const unsigned char* cfgArray, char useDelay, char do
} }
// read CFG // read CFG
if (galinfo.cfgmethod == CFG_STROBE_ROW) { if (galinfo.cfgmethod == CFG_STROBE_ROW2) { //ATF750C
strobeRow(galinfo.cfgrow); const uint8_t cfgstroberow = 96;
if (flagBits & FLAG_BIT_ATF16V8C) { const uint8_t cfgrowlen = 10;
setSDIN(0); const uint8_t cfgrowcount = (galinfo.cfgbits + (cfgrowlen - 1)) /cfgrowlen;
setPV(1); uint8_t i;
for(i = 0; i < cfgrowcount; i++) {
strobeConfigRow(cfgstroberow + i);
for(bit = 0; bit < cfgrowlen; bit++) {
uint8_t absBit = (cfgrowlen * i) + bit;
if (absBit >= galinfo.cfgbits)
break;
if (receiveBit()) {
unsigned char cfgOffset = pgm_read_byte(&cfgArray[absBit]);
setFuseBit(cfgAddr + cfgOffset);
}
}
if (useDelay) {
delay(useDelay);
}
} }
} else { } else {
setRow(galinfo.cfgrow); if (galinfo.cfgmethod == CFG_STROBE_ROW) {
strobe(1); strobeRow(galinfo.cfgrow);
} if (flagBits & FLAG_BIT_ATF16V8C) {
for(bit = 0; bit < galinfo.cfgbits; bit++) { setSDIN(0);
if (receiveBit()) { setPV(1);
unsigned char cfgOffset = pgm_read_byte(&cfgArray[bit]); //read array byte flom flash }
setFuseBit(cfgAddr + cfgOffset); }
else {
setRow(galinfo.cfgrow);
strobe(1);
}
for(bit = 0; bit < galinfo.cfgbits; bit++) {
if (receiveBit()) {
unsigned char cfgOffset = pgm_read_byte(&cfgArray[bit]); //read array byte flom flash
setFuseBit(cfgAddr + cfgOffset);
}
} }
} }
@ -1700,6 +1737,11 @@ static unsigned short verifyGalFuseMap(const unsigned char* cfgArray, char useDe
char mapBit; // fuse bit stored in RAM char mapBit; // fuse bit stored in RAM
unsigned short errors = 0; unsigned short errors = 0;
#ifdef DEBUG_VERIFY
Serial.print(F("rot f:"));
Serial.println(rotatedFuseMap, DEC);
#endif
if (flagBits & FLAG_BIT_ATF16V8C) { if (flagBits & FLAG_BIT_ATF16V8C) {
setPV(0); setPV(0);
} }
@ -1715,12 +1757,12 @@ static unsigned short verifyGalFuseMap(const unsigned char* cfgArray, char useDe
addr = galinfo.rows; addr = galinfo.rows;
addr *= bit; addr *= bit;
addr += row; addr += row;
mapBit = getFuseBit(addr); mapBit = getFuseBit(addr); //bit from RAM
fuseBit = receiveBit(); fuseBit = receiveBit(); // read from GAL
if (mapBit != fuseBit) { if (mapBit != fuseBit) {
#ifdef DEBUG_VERIFY #ifdef DEBUG_VERIFY
Serial.print(F("f a=")); Serial.print(F("f a="));
Serial.println((row * galinfo.bits) + bit, DEC); Serial.print(addr, DEC);
#endif #endif
errors++; errors++;
} }
@ -1761,27 +1803,55 @@ static unsigned short verifyGalFuseMap(const unsigned char* cfgArray, char useDe
if (flagBits & FLAG_BIT_ATF16V8C) { if (flagBits & FLAG_BIT_ATF16V8C) {
setPV(0); setPV(0);
} }
// read CFG
if (galinfo.cfgmethod == CFG_STROBE_ROW) { if (galinfo.cfgmethod == CFG_STROBE_ROW2) { //ATF750C
strobeRow(galinfo.cfgrow); const uint8_t cfgstroberow = 96;
if (flagBits & FLAG_BIT_ATF16V8C) { const uint8_t cfgrowlen = 10;
setSDIN(0); const uint8_t cfgrowcount = (galinfo.cfgbits + (cfgrowlen - 1)) /cfgrowlen;
setPV(1); uint8_t i;
} for(i = 0; i < cfgrowcount; i++) {
strobeConfigRow(cfgstroberow + i);
for(bit = 0; bit < cfgrowlen; bit++) {
uint8_t absBit = (cfgrowlen * i) + bit;
if (absBit >= galinfo.cfgbits) {
break;
}
mapBit = getFuseBit(cfgAddr + pgm_read_byte(&cfgArray[absBit])); // cfgAddr + cfgOffset
fuseBit = receiveBit();
if (mapBit != fuseBit) {
#ifdef DEBUG_VERIFY
Serial.print(F("C a="));
Serial.println(absBit, DEC);
#endif
errors++;
}
}
if (useDelay) {
delay(useDelay);
}
}
} else { } else {
setRow(galinfo.cfgrow); if (galinfo.cfgmethod == CFG_STROBE_ROW) {
strobe(1); strobeRow(galinfo.cfgrow);
} if (flagBits & FLAG_BIT_ATF16V8C) {
for(bit = 0; bit < galinfo.cfgbits; bit++) { setSDIN(0);
unsigned char cfgOffset = pgm_read_byte(&cfgArray[bit]); //read array byte flom flash setPV(1);
mapBit = getFuseBit(cfgAddr + cfgOffset); }
fuseBit = receiveBit(); } else {
if (mapBit != fuseBit) { setRow(galinfo.cfgrow);
#ifdef DEBUG_VERIFY strobe(1);
Serial.print(F("C a=")); }
Serial.println(bit, DEC); for(bit = 0; bit < galinfo.cfgbits; bit++) {
#endif unsigned char cfgOffset = pgm_read_byte(&cfgArray[bit]); //read array byte flom flash
errors++; mapBit = getFuseBit(cfgAddr + cfgOffset);
fuseBit = receiveBit();
if (mapBit != fuseBit) {
#ifdef DEBUG_VERIFY
Serial.print(F("C a="));
Serial.println(bit, DEC);
#endif
errors++;
}
} }
} }
@ -2112,17 +2182,22 @@ static void writeGalFuseMapV10(const unsigned char* cfgArray, char fillUesStart,
} }
// fuse-map writing function for ATF750C chips // fuse-map writing function for ATF750C chips
static void writeGalFuseMapV750(const unsigned char* cfgArray, char fillUesStart, char useSdin) { static void writeGalFuseMapV750(const unsigned char* cfgArray) {
unsigned short cfgAddr = galinfo.cfgbase; unsigned short cfgAddr = galinfo.cfgbase;
unsigned char row, bit; unsigned char row, bit;
unsigned short addr; unsigned short addr;
unsigned short uesFill = galinfo.bits - (galinfo.uesbytes * 8) - 1;
uint8_t cfgRowLen = 10; //ATF750C
uint8_t cfgStrobeRow = 96; //ATF750C
// write fuse rows // write fuse rows
setRow(0); //RA0-5 low setRow(0); //RA0-5 low
delayMicroseconds(20); delayMicroseconds(20);
for(row = 0; row < galinfo.rows; row++) { for(row = 0; row < galinfo.rows; row++) {
for (bit = 0; bit < galinfo.bits; bit++) { for (bit = 0; bit < galinfo.bits; bit++) {
addr = (galinfo.bits * row) + bit; addr = galinfo.rows;
addr *= bit;
addr += row;
sendBit(getFuseBit(addr)); sendBit(getFuseBit(addr));
} }
@ -2135,72 +2210,63 @@ static void writeGalFuseMapV750(const unsigned char* cfgArray, char fillUesStart
delayMicroseconds(12); delayMicroseconds(12);
} }
// write UES
uint8_t fillBitsBegin = galinfo.bits - (8 * galinfo.uesbytes) - 1;
setRow(0); //RA0-5 low setRow(0); //RA0-5 low
if (fillUesStart) { sendBits(uesFill, 0); //send X number of 0 bits between fuse rows and UES data
sendBits(fillBitsBegin, 0);
} //write UES
else { for (bit = 0; bit < (8 * galinfo.uesbytes); bit++) {
fillBitsBegin = 0; addr = galinfo.uesfuse;
addr += bit;
sendBit(getFuseBit(addr));
}
//set 1 bit after UES to 0
sendBits(1, 0);
row = galinfo.uesrow;
sendAddress(7, row);
setPV(1);
strobe(progtime);
setPV(0);
delay(progtime);
// write CFG
uint8_t cfgrowcount = (galinfo.cfgbits + (cfgRowLen - 1)) / cfgRowLen;
for(uint8_t i = 0; i < cfgrowcount; i++) {
setRow(0);
delayMicroseconds(10);
setRow(galinfo.cfgrow);
for(bit = 0; bit < cfgRowLen; bit++) {
uint8_t absBit = bit + (i * cfgRowLen);
//addr = galinfo.cfgbase - (galinfo[gal].bits * rangeStartRow) + cfgArray[absBit];
addr = galinfo.cfgbase + pgm_read_byte(&cfgArray[absBit]);
uint8_t v = getFuseBit(addr);
sendBit(v);
} }
for (bit = 0; bit < (8 * galinfo.uesbytes); bit++) { sendAddress(7, i + cfgStrobeRow);
addr = bit; delayMicroseconds(10);
sendBit(getFuseBit(addr)); setPV(1);
} delayMicroseconds(18);
strobe(progtime); // 20ms
uint8_t fillBitsEnd = galinfo.bits - (8 * galinfo.uesbytes) - fillBitsBegin; delayMicroseconds(32);
if (fillBitsEnd > 0) { setPV(0);
sendBits(fillBitsEnd, 0); delayMicroseconds(12);
} setRow(0);
delayMicroseconds(12);
row = galinfo.uesrow; }
sendAddress(7, row); //TODO - read the power down fuse bit state from the fuse map and set it only if needed
if (1) {
// disable power-down feature (JEDEC bit #5892)
setRow(0);
sendAddress(7, 125);
setPV(1); setPV(1);
strobe(progtime); strobe(progtime);
setPV(0); setPV(0);
delay(progtime); delay(progtime);
}
uint8_t cfgRowLen = 10; //ATF750C
uint8_t cfgStrobeRow = 96; //ATF750C
// write CFG
uint8_t cfgrowcount = (galinfo.cfgbits + (cfgRowLen - 1)) / cfgRowLen;
for(uint8_t i = 0; i < cfgrowcount; i++) {
setRow(0);
delayMicroseconds(10);
setRow(galinfo.cfgrow);
for(bit = 0; bit < cfgRowLen; bit++) {
uint8_t absBit = bit + (i * cfgRowLen);
//addr = galinfo.cfgbase - (galinfo[gal].bits * rangeStartRow) + cfgArray[absBit];
addr = galinfo.cfgbase + pgm_read_byte(&cfgArray[absBit]);
uint8_t v = getFuseBit(addr);
sendBit(v);
}
sendAddress(7, i + cfgStrobeRow);
delayMicroseconds(10);
setPV(1);
delayMicroseconds(18);
strobe(progtime); // 20ms
delayMicroseconds(32);
setPV(0);
delayMicroseconds(12);
setRow(0);
delayMicroseconds(12);
}
if (useSdin) {
// disable power-down feature (JEDEC bit #5892)
setRow(0);
sendAddress(7, 125); //TODO - read the power down fuse bit state from the fuse map and set it only if needed
setPV(1);
strobe(progtime);
setPV(0);
delay(progtime);
}
} }
// fuse-map writing function for 600x GAL chips // fuse-map writing function for 600x GAL chips
@ -2311,7 +2377,7 @@ static void writeGal()
writeGalFuseMapV10(cfgV10, (gal == GAL22V10) ? 0 : 1, (gal == ATF22V10C) ? 1 : 0); writeGalFuseMapV10(cfgV10, (gal == GAL22V10) ? 0 : 1, (gal == ATF22V10C) ? 1 : 0);
break; break;
case ATF750C: case ATF750C:
writeGalFuseMapV750(cfgV750, 1, 1); writeGalFuseMapV750(cfgV750);
} }
turnOff(); turnOff();
} }
@ -2511,6 +2577,7 @@ static void printGalName() {
case ATF20V8B: Serial.println(F("ATF20V8B")); break; case ATF20V8B: Serial.println(F("ATF20V8B")); break;
case ATF22V10B: Serial.println(F("ATF22V10B")); break; case ATF22V10B: Serial.println(F("ATF22V10B")); break;
case ATF22V10C: Serial.println(F("ATF22V10C")); break; case ATF22V10C: Serial.println(F("ATF22V10C")); break;
case ATF750C: Serial.println(F("ATF750C")); break;
default: Serial.println(F("GAL")); break; default: Serial.println(F("GAL")); break;
} }
} }