Read parts description from config file
authorNathael Pajani <nathael.pajani@ed3l.fr>
Sun, 21 Jul 2013 23:19:36 +0000 (01:19 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Sun, 21 Jul 2013 23:19:36 +0000 (01:19 +0200)
README
lpcprog.c
parts.c
parts.h

diff --git a/README b/README
index 018ad0c..ffc635d 100644 (file)
--- 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 ?
 
index 360c028..d75135e 100644 (file)
--- a/lpcprog.c
+++ b/lpcprog.c
 #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 <dev_name> -c <command> [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" \
                "  <command> 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 (file)
--- a/parts.c
+++ b/parts.c
  *
  *********************************************************************/
 
-#include <stdint.h> /* uint64_t */
+#include <stdint.h> /* uint64_t and uint32_t */
 #include <stdlib.h> /* NULL */
-#include "parts.h"
+#include <stddef.h> /* For offsetof */
+#include <stdio.h>  /* perror(), fopen(), fclose() */
+#include <errno.h>
 
-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 (file)
--- a/parts.h
+++ b/parts.h
 #ifndef FIND_PART_H
 #define FIND_PART_H
 
-#include <stdint.h>
+#include <stdint.h> /* 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 */