From a0cc700a89537ae7f6e8bd48454d3818f277ee3f Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Mon, 22 Jul 2013 01:19:36 +0200 Subject: [PATCH] Read parts description from config file --- README | 4 +-- lpcprog.c | 34 +++++++++++++++++-- parts.c | 98 +++++++++++++++++++++++++++++++++++++++++++++---------- parts.h | 16 +++++++-- 4 files changed, 127 insertions(+), 25 deletions(-) diff --git a/README b/README index 018ad0c..ffc635d 100644 --- a/README +++ b/README @@ -24,11 +24,9 @@ or in the included LICENCE file. ******************** TODO : -Allow reading of parts information in a separate file (modify parts.c) -to enable easy definition of new parts. - Allow flashing of parts with flash sectors of different sizes (LPC1764 has 16 small 4k sectors and two big 32k sectors). +--> Need to change parts definition format. Add the definition of all LPC parts ? diff --git a/lpcprog.c b/lpcprog.c index 360c028..d75135e 100644 --- a/lpcprog.c +++ b/lpcprog.c @@ -37,13 +37,14 @@ #include "parts.h" #define PROG_NAME "LPC ISP Prog tool" -#define VERSION "1.01" +#define VERSION "1.02" void help(char *prog_name) { fprintf(stderr, "---------------- "PROG_NAME" --------------------------------\n"); fprintf(stderr, "Usage: %s -d -c [options] [dump/prog file name]\n" \ + " Default parts description files are /etc/lpctools_parts.def or ./lpctools_parts.def\n" \ " Default baudrate is B115200\n" \ " Default oscilator frequency used is 10000 KHz\n" \ " is one of:\n" \ @@ -54,6 +55,7 @@ void help(char *prog_name) " \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 -p | --parts=file : Parts description file (see defaults)\n" \ " \t -c | --command=cmd : \n" \ " \t -d | --device=dev_path : Host serial line used to programm the device\n" \ " \t -b | --baudrate=N : Use this baudrate (Same baudrate must be used across whole session)\n" \ @@ -71,6 +73,10 @@ int trace_on = 0; int quiet = 0; static int calc_user_code = 1; /* User code is computed by default */ +char* parts_file_name = NULL; +#define DEFAULT_PART_FILE_NAME_ETC "/etc/lpctools_parts.def" +#define DEFAULT_PART_FILE_NAME_CURRENT "./lpctools_parts.def" + static int prog_connect_and_id(int freq); static int prog_handle_command(char* cmd, int dev_id, int arg_count, char** args); @@ -93,6 +99,7 @@ int main(int argc, char** argv) int c = 0; struct option long_options[] = { + {"parts", required_argument, 0, 'p'}, {"command", required_argument, 0, 'c'}, {"device", required_argument, 0, 'd'}, {"baudrate", required_argument, 0, 'b'}, @@ -104,12 +111,17 @@ int main(int argc, char** argv) {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "c:d:b:tf:nhv", long_options, &option_index); + c = getopt_long(argc, argv, "p:c:d:b:tf:nhv", long_options, &option_index); /* no more options to parse */ if (c == -1) break; switch (c) { + /* p, parts description file */ + case 'p': + parts_file_name = strdup(optarg); + break; + /* c, command */ case 'c': command = strdup(optarg); @@ -160,8 +172,24 @@ int main(int argc, char** argv) printf("No command given. use -h or --help for help on available commands.\n"); return -1; } + /* Check for default parts file availability if none given as argument */ + if (parts_file_name == NULL) { + FILE* parts_file = NULL; + + parts_file_name = DEFAULT_PART_FILE_NAME_ETC; + parts_file = fopen(parts_file_name, "r"); + if (parts_file == NULL) { + parts_file_name = DEFAULT_PART_FILE_NAME_CURRENT; + parts_file = fopen(parts_file_name, "r"); } + if (parts_file == NULL) { + printf("Unable to open default parts file to read LPC descriptions !\n"); + printf("Tried : '%s' and '%s'\n", DEFAULT_PART_FILE_NAME_ETC, DEFAULT_PART_FILE_NAME_CURRENT); + return -1; + } + fclose(parts_file); } + /* Open serial device */ if (isp_serial_device == NULL) { printf("No serial device given, exiting\n"); @@ -266,7 +294,7 @@ static int prog_handle_command(char* cmd, int dev_id, int arg_count, char** args return -1; } - part = find_part(dev_id); + part = find_part_in_file(dev_id, parts_file_name); if (part == NULL) { printf("Unknown part number : 0x%08x.\n", dev_id); return -2; diff --git a/parts.c b/parts.c index 76e139a..d224595 100644 --- a/parts.c +++ b/parts.c @@ -10,32 +10,96 @@ * *********************************************************************/ -#include /* uint64_t */ +#include /* uint64_t and uint32_t */ #include /* NULL */ -#include "parts.h" +#include /* For offsetof */ +#include /* perror(), fopen(), fclose() */ +#include -struct part_desc parts[] = { - /* part info | flash | reset | ram */ - /* | nb | vector | buffer */ - /* part_id part name | base addr size sect | offset | base addr size off size */ - { 0x2540102B, "LPC1114FHN33/302", 0x00000000, 0x8000, 8, 0x04, 0x10000000, 0x2000, 0x800, 0x400 }, - { 0x3640C02B, "LPC1224FBD48/101", 0x00000000, 0x8000, 8, 0x04, 0x10000000, 0x1000, 0x800, 0x400 }, - { 0x26011922, "LPC1764FBD100", 0x00000000, 0x10000, 16, 0x04, 0x10000000, 0x4000, 0x800, 0x800 }, - {0, NULL, 0, 0, 0, 0, 0, 0, 0, 0}, -}; +#include "parts.h" +#define CONF_READ_BUF_SIZE 250 -struct part_desc* find_part(uint64_t dev_id) +/* When looking for parts description in a file ee do allocate (malloc) two memory + * chunks which we will never free. + * The user should free part_desc->name and part_desc when they are no more usefull + */ +struct part_desc* find_part_in_file(uint64_t dev_id, char* parts_file_name) { - int i = 0; + FILE* parts_file = NULL; + unsigned int i = 0; + unsigned int line = 0; /* Store current line number when reading file */ + struct part_desc* part = malloc(sizeof(struct part_desc)); + + parts_file = fopen(parts_file_name, "r"); + if (parts_file == NULL) { + perror("Unable to open file to read LPC descriptions !"); + return NULL; + } + + while (1) { + char buf[CONF_READ_BUF_SIZE]; + char* endp = NULL; + uint32_t* part_values = NULL; + unsigned int nval = 0; - while (parts[i].name != NULL) { - if (parts[i].part_id == dev_id) { - return &parts[i]; + if (fgets(buf, CONF_READ_BUF_SIZE, parts_file) == NULL) { + printf("Part not found before end of parts description file.\n"); + goto out_err_1; + } + line++; /* Store current line number to help parts description file correction */ + if (buf[0] == '#') { + /* skip comments */ + continue; } - i++; + part->part_id = strtoul(buf, &endp, 0); + if (part->part_id != dev_id) { + continue; + } + printf("Part ID 0x%08x found on line %d\n", (unsigned int)part->part_id, line); + /* We found the right part ID, get all the data */ + part->name = malloc(PART_NAME_LENGTH); + /* Part names must start with "LPC" */ + while ((*endp != '\0') && (*endp != 'L')) { + endp++; + } + /* Copy part name */ + for (i = 0; i < PART_NAME_LENGTH; i++) { + if (endp[i] == '\0') { + /* Hey, we need the part description after the name */ + printf("Malformed parts description file at line %d, nothing after part name.\n", line); + goto out_err_2; + } + if (endp[i] == ',') { + break; + } + part->name[i] = endp[i]; + } + if ((i == PART_NAME_LENGTH) && (endp[i] != ',')) { + printf("Malformed parts description file at line %d, part name too long.\n", line); + goto out_err_2; + } + endp += i; + /* Get all the values */ + nval = ((sizeof(struct part_desc) - offsetof(struct part_desc, flash_base)) / sizeof(uint32_t)); + part_values = &(part->flash_base); /* Use a table to read the data, we do not care of what the data is */ + for (i = 0; i < nval; i++) { + part_values[i] = strtoul((endp + 1), &endp, 0); + if ((part_values[i] == 0) && (errno == EINVAL)) { + printf("Malformed parts description file at line %d, error reading value %d\n", line, i); + goto out_err_2; + } + } + /* Done, retrun the part ! */ + return part; } + +out_err_2: + free(part->name); +out_err_1: + free(part); + fclose(parts_file); return NULL; } diff --git a/parts.h b/parts.h index 6357875..e702fd5 100644 --- a/parts.h +++ b/parts.h @@ -13,8 +13,12 @@ #ifndef FIND_PART_H #define FIND_PART_H -#include +#include /* uint64_t and uint32_t */ +#define PART_NAME_LENGTH 25 + +/* Part descriptor */ +/* ALL data below name MUST be of type uint32_t */ struct part_desc { uint64_t part_id; char* name; @@ -30,7 +34,15 @@ struct part_desc { uint32_t ram_buff_size; }; -struct part_desc* find_part(uint64_t dev_id); +/* When looking for parts description in a file ee do allocate (malloc) two memory + * chunks which we will never free. + * The user should free part_desc->name and part_desc when they are no more usefull + */ +struct part_desc* find_part_in_file(uint64_t dev_id, char* conf_file_name); + +/* Find a part in the internal parts table */ +/* FIXME : To be inplemented ? */ +struct part_desc* find_part_internal_tab(uint64_t dev_id); #endif /* FIND_PART_H */ -- 2.43.0