Initial support for ATF750C based on nospam2000 fork

Setup and PES reading works.

Based on fork: https://github.com/nospam2000/afterburner
By Michael D. - nospam2000
This commit is contained in:
ole00 2023-12-09 10:56:24 +00:00
parent bd19c7c776
commit b216b16c9a
2 changed files with 216 additions and 19 deletions

View File

@ -144,6 +144,7 @@
#define SGSTHOMSON 0x20
#define ATMEL16 'V'
#define ATMEL22 '1'
#define ATMEL750 'C'
typedef enum {
UNKNOWN,
@ -161,6 +162,7 @@ typedef enum {
ATF20V8B,
ATF22V10B,
ATF22V10C,
ATF750C,
LAST_GAL_TYPE //dummy
} GALTYPE;
@ -188,13 +190,24 @@ typedef enum {
#define CFG_BASE_26CV 6344
#define CFG_BASE_26V 7800
#define CFG_BASE_600 8154
#define CFG_BASE_750 14364
#define CFG_STROBE_ROW 0
#define CFG_SET_ROW 1
#define CFG_STROBE_ROW2 3
// Atmel power-down row
#define CFG_ROW_APD 59
// Naive detection of the board's RAM size - for support of big Fuse map:
// PIN_A11 - present on MEGA (8kB) or Leonardo (2.5kB SRAM)
// _RENESAS_RA_ - Uno R4 (32kB)
#if defined(PIN_A11) || defined(_RENESAS_RA_)
#define RAM_BIG
#endif
// 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
@ -317,6 +330,25 @@ static const unsigned char cfg6002[] PROGMEM =
64, 65
};
// TODO: handle those:
/*
30, // 75: Security?
135, // 70: Powerdown
136, // 71: PinKeeper
137, // 72: reserved1
138, // 73: reserved2
139, // 74: reserved3
*/
static const uint8_t cfgV750[] PROGMEM = {
0, 3, 6, 9, 12, 15, 18, 21, 24, 27, // S0
1, 4, 7, 10, 13, 16, 19, 22, 25, 28, // S1
2, 5, 8, 11, 14, 17, 20, 23, 26, 29, // S2
31, 35, 39, 43, 47, 51, 55, 59, 63, 67, // S3
32, 36, 40, 44, 48, 52, 56, 60, 64, 68, // S4
33, 37, 41, 45, 49, 53, 57, 61, 65, 69, // S5
34, 38, 42, 46, 50, 54, 58, 62, 66, 70 // S6
};
// UES user electronic signature
// PES programmer electronic signature (ATF = text string, others = Vendor/Vpp/timing)
// cfg configuration bits for OLMCs
@ -347,7 +379,7 @@ typedef struct
const static galinfo_t galInfoList[] PROGMEM =
{
// +fuses +bits +uesbytes +cfgbase
// +fuses +bits +uesbytes +pesrow +cfgbase
// | +pins | +uesrow | +eraserow| +pesbytes | +cfg
// +-- type + id0 + id1 | | +rows | | +uesfuse | +eraseallrow +cfgrow | | + cfgbits +cfgmethod +pinout
// | | | | | | | | | | | | | | | | | | | |
@ -366,12 +398,21 @@ const static galinfo_t galInfoList[] PROGMEM =
{ATF20V8B, 0x00, 0x00, 2706, 24, 40, 64, 40, 2568, 8, 63, 62, 58, 8, 60, CFG_BASE_20 , cfgV8AB , sizeof(cfgV8AB) , CFG_STROBE_ROW, PINOUT_20V8 },
{ATF22V10B, 0x00, 0x00, 5892, 24, 44, 132, 44, 5828, 8, 61, 62, 58, 10, 16, CFG_BASE_22 , cfgV10 , sizeof(cfgV10) , CFG_SET_ROW , PINOUT_22V10 },
{ATF22V10C, 0x00, 0x00, 5892, 24, 44, 132, 44, 5828, 8, 61, 62, 58, 10, 16, CFG_BASE_22 , cfgV10 , sizeof(cfgV10) , CFG_SET_ROW , PINOUT_22V10 },
{ATF750C, 0x00, 0x00, 14499, 24, 84, 171, 84,14435, 8, 61, 60,127, 10, 16, CFG_BASE_750 , cfgV750 , sizeof(cfgV750) , CFG_STROBE_ROW2, PINOUT_22V10 }, // TODO: not all numbers are clear
};
galinfo_t galinfo __attribute__ ((section (".noinit"))); //preserve data between resets
#ifdef RAM_BIG
// for ATF750C
// MAXFUSES = (((171 * 84 bits) + uesbits + (10*3 + 1 + 10*4 + 5)) + 7) / 8
// (14504 + 7) / 8 = 1813
#define MAXFUSES 1813
#else
// Boards with small RAM (< 2.5kB) do not support ATF750C
// 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
#define MAXFUSES 1042
#endif
GALTYPE gal __attribute__ ((section (".noinit"))); //the gal device index pointing to galInfoList, value is preserved between resets
@ -406,6 +447,10 @@ void printHelp(char full) {
if (varVppExists) {
Serial.println(F(" varVpp "));
}
#ifdef RAM_BIG
Serial.println(F(" RAM-BIG "));
#endif
if (!full) {
Serial.println(F("type 'h' for help"));
return;
@ -487,6 +532,7 @@ static void setPinMux(uint8_t pm) {
case GAL26V12:
case ATF22V10B:
case ATF22V10C:
case ATF750C:
pinMode(PIN_ZIF10, pm);
pinMode(PIN_ZIF11, pm);
pinMode(PIN_ZIF13, pm);
@ -836,11 +882,15 @@ static void setVPP(char on) {
// when PES is read the VPP is not determined via PES
if (on == READPES) {
if (gal == ATF16V8B || gal == ATF20V8B || gal == ATF22V10B || gal == ATF22V10C) {
if (gal == ATF16V8B || gal == ATF20V8B || gal == ATF22V10B || gal == ATF22V10C || gal == ATF750C) {
v = VPP_10V5;
} else {
v = VPP_11V5;
}
#if 0
Serial.print(F("VPP index="));
Serial.println(v);
#endif
} else {
//safety check
if (vpp < 36) {
@ -850,12 +900,12 @@ static void setVPP(char on) {
vpp = 48; //12V
}
v = (vpp >> 1) - 18; // 18: 2 * 9V, resolution 0.5V (not 0.25V) hence 'vpp >> 1'
#if 0
#if 0
Serial.print(F("setVPP "));
Serial.print(vpp);
Serial.print(F(" index="));
Serial.println(v);
#endif
#endif
}
varVppSet(on ? v : VPP_5V0);
delay(50); //settle the voltage
@ -1119,6 +1169,13 @@ static void sendAddress(unsigned char n, unsigned char row)
}
setSDIN(row & 32); // SDIN = row number bit 0
break;
case ATF750C:
while (n-- > 1) {
sendBit(row & 1); // clock in row number bits 0-5
row >>= 1;
}
setSDIN(row & 1); // SDIN = row number bit 6
break;
default:
while (n-- > 0) {
sendBit(row & 1); // clock in row number bits 0-5
@ -1142,6 +1199,7 @@ static void strobe(unsigned short msec)
// setBit: 0 - do not set bit, 1- set bit value 0, 2 - set bit value 1
static void strobeRow(char row, char setBit = BIT_NONE)
{
unsigned char nBits = 6;
switch(gal) {
case GAL16V8:
case GAL20V8:
@ -1153,6 +1211,9 @@ static void strobeRow(char row, char setBit = BIT_NONE)
}
strobe(2); // pulse /STB for 2ms
break;
case ATF750C:
nBits = 7;
//fall through
case GAL18V10:
case GAL20RA10:
case GAL20XV10:
@ -1162,7 +1223,7 @@ static void strobeRow(char row, char setBit = BIT_NONE)
case ATF22V10B:
case ATF22V10C:
setRow(0); // set RA0-5 low
sendAddress(6,row); // send row number (6 bits)
sendAddress(nBits, row); // send row number (6 or 7 bits)
setSTB(0);
setSTB(1); // pulse /STB
setSDIN(0); // SDIN low
@ -1179,6 +1240,20 @@ static void strobeRow(char row, char setBit = BIT_NONE)
}
}
static void strobeConfigRow(char row)
{
switch(gal) {
case ATF750C:
setRow(0); // set RA0-5 low
setRow(galinfo.cfgrow);
sendAddress(7, row); // send row number (6 bits)
setSDIN(1); // SDIN high
setSTB(0);
setSTB(1); // pulse /STB
break;
}
}
// read PES: programmer electronic signature (ATF = text string, others = Vendor/Vpp/timing)
static void readPes(void) {
unsigned short bitmask;
@ -1271,7 +1346,7 @@ static unsigned char getDuration(unsigned char index) {
}
static void setGalDefaults(void) {
if (gal == ATF16V8B || gal == ATF20V8B || gal == ATF22V10B || gal == ATF22V10C) {
if (gal == ATF16V8B || gal == ATF20V8B || gal == ATF22V10B || gal == ATF22V10C || gal == ATF750C) {
progtime = 20;
erasetime = 100;
vpp = 42; /* 10.5V */
@ -1299,6 +1374,7 @@ void parsePes(char type) {
case ATF20V8B:
case ATF22V10B:
case ATF22V10C:
case ATF750C:
progtime = 20;
erasetime = 100;
vpp = 48; /* 12.0V */
@ -1374,7 +1450,7 @@ void printPes(char type) {
Serial.print(F("PES info: "));
//voltage
if (pes[3] == ATMEL16 || pes[3] == ATMEL22) {
if (pes[3] == ATMEL16 || pes[3] == ATMEL22 || pes[3] == ATMEL750) {
//Serial.print(" ");
} else {
if (pes[1] & 0x10) {
@ -1389,6 +1465,7 @@ void printPes(char type) {
case LATTICE: Serial.print(F("Lattice ")); break;
case NATIONAL: Serial.print(F("National ")); break;
case SGSTHOMSON: Serial.print(F("ST Microsystems ")); break;
case ATMEL750:
case ATMEL16:
case ATMEL22: Serial.print(F("Atmel ")); break;
default: Serial.print(F("Unknown GAL, "));
@ -1410,6 +1487,7 @@ void printPes(char type) {
case ATF20V8B: Serial.print(F("ATF20V8B ")); break;
case ATF22V10B: Serial.print(F("ATF22V10B ")); break;
case ATF22V10C: Serial.print(F("ATF22V10C ")); break;
case ATF750C: Serial.print(F("ATF750C ")); break;
}
//programming info
@ -1873,6 +1951,13 @@ static void readOrVerifyGal(char verify)
readGalFuseMap(cfgV10, 1, (gal == GAL22V10) ? 0 : 68);
}
break;
case ATF750C:
//read with delay 1 ms, discard 107 bits on ATF750C
if (verify) {
i = verifyGalFuseMap(galinfo.cfg, 1, galinfo.bits - 8 * galinfo.uesbytes - 1);
} else {
readGalFuseMap(galinfo.cfg, 1, galinfo.bits - 8 * galinfo.uesbytes - 1);
}
}
turnOff();
@ -1993,6 +2078,98 @@ static void writeGalFuseMapV10(const unsigned char* cfgArray, char fillUesStart,
}
}
// fuse-map writing function for ATF750C chips
static void writeGalFuseMapV750(const unsigned char* cfgArray, char fillUesStart, char useSdin) {
unsigned short cfgAddr = galinfo.cfgbase;
unsigned char row, bit;
unsigned short addr;
// write fuse rows
setRow(0); //RA0-5 low
delayMicroseconds(20);
for(row = 0; row < galinfo.rows; row++) {
for (bit = 0; bit < galinfo.bits; bit++) {
addr = (galinfo.bits * row) + bit;
sendBit(getFuseBit(addr));
}
sendAddress(7, row);
setPV(1);
delayMicroseconds(20);
strobe(progtime);
delayMicroseconds(100);
setPV(0);
delayMicroseconds(12);
}
// write UES
uint8_t fillBitsBegin = galinfo.bits - (8 * galinfo.uesbytes) - 1;
setRow(0); //RA0-5 low
if (fillUesStart) {
sendBits(fillBitsBegin, 0);
}
else {
fillBitsBegin = 0;
}
for (bit = 0; bit < (8 * galinfo.uesbytes); bit++) {
addr = bit;
sendBit(getFuseBit(addr));
}
uint8_t fillBitsEnd = galinfo.bits - (8 * galinfo.uesbytes) - fillBitsBegin;
if (fillBitsEnd > 0) {
sendBits(fillBitsEnd, 0);
}
row = galinfo.uesrow;
sendAddress(7, row);
setPV(1);
strobe(progtime);
setPV(0);
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
static void writeGalFuseMap600(const unsigned char* cfgArray) {
unsigned short cfgAddr = galinfo.cfgbase;
@ -2099,7 +2276,9 @@ static void writeGal()
case ATF22V10B:
case ATF22V10C:
writeGalFuseMapV10(cfgV10, (gal == GAL22V10) ? 0 : 1, (gal == ATF22V10C) ? 1 : 0);
break;
break;
case ATF750C:
writeGalFuseMapV750(cfgV750, 1, 1);
}
turnOff();
}
@ -2162,6 +2341,10 @@ static char checkGalTypeViaPes(void)
setFlagBit(FLAG_BIT_ATF16V8C, 1);
}
}
else if (pes[8] == 'F' && pes[7] == 'V' && pes[6] == '7' && pes[5] == '5' && pes[4] == '0' && pes[3] =='C') {
// complete string at beginning of row 127: "300C057VF100"
type = ATF750C;
}
else if (pes[2] != 0x00 && pes[2] != 0xFF) {
for (type = (sizeof(galInfoList) / sizeof(galinfo_t)) - 1; type; type--) {
uint8_t id0 = pgm_read_byte(&galInfoList[type].id0);
@ -2377,7 +2560,7 @@ static void printJedec()
n = 0;
for (i = 0; i < 8; i++) {
if (getFuseBit(k + 8 * j + i)) {
if (gal == ATF22V10C) {
if (gal == ATF22V10C || gal == ATF750C) {
n |= 1 << (7 - i); // big-endian
}
else {

View File

@ -70,7 +70,8 @@ typedef enum {
ATF16V8B,
ATF20V8B,
ATF22V10B,
ATF22V10C
ATF22V10C,
ATF750C,
} Galtype;
@ -109,6 +110,7 @@ galinfo[] = {
{ATF20V8B, 0x00, 0x00, "ATF20V8B", 2706, 24, 40, 64, 40, 2568, 8, 63, 59, 58, 8, 60, 82},
{ATF22V10B, 0x00, 0x00, "ATF22V10B", 5892, 24, 44, 132, 44, 5828, 8, 61, 60, 58, 10, 16, 20},
{ATF22V10C, 0x00, 0x00, "ATF22V10C", 5892, 24, 44, 132, 44, 5828, 8, 61, 60, 58, 10, 16, 20},
{ATF750C, 0x00, 0x00, "ATF750C", 14499, 24, 84, 171, 84, 14435, 8, 61, 60, 127, 10, 16, 71},
};
char verbose = 0;
@ -127,6 +129,7 @@ char varVppExists = 0;
char printSerialWhileWaiting = 0;
int calOffset = 0; //no calibration offset is applied
char enableSecurity = 0;
char bigRam = 0;
char opRead = 0;
char opWrite = 0;
@ -510,11 +513,11 @@ static int parseFuseMap(char *ptr) {
if (
(lastfuse == 0 ||
galinfo[i].fuses == lastfuse ||
galinfo[i].uesfuse == lastfuse && galinfo[i].uesfuse + 8 * galinfo[i].uesbytes == galinfo[i].fuses)
(galinfo[i].uesfuse == lastfuse && galinfo[i].uesfuse + 8 * galinfo[i].uesbytes == galinfo[i].fuses))
&&
(pins == 0 ||
galinfo[i].pins == pins ||
galinfo[i].pins == 24 && pins == 28)
(galinfo[i].pins == 24 && pins == 28))
) {
if (gal == 0) {
type = i;
@ -556,6 +559,11 @@ static char readJedec(void) {
return 0;
}
static char checkForString(char* buf, int start, const char* key) {
int labelPos = strstr(buf + start, key) - buf;
return (labelPos > 0 && labelPos < 500) ? 1 : 0;
}
static int openSerial(void) {
char buf[512] = {0};
char devName[256] = {0};
@ -589,14 +597,17 @@ static int openSerial(void) {
//check we are communicating with Afterburner programmer
labelPos = strstr(buf, "AFTerburner v.") - buf;
bigRam = 0;
if (labelPos >= 0 && labelPos < 500 && buf[total - 3] == '>') {
// check for new board desgin: variable VPP
labelPos = strstr(buf + labelPos, " varVpp ") - buf;
if (labelPos > 0 && labelPos < 500) {
if (verbose) {
printf("variable VPP board detected\n");
}
varVppExists = 1;
varVppExists = checkForString(buf, labelPos, " varVpp ");
if (verbose && varVppExists) {
printf("variable VPP board detected\n");
}
// check for Big Ram
bigRam = checkForString(buf, labelPos, " RAM-BIG");
if (verbose & bigRam) {
printf("MCU Big RAM detected\n");
}
//all OK
return 0;
@ -724,7 +735,10 @@ static int waitForSerialPrompt(char* buf, int bufSize, int maxDelay) {
maxDelay -= 10;
#else
maxDelay -= 30;
#endif
#endif
if(maxDelay <= 0 && verbose) {
printf("waitForSerialPrompt timed out\n");
}
}
}
return bufPos;