📄 prog89s52-1.0.c
字号:
case 2: /* LB1 set, B2 = 1 B1 = 0 */ byteout(0xAC) ; byteout(0xE0 | B2) ; byteout(0x00) ; byteout(0x00) ; break ; case 3: /* LB2 set, B2 = 0 B1 = 1 */ byteout(0xAC) ; byteout(0xE0 | B1) ; byteout(0x00) ; byteout(0x00) ; break ; case 4: /* LB3 set, B2 = 1 B1 = 1 (other modes to be set sequentially first) */ byteout(0xAC) ; byteout(0xE0 | B1 | B2) ; byteout(0x00) ; byteout(0x00) ; break ; default: msg(0, "Invalid lock mode (should be between 1 and 4\n") ; } }/*--------------------------------------------------------------------------------------------------------------*//*--------------------------------------------------------------------------------------------------------------*//* Parse the program arguments */#define GETDECARG {\ if(argindex+1 >= argc || !argv[argindex+1] || !sscanf(argv[argindex+1], "%i", &intarg)) {\ msg(0, "%s requires decimal integer argument\n", argv[argindex]) ;\ return(1) ; }\ }#define GETHEXARG {\ if(argindex+1 >= argc || !argv[argindex+1] || !sscanf(argv[argindex+1], "%x", &intarg)) {\ msg(0, "%s requires hexadecimal argument\n", argv[argindex]) ;\ return(1) ; }\ }#define GETSTRARG {\ if(argindex+1 >= argc || !argv[argindex+1] || argv[argindex+1][0] == '-') {\ msg(0, "%s requires string argument\n", argv[argindex]) ;\ return(1) ; }\ else {\ strarg = argv[argindex+1] ;\ }\ }int parseargs(int argc, char *argv[]) { int argindex ; int intarg ; char *strarg ; for(argindex = 1; argindex < argc; argindex ++) { if(argv[argindex][0] == '-' && strlen(argv[argindex]) > 1) { /* beginning of a switch sequence such as -x*/ switch(argv[argindex][1]) { case 'd': /* delay */ GETDECARG ; delay = intarg ; msg(90, "Option: delay = %i\n", delay) ; break ; case 'v': /* verbosity */ GETDECARG ; verbosity = intarg ; msg(90, "Option: verbosity = %i\n", verbosity) ; break ; case 'i': /* read device ID */ doreadid = 1 ; msg(90, "Option: Read device identification bits\n") ; break ; case 'l': /* read lockbits */ doreadlocks = 1 ; msg(90, "Option: read lock bits\n") ; break ; case 'L': /* write lockbits */ GETDECARG ; dowritelocks = intarg ; msg(90, "Option: Set lock mode %i\n", dowritelocks) ; break ; case 'p': /* program (arg is name of hex file) */ GETSTRARG ; hexfilename = strdup(strarg) ; if(!donoerase) doerase = 1 ; doprogram = 1 ; msg(90, "Option: Program from HEX file %s\n", hexfilename) ; break ; case 'e': /* erase part */ if(!donoerase) doerase = 1 ; msg(90, "Option: erase flash\n") ; break ; case 'n': /* do not erase (used with p) */ donoerase = 1 ; doerase = 0 ; msg(90, "Option: do not erase flash\n") ; break ; case 's': /* simulate; parse hex file but do not write */ domock = 1 ; msg(90, "Option: mock only (do not program)\n") ; break ; case 'm': /* memory map - create a text file showing the contants of the memory to be programmed. arg is file name */ GETSTRARG ; initmemmap(&mapfromfile, strarg, 0) ; /* initialise an empty map */ domemfile = 1 ; msg(90, "Option: write hex file to memory dump in file %s\n", mapfromfile.filename) ; break ; case 'a': /* port address */ GETHEXARG ; portbase = intarg ; msg(90, "Option: use parallel port at 0x%X\n", portbase) ; break ; case 'r': /* perform a reset */ doreset = 1 ; msg(90, "Option: reset part\n") ; break ; case 'G': /* get program from part - arguments are memory size (k) and filename. file is hex format (G) */ docopytohexfile = 1 ; case 'g': /* get program from part - arguments are memory size (k) and filename. file is memory dump format (g) */ if(!docopytohexfile) docopytomemfile = 1 ; GETDECARG ; argindex ++ ; GETSTRARG ; if(initmemmap(&mapfrompart, strarg, (1024 * intarg) / BLOCKSIZE)) { /* initialise map of the correct size - dissable dump if this fails */ docopytomemfile = 0 ; docopytohexfile = 0 ; } msg(90, "Option: copy %i bytes of program memory into file %s\n", (1024 * intarg), mapfrompart.filename) ; break ; case 'V': msg(0, "prog89s %s by TOMi. Build date %s at %s.\n", VERSION, __DATE__, __TIME__) ; exit(0) ; default: case 'h': /* help */ help() ; exit(0) ; } } } return(0) ; }/*--------------------------------------------------------------------------------------------------------------*//*--------------------------------------------------------------------------------------------------------------*//* open the hex file */int openfile(void) { int hexfd ; msg(100, "Proceeding to open file %s for read-only access\n", hexfilename) ; hexfd = open(hexfilename, O_RDONLY) ; if(hexfd < 0) { msg(0, "Unable to open HEX file %s\n", hexfilename) ; perror("open") ; } else { msg(50, "Opened HEX file %s\n", hexfilename) ; } return(hexfd) ; }/*--------------------------------------------------------------------------------------------------------------*//*--------------------------------------------------------------------------------------------------------------*//* Translate binary data into human readable string (return must be free()'d) */char *binstring(void *data, int length) { char *str ; int count ; if(!(str = malloc(length*3 + 1))) { msg(0, "Failed to allocate %i bytes of memory for creating human-readable hex string\n", length*3 + 1) ; return(NULL) ; } for(count = 0; count < length; count++) { sprintf(str + count*3, "%02X ", ((unsigned char*)data)[count]) ; } str[length*3] = 0 ; return(str) ; }/*--------------------------------------------------------------------------------------------------------------*//*--------------------------------------------------------------------------------------------------------------*//* Read a HEX integer number a specified number of nibbles long from the current file position */int readrecordint(int hexfd, int length) { char buffer[5] ; ssize_t readbytes ; int intvalue ; if(length > 4) return(-1) ; readbytes = read(hexfd, buffer, length) ; if(readbytes < length) { msg(0, "Unxepected end-of-file at %i bytes whilst reading hex file\n", lseek(hexfd, 0, SEEK_CUR)) ; return(-1) ; } if(readbytes == -1) { msg(0, "File read error at %i bytes whilst reading hex file\n", lseek(hexfd, 0, SEEK_CUR)) ; perror("read") ; return(-1) ; } buffer[length] = 0 ; msg(100, "Extracted %i bytes from hex file: '%s'\n", length, buffer) ; if(!sscanf(buffer, "%x", &intvalue)) { msg(0, "The string %s (at %i bytes) is not a valid hexadecimal number\n", buffer, lseek(hexfd, 0, SEEK_CUR)) ; return(-1) ; } return(intvalue) ; }/*--------------------------------------------------------------------------------------------------------------*//*--------------------------------------------------------------------------------------------------------------*//* Read an array of bytes from the HEX file (return must be free()'d) */unsigned char *readrecordbytes(int hexfd, int length) { char buffer[3] ; ssize_t readbytes ; unsigned char *data ; int bytecount ; int value ; if(!(data = malloc(length))) { msg(0, "Failed to allocate %i bytes of memory for reading record data\n", length) ; return(NULL) ; } for(bytecount = 0; bytecount < length; bytecount ++) { readbytes = read(hexfd, buffer, 2) ; if(readbytes < 2) { msg(0, "Unxepected end-of-file at %i bytes whilst reading hex file record data\n", lseek(hexfd, 0, SEEK_CUR)) ; return(NULL) ; } if(readbytes == -1) { msg(0, "File read error at %i bytes whilst reading hex file record data\n", lseek(hexfd, 0, SEEK_CUR)) ; perror("read") ; return(NULL) ; } buffer[2] = 0 ; if(!sscanf(buffer, "%x", &value)) { msg(0, "The string %s (at %i bytes) is not a valid hexadecimal number\n", buffer, lseek(hexfd, 0, SEEK_CUR)) ; return(NULL) ; } data[bytecount] = (unsigned char)value ; } return(data) ; }/*--------------------------------------------------------------------------------------------------------------*/#define OK 0#define ERROR 1#define END 2#define ABORT 3#define IGNORE 4typedef struct { unsigned char *data ; int address ; int length ; char status ; } record ;/*--------------------------------------------------------------------------------------------------------------*//* Read a single record from the hex file */record readrecord(int hexfd, int seekstart, int* seekend) { char startstr ; int datalength ; int address ; int rectype ; int chksum ; unsigned char *data ; char *datastring ; int databytecount ; unsigned char calcsum = 0 ; ssize_t readbytes ; record thisrec ; /* seek to the beginning of the next record */ lseek(hexfd, seekstart, SEEK_SET) ; do { readbytes = read(hexfd, &startstr, 1) ; if(readbytes == 0) { /* unexpected EOF whilst seeking record start */ msg(0, "Unxepected end-of-file at %i bytes whilst seeking hex file record start\n", lseek(hexfd, 0, SEEK_CUR)) ; thisrec.status = ABORT ; return(thisrec) ; } if(readbytes == -1) { /* other IO error */ msg(0, "File read error at %i bytes whilst seeking hex file record start\n", lseek(hexfd, 0, SEEK_CUR)) ; thisrec.status = ABORT ; return(thisrec) ; } } while(startstr != ':') ; /* finish loop once we find a colon (start of record marker) */ msg(100, "Record start located at file offset %i\n", lseek(hexfd, 0, SEEK_CUR)) ; /* read record data length */ if((datalength = readrecordint(hexfd, 2)) < 0) { thisrec.status = ABORT ; return(thisrec) ; } calcsum += datalength ; /* calculate running checksum */ msg(100, "Record length is %i (0x%X) bytes\n", datalength, datalength) ; /* read record address */ if((address = readrecordint(hexfd, 4)) < 0) { thisrec.status = ABORT ; return(thisrec) ; } calcsum += address & 0x00FF ; /* calculate running checksum (add low byte) */ calcsum += (address>>8) & 0x00FF ; /* calculate running checksum (add high byte) */ msg(100, "Record start address is %i (0x%X)\n", address, address) ; /* read record type */ if((rectype = readrecordint(hexfd, 2)) < 0) { thisrec.status = ABORT ; return(thisrec) ; } calcsum += rectype ; /* calculate running checksum */ msg(100, "Record type is %i (0x%X)\n", rectype, rectype) ; switch(rectype) { case 0: msg(100, "Record type is Data\n") ; break ; case 1: msg(100, "Record type is End-of-file\n") ; thisrec.status = END ; return(thisrec) ; break ; case 2: msg(0, "Warning: Extended segment address records are not supported\n") ; thisrec.status = IGNORE ; return(thisrec) ; break ; case 4: msg(0, "Warning: Extended linear address records are not supported\n") ; thisrec.status = IGNORE ; return(thisrec) ; break ; } /* read record data */ if((data = readrecordbytes(hexfd, datalength)) == NULL) { thisrec.status = ABORT ; return(thisrec) ; } for(databytecount = 0; databytecount < datalength; databytecount++) calcsum += data[databytecount] ; if(verbosity >= 100 && (datastring = binstring(data, datalength))) { msg(100, "Record data: %s (%i bytes)\n", datastring, datalength) ; free(datastring) ; } /* read the checksum */ if((chksum = readrecordint(hexfd, 2)) < 0) { free(data) ; thisrec.status = ABORT ; return(thisrec) ; } msg(100, "Record checksum is %i (0x%X)\n", chksum, chksum) ; calcsum = 1 + ~calcsum ; if(calcsum == chksum) { /* checksum OK */ thisrec.status = OK ; msg(100, "Record checksum verified\n") ; } else { /* checksum does not match */ thisrec.status = ERROR ; msg(0, "Warning: Record checksum (0x%02X) does not match calculated checksum (0x%02X)\n", chksum, calcsum) ; } *seekend = lseek(hexfd, 0, SEEK_CUR) ; /* place the record finishing offset in the passed variable */ msg(100, "Record end located at file offset %i\n", *seekend) ; thisrec.data = data ; thisrec.address = address ; thisrec.length = datalength ; return(thisrec) ; }/*--------------------------------------------------------------------------------------------------------------*//*--------------------------------------------------------------------------------------------------------------*//* add the record to the internal memory map */void makememmap(record thisrec, memmap *map) { unsigned int requiredblocks ; unsigned int index ; /* work out if this record will place data off the end of the allready existing memory, and allocate more if so */ requiredblocks = ((thisrec.address + thisrec.length)/BLOCKSIZE) + 1 ; if(requiredblocks > (*map).blocks) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -