********************
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 ?
#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" \
" \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" \
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);
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'},
{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);
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");
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;
*
*********************************************************************/
-#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;
}
#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;
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 */