authorNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 1 Mar 2013 13:46:32 +0000 (14:46 +0100)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 1 Mar 2013 13:46:32 +0000 (14:46 +0100)
Makefile
isp_main.c [deleted file]
lpc_prog.c [deleted file]
lpcisp.c [new file with mode: 0644]
lpcprog.c [new file with mode: 0644]

index ddbe91f..702b0d6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,15 +4,15 @@ CC = $(CROSS_COMPILE)gcc
 
 CFLAGS += -Wall -Wextra -O2
 
-all: isp prog
+all: lpcisp lpcprog
 
-isp: isp_main.o isp_utils.o isp_commands.o isp_wrapper.o
+lpcisp: lpcisp.o isp_utils.o isp_commands.o isp_wrapper.o
 
-prog: lpc_prog.o isp_utils.o isp_commands.o prog_commands.o parts.o
+lpcprog: lpcprog.o isp_utils.o isp_commands.o prog_commands.o parts.o
 
 
 
-isp_main.o: isp_utils.h isp_commands.h
+lpcisp.o: isp_utils.h isp_commands.h
 
 isp_utils.o:
 
@@ -20,7 +20,7 @@ isp_commands.o: isp_utils.h
 
 isp_wrapper.o: isp_utils.h isp_commands.h
 
-lpc_prog.o: isp_utils.h isp_commands.h prog_commands.h parts.h
+lpcprog.o: isp_utils.h isp_commands.h prog_commands.h parts.h
 
 prog_commands.o: isp_utils.h isp_commands.h parts.h
 
diff --git a/isp_main.c b/isp_main.c
deleted file mode 100644 (file)
index 4a27b23..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/*********************************************************************
- *
- *   LPC1114 ISP
- *
- *
- * Written by Nathael Pajani <nathael.pajani@nathael.net>
- *
- * This programm is released under the terms of the GNU GPLv3 licence
- * as can be found on the GNU website : <http://www.gnu.org/licenses/>
- *
- *********************************************************************/
-
-
-#include <stdlib.h> /* malloc, free */
-#include <stdio.h>
-#include <stdint.h>
-
-#include <unistd.h> /* open, getopt, close, usleep */
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <getopt.h>
-
-#include <termios.h> /* for serial config */
-#include <ctype.h>
-
-#include <string.h> /* strncmp, strlen */
-
-#include "isp_utils.h"
-#include "isp_commands.h"
-
-#define PROG_NAME "LPC11xx ISP"
-#define VERSION   "1.0"
-
-/* short explanation on exit values:
- *
- * 0 is OK
- * 1 is arg error
- *
- */
-
-
-void help(char *prog_name)
-{
-       fprintf(stderr, "-----------------------------------------------------------------------\n");
-       fprintf(stderr, "Usage: %s [options] device [-s | --synchronize]\n" \
-               "       %s [options] device command [command arguments]\n" \
-               "  Default baudrate is B115200\n" \
-               "  <device> is the (host) serial line used to programm the device\n" \
-               "  <command> is one of:\n" \
-               "  \t unlock, write-to-ram, read-memory, prepare-for-write, copy-ram-to-flash, go, erase,\n" \
-               "  \t blank-check, read-part-id, read-boot-version, compare, and read-uid.\n" \
-               "  command specific arguments are as follow:\n" \
-               "  \t unlock \n" \
-               "  \t write-to-ram address file : send 'file' to 'address' in ram\n" \
-               "  \t read-memory address count file : read 'count' bytes from 'address', store then in 'file'\n" \
-               "  \t prepare-for-write first last : prepare sectors from 'first' to 'last' for write operation\n" \
-               "  \t copy-ram-to-flash flash_addr ram_addr count : copy count bytes (256, 512, 1024 or 4096)\n" \
-               "  \t     from 'ram_addr' to 'flash_addr'\n" \
-               "  \t go address mode : execute programm at 'address' (> 0x200) in 'mode' ('arm' or 'thumb')\n" \
-               "  \t erase first last : erase flash starting from 'first' sector up to (including) 'last' sector \n" \
-               "  \t blank-check first last : check flash starting from 'first' sector to 'last' sector is blank\n" \
-               "  \t read-part-id \n" \
-               "  \t read-boot-version \n" \
-               "  \t compare address1 address2 count : compare count bytes between address1 and address2\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" \
-               "   - User must issue an 'unlock' command before any of 'copy-ram-to-flash', 'erase',\n" \
-               "     and 'go' commands.\n" \
-               "  Available options:\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, prog_name);
-       fprintf(stderr, "-----------------------------------------------------------------------\n");
-}
-
-#define SERIAL_BAUD  B115200
-
-int trace_on = 0;
-
-int isp_handle_command(char* cmd, int arg_count, char** args);
-
-int main(int argc, char** argv)
-{
-       int baudrate = SERIAL_BAUD;
-       int crystal_freq = 10000;
-       int synchronize = 0;
-       char* isp_serial_device = NULL;
-
-       /* For "command" handling */
-       char* command = NULL;
-       char** cmd_args = NULL;
-       int nb_cmd_args = 0;
-
-
-       /* parameter parsing */
-       while(1) {
-               int option_index = 0;
-               int c = 0;
-
-               struct option long_options[] = {
-                       {"synchronize", no_argument, 0, 's'},
-                       {"baudrate", required_argument, 0, 'b'},
-                       {"trace", no_argument, 0, 't'},
-                       {"help", no_argument, 0, 'h'},
-                       {"version", no_argument, 0, 'v'},
-                       {0, 0, 0, 0}
-               };
-
-               c = getopt_long(argc, argv, "sb:thv", long_options, &option_index);
-
-               /* no more options to parse */
-               if (c == -1) break;
-
-               switch (c) {
-                       /* b, baudrate */
-                       case 'b':
-                               baudrate = atoi(optarg);
-                               /* FIXME: validate baudrate */
-                               break;
-
-                       /* t, trace */
-                       case 't':
-                               trace_on = 1;
-                               break;
-
-                       /* s, synchronize */
-                       case 's':
-                               synchronize = 1;
-                               break;
-
-                       /* v, version */
-                       case 'v':
-                               printf("%s Version %s\n", PROG_NAME, VERSION);
-                               return 0;
-                               break;
-
-                       /* h, help */
-                       case 'h':
-                       default:
-                               help(argv[0]);
-                               return 0;
-               }
-       }
-
-       /* Parse remaining command line arguments (not options). */
-
-       /* First one should (must) be serial device */
-       if (optind < argc) {
-               isp_serial_device = argv[optind++];
-               if (trace_on) {
-                       printf("Serial device : %s\n", isp_serial_device);
-               }
-       }
-       if (isp_serial_device == NULL) {
-               printf("No serial device given, exiting\n");
-               help(argv[0]);
-               return 0;
-       }
-       if (isp_serial_open(baudrate, isp_serial_device) != 0) {
-               printf("Serial open failed, unable to initiate serial communication with target.\n");
-               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, 0);
-               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) {
-               nb_cmd_args = argc - optind;
-               cmd_args = malloc(nb_cmd_args * sizeof(char *));
-               if (trace_on) {
-                       printf("Command arguments :\n");
-               }
-               while (optind < argc) {
-                       static unsigned int idx = 0;
-                       cmd_args[idx++] = argv[optind++];
-                       if (trace_on) {
-                               printf("%s\n", cmd_args[idx - 1]);
-                       }
-               }
-       }
-
-       if (command != NULL)  {
-               int err = 0;
-               err = isp_handle_command(command, nb_cmd_args, cmd_args);
-               if (err >= 0) {
-                       if (trace_on) {
-                               printf("Command \"%s\" handled OK.\n", command);
-                       }
-               } else {
-                       printf("Error handling command \"%s\" : %d\n", command, err);
-               }
-       }
-
-
-       if (cmd_args != NULL) {
-               free(cmd_args);
-       }
-       isp_serial_close();
-       return 0;
-}
-
-struct isp_command {
-       int cmd_num;
-       char* name;
-       int nb_args;
-       int (*handler)(int arg_count, char** args);
-};
-
-
-static struct isp_command isp_cmds_list[] = {
-       {0, "unlock", 0, NULL},
-       {1, "write-to-ram", 2, isp_cmd_write_to_ram},
-       {2, "read-memory", 3, isp_cmd_read_memory},
-       {3, "prepare-for-write", 2, isp_cmd_prepare_for_write},
-       {4, "copy-ram-to-flash", 3, isp_cmd_copy_ram_to_flash},
-       {5, "go", 2, isp_cmd_go},
-       {6, "erase", 2, isp_cmd_erase},
-       {7, "blank-check", 2, isp_cmd_blank_check},
-       {8, "read-part-id", 0, NULL},
-       {9, "read-boot-version", 0, NULL},
-       {10, "compare", 3, isp_cmd_compare},
-       {11, "read-uid", 0, NULL},
-       {-1, NULL, 0, NULL}
-};
-
-void isp_warn_args(int cmd_num, int arg_count, char** args)
-{
-       int i = 0;
-       printf("command \"%s\" needs %d args, got %d.\n",
-                       isp_cmds_list[cmd_num].name,
-                       isp_cmds_list[cmd_num].nb_args, arg_count);
-       for (i=0; i<arg_count; i++) {
-               printf("\targ[%d] : \"%s\"\n", i, args[i]);
-       }
-}
-
-/* Handle one command
- * Return positive or NULL value when command handling is OK, or negative value otherwise.
- */
-int isp_handle_command(char* cmd, int arg_count, char** args)
-{
-       int cmd_found = -1;
-       int ret = 0;
-       int index = 0;
-
-       if (cmd == NULL) {
-               printf("isp_handle_command called with no command !\n");
-               return -1;
-       }
-
-       while ((cmd_found == -1) && (isp_cmds_list[index].name != NULL)) {
-               if (strncmp(isp_cmds_list[index].name, cmd, strlen(isp_cmds_list[index].name)) == 0) {
-                       cmd_found = index;
-                       break;
-               }
-               index++;
-       }
-       if (cmd_found == -1) {
-               printf("Unknown command \"%s\", use -h or --help for a list.\n", cmd);
-               return -2;
-       }
-       if (arg_count != isp_cmds_list[cmd_found].nb_args) {
-               isp_warn_args(cmd_found, arg_count, args);
-       }
-
-       switch (isp_cmds_list[cmd_found].cmd_num) {
-               case 0: /* unlock */
-                       ret = isp_cmd_unlock(0);
-                       break;
-               case 8: /* read-part-id */
-                       ret = isp_cmd_part_id(0);
-                       break;
-               case 9: /* read-boot-version */
-                       ret = isp_cmd_boot_version();
-                       break;
-               case 11: /* read-uid */
-                       ret = isp_cmd_read_uid();
-                       break;
-               default:
-                       ret = isp_cmds_list[cmd_found].handler(arg_count, args);
-       }
-
-       return ret;
-}
-
diff --git a/lpc_prog.c b/lpc_prog.c
deleted file mode 100644 (file)
index 240841b..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/*********************************************************************
- *
- *   LPC1114 ISP
- *
- *
- * Written by Nathael Pajani <nathael.pajani@nathael.net>
- *
- * This programm is released under the terms of the GNU GPLv3 licence
- * as can be found on the GNU website : <http://www.gnu.org/licenses/>
- *
- *********************************************************************/
-
-
-#include <stdlib.h> /* malloc, free */
-#include <stdio.h>
-#include <stdint.h>
-
-#include <unistd.h> /* open, getopt, close, usleep */
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <getopt.h>
-
-#include <termios.h> /* for serial config */
-#include <ctype.h>
-
-#include <string.h> /* strncmp, strlen */
-
-#include "isp_utils.h"
-#include "isp_commands.h"
-#include "prog_commands.h"
-#include "parts.h"
-
-#define PROG_NAME "LPC11xx ISP Prog tool"
-#define VERSION   "0.01"
-
-
-void help(char *prog_name)
-{
-       fprintf(stderr, "---------------- "PROG_NAME" --------------------------------\n");
-       fprintf(stderr, "Usage: %s [options] serial_device command [command arguments]\n" \
-               "  Default baudrate is B115200\n" \
-               "  Default oscilator frequency used is 10000 KHz\n" \
-               "  <serial_device> is the (host) serial line used to programm the device\n" \
-               "  <command> is one of:\n" \
-               "  \t dump, flash, id, blank, go\n" \
-               "  command specific arguments are:\n" \
-               "  \t dump file : dump flash content to 'file'\n" \
-               "  \t flash file : put 'file' to flash, erasing requiered sectors\n" \
-               "  \t blank : erase whole flash\n" \
-               "  \t id : get all id information\n" \
-               "  \t go : execute programm from reset handler in thumb mode and open terminal\n" \
-               "  Available options:\n" \
-               "  \t -b | --baudrate=N : Use this baudrate (Same baudrate must be used across whole session)\n" \
-               "  \t -t | --trace : turn on trace output of serial communication\n" \
-               "  \t -f | --freq=N : Oscilator frequency of target device\n" \
-               "  \t -u | --user-code : compute a valid user code for exception vector 7\n" \
-               "  \t -h | --help : display this help\n" \
-               "  \t -v | --version : display version information\n", prog_name);
-       fprintf(stderr, "-----------------------------------------------------------------------\n");
-}
-
-#define SERIAL_BAUD  B115200
-
-int trace_on = 0;
-int quiet = 0;
-static int calc_user_code = 0;
-
-static int prog_connect_and_id(int freq);
-static int prog_handle_command(char* cmd, int dev_id, int arg_count, char** args);
-
-int main(int argc, char** argv)
-{
-       int baudrate = SERIAL_BAUD;
-       int crystal_freq = 10000;
-       char* isp_serial_device = NULL;
-       int dev_id = 0;
-
-       /* For "command" handling */
-       char* command = NULL;
-       char** cmd_args = NULL;
-       int nb_cmd_args = 0;
-
-
-       /* parameter parsing */
-       while(1) {
-               int option_index = 0;
-               int c = 0;
-
-               struct option long_options[] = {
-                       {"synchronized", no_argument, 0, 's'},
-                       {"baudrate", required_argument, 0, 'b'},
-                       {"trace", no_argument, 0, 't'},
-                       {"freq", required_argument, 0, 'f'},
-                       {"user-code", no_argument, 0, 'u'},
-                       {"help", no_argument, 0, 'h'},
-                       {"version", no_argument, 0, 'v'},
-                       {0, 0, 0, 0}
-               };
-
-               c = getopt_long(argc, argv, "sb:tfuhv", long_options, &option_index);
-
-               /* no more options to parse */
-               if (c == -1) break;
-
-               switch (c) {
-                       /* b, baudrate */
-                       case 'b':
-                               baudrate = atoi(optarg);
-                               /* FIXME: validate baudrate */
-                               break;
-
-                       /* t, trace */
-                       case 't':
-                               trace_on = 1;
-                               break;
-
-                       /* f, freq */
-                       case 'f':
-                               crystal_freq = atoi(optarg);
-                               break;
-
-                       /* u, user-code */
-                       case 'u':
-                               calc_user_code = 1;
-                               break;
-
-                       /* v, version */
-                       case 'v':
-                               printf("%s Version %s\n", PROG_NAME, VERSION);
-                               return 0;
-                               break;
-
-                       /* h, help */
-                       case 'h':
-                       default:
-                               help(argv[0]);
-                               return 0;
-               }
-       }
-
-       /* Parse remaining command line arguments (not options). */
-
-       /* First one should (must) be serial device */
-       if (optind < argc) {
-               isp_serial_device = argv[optind++];
-               if (trace_on) {
-                       printf("Serial device : %s\n", isp_serial_device);
-               }
-       }
-       if (isp_serial_device == NULL) {
-               printf("No serial device given, exiting\n");
-               help(argv[0]);
-               return 0;
-       }
-       if (isp_serial_open(baudrate, isp_serial_device) != 0) {
-               printf("Serial open failed, unable to initiate serial communication with target.\n");
-               return -1;
-       }
-
-       /* 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) {
-               nb_cmd_args = argc - optind;
-               cmd_args = malloc(nb_cmd_args * sizeof(char *));
-               if (trace_on) {
-                       printf("Command arguments :\n");
-               }
-               while (optind < argc) {
-                       static unsigned int idx = 0;
-                       cmd_args[idx++] = argv[optind++];
-                       if (trace_on) {
-                               printf("%s\n", cmd_args[idx - 1]);
-                       }
-               }
-       }
-
-       /* Frist : sync with device */
-       dev_id = prog_connect_and_id(crystal_freq);
-       if (dev_id < 0) {
-               printf("Unable to connect to target, consider hard reset of target or link\n");
-               return -1;
-       }
-
-       if (command != NULL)  {
-               int err = 0;
-               err = prog_handle_command(command, dev_id, nb_cmd_args, cmd_args);
-               if (err >= 0) {
-                       if (trace_on) {
-                               printf("Command \"%s\" handled OK.\n", command);
-                       }
-               } else {
-                       printf("Error handling command \"%s\" : %d\n", command, err);
-               }
-       }
-
-
-       if (cmd_args != NULL) {
-               free(cmd_args);
-       }
-       isp_serial_close();
-       return 0;
-}
-
-struct prog_command {
-       int cmd_num;
-       char* name;
-};
-
-static struct prog_command prog_cmds_list[] = {
-       {0, "dump"},
-       {1, "flash"},
-       {2, "id"},
-       {3, "blank"},
-       {4, "go"},
-       {5, NULL}
-};
-
-/*
- * Try to connect to the target and identify the device.
- * First try sync, and if it fails, try to read id twice. if both fail, then we are not connected
- */
-static int prog_connect_and_id(int freq)
-{
-       int sync_ret = 0;
-
-       /* Try to connect */
-       sync_ret = isp_connect(freq, 1);
-       /* Synchro failed or already synchronised ? */
-       if (sync_ret < 0) {
-               /* If already synchronized, then sync command and the next command fail.
-                  Sync failed, maybe we are already sync'ed, then send one command for nothing */
-               isp_cmd_part_id(1);
-       }
-
-       return isp_cmd_part_id(1);
-}
-
-static int prog_handle_command(char* cmd, int dev_id, int arg_count, char** args)
-{
-       int cmd_found = -1;
-       int ret = 0;
-       int index = 0;
-       struct part_desc* part = NULL;
-
-       if (cmd == NULL) {
-               printf("prog_handle_command called with no command !\n");
-               return -1;
-       }
-
-       part = find_part(dev_id);
-       if (part == NULL) {
-               printf("Unknown part number : 0x%08x.\n", dev_id);
-               return -2;
-       }
-
-       while ((cmd_found == -1) && (prog_cmds_list[index].name != NULL)) {
-               if (strncmp(prog_cmds_list[index].name, cmd, strlen(prog_cmds_list[index].name)) == 0) {
-                       cmd_found = index;
-                       break;
-               }
-               index++;
-       }
-       if (cmd_found == -1) {
-               printf("Unknown command \"%s\", use -h or --help for a list.\n", cmd);
-               return -3;
-       }
-
-       switch (prog_cmds_list[cmd_found].cmd_num) {
-               case 0: /* dump, need one arg : filename */
-                       if (arg_count != 1) {
-                               printf("command dump needs one arg (filename), got %d.\n", arg_count);
-                               return -4;
-                       }
-                       ret = dump_to_file(part, args[0]);
-                       break;
-
-               case 1: /* flash, need one arg : filename */
-                       if (arg_count != 1) {
-                               printf("command flash needs one arg (filename), got %d.\n", arg_count);
-                               return -4;
-                       }
-                       ret = flash_target(part, args[0], calc_user_code);
-                       break;
-
-               case 2: /* id : no args */
-                       ret = get_ids();
-                       break;
-
-               case 3: /* blank : no args */
-                       ret = erase_flash(part);
-                       break;
-
-               case 4: /* go : no args */
-                       ret = start_prog(part);
-                       break;
-       }
-
-       return ret;
-}
-
diff --git a/lpcisp.c b/lpcisp.c
new file mode 100644 (file)
index 0000000..4a27b23
--- /dev/null
+++ b/lpcisp.c
@@ -0,0 +1,319 @@
+/*********************************************************************
+ *
+ *   LPC1114 ISP
+ *
+ *
+ * Written by Nathael Pajani <nathael.pajani@nathael.net>
+ *
+ * This programm is released under the terms of the GNU GPLv3 licence
+ * as can be found on the GNU website : <http://www.gnu.org/licenses/>
+ *
+ *********************************************************************/
+
+
+#include <stdlib.h> /* malloc, free */
+#include <stdio.h>
+#include <stdint.h>
+
+#include <unistd.h> /* open, getopt, close, usleep */
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <getopt.h>
+
+#include <termios.h> /* for serial config */
+#include <ctype.h>
+
+#include <string.h> /* strncmp, strlen */
+
+#include "isp_utils.h"
+#include "isp_commands.h"
+
+#define PROG_NAME "LPC11xx ISP"
+#define VERSION   "1.0"
+
+/* short explanation on exit values:
+ *
+ * 0 is OK
+ * 1 is arg error
+ *
+ */
+
+
+void help(char *prog_name)
+{
+       fprintf(stderr, "-----------------------------------------------------------------------\n");
+       fprintf(stderr, "Usage: %s [options] device [-s | --synchronize]\n" \
+               "       %s [options] device command [command arguments]\n" \
+               "  Default baudrate is B115200\n" \
+               "  <device> is the (host) serial line used to programm the device\n" \
+               "  <command> is one of:\n" \
+               "  \t unlock, write-to-ram, read-memory, prepare-for-write, copy-ram-to-flash, go, erase,\n" \
+               "  \t blank-check, read-part-id, read-boot-version, compare, and read-uid.\n" \
+               "  command specific arguments are as follow:\n" \
+               "  \t unlock \n" \
+               "  \t write-to-ram address file : send 'file' to 'address' in ram\n" \
+               "  \t read-memory address count file : read 'count' bytes from 'address', store then in 'file'\n" \
+               "  \t prepare-for-write first last : prepare sectors from 'first' to 'last' for write operation\n" \
+               "  \t copy-ram-to-flash flash_addr ram_addr count : copy count bytes (256, 512, 1024 or 4096)\n" \
+               "  \t     from 'ram_addr' to 'flash_addr'\n" \
+               "  \t go address mode : execute programm at 'address' (> 0x200) in 'mode' ('arm' or 'thumb')\n" \
+               "  \t erase first last : erase flash starting from 'first' sector up to (including) 'last' sector \n" \
+               "  \t blank-check first last : check flash starting from 'first' sector to 'last' sector is blank\n" \
+               "  \t read-part-id \n" \
+               "  \t read-boot-version \n" \
+               "  \t compare address1 address2 count : compare count bytes between address1 and address2\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" \
+               "   - User must issue an 'unlock' command before any of 'copy-ram-to-flash', 'erase',\n" \
+               "     and 'go' commands.\n" \
+               "  Available options:\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, prog_name);
+       fprintf(stderr, "-----------------------------------------------------------------------\n");
+}
+
+#define SERIAL_BAUD  B115200
+
+int trace_on = 0;
+
+int isp_handle_command(char* cmd, int arg_count, char** args);
+
+int main(int argc, char** argv)
+{
+       int baudrate = SERIAL_BAUD;
+       int crystal_freq = 10000;
+       int synchronize = 0;
+       char* isp_serial_device = NULL;
+
+       /* For "command" handling */
+       char* command = NULL;
+       char** cmd_args = NULL;
+       int nb_cmd_args = 0;
+
+
+       /* parameter parsing */
+       while(1) {
+               int option_index = 0;
+               int c = 0;
+
+               struct option long_options[] = {
+                       {"synchronize", no_argument, 0, 's'},
+                       {"baudrate", required_argument, 0, 'b'},
+                       {"trace", no_argument, 0, 't'},
+                       {"help", no_argument, 0, 'h'},
+                       {"version", no_argument, 0, 'v'},
+                       {0, 0, 0, 0}
+               };
+
+               c = getopt_long(argc, argv, "sb:thv", long_options, &option_index);
+
+               /* no more options to parse */
+               if (c == -1) break;
+
+               switch (c) {
+                       /* b, baudrate */
+                       case 'b':
+                               baudrate = atoi(optarg);
+                               /* FIXME: validate baudrate */
+                               break;
+
+                       /* t, trace */
+                       case 't':
+                               trace_on = 1;
+                               break;
+
+                       /* s, synchronize */
+                       case 's':
+                               synchronize = 1;
+                               break;
+
+                       /* v, version */
+                       case 'v':
+                               printf("%s Version %s\n", PROG_NAME, VERSION);
+                               return 0;
+                               break;
+
+                       /* h, help */
+                       case 'h':
+                       default:
+                               help(argv[0]);
+                               return 0;
+               }
+       }
+
+       /* Parse remaining command line arguments (not options). */
+
+       /* First one should (must) be serial device */
+       if (optind < argc) {
+               isp_serial_device = argv[optind++];
+               if (trace_on) {
+                       printf("Serial device : %s\n", isp_serial_device);
+               }
+       }
+       if (isp_serial_device == NULL) {
+               printf("No serial device given, exiting\n");
+               help(argv[0]);
+               return 0;
+       }
+       if (isp_serial_open(baudrate, isp_serial_device) != 0) {
+               printf("Serial open failed, unable to initiate serial communication with target.\n");
+               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, 0);
+               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) {
+               nb_cmd_args = argc - optind;
+               cmd_args = malloc(nb_cmd_args * sizeof(char *));
+               if (trace_on) {
+                       printf("Command arguments :\n");
+               }
+               while (optind < argc) {
+                       static unsigned int idx = 0;
+                       cmd_args[idx++] = argv[optind++];
+                       if (trace_on) {
+                               printf("%s\n", cmd_args[idx - 1]);
+                       }
+               }
+       }
+
+       if (command != NULL)  {
+               int err = 0;
+               err = isp_handle_command(command, nb_cmd_args, cmd_args);
+               if (err >= 0) {
+                       if (trace_on) {
+                               printf("Command \"%s\" handled OK.\n", command);
+                       }
+               } else {
+                       printf("Error handling command \"%s\" : %d\n", command, err);
+               }
+       }
+
+
+       if (cmd_args != NULL) {
+               free(cmd_args);
+       }
+       isp_serial_close();
+       return 0;
+}
+
+struct isp_command {
+       int cmd_num;
+       char* name;
+       int nb_args;
+       int (*handler)(int arg_count, char** args);
+};
+
+
+static struct isp_command isp_cmds_list[] = {
+       {0, "unlock", 0, NULL},
+       {1, "write-to-ram", 2, isp_cmd_write_to_ram},
+       {2, "read-memory", 3, isp_cmd_read_memory},
+       {3, "prepare-for-write", 2, isp_cmd_prepare_for_write},
+       {4, "copy-ram-to-flash", 3, isp_cmd_copy_ram_to_flash},
+       {5, "go", 2, isp_cmd_go},
+       {6, "erase", 2, isp_cmd_erase},
+       {7, "blank-check", 2, isp_cmd_blank_check},
+       {8, "read-part-id", 0, NULL},
+       {9, "read-boot-version", 0, NULL},
+       {10, "compare", 3, isp_cmd_compare},
+       {11, "read-uid", 0, NULL},
+       {-1, NULL, 0, NULL}
+};
+
+void isp_warn_args(int cmd_num, int arg_count, char** args)
+{
+       int i = 0;
+       printf("command \"%s\" needs %d args, got %d.\n",
+                       isp_cmds_list[cmd_num].name,
+                       isp_cmds_list[cmd_num].nb_args, arg_count);
+       for (i=0; i<arg_count; i++) {
+               printf("\targ[%d] : \"%s\"\n", i, args[i]);
+       }
+}
+
+/* Handle one command
+ * Return positive or NULL value when command handling is OK, or negative value otherwise.
+ */
+int isp_handle_command(char* cmd, int arg_count, char** args)
+{
+       int cmd_found = -1;
+       int ret = 0;
+       int index = 0;
+
+       if (cmd == NULL) {
+               printf("isp_handle_command called with no command !\n");
+               return -1;
+       }
+
+       while ((cmd_found == -1) && (isp_cmds_list[index].name != NULL)) {
+               if (strncmp(isp_cmds_list[index].name, cmd, strlen(isp_cmds_list[index].name)) == 0) {
+                       cmd_found = index;
+                       break;
+               }
+               index++;
+       }
+       if (cmd_found == -1) {
+               printf("Unknown command \"%s\", use -h or --help for a list.\n", cmd);
+               return -2;
+       }
+       if (arg_count != isp_cmds_list[cmd_found].nb_args) {
+               isp_warn_args(cmd_found, arg_count, args);
+       }
+
+       switch (isp_cmds_list[cmd_found].cmd_num) {
+               case 0: /* unlock */
+                       ret = isp_cmd_unlock(0);
+                       break;
+               case 8: /* read-part-id */
+                       ret = isp_cmd_part_id(0);
+                       break;
+               case 9: /* read-boot-version */
+                       ret = isp_cmd_boot_version();
+                       break;
+               case 11: /* read-uid */
+                       ret = isp_cmd_read_uid();
+                       break;
+               default:
+                       ret = isp_cmds_list[cmd_found].handler(arg_count, args);
+       }
+
+       return ret;
+}
+
diff --git a/lpcprog.c b/lpcprog.c
new file mode 100644 (file)
index 0000000..240841b
--- /dev/null
+++ b/lpcprog.c
@@ -0,0 +1,314 @@
+/*********************************************************************
+ *
+ *   LPC1114 ISP
+ *
+ *
+ * Written by Nathael Pajani <nathael.pajani@nathael.net>
+ *
+ * This programm is released under the terms of the GNU GPLv3 licence
+ * as can be found on the GNU website : <http://www.gnu.org/licenses/>
+ *
+ *********************************************************************/
+
+
+#include <stdlib.h> /* malloc, free */
+#include <stdio.h>
+#include <stdint.h>
+
+#include <unistd.h> /* open, getopt, close, usleep */
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <getopt.h>
+
+#include <termios.h> /* for serial config */
+#include <ctype.h>
+
+#include <string.h> /* strncmp, strlen */
+
+#include "isp_utils.h"
+#include "isp_commands.h"
+#include "prog_commands.h"
+#include "parts.h"
+
+#define PROG_NAME "LPC11xx ISP Prog tool"
+#define VERSION   "0.01"
+
+
+void help(char *prog_name)
+{
+       fprintf(stderr, "---------------- "PROG_NAME" --------------------------------\n");
+       fprintf(stderr, "Usage: %s [options] serial_device command [command arguments]\n" \
+               "  Default baudrate is B115200\n" \
+               "  Default oscilator frequency used is 10000 KHz\n" \
+               "  <serial_device> is the (host) serial line used to programm the device\n" \
+               "  <command> is one of:\n" \
+               "  \t dump, flash, id, blank, go\n" \
+               "  command specific arguments are:\n" \
+               "  \t dump file : dump flash content to 'file'\n" \
+               "  \t flash file : put 'file' to flash, erasing requiered sectors\n" \
+               "  \t blank : erase whole flash\n" \
+               "  \t id : get all id information\n" \
+               "  \t go : execute programm from reset handler in thumb mode and open terminal\n" \
+               "  Available options:\n" \
+               "  \t -b | --baudrate=N : Use this baudrate (Same baudrate must be used across whole session)\n" \
+               "  \t -t | --trace : turn on trace output of serial communication\n" \
+               "  \t -f | --freq=N : Oscilator frequency of target device\n" \
+               "  \t -u | --user-code : compute a valid user code for exception vector 7\n" \
+               "  \t -h | --help : display this help\n" \
+               "  \t -v | --version : display version information\n", prog_name);
+       fprintf(stderr, "-----------------------------------------------------------------------\n");
+}
+
+#define SERIAL_BAUD  B115200
+
+int trace_on = 0;
+int quiet = 0;
+static int calc_user_code = 0;
+
+static int prog_connect_and_id(int freq);
+static int prog_handle_command(char* cmd, int dev_id, int arg_count, char** args);
+
+int main(int argc, char** argv)
+{
+       int baudrate = SERIAL_BAUD;
+       int crystal_freq = 10000;
+       char* isp_serial_device = NULL;
+       int dev_id = 0;
+
+       /* For "command" handling */
+       char* command = NULL;
+       char** cmd_args = NULL;
+       int nb_cmd_args = 0;
+
+
+       /* parameter parsing */
+       while(1) {
+               int option_index = 0;
+               int c = 0;
+
+               struct option long_options[] = {
+                       {"synchronized", no_argument, 0, 's'},
+                       {"baudrate", required_argument, 0, 'b'},
+                       {"trace", no_argument, 0, 't'},
+                       {"freq", required_argument, 0, 'f'},
+                       {"user-code", no_argument, 0, 'u'},
+                       {"help", no_argument, 0, 'h'},
+                       {"version", no_argument, 0, 'v'},
+                       {0, 0, 0, 0}
+               };
+
+               c = getopt_long(argc, argv, "sb:tfuhv", long_options, &option_index);
+
+               /* no more options to parse */
+               if (c == -1) break;
+
+               switch (c) {
+                       /* b, baudrate */
+                       case 'b':
+                               baudrate = atoi(optarg);
+                               /* FIXME: validate baudrate */
+                               break;
+
+                       /* t, trace */
+                       case 't':
+                               trace_on = 1;
+                               break;
+
+                       /* f, freq */
+                       case 'f':
+                               crystal_freq = atoi(optarg);
+                               break;
+
+                       /* u, user-code */
+                       case 'u':
+                               calc_user_code = 1;
+                               break;
+
+                       /* v, version */
+                       case 'v':
+                               printf("%s Version %s\n", PROG_NAME, VERSION);
+                               return 0;
+                               break;
+
+                       /* h, help */
+                       case 'h':
+                       default:
+                               help(argv[0]);
+                               return 0;
+               }
+       }
+
+       /* Parse remaining command line arguments (not options). */
+
+       /* First one should (must) be serial device */
+       if (optind < argc) {
+               isp_serial_device = argv[optind++];
+               if (trace_on) {
+                       printf("Serial device : %s\n", isp_serial_device);
+               }
+       }
+       if (isp_serial_device == NULL) {
+               printf("No serial device given, exiting\n");
+               help(argv[0]);
+               return 0;
+       }
+       if (isp_serial_open(baudrate, isp_serial_device) != 0) {
+               printf("Serial open failed, unable to initiate serial communication with target.\n");
+               return -1;
+       }
+
+       /* 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) {
+               nb_cmd_args = argc - optind;
+               cmd_args = malloc(nb_cmd_args * sizeof(char *));
+               if (trace_on) {
+                       printf("Command arguments :\n");
+               }
+               while (optind < argc) {
+                       static unsigned int idx = 0;
+                       cmd_args[idx++] = argv[optind++];
+                       if (trace_on) {
+                               printf("%s\n", cmd_args[idx - 1]);
+                       }
+               }
+       }
+
+       /* Frist : sync with device */
+       dev_id = prog_connect_and_id(crystal_freq);
+       if (dev_id < 0) {
+               printf("Unable to connect to target, consider hard reset of target or link\n");
+               return -1;
+       }
+
+       if (command != NULL)  {
+               int err = 0;
+               err = prog_handle_command(command, dev_id, nb_cmd_args, cmd_args);
+               if (err >= 0) {
+                       if (trace_on) {
+                               printf("Command \"%s\" handled OK.\n", command);
+                       }
+               } else {
+                       printf("Error handling command \"%s\" : %d\n", command, err);
+               }
+       }
+
+
+       if (cmd_args != NULL) {
+               free(cmd_args);
+       }
+       isp_serial_close();
+       return 0;
+}
+
+struct prog_command {
+       int cmd_num;
+       char* name;
+};
+
+static struct prog_command prog_cmds_list[] = {
+       {0, "dump"},
+       {1, "flash"},
+       {2, "id"},
+       {3, "blank"},
+       {4, "go"},
+       {5, NULL}
+};
+
+/*
+ * Try to connect to the target and identify the device.
+ * First try sync, and if it fails, try to read id twice. if both fail, then we are not connected
+ */
+static int prog_connect_and_id(int freq)
+{
+       int sync_ret = 0;
+
+       /* Try to connect */
+       sync_ret = isp_connect(freq, 1);
+       /* Synchro failed or already synchronised ? */
+       if (sync_ret < 0) {
+               /* If already synchronized, then sync command and the next command fail.
+                  Sync failed, maybe we are already sync'ed, then send one command for nothing */
+               isp_cmd_part_id(1);
+       }
+
+       return isp_cmd_part_id(1);
+}
+
+static int prog_handle_command(char* cmd, int dev_id, int arg_count, char** args)
+{
+       int cmd_found = -1;
+       int ret = 0;
+       int index = 0;
+       struct part_desc* part = NULL;
+
+       if (cmd == NULL) {
+               printf("prog_handle_command called with no command !\n");
+               return -1;
+       }
+
+       part = find_part(dev_id);
+       if (part == NULL) {
+               printf("Unknown part number : 0x%08x.\n", dev_id);
+               return -2;
+       }
+
+       while ((cmd_found == -1) && (prog_cmds_list[index].name != NULL)) {
+               if (strncmp(prog_cmds_list[index].name, cmd, strlen(prog_cmds_list[index].name)) == 0) {
+                       cmd_found = index;
+                       break;
+               }
+               index++;
+       }
+       if (cmd_found == -1) {
+               printf("Unknown command \"%s\", use -h or --help for a list.\n", cmd);
+               return -3;
+       }
+
+       switch (prog_cmds_list[cmd_found].cmd_num) {
+               case 0: /* dump, need one arg : filename */
+                       if (arg_count != 1) {
+                               printf("command dump needs one arg (filename), got %d.\n", arg_count);
+                               return -4;
+                       }
+                       ret = dump_to_file(part, args[0]);
+                       break;
+
+               case 1: /* flash, need one arg : filename */
+                       if (arg_count != 1) {
+                               printf("command flash needs one arg (filename), got %d.\n", arg_count);
+                               return -4;
+                       }
+                       ret = flash_target(part, args[0], calc_user_code);
+                       break;
+
+               case 2: /* id : no args */
+                       ret = get_ids();
+                       break;
+
+               case 3: /* blank : no args */
+                       ret = erase_flash(part);
+                       break;
+
+               case 4: /* go : no args */
+                       ret = start_prog(part);
+                       break;
+       }
+
+       return ret;
+}
+