mirror of
https://github.com/ole00/afterburner.git
synced 2025-02-16 19:31:15 +00:00
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:
parent
053c914fae
commit
e99494df09
285
afterburner.ino
285
afterburner.ino
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user