diff --git a/afterburner.ino b/afterburner.ino index 2d7e3fe..6b602a2 100644 --- a/afterburner.ino +++ b/afterburner.ino @@ -39,7 +39,7 @@ */ -#define VERSION "0.4.1" +#define VERSION "0.4.2" //#define DEBUG_PES //#define DEBUG_VERIFY @@ -84,6 +84,8 @@ #define COMMAND_ENABLE_CHECK_TYPE 'f' #define COMMAND_DISABLE_CHECK_TYPE 'F' #define COMMAND_ENABLE_SECURITY 's' +#define COMMAND_ENABLE_APD 'z' +#define COMMAND_DISABLE_APD 'Z' #define READGAL 0 #define VERIFYGAL 1 @@ -103,6 +105,9 @@ // ATF16V8C flavour #define FLAG_BIT_ATF16V8C (1 << 1) +// Keep the power-down feature enabled for ATF C GALs +#define FLAG_BIT_APD (1 << 2) + // contents of pes[3] // Atmel PES is text string eg. 1B8V61F1 or 3Z01V22F1 // ^ ^ @@ -136,6 +141,9 @@ typedef enum { #define CFG_STROBE_ROW 0 #define CFG_SET_ROW 1 +// Atmel power-down row +#define CFG_ROW_APD 59 + // common CFG fuse address map for cfg16V8 and cfg20V8 // the only difference is the starting address: 2048 for cfg16V8 and 2560 for cfg20V8 // total size: 82 @@ -166,6 +174,7 @@ static const unsigned char cfgV8AB[]= // common CFG fuse address map for cfg22V10 // starting address: 5808 +// total size 20 static const unsigned char cfgV10[]= { 1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14,17,16,19,18, @@ -214,7 +223,7 @@ galinfo[]= }; // MAXFUSES calculated as the biggest required space to hold the fuse bitmap + UES bitmap + CFG bitmap -// MAXFUSES = ((132 * 44 bits) / 8) + uesbytes + (20 / 8) +// MAXFUSES = ((132 * 44 bits) / 8) + uesbytes + ((20 + 1) / 8) // +1 is the power-down extra fuse // 726 + 8 + 3 #define MAXFUSES 737 @@ -479,7 +488,8 @@ void parseUploadLine() { //checksum case 'c': { unsigned short val = parse4hex(3); - unsigned short cs = checkSum(galinfo[gal].fuses); + unsigned char apdFuse = (flagBits & FLAG_BIT_APD) ? 1 : 0; + unsigned short cs = checkSum(galinfo[gal].fuses + apdFuse); if (cs == val) { Serial.println(F("OK checksum matches")); } else { @@ -974,6 +984,21 @@ static void readGalFuseMap(const unsigned char* cfgArray, char useDelay, char do setFuseBit(cfgAddr + cfgArray[bit]); } } + + //check APD fuse bit - only for ATF16V8C or ATF22V10C + if ((flagBits & FLAG_BIT_ATF16V8C) || gal == ATF22V10C) { + setPV(0); + if (gal == ATF22V10C) { + setRow(0); + sendAddress(6, CFG_ROW_APD); + strobe(1); + } else { //ATF16V8C + setRow(CFG_ROW_APD); + strobe(1); + setPV(1); + } + setFlagBit(FLAG_BIT_APD, receiveBit()); + } } // generic fuse-map verification, fuse map bits are compared against read bits @@ -1068,6 +1093,30 @@ static unsigned short verifyGalFuseMap(const unsigned char* cfgArray, char useDe errors++; } } + + //verify PD fuse on Atmel's C GALs + if ((flagBits & FLAG_BIT_ATF16V8C) || gal == ATF22V10C) { + setPV(0); + if (gal == ATF22V10C) { + setRow(0); + sendAddress(6, CFG_ROW_APD); + strobe(1); + } else { //ATF16V8C + setRow(CFG_ROW_APD); + strobe(1); + setPV(1); + } + + mapBit = (flagBits & FLAG_BIT_APD)? 1 : 0; + fuseBit = receiveBit(); + if (mapBit != fuseBit) { +#ifdef DEBUG_VERIFY + Serial.println(F("C pd")); +#endif + errors++; + } + } + return errors; } @@ -1170,6 +1219,13 @@ static void writeGalFuseMapV8(const unsigned char* cfgArray) { } strobe(progtime); setPV(0); + + // disable power-down if the APD flag is not set (only for ATF16V8C) + if (skipLastClk && (flagBits & FLAG_BIT_APD) == 0) { + setPV(1); + strobeRow(CFG_ROW_APD, BIT_ZERO); // strobe row and send one bit with value 0 + setPV(0); + } } // fuse-map writing function for V10 GAL chips @@ -1222,15 +1278,14 @@ static void writeGalFuseMapV10(const unsigned char* cfgArray, char fillUesStart, strobe(progtime); setPV(0); - if (useSdin) { + if (useSdin && (flagBits & FLAG_BIT_APD) == 0) { // disable power-down feature (JEDEC bit #5892) setRow(0); - sendAddress(6, 59); + sendAddress(6, CFG_ROW_APD); setPV(1); strobe(progtime); setPV(0); } - } // main fuse-map writing function @@ -1450,11 +1505,12 @@ static void printJedec() { unsigned short i, j, k, n; unsigned char unused, start; + uint8_t apdFuse = (flagBits & FLAG_BIT_APD) ? 1 : 0; Serial.print(F("JEDEC file for ")); printGalName(); Serial.print(F("*QP")); Serial.print(galinfo[gal].pins, DEC); - Serial.print(F("*QF")); Serial.print(galinfo[gal].fuses, DEC); + Serial.print(F("*QF")); Serial.print(galinfo[gal].fuses + apdFuse, DEC); Serial.println(F("*QV0*F0*G0*X0*")); for( i = k = 0; i < galinfo[gal].bits; i++) { @@ -1503,6 +1559,7 @@ static void printJedec() line[0] = 0; + // UES in byte form Serial.print(F("N UES")); for (j = 0;j < galinfo[gal].uesbytes; j++) { n = 0; @@ -1521,6 +1578,7 @@ static void printJedec() } Serial.println(F("*")); + // UES in bit form Serial.print(F("L")); printFormatedNumberDec4(k); Serial.print(F(" ")); @@ -1534,7 +1592,7 @@ static void printJedec() } Serial.println(F("*")); - + // CFG bits if (k < galinfo[gal].fuses) { Serial.print(F("L")); printFormatedNumberDec4(k); @@ -1547,7 +1605,17 @@ static void printJedec() Serial.print(F("0")); } } + //ATF16V8C + if (apdFuse) { + Serial.print(F("1")); + setFuseBit(k); // set for correct check-sum calculation + } Serial.println(F("*")); + } else if (apdFuse) { //ATF22V10C + Serial.print(F("L")); + printFormatedNumberDec4(k); + Serial.println(F(" 1*")); + setFuseBit(k); // set for correct check-sum calculation } Serial.print(F("N PES")); @@ -1557,7 +1625,7 @@ static void printJedec() } Serial.println(F("*")); Serial.print(F("C")); - printFormatedNumberHex4(checkSum(galinfo[gal].fuses)); + printFormatedNumberHex4(checkSum(galinfo[gal].fuses + apdFuse)); Serial.println(); Serial.println(F("*")); } @@ -1688,6 +1756,17 @@ void loop() { } } break; + // keep atmel power-down feature enabled during write + case COMMAND_ENABLE_APD: { + setFlagBit(FLAG_BIT_APD, 1); + Serial.println(F("OK APD set")); + } break; + + case COMMAND_DISABLE_APD: { + setFlagBit(FLAG_BIT_APD, 0); + Serial.println(F("OK APD cleared")); + } break; + // toggles terminal echo case COMMAND_ECHO : { echoEnabled = 1 - echoEnabled; diff --git a/src_pc/afterburner.c b/src_pc/afterburner.c index f4176c7..ea048a9 100644 --- a/src_pc/afterburner.c +++ b/src_pc/afterburner.c @@ -51,7 +51,7 @@ To compile: gcc -g3 -O0 afterburner afterburner.c #include "serial_port.h" -#define VERSION "v.0.4.1" +#define VERSION "v.0.4.2" #define MAX_LINE 200 @@ -118,6 +118,7 @@ char opInfo = 0; char opVerify = 0; char opTestVPP = 0; char opSecureGal = 0; +char flagEnableApd = 0; static int waitForSerialPrompt(char* buf, int bufSize, int maxDelay); @@ -451,6 +452,18 @@ static int parseFuseMap(char *ptr) { } } } + if (lastfuse == 2195 && gal == ATF16V8B) { + flagEnableApd = fusemap[2194]; + if (verbose) { + printf("PD fuse detected: %i\n", fusemap[2194]); + } + } + if (lastfuse == 5893 && gal == ATF22V10C) { + flagEnableApd = fusemap[5892]; + if (verbose) { + printf("PD fuse detected: %i\n", fusemap[5892]); + } + } return n; } @@ -655,9 +668,12 @@ static char upload() { char buf[MAX_LINE]; char line[64]; unsigned int i, j, n; + unsigned short csum; + int apdFuse = flagEnableApd; + int totalFuses = galinfo[gal].fuses; - if (openSerial() != 0) { - return -1; + if (apdFuse) { + totalFuses++; } // Start upload @@ -671,7 +687,7 @@ static char upload() { //fuse map buf[0] = 0; fuseSet = 0; - for (i = 0; i < galinfo[gal].fuses;) { + for (i = 0; i < totalFuses;) { unsigned char f = 0; if (i % 32 == 0) { if (i != 0) { @@ -689,7 +705,7 @@ static char upload() { sprintf(buf, "#f %04i ", i); } f = 0; - for (j = 0; j < 8 && i < galinfo[gal].fuses; j++,i++) { + for (j = 0; j < 8 && i < totalFuses; j++,i++) { if (fusemap[i]) { f |= (1 << j); fuseSet = 1; @@ -711,10 +727,11 @@ static char upload() { } //checksum + csum = checkSum(totalFuses); if (verbose) { - printf("sending csum: %04X\n", checkSum(galinfo[gal].fuses)); + printf("sending csum: %04X\n", csum); } - sprintf(buf, "#c %04X\r", checkSum(galinfo[gal].fuses)); + sprintf(buf, "#c %04X\r", csum); sendLine(buf, MAX_LINE, 300); //end of upload @@ -722,6 +739,7 @@ static char upload() { } +//returns 0 on success static char sendGenericCommand(const char* command, const char* errorText, int maxDelay, char printResult) { char buf[MAX_LINE]; int readSize; @@ -760,6 +778,16 @@ static char operationWriteOrVerify(char doWrite) { if (verbose) { printf("parse result=%i\n", result); } + + if (openSerial() != 0) { + return -1; + } + + // set power-down fuse bit (do it before upload to correctly calculate check-sum) + result = sendGenericCommand(flagEnableApd ? "z\r" : "Z\r", "APD set failed ?", 4000, 0); + if (result) { + goto finish; + } result = upload(); if (result) { return result;