From: Nathael Pajani Date: Fri, 13 Apr 2012 03:47:07 +0000 (+0200) Subject: Synchro now OK, simple read commands (no arguments) working. X-Git-Tag: v1.0~49 X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=ae22266b075b8b0395cca9093ad36f1f2d91c28f;p=soft%2Ftools%2Flpctools Synchro now OK, simple read commands (no arguments) working. --- diff --git a/isp_commands.c b/isp_commands.c index f02c9c7..862b42a 100644 --- a/isp_commands.c +++ b/isp_commands.c @@ -5,89 +5,268 @@ *********************************************************************/ -#include +#include /* strtoul */ #include #include #include -#include +#include /* strncmp */ #include #include -/* List of commands to be supported : - synchronize : OK - unlock - set-baud-rate - echo - write-to-ram - read-memory - prepare-for-write - copy-ram-to-flash - go - erase - blank-check - read-part-id - read-boot-version - compare - read-uid -*/ - - #include "isp_utils.h" extern int trace_on; +struct isp_command { + char* name; + int nb_args; + int (*handler)(int arg_count, char** args); +}; + + #define SERIAL_BUFSIZE 128 #define SYNCHRO_START "?" -#define SYNCHRO "Synchronized" +#define SYNCHRO "Synchronized\r\n" +#define SYNCHRO_OK "OK\r\n" +#define SYNCHRO_ECHO_OFF "A 0\r\n" + +#define ISP_ABORT "" +#define READ_UID "N\r\n" +#define READ_PART_ID "J\r\n" +#define READ_BOOT_VERSION "K\r\n" -int isp_ret_code(char* buf) +char* error_codes[] = { + "CMD_SUCCESS", + "INVALID_COMMAND", + "SRC_ADDR_ERROR", + "DST_ADDR_ERROR", + "SRC_ADDR_NOT_MAPPED", + "DST_ADDR_NOT_MAPPED", + "COUNT_ERROR", + "INVALID_SECTOR", + "SECTOR_NOT_BLANK", + "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION", + "COMPARE_ERROR", + "BUSY", + "PARAM_ERROR", + "ADDR_ERROR", + "ADDR_NOT_MAPPED", + "CMD_LOCKED", + "INVALID_CODE", + "INVALID_BAUD_RATE", + "INVALID_STOP_BIT", + "CODE_READ_PROTECTION_ENABLED", +}; + +int isp_ret_code(char* buf, char** endptr) { + unsigned int ret = 0; + ret = strtoul(buf, endptr, 10); if (trace_on) { /* FIXME : Find how return code are sent (binary or ASCII) */ - printf("Received code: '0x%02x'\n", *buf); + if (ret > (sizeof(error_codes)/sizeof(char*))) { + printf("Received unknown error code '%u' !\n", ret); + } else { + printf("Received error code '%u': %s\n", ret, error_codes[ret]); + } } - return 0; + return ret; } /* Connect or reconnect to the target. * Return positive or NULL value when connection is OK, or negative value otherwise. */ -int isp_connect() +int isp_connect(unsigned int crystal_freq) { char buf[SERIAL_BUFSIZE]; + char freq[10]; + + snprintf(freq, 8, "%d\r\n", crystal_freq); /* Send synchronize request */ if (isp_serial_write(SYNCHRO_START, strlen(SYNCHRO_START)) != strlen(SYNCHRO_START)) { printf("Unable to send synchronize request.\n"); return -5; } - /* Wait for answer */ if (isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO)) < 0) { printf("Error reading synchronize answer.\n"); return -4; } - - /* Check answer, and acknoledge if OK */ + /* Check answer, and acknowledge if OK */ if (strncmp(SYNCHRO, buf, strlen(SYNCHRO)) == 0) { isp_serial_write(SYNCHRO, strlen(SYNCHRO)); } else { - printf("Unable to synchronize.\n"); + printf("Unable to synchronize, no synchro received.\n"); + return -3; + } + /* Empty read buffer (echo is on) */ + isp_serial_read(buf, strlen(SYNCHRO), strlen(SYNCHRO)); + /* Read reply (OK) */ + isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO_OK)); + if (strncmp(SYNCHRO_OK, buf, strlen(SYNCHRO_OK)) != 0) { + printf("Unable to synchronize, synchro not acknowledged.\n"); + return -2; + } + + /* Documentation says we should send crystal frequency .. sending anything is OK */ + isp_serial_write(freq, strlen(freq)); + /* Empty read buffer (echo is on) */ + isp_serial_read(buf, strlen(freq), strlen(freq)); + /* Read reply (OK) */ + isp_serial_read(buf, SERIAL_BUFSIZE, strlen(SYNCHRO_OK)); + if (strncmp(SYNCHRO_OK, buf, strlen(SYNCHRO_OK)) != 0) { + printf("Unable to synchronize, crystal frequency not acknowledged.\n"); + return -2; + } + + /* Turn off echo */ + isp_serial_write(SYNCHRO_ECHO_OFF, strlen(SYNCHRO_ECHO_OFF)); + /* Empty read buffer (echo still on) */ + isp_serial_read(buf, strlen(SYNCHRO_ECHO_OFF), strlen(SYNCHRO_ECHO_OFF)); + /* Read eror code for command */ + isp_serial_read(buf, SERIAL_BUFSIZE, 3); + + return 1; +} + + +int isp_cmd_read_uid(int arg_count, char** args) +{ + char buf[SERIAL_BUFSIZE]; + char* tmp = NULL; + int i = 0, ret = 0, len = 0; + unsigned long int uid[4]; + + /* Send read-uid request */ + if (isp_serial_write(READ_UID, strlen(READ_UID)) != strlen(READ_UID)) { + printf("Unable to send read-uid request.\n"); + return -5; + } + /* Wait for answer */ + usleep( 5000 ); + len = isp_serial_read(buf, SERIAL_BUFSIZE, 50); + if (len <= 0) { + printf("Error reading uid.\n"); + return -4; + } + ret = isp_ret_code(buf, &tmp); + if (ret != 0) { + printf("This cannot happen ... as long as you trust the user manual.\n"); return -1; } + for (i=0; i<4; i++) { + static char* endptr = NULL; + uid[i] = strtoul(tmp, &endptr, 10); + tmp = endptr; + } + printf("UID: 0x%08lx - 0x%08lx - 0x%08lx - 0x%08lx\n", uid[0], uid[1], uid[2], uid[3]); - /* Empty read buffer (maybe echo is on ?) */ + return 0; +} + +int isp_cmd_part_id(int arg_count, char** args) +{ + char buf[SERIAL_BUFSIZE]; + int ret = 0, len = 0; + char* tmp = NULL; + unsigned long int part_id = 0; + + /* Send read-part-id request */ + if (isp_serial_write(READ_PART_ID, strlen(READ_PART_ID)) != strlen(READ_PART_ID)) { + printf("Unable to send read-part-id request.\n"); + return -5; + } + /* Wait for answer */ usleep( 5000 ); - isp_serial_read(buf, SERIAL_BUFSIZE, 0); + len = isp_serial_read(buf, SERIAL_BUFSIZE, 10); + if (len <= 0) { + printf("Error reading part id.\n"); + return -4; + } + ret = isp_ret_code(buf, &tmp); + if (ret != 0) { + printf("This cannot happen ... as long as you trust the user manual.\n"); + return -1; + } + /* FIXME : some part IDs are on two 32bits values */ + part_id = strtoul(tmp, NULL, 10); + printf("Part ID is 0x%08lx\n", part_id); - /* FIXME : Do we always turn off echo ? */ - /* and turn off echo */ - isp_serial_write("A 0\r\n", 5); + return 0; +} - return 1; +int isp_cmd_boot_version(int arg_count, char** args) +{ + char buf[SERIAL_BUFSIZE]; + int ret = 0, len = 0; + char* tmp = NULL; + unsigned int ver[2]; + + /* Send read-boot-version request */ + if (isp_serial_write(READ_BOOT_VERSION, strlen(READ_BOOT_VERSION)) != strlen(READ_BOOT_VERSION)) { + printf("Unable to send read-boot-version request.\n"); + return -5; + } + /* Wait for answer */ + usleep( 5000 ); + len = isp_serial_read(buf, SERIAL_BUFSIZE, 5); + if (len <= 0) { + printf("Error reading boot version.\n"); + return -4; + } + ret = isp_ret_code(buf, &tmp); + if (ret != 0) { + printf("This cannot happen ... as long as you trust the user manual.\n"); + return -1; + } + ver[0] = strtoul(tmp, &tmp, 10); + ver[1] = strtoul(tmp, NULL, 10); + printf("Boot code version is %u.%u\n", ver[0], ver[1]); + + return 0; +} + + +/* FIXME : Temporary place-holder */ +int isp_cmd_null(int arg_count, char** args) +{ + int i = 0; + printf("command not yet handled, called with %d arguments.\n", arg_count); + for (i=0; i #include -#include /* strncmp */ #include #include @@ -38,14 +37,12 @@ void help(char *prog_name) { fprintf(stderr, "-----------------------------------------------------------------------\n"); - fprintf(stderr, "Usage: %s [options] device command [command arguments]\n" \ + fprintf(stderr, "Usage: %s [options] device [-s | --synchronize]\n" \ + " %s [options] device command [command arguments]\n" \ " Default baudrate is B115200\n" \ " is the (host) serial line used to programm the device\n" \ " is one of:\n" \ - " \t synchronize (sync done each time unless -n is used (for multiple successive calls))\n" \ " \t unlock \n" \ - " \t set-baud-rate \n" \ - " \t echo \n" \ " \t write-to-ram \n" \ " \t read-memory \n" \ " \t prepare-for-write \n" \ @@ -57,12 +54,21 @@ void help(char *prog_name) " \t read-boot-version \n" \ " \t compare \n" \ " \t read-uid \n" \ + " Notes:\n" \ + " - Access to the ISP mode is done by calling this utility once with the synchronize\n" \ + " option and no command. This starts a session. No command can be used before starting\n" \ + " a session, and no other synchronize request must be done once the session is started\n" \ + " unless the target is reseted, which closes the session.\n" \ + " - Echo is turned OFF when starting a session and the command is not available.\n" \ + " - The set-baud-rate command is not available. The SAME baudrate MUST be used for the\n" \ + " whole session. It must be specified on each successive call if the default baudrate\n" \ + " is not used.\n" \ " Available options:\n" \ - " \t -n | --no-synchronize : Do not perform synchronization before sending command\n" \ + " \t -s | --synchronize : Perform synchronization (open session)\n" \ " \t -b | --baudrate=N : Use this baudrate (does not issue the set-baud-rate command)\n" \ " \t -t | --trace : turn on trace output of serial communication\n" \ " \t -h | --help : display this help\n" \ - " \t -v | --version : display version information\n", prog_name); + " \t -v | --version : display version information\n", prog_name, prog_name); fprintf(stderr, "-----------------------------------------------------------------------\n"); } @@ -74,7 +80,8 @@ int trace_on = 0; int main(int argc, char** argv) { int baudrate = SERIAL_BAUD; - int dont_synchronize = 0; + int crystal_freq = 10000; + int synchronize = 0; char* isp_serial_device = NULL; /* For "command" handling */ @@ -89,7 +96,7 @@ int main(int argc, char** argv) int c = 0; struct option long_options[] = { - {"no-synchronize", no_argument, 0, 'n'}, + {"synchronize", no_argument, 0, 's'}, {"baudrate", required_argument, 0, 'b'}, {"trace", no_argument, 0, 't'}, {"help", no_argument, 0, 'h'}, @@ -97,7 +104,7 @@ int main(int argc, char** argv) {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "nb:thv", long_options, &option_index); + c = getopt_long(argc, argv, "sb:thv", long_options, &option_index); /* no more options to parse */ if (c == -1) break; @@ -115,8 +122,8 @@ int main(int argc, char** argv) break; /* s, synchronize */ - case 'n': - dont_synchronize = 1; + case 's': + synchronize = 1; break; /* v, version */ @@ -152,12 +159,28 @@ int main(int argc, char** argv) return -1; } + if (synchronize) { + if (optind < argc) { + /* no command can be specified when opening a session */ + printf("No command can be specified with -s or --synchronize (Session opening)\n"); + printf("NOT SYNCHRONIZED !\n"); + return -1; + } + isp_connect(crystal_freq); + isp_serial_close(); + return 0; + } + /* Next one should be "command" (if present) */ if (optind < argc) { command = argv[optind++]; if (trace_on) { printf("Command : %s\n", command); } + } else { + printf("No command given. use -h or --help for help on available commands.\n"); + isp_serial_close(); + return -1; } /* And then remaining ones (if any) are command arguments */ if (optind < argc) { @@ -175,12 +198,7 @@ int main(int argc, char** argv) } } - if (! dont_synchronize) { - isp_connect(); - } - - /* FIXME : call command handler */ - if (command != NULL) { + if (command != NULL) { int err = 0; err = isp_handle_command(command, nb_cmd_args, cmd_args); if (err >= 0) { @@ -190,8 +208,6 @@ int main(int argc, char** argv) } else { printf("Error handling command \"%s\" : %d\n", command, err); } - } else { - printf("No command given. use -h or --help for help on available commands.\n"); } diff --git a/isp_utils.c b/isp_utils.c index c1b0707..3a858fc 100644 --- a/isp_utils.c +++ b/isp_utils.c @@ -60,6 +60,9 @@ void isp_dump(const unsigned char* buf, unsigned int buf_size) if (pass == 0) { count -= 0x10; } else { + if (count == buf_size) { + break; /* prevent infinite loop */ + } printf("|\n"); } pass = !pass;