From dbf6c317f10c976d19369abe7236a01df2b71b03 Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Thu, 17 May 2012 02:01:26 +0200 Subject: [PATCH] Creating new tool to ease programming, enabling one command programming for supported parts --- Makefile | 6 +- lpc_prog.c | 327 ++++++++++++++++++++++++++++++++++++++++++++++++ parts.c | 39 ++++++ parts.h | 35 ++++++ prog_commands.c | 84 +++++++++++++ prog_commands.h | 30 +++++ 6 files changed, 520 insertions(+), 1 deletion(-) create mode 100644 lpc_prog.c create mode 100644 parts.c create mode 100644 parts.h create mode 100644 prog_commands.c create mode 100644 prog_commands.h diff --git a/Makefile b/Makefile index f8f0520..c262640 100644 --- 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 index 0000000..bd4e0f9 --- /dev/null +++ b/lpc_prog.c @@ -0,0 +1,327 @@ +/********************************************************************* + * + * LPC1114 ISP + * + * + * Written by Nathael Pajani + * + * This programm is released under the terms of the GNU GPLv3 licence + * as can be found on the GNU website : + * + *********************************************************************/ + + +#include /* malloc, free */ +#include +#include + +#include /* open, getopt, close, usleep */ +#include +#include +#include + +#include +#include + +#include /* for serial config */ +#include + +#include /* 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" \ + " is the (host) serial line used to programm the device\n" \ + " 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 index 0000000..4df2f4c --- /dev/null +++ b/parts.c @@ -0,0 +1,39 @@ +/********************************************************************* + * + * LPC Parts identification + * + * + * Written by Nathael Pajani + * + * This programm is released under the terms of the GNU GPLv3 licence + * as can be found on the GNU website : + * + *********************************************************************/ + +#include /* uint64_t */ +#include /* 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 index 0000000..e92aa31 --- /dev/null +++ b/parts.h @@ -0,0 +1,35 @@ +/********************************************************************* + * + * LPC Parts identification + * + * + * Written by Nathael Pajani + * + * This programm is released under the terms of the GNU GPLv3 licence + * as can be found on the GNU website : + * + *********************************************************************/ + +#ifndef FIND_PART_H +#define FIND_PART_H + +#include + +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 index 0000000..6864ee9 --- /dev/null +++ b/prog_commands.c @@ -0,0 +1,84 @@ +/********************************************************************* + * + * LPC1114 ISP Commands for flash tool + * + * + * Written by Nathael Pajani + * + * This programm is released under the terms of the GNU GPLv3 licence + * as can be found on the GNU website : + * + *********************************************************************/ + +#include /* strtoul */ +#include /* printf, snprintf */ +#include +#include +#include /* strncmp */ +#include +#include + +#include /* for open, close */ +#include +#include +#include + +#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 index 0000000..41c17d4 --- /dev/null +++ b/prog_commands.h @@ -0,0 +1,30 @@ +/********************************************************************* + * + * LPC1114 ISP Commands for flash tool + * + * + * Written by Nathael Pajani + * + * This programm is released under the terms of the GNU GPLv3 licence + * as can be found on the GNU website : + * + *********************************************************************/ + +#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 */ + -- 2.43.0