PC app: added support for JTAG and ATF1502 and ATF1504

This commit is contained in:
ole00 2024-03-31 14:45:10 +01:00
parent 5621df2f1f
commit 0e99f07370

View File

@ -59,7 +59,10 @@ To compile: gcc -g3 -O0 -o afterburner afterburner.c
#define MAX_LINE (16*1024)
#define MAXFUSES 30000
#define GALBUFSIZE 65536
#define GALBUFSIZE (256 * 1024)
#define JTAG_ID 0xFF
typedef enum {
UNKNOWN,
@ -78,6 +81,9 @@ typedef enum {
ATF22V10B,
ATF22V10C,
ATF750C,
//jtag based PLDs at the end: they do not have a gal type in MCU software
ATF1502AS,
ATF1504AS,
} Galtype;
@ -117,6 +123,8 @@ galinfo[] = {
{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},
{ATF1502AS, JTAG_ID, JTAG_ID, "ATF1502AS", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0},
{ATF1504AS, JTAG_ID, JTAG_ID, "ATF1504AS", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0},
};
char verbose = 0;
@ -228,10 +236,6 @@ static int8_t verifyArgs(char* type) {
printf("Error: VPP functions can not be conbined with read/write/verify operations\n");
return -1;
}
if (0 == filename && (opWrite == 1 || opVerify == 1)) {
printf("Error: missing JED filename\n");
return -1;
}
if (0 == type && (opWrite || opRead || opErase || opVerify || opInfo || opWritePes)) {
printf("Error: missing GAL type. Use -t <type> to specify.\n");
return -1;
@ -250,6 +254,10 @@ static int8_t verifyArgs(char* type) {
return -1;
}
}
if (0 == filename && (opWrite == 1 || opVerify == 1)) {
printf("Error: missing %s filename (param: -f fname)\n", galinfo[gal].id0 == JTAG_ID ? ".xsvf" : ".jed");
return -1;
}
return 0;
}
@ -552,11 +560,14 @@ static int parseFuseMap(char *ptr) {
return n;
}
static char readJedec(void) {
static char readFile(int* fileSize) {
FILE* f;
int size;
f = fopen(filename, "r");
if (verbose) {
printf("opening file: '%s'\n", filename);
}
f = fopen(filename, "rb");
if (f) {
size = fread(galbuffer, 1, GALBUFSIZE, f);
fclose(f);
@ -565,6 +576,9 @@ static char readJedec(void) {
printf("Error: failed to open file: %s\n", filename);
return -1;
}
if (fileSize != NULL) {
*fileSize = size;
}
return 0;
}
@ -760,19 +774,13 @@ static int waitForSerialPrompt(char* buf, int bufSize, int maxDelay) {
return bufPos;
}
static int sendLine(char* buf, int bufSize, int maxDelay) {
static int sendBuffer(char* buf) {
int total;
int writeSize;
char* obuf = buf;
if (serialF == INVALID_HANDLE) {
return -1;
}
if (buf == 0) {
return -1;
}
total = strlen(buf);
// write the query into the serial port's file
// file is opened non blocking so we have to ensure all contents is written
@ -785,6 +793,21 @@ static int sendLine(char* buf, int bufSize, int maxDelay) {
buf += writeSize;
total -= writeSize;
}
return 0;
}
static int sendLine(char* buf, int bufSize, int maxDelay) {
int total;
char* obuf = buf;
if (serialF == INVALID_HANDLE) {
return -1;
}
total = sendBuffer(buf);
if (total) {
return total;
}
total = waitForSerialPrompt(obuf, bufSize, (maxDelay < 0) ? 6 : maxDelay);
if (total < 0) {
@ -922,7 +945,7 @@ static char operationWriteOrVerify(char doWrite) {
char result;
if (readJedec()) {
if (readFile(NULL)) {
return -1;
}
@ -1208,6 +1231,286 @@ static char operationReadFuses(void) {
return 0;
}
static int readJtagSerialLine(char* buf, int bufSize, int maxDelay, int* feedRequest) {
char* bufStart = buf;
int readSize;
int bufPos = 0;
memset(buf, 0, bufSize);
while (maxDelay > 0) {
readSize = serialDeviceRead(serialF, buf, 1);
if (readSize > 0) {
bufPos += readSize;
buf[1] = 0;
//handle the feed request
if (buf[0] == '$') {
char tmp[5];
bufPos -= readSize;
buf[0] = 0;
//extra 5 bytes should be present: 3 bytes of size, 2 new line chars
readSize = serialDeviceRead(serialF, tmp, 5);
if (readSize == 5) {
tmp[3] = 0;
*feedRequest = atoi(tmp);
maxDelay = 0; //force exit
} else {
printf("Warning: corrupted feed request!\n");
}
//printf("***\n");
} else
if (buf[0] == '\r') {
readSize = serialDeviceRead(serialF, buf, 1); // read \n coming from Arduino
//printf("-%c-\n", buf[0] == '\n' ? 'n' : 'r');
buf[0] = 0;
bufPos++;
maxDelay = 0; //force exit
} else {
//printf("(0x%02x %d) \n", buf[0], (int) buf[0]);
buf += readSize;
if (bufPos == bufSize) {
printf("ERROR: serial port read buffer is too small!\nAre you dumping large amount of data?\n");
return -1;
}
}
}
if (maxDelay > 0) {
/* WIN_API handles timeout itself */
#ifndef _USE_WIN_API_
usleep(1 * 1000);
maxDelay -= 10;
#else
maxDelay -= 30;
#endif
}
}
return bufPos;
}
static int playJtagFile(char* label, int fSize, int vpp, int showProgress) {
char buf[MAX_LINE] = {0};
int sendPos = 0;
char ready = 0;
int result = 0;
unsigned int csum = 0;
int feedRequest = 0;
// support for XCOMMENT messages which might be interrupted by a feed request
int continuePrinting = 0;
if (openSerial() != 0) {
return -1;
}
//compute check sum
if (verbose) {
int i;
for (i = 0; i < fSize; i++) {
csum += (unsigned char) galbuffer[i];
}
}
// send start-JTAG-player command
sprintf(buf, "j%d\r", vpp ? 1: 0);
sendBuffer(buf);
// read response from MCU and feed the XSVF player with data
while(1) {
int readBytes;
feedRequest = 0;
buf[0] = 0;
readBytes = readJtagSerialLine(buf, MAX_LINE, 3000, &feedRequest);
//printf(">> read %d len=%d cp=%d '%s'\n", readBytes, (int) strlen(buf), continuePrinting, buf);
//request to send more data was received
if (feedRequest > 0) {
if (ready) {
int chunkSize = fSize - sendPos;
if (chunkSize > feedRequest) {
chunkSize = feedRequest;
// make the initial chunk big so the data are buffered by the OS
if (sendPos == 0) {
chunkSize *= 4;
if (chunkSize > fSize) {
chunkSize = fSize;
}
}
}
if (chunkSize > 0) {
// send the data over serial line
int w = serialDeviceWrite(serialF, galbuffer + sendPos, chunkSize);
sendPos += w;
// print progress / file position
if (showProgress && (sendPos % 1024 == 0 || sendPos == fSize)) {
updateProgressBar(label, sendPos, fSize);
}
}
}
if (readBytes > 2) {
continuePrinting = 1;
}
}
// when the feed request was detected, there might be still some data in the buffer
if (buf[0] != 0) {
//prevous line had a feed request - this is a continuation
if (feedRequest == 0 && continuePrinting) {
continuePrinting = 0;
printf("%s\n", buf);
} else
//print debug messages
if (buf[0] == 'D') {
if (feedRequest) { // the rest of the message will follow
printf("%s", buf + 1);
} else {
printf("%s\n", buf + 1);
}
}
// quit
if (buf[0] == 'Q') {
result = atoi(buf + 1);
//print error result
if (result != 0) {
printf("%s\n", buf + 1);
} else
// when all is OK and verbose mode is on, then print the checksum for comparison
if (verbose) {
printf("PC : 0x%08X\n", csum);
}
break;
} else
// ready to receive anouncement
if (strcmp("RXSVF", buf) == 0) {
ready = 1;
} else
// print important messages
if (buf[0] == '!') {
// in verbose mode print all messages, otherwise print only success or fail messages
if (verbose || 0 == strcmp("!Success", buf) || 0 == strcmp("!Fail", buf)) {
printf("%s\n", buf + 1);
}
}
#if 0
//print all the rest
else if (verbose) {
printf("'%s'\n", buf);
}
#endif
} else
// the buffer is empty but there was a feed request just before - print a new line
if (readBytes > 0 && continuePrinting) {
printf("\n");
continuePrinting = 0;
}
}
readJtagSerialLine(buf, MAX_LINE, 1000, &feedRequest);
return result;
}
static int processJtagInfo(void) {
int result;
int fSize = 0;
char tmp[256];
if (!opInfo) {
return 0;
}
if (!(gal == ATF1502AS || gal == ATF1504AS)) {
printf("error: infor command is unsupported");
return 1;
}
// Use default .xsvf file for erase if no file is provided.
// if the file is provided while write operation is also requested
// then the file is specified for writing -> do not use it for erasing
sprintf(tmp, "xsvf/id_ATF150X.xsvf");
filename = tmp;
result = readFile(&fSize);
if (result) {
return result;
}
//play the info file and use high VPP
return playJtagFile("", fSize, 1, 0);
}
static int processJtagErase(void) {
int result;
int fSize = 0;
char tmp[256];
char* originalFname = filename;
if (!opErase) {
return 0;
}
// Use default .xsvf file for erase.
sprintf(tmp, "xsvf/erase_%s.xsvf", galinfo[gal].name);
filename = tmp;
result = readFile(&fSize);
if (result) {
filename = originalFname;
return result;
}
filename = originalFname;
//play the erase file and use high VPP
return playJtagFile("erase ", fSize, 1, 1);
}
static int processJtagWrite(void) {
int result;
int fSize = 0;
if (!opWrite) {
return 0;
}
// paranoid: this condition should be already checked during argument's check
if (0 == filename) {
return -1;
}
result = readFile(&fSize);
if (result) {
return result;
}
//play the file and use low VPP
return playJtagFile("write ", fSize, 0, 1);
}
static int processJtag(void) {
int result;
if (verbose) {
printf("JTAG\n");
}
if ((gal == ATF1502AS || gal == ATF1504AS) && (opRead || opVerify)) {
printf("error: read and verify operation is not supported\n");
return 1;
}
result = processJtagInfo();
if (result) {
return result;
}
result = processJtagErase();
if (result) {
return result;
}
result = processJtagWrite();
if (result) {
return result;
}
return 0;
}
int main(int argc, char** argv) {
char result = 0;
int i;
@ -1220,6 +1523,12 @@ int main(int argc, char** argv) {
printf("Afterburner " VERSION " \n");
}
// process JTAG operations
if (gal != 0 && galinfo[gal].id0 == JTAG_ID && galinfo[gal].id1 == JTAG_ID) {
result = processJtag();
goto finish;
}
result = operationSetGalCheck();
if (gal != UNKNOWN && 0 == result) {
@ -1262,6 +1571,7 @@ int main(int argc, char** argv) {
}
}
finish:
if (verbose) {
printf("result=%i\n", (char)result);
}