Creating new tool to ease programming, enabling one command programming
authorNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 17 May 2012 00:01:26 +0000 (02:01 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Thu, 17 May 2012 00:01:26 +0000 (02:01 +0200)
for supported parts

Makefile
lpc_prog.c [new file with mode: 0644]
parts.c [new file with mode: 0644]
parts.h [new file with mode: 0644]
prog_commands.c [new file with mode: 0644]
prog_commands.h [new file with mode: 0644]

index f8f0520..c262640 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,10 +4,14 @@ CC = $(CROSS_COMPILE)gcc
 
 CFLAGS += -Wall -Wextra -O2
 
-all: isp
+all: isp prog
 
 isp: isp_main.c isp_utils.c isp_commands.c
        $(CC) $(CFLAGS) $^ -o $@
 
+prog: lpc_prog.c isp_utils.c isp_commands.c prog_commands.c parts.c
+       $(CC) $(CFLAGS) $^ -o $@
+
 clean:
        rm -f isp
+       rm -f prog
diff --git a/lpc_prog.c b/lpc_prog.c
new file mode 100644 (file)
index 0000000..bd4e0f9
--- /dev/null
@@ -0,0 +1,327 @@
+/*********************************************************************
+ *
+ *   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, sync, 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 -w | --wipe : erase whole flash before programm operation (no effect with other commands)\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 wipe = 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'},
+                       {"wipe", no_argument, 0, 'w'},
+                       {"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: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;
+
+                       /* w, wipe */
+                       case 'w':
+                               wipe = 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 */
+               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;
+                       }
+                       if (wipe == 1) {
+                               ret = erase_flash(part);
+                               if (ret < 0) {
+                                       return ret;
+                               }
+                       }
+                       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();
+                       break;
+       }
+
+       return ret;
+}
+
diff --git a/parts.c b/parts.c
new file mode 100644 (file)
index 0000000..4df2f4c
--- /dev/null
+++ b/parts.c
@@ -0,0 +1,39 @@
+/*********************************************************************
+ *
+ *   LPC Parts identification
+ *
+ *
+ * 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 <stdint.h> /* uint64_t */
+#include <stdlib.h> /* NULL */
+#include "parts.h"
+
+struct part_desc parts[] = {
+       /*        part info             |        flash            |            ram                  */
+       /*                              |                     nb  |                      buffer     */
+       /*  part_id      part name      | base addr    size  sect | base addr   size    off   size  */
+       { 0x2540102B, "LPC1114FHN33/302", 0x00000000, 0x8000, 8,    0x10000000, 0x2000, 0x800, 0x400 },
+       {0, NULL, 0, 0, 0, 0, 0, 0, 0},
+};
+
+
+struct part_desc* find_part(uint64_t dev_id)
+{
+       int i = 0;
+
+       while (parts[i].name != NULL) {
+               if (parts[i].part_id == dev_id) {
+                       return &parts[i];
+               }
+               i++;
+       }
+
+       return NULL;
+}
+
diff --git a/parts.h b/parts.h
new file mode 100644 (file)
index 0000000..e92aa31
--- /dev/null
+++ b/parts.h
@@ -0,0 +1,35 @@
+/*********************************************************************
+ *
+ *   LPC Parts identification
+ *
+ *
+ * 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/>
+ *
+ *********************************************************************/
+
+#ifndef FIND_PART_H
+#define FIND_PART_H
+
+#include <stdint.h>
+
+struct part_desc {
+       uint64_t part_id;
+       char* name;
+       /* Flash */
+       uint32_t flash_base;
+       uint32_t flash_size;
+       uint32_t flash_nb_sectors;
+       /* RAM */
+       uint32_t ram_base;
+       uint32_t ram_size;
+       uint32_t ram_buff_offset; /* Used to transfer data for flashing */
+       uint32_t ram_buff_size;
+};
+
+struct part_desc* find_part(uint64_t dev_id);
+
+#endif /* FIND_PART_H */
+
diff --git a/prog_commands.c b/prog_commands.c
new file mode 100644 (file)
index 0000000..6864ee9
--- /dev/null
@@ -0,0 +1,84 @@
+/*********************************************************************
+ *
+ *   LPC1114 ISP Commands for flash tool
+ *
+ *
+ * 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> /* strtoul */
+#include <stdio.h> /* printf, snprintf */
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h> /* strncmp */
+#include <ctype.h>
+#include <errno.h>
+
+#include <unistd.h> /* for open, close */
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "isp_utils.h"
+#include "isp_commands.h"
+#include "parts.h"
+
+extern int trace_on;
+
+
+int get_ids(void)
+{
+       int ret = 0;
+
+       isp_cmd_part_id(0);
+       isp_cmd_read_uid();
+       isp_cmd_boot_version();
+
+       return ret;
+}
+
+
+int dump_to_file(struct part_desc* part, char* filename)
+{
+       int ret = 0;
+       int argc = 3;
+       char* args[3];
+       #define STR_SIZE 15
+       char flash_size[STR_SIZE];
+
+       args[0] = "0x00000000";
+       snprintf(flash_size, STR_SIZE, "0x%08x", part->flash_size); /* Get count from part ID */
+       args[1] = flash_size;
+       args[2] = filename;
+
+       isp_cmd_read_memory(argc, args);
+       return ret;
+}
+
+
+int erase_flash(struct part_desc* part)
+{
+       int ret = 0;
+
+       return ret;
+}
+
+int start_prog(void)
+{
+       int ret = 0;
+
+       return ret;
+}
+
+
+int flash_target(struct part_desc* part, char* filename, int check)
+{
+       int ret = 0;
+
+       return ret;
+}
+
diff --git a/prog_commands.h b/prog_commands.h
new file mode 100644 (file)
index 0000000..41c17d4
--- /dev/null
@@ -0,0 +1,30 @@
+/*********************************************************************
+ *
+ *   LPC1114 ISP Commands for flash tool
+ *
+ *
+ * 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/>
+ *
+ *********************************************************************/
+
+#ifndef ISP_CMDS_FLASH_H
+#define ISP_CMDS_FLASH_H
+
+#include "parts.h"
+
+int dump_to_file(struct part_desc* part, char* filename);
+
+int erase_flash(struct part_desc* part);
+
+int flash_target(struct part_desc* part, char* filename, int check);
+
+int get_ids(void);
+
+int start_prog(void);
+
+
+#endif /* ISP_CMDS_FLASH_H */
+