authorNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 18 May 2012 23:43:22 +0000 (01:43 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 18 May 2012 23:43:22 +0000 (01:43 +0200)
easier re-use of the functions.

Makefile
isp_commands.c
isp_commands.h
isp_wrapper.c [new file with mode: 0644]

index c262640..b7d01f9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ CFLAGS += -Wall -Wextra -O2
 
 all: isp prog
 
-isp: isp_main.c isp_utils.c isp_commands.c
+isp: isp_main.c isp_utils.c isp_commands.c isp_wrapper.c
        $(CC) $(CFLAGS) $^ -o $@
 
 prog: lpc_prog.c isp_utils.c isp_commands.c prog_commands.c parts.c
index f1f2f7a..b073f5c 100644 (file)
@@ -4,7 +4,7 @@
  *
  *
  * 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/>
  *
@@ -51,58 +51,36 @@ extern int trace_on;
 #define LINES_PER_BLOCK 20
 #define MAX_DATA_BLOCK_SIZE (LINES_PER_BLOCK * LINE_DATA_LENGTH) /* 900 */
 #define MAX_BYTES_PER_LINE (1 + ((LINE_DATA_LENGTH / 3) * 4) + 2) /* "line length" (1) + 60 + \r\n */
-#define FILE_CREATE_MODE (S_IRUSR | S_IWUSR | S_IRGRP)
 
 #if (SERIAL_BUFSIZE < (MAX_BYTES_PER_LINE * LINES_PER_BLOCK + 10 + 2)) /* uuencoded data + checksum + \r\n */
 #error "SERIAL_BUFSIZE too small"
 #endif
 
-#define RAM_MAX_SIZE (8 * 1024) /* 8 KB */
-
+/* Order in this table is important */
 char* error_codes[] = {
-#define CMD_SUCCESS 0
        "CMD_SUCCESS",
-#define INVALID_COMMAND 1
        "INVALID_COMMAND",
-#define SRC_ADDR_ERROR 2
        "SRC_ADDR_ERROR",
-#define DST_ADDR_ERROR 3
        "DST_ADDR_ERROR",
-#define SRC_ADDR_NOT_MAPPED 4
        "SRC_ADDR_NOT_MAPPED",
-#define DST_ADDR_NOT_MAPPED 5
        "DST_ADDR_NOT_MAPPED",
-#define COUNT_ERROR 6
        "COUNT_ERROR",
-#define INVALID_SECTOR 7
        "INVALID_SECTOR",
-#define SECTOR_NOT_BLANK 8
        "SECTOR_NOT_BLANK",
-#define SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9
        "SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION",
-#define COMPARE_ERROR 10
        "COMPARE_ERROR",
-#define BUSY 11
        "BUSY",
-#define PARAM_ERROR 12
        "PARAM_ERROR",
-#define ADDR_ERROR 13
        "ADDR_ERROR",
-#define ADDR_NOT_MAPPED 14
        "ADDR_NOT_MAPPED",
-#define CMD_LOCKED 15
        "CMD_LOCKED",
-#define INVALID_CODE 16
        "INVALID_CODE",
-#define INVALID_BAUD_RATE 17
        "INVALID_BAUD_RATE",
-#define INVALID_STOP_BIT 18
        "INVALID_STOP_BIT",
-#define CODE_READ_PROTECTION_ENABLED 19
        "CODE_READ_PROTECTION_ENABLED",
 };
 
-int isp_ret_code(char* buf, char** endptr, int quiet)
+static int isp_ret_code(char* buf, char** endptr, int quiet)
 {
        unsigned int ret = 0;
        ret = strtoul(buf, endptr, 10);
@@ -125,7 +103,7 @@ int isp_connect(unsigned int crystal_freq, int quiet)
 {
        char buf[REP_BUFSIZE];
        char freq[10];
-       
+
        snprintf(freq, 8, "%d\r\n", crystal_freq);
 
        /* Send synchronize request */
@@ -184,7 +162,7 @@ int isp_send_cmd_no_args(char* cmd_name, char* cmd, int quiet)
 {
        char buf[5];
        int ret = 0, len = 0;
-       
+
        /* Send request */
        if (isp_serial_write(cmd, strlen(cmd)) != (int)strlen(cmd)) {
                printf("Unable to send %s request.\n", cmd_name);
@@ -223,7 +201,7 @@ int isp_cmd_read_uid(void)
        char* tmp = NULL;
        int i = 0, ret = 0, len = 0;
        unsigned long int uid[4];
-       
+
        ret = isp_send_cmd_no_args("read-uid", READ_UID, 0);
        if (ret != 0) {
                printf("Read UID error.\n");
@@ -323,7 +301,7 @@ int isp_send_cmd_two_args(char* cmd_name, char cmd, unsigned int arg1, unsigned
        return ret;
 }
 
-int get_remaining_blocksize(unsigned int count, unsigned int actual_count, char* dir, unsigned int i)
+static int get_remaining_blocksize(unsigned int count, unsigned int actual_count, char* dir, unsigned int i)
 {
        unsigned int blocksize = 0;
        unsigned int remain = count - actual_count;
@@ -354,7 +332,7 @@ int get_remaining_blocksize(unsigned int count, unsigned int actual_count, char*
 }
 
 /* Compute the number of blocks of the transmitted data. */
-int get_nb_blocks(unsigned int count, char* dir)
+static int get_nb_blocks(unsigned int count, char* dir)
 {
        unsigned int lines = 0;
        unsigned int blocks = 0;
@@ -375,7 +353,7 @@ int get_nb_blocks(unsigned int count, char* dir)
        return blocks;
 }
 
-unsigned int calc_checksum(unsigned char* data, unsigned int size)
+static unsigned int calc_checksum(unsigned char* data, unsigned int size)
 {
        unsigned int i = 0;
        unsigned int checksum = 0;
@@ -386,63 +364,32 @@ unsigned int calc_checksum(unsigned char* data, unsigned int size)
        return checksum;
 }
 
-int isp_cmd_read_memory(int arg_count, char** args)
+/*
+ * perform read-memory operation
+ * read 'count' bytes from 'addr' to 'data' buffer
+ */
+int isp_read_memory(char* data, uint32_t addr, unsigned int count)
 {
        /* Serial communication */
        char buf[SERIAL_BUFSIZE];
        int ret = 0, len = 0;
-       /* Arguments */
-       unsigned long int addr = 0, count = 0;
-       char* out_file_name = NULL;
-       int out_fd = -1;
        /* Reply handling */
        unsigned int blocks = 0;
        unsigned int total_bytes_received = 0; /* actual count of bytes received */
        unsigned int i = 0;
 
-       /* Check read-memory arguments */
-       if (arg_count != 3) {
-               printf("read-memory command needs address and count. Both must be multiple of 4.\n");
-               return -12;
-       }
-       addr = strtoul(args[0], NULL, 0);
-       count = strtoul(args[1], NULL, 0);
-       if (trace_on) {
-               printf("read-memory command called for 0x%08lx (%lu) bytes at address 0x%08lx.\n",
-                               count, count, addr);
-       }
-       if ((addr & 0x03) || (count & 0x03)) {
-               printf("Address and count must be multiple of 4 for read-memory command.\n");
-               return -11;
-       }
-       out_file_name = args[2];
-       
        /* Send command */
        ret = isp_send_cmd_two_args("read-memory", 'R', addr, count);
        if (ret != 0) {
-               printf("Error when trying to read %lu bytes of memory at address 0x%08lx.\n", count, addr);
+               printf("Error when trying to read %u bytes of memory at address 0x%08x.\n", count, addr);
                return ret;
        }
 
        /* Now, find the number of blocks of the reply. */
        blocks = get_nb_blocks(count, "Reading");
 
-       /* Open file for writing if output is not stdout */
-       if (strncmp(out_file_name, "-", strlen(out_file_name)) == 0) {
-               out_fd = STDOUT_FILENO;
-       } else {
-               out_fd = open(out_file_name, (O_WRONLY | O_CREAT | O_TRUNC), FILE_CREATE_MODE);
-               if (out_fd <= 0) {
-                       perror("Unable to open or create file for writing");
-                       printf("Tried to open \"%s\".\n", out_file_name);
-                       return -7;
-               }
-       }
-       
        /* Receive and decode the data */
-       /* FIXME : Factorize ? */
        for (i=0; i<blocks; i++) {
-               char data[SERIAL_BUFSIZE];
                unsigned int blocksize = 0, decoded_size = 0;
                unsigned int received_checksum = 0, computed_checksum = 0;
                static int resend_request_for_block = 0;
@@ -466,12 +413,12 @@ int isp_cmd_read_memory(int arg_count, char** args)
                }
                /* Decode. This must be done before sending acknowledge because we must
                 * compute the checksum */
-               decoded_size = isp_uu_decode(data, buf, blocksize);
+               decoded_size = isp_uu_decode((data + total_bytes_received), buf, blocksize);
                received_checksum = strtoul((buf + blocksize), NULL, 10);
-               computed_checksum = calc_checksum((unsigned char*)data, decoded_size);
+               computed_checksum = calc_checksum((unsigned char*)(data + total_bytes_received), decoded_size);
                if (trace_on) {
                        printf("Decoded Data :\n");
-                       isp_dump((unsigned char*)data, decoded_size);
+                       isp_dump((unsigned char*)(data + total_bytes_received), decoded_size);
                }
                if (computed_checksum == received_checksum) {
                        resend_request_for_block = 0; /* reset resend request counter */
@@ -486,15 +433,6 @@ int isp_cmd_read_memory(int arg_count, char** args)
                        }
                        /* Add data length to sum of received data */
                        total_bytes_received += decoded_size;
-                       /* Write data to file */
-                       ret = write(out_fd, data, decoded_size);
-                       if (ret != (int)decoded_size) {
-                               perror("File write error");
-                               printf("Unable to write %u bytes of data to file \"%s\", returned %d !",
-                                               decoded_size, out_file_name, ret);
-                               ret = -3;
-                               break;
-                       }
                } else {
                        resend_request_for_block++;
                        if (trace_on) {
@@ -516,14 +454,15 @@ int isp_cmd_read_memory(int arg_count, char** args)
                        }
                }
        }
-       /* Close file */
-       if (out_fd != STDOUT_FILENO) {
-               close(out_fd);
-       }
 
-       return ret;
+       return total_bytes_received;
 }
 
+
+/*
+ * perform write-to-ram operation
+ * send 'count' bytes from 'data' to 'addr' in RAM
+ */
 int isp_send_buf_to_ram(char* data, unsigned long int addr, unsigned int count)
 {
        /* Serial communication */
@@ -542,7 +481,7 @@ int isp_send_buf_to_ram(char* data, unsigned long int addr, unsigned int count)
 
        /* Now, find the number of blocks of data to send. */
        blocks = get_nb_blocks(count, "Sending");
-       
+
        /* Encode and send the data */
        for (i=0; i<blocks; i++) {
                char buf[SERIAL_BUFSIZE]; /* Store encoded data, to be sent to the microcontroller */
@@ -601,129 +540,15 @@ int isp_send_buf_to_ram(char* data, unsigned long int addr, unsigned int count)
        return ret;
 }
 
-int isp_cmd_write_to_ram(int arg_count, char** args)
-{
-       /* Arguments */
-       unsigned long int addr = 0;
-       char* in_file_name = NULL;
-       int in_fd = -1;
-       char file_buff[RAM_MAX_SIZE];
-       unsigned int bytes_read = 0;
-       int ret = 0;
-
-       /* Check write-to-ram arguments */
-       if (arg_count != 2) {
-               printf("write-to-ram command needs ram address. Must be multiple of 4.\n");
-               return -15;
-       }
-       addr = strtoul(args[0], NULL, 0);
-       if (trace_on) {
-               printf("write-to-ram command called, destination address in ram is 0x%08lx.\n", addr);
-       }
-       if (addr & 0x03) {
-               printf("Address must be multiple of 4 for write-to-ram command.\n");
-               return -14;
-       }
-       in_file_name = args[1];
-
-       /* Open file for reading if input is not stdin */
-       if (strncmp(in_file_name, "-", strlen(in_file_name)) == 0) {
-               /* FIXME : set as non blocking ? */
-               in_fd = STDIN_FILENO;
-       } else {
-               in_fd = open(in_file_name, O_RDONLY | O_NONBLOCK);
-               if (in_fd <= 0) {
-                       perror("Unable to open file for reading");
-                       printf("Tried to open \"%s\".\n", in_file_name);
-                       return -13;
-               }
-       }
-       /* Read file content */
-       do {
-               int nb = read(in_fd, &file_buff[bytes_read], (RAM_MAX_SIZE - bytes_read));
-               if (nb < 0) {
-                       if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
-                               usleep( 50 );
-                               continue;
-                       }
-                       perror("Input file read error");
-                       if (in_fd != STDIN_FILENO) {
-                               close(in_fd);
-                       }
-                       return -12;
-               } else if (nb == 0) {
-                       /* End of file */
-                       break;
-               }
-               bytes_read += nb;
-       } while (bytes_read < RAM_MAX_SIZE);
-       if (in_fd != STDIN_FILENO) {
-               close(in_fd);
-       }
-       if (trace_on) {
-               printf("Read %d octet(s) from input file\n", bytes_read);
-       }
-
-       /* Pad data size to 4 */
-       if (bytes_read & 0x03) {
-               bytes_read = (bytes_read & ~0x03) + 0x04;
-       }
-
-       /* And send to ram */
-       ret = isp_send_buf_to_ram(file_buff, addr, bytes_read);
-
-       return ret;
-}
 
-int isp_send_cmd_address(int arg_count, char** args, char* name, char cmd)
+int isp_send_cmd_address(char cmd, uint32_t addr1, uint32_t addr2, uint32_t length, char* name)
 {
        char buf[SERIAL_BUFSIZE];
        int ret = 0, len = 0;
        char* tmp = NULL;
-       /* Arguments */
-       unsigned long int addr1 = 0, addr2 = 0;
-       unsigned long int length = 0;
-
-       /* Check arguments */
-       if (arg_count != 3) {
-               printf("%s command needs two addresses and byte count.\n", name);
-               return -7;
-       }
-       addr1 = strtoul(args[0], NULL, 0);
-       addr2 = strtoul(args[1], NULL, 0);
-       length = strtoul(args[2], NULL, 0);
-       if (trace_on) {
-               printf("%s command called for %lu bytes between addresses %lu and %lu.\n",
-                               name, length, addr1, addr2);
-       }
-       switch (cmd) {
-               case 'M':
-                       if ((addr1 & 0x03) || (addr2 & 0x03) || (length & 0x03)) {
-                               printf("Error: addresses and count must be multiples of 4 for %s command.\n", name);
-                               return -7;
-                       }
-                       break;
-               case 'C':
-                       if ((addr1 & 0x00FF) || (addr2 & 0x03)) {
-                               printf("Error: flash address must be on 256 bytes boundary, ram address on 4 bytes boundary.\n");
-                               return -8;
-                       }
-                       /* According to section 21.5.7 of LPC11xx user's manual (UM10398), number of bytes
-                        * written should be 256 | 512 | 1024 | 4096 */
-                       len = ((length >> 8) & 0x01) + ((length >> 9) & 0x01);
-                       len += ((length >> 10) & 0x01) + ((length >> 12) & 0x01);
-                       if (len != 1) {
-                               printf("Error: bytes count must be one of 256 | 512 | 1024 | 4096\n");
-                               return -7;
-                       }
-                       break;
-               default:
-                       printf("Error: unsupported command code: '%c'\n", cmd);
-                       return -6;
-       }
 
        /* Create request */
-       len = snprintf(buf, SERIAL_BUFSIZE, "%c %lu %lu %lu\r\n", cmd, addr1, addr2, length);
+       len = snprintf(buf, SERIAL_BUFSIZE, "%c %u %u %u\r\n", cmd, addr1, addr2, length);
        if (len > SERIAL_BUFSIZE) {
                len = SERIAL_BUFSIZE;
        }
@@ -744,84 +569,23 @@ int isp_send_cmd_address(int arg_count, char** args, char* name, char cmd)
        return ret;
 }
 
-int isp_cmd_compare(int arg_count, char** args)
-{
-       char buf[SERIAL_BUFSIZE];
-       int ret = 0, len = 0;
-       unsigned long int offset = 0;
-       
-       ret = isp_send_cmd_address(arg_count, args, "compare", 'M');
-       switch (ret) {
-               case CMD_SUCCESS:
-                       printf("Source and destination data are equal.\n");
-                       break;
-               case COMPARE_ERROR:
-                       /* read remaining data */
-                       usleep( 2000 );
-                       len = isp_serial_read(buf, SERIAL_BUFSIZE, 3);
-                       if (len <= 0) {
-                               printf("Error reading blank-check result.\n");
-                               return -3;
-                       }
-                       offset = strtoul(buf, NULL, 10);
-                       printf("First mismatch occured at offset 0x%08lx\n", offset);
-                       break;
-               default :
-                       printf("Error for compare command.\n");
-                       return -1;
-       }
-
-       return 0;
-}
-
-int isp_cmd_copy_ram_to_flash(int arg_count, char** args)
-{
-       int ret = 0;
-
-       ret = isp_send_cmd_address(arg_count, args, "copy-ram-to-flash", 'C');
-       
-       if (ret != 0) {
-               printf("Error when trying to copy data from ram to flash.\n");
-               return ret;
-       }
-       printf("Data copied from ram to flash.\n");
-
-       return 0;
-}
 
-int isp_cmd_go(int arg_count, char** args)
+int isp_send_cmd_go(uint32_t addr, char mode)
 {
        char buf[SERIAL_BUFSIZE];
        int ret = 0, len = 0;
-       /* Arguments */
-       unsigned long int addr = 0;
-       char* mode = NULL;
 
-       /* Check go arguments */
-       if (arg_count != 2) {
-               printf("go command needs address (> 0x200) and mode ('thumb' or 'arm').\n");
-               return -7;
-       }
-       addr = strtoul(args[0], NULL, 0);
-       mode = args[1];
-       if (trace_on) {
-               printf("go command called with address 0x%08lx and mode %s.\n", addr, mode);
-       }
        if (addr < 0x200) {
                printf("Error: address must be 0x00000200 or greater for go command.\n");
                return -6;
        }
-       if (strncmp(mode, "thumb", strlen(mode)) == 0) {
-               mode[0] = 'T';
-       } else if (strncmp(mode, "arm", strlen(mode)) == 0) {
-               mode[0] = 'A';
-       } else {
-               printf("Error: mode must be 'thumb' or 'arm' for go command.\n");
+       if ((mode != 'T') && (mode != 'A')) {
+               printf("Error: mode must be 'thumb' (T) or 'arm' (A) for go command.\n");
                return -5;
        }
 
        /* Create go request */
-       len = snprintf(buf, SERIAL_BUFSIZE, "G %lu %c\r\n", addr, mode[0]);
+       len = snprintf(buf, SERIAL_BUFSIZE, "G %u %c\r\n", addr, mode);
        if (len > SERIAL_BUFSIZE) {
                len = SERIAL_BUFSIZE;
        }
@@ -840,37 +604,25 @@ int isp_cmd_go(int arg_count, char** args)
        }
        ret = isp_ret_code(buf, NULL, 0);
        if (ret != 0) {
-               printf("Error when trying to execute programm at 0x%08lx in %s mode.\n", addr, mode);
+               printf("Error when trying to execute programm at 0x%08x in '%c' mode.\n", addr, mode);
                return -1;
        }
 
        return 0;
 }
 
-int isp_cmd_sectors_skel(int arg_count, char** args, char* name, char cmd)
+int isp_send_cmd_sectors(char* name, char cmd, int first_sector, int last_sector)
 {
        char buf[SERIAL_BUFSIZE];
        int ret = 0, len = 0;
-       /* Arguments */
-       unsigned long int first_sector = 0, last_sector = 0;
 
-       /* Check arguments */
-       if (arg_count != 2) {
-               printf("%s command needs first and last sectors (1 sector = 4KB of flash).\n", name);
-               return -7;
-       }
-       first_sector = strtoul(args[0], NULL, 0);
-       last_sector = strtoul(args[1], NULL, 0);
-       if (trace_on) {
-               printf("%s command called for sectors %lu to %lu.\n", name, first_sector, last_sector);
-       }
        if (last_sector < first_sector) {
                printf("Last sector must be after (or equal to) first sector for %s command.\n", name);
                return -6;
        }
 
        /* Create request */
-       len = snprintf(buf, SERIAL_BUFSIZE, "%c %lu %lu\r\n", cmd, first_sector, last_sector);
+       len = snprintf(buf, SERIAL_BUFSIZE, "%c %u %u\r\n", cmd, first_sector, last_sector);
        if (len > SERIAL_BUFSIZE) {
                len = SERIAL_BUFSIZE;
        }
@@ -891,70 +643,4 @@ int isp_cmd_sectors_skel(int arg_count, char** args, char* name, char cmd)
        return ret;
 }
 
-int isp_cmd_blank_check(int arg_count, char** args)
-{
-       char* tmp = NULL;
-       unsigned long int offset = 0, content = 0;
-       char buf[SERIAL_BUFSIZE];
-       int ret = 0, len = 0;
-
-       ret = isp_cmd_sectors_skel(arg_count, args, "blank-check", 'I');
-       if (ret < 0) {
-               return ret;
-       }
-
-       switch (ret) {
-               case CMD_SUCCESS:
-                       printf("Specified sector(s) all blank(s).\n");
-                       break;
-               case SECTOR_NOT_BLANK:
-                       /* read remaining data */
-                       usleep( 2000 );
-                       len = isp_serial_read(buf, SERIAL_BUFSIZE, 3);
-                       if (len <= 0) {
-                               printf("Error reading blank-check result.\n");
-                               return -3;
-                       }
-                       offset = strtoul(buf, &tmp, 10);
-                       content = strtoul(tmp, NULL, 10);
-                       printf("First non blank word is at offset 0x%08lx and contains 0x%08lx\n", offset, content);
-                       break;
-               case INVALID_SECTOR :
-                       printf("Invalid sector for blank-check command.\n");
-                       return -2;
-               case PARAM_ERROR:
-                       printf("Param error for blank-check command.\n");
-                       return -1;
-       }
-
-       return 0;
-}
-
-int isp_cmd_prepare_for_write(int arg_count, char** args)
-{
-       int ret = isp_cmd_sectors_skel(arg_count, args, "prepare-for-write", 'P');
-
-       if (ret != 0) {
-               printf("Error when trying to prepare sectors for write operation.\n");
-               return ret;
-       }
-       printf("Sectors prepared for write operation.\n");
-
-       return 0;
-}
-
-int isp_cmd_erase(int arg_count, char** args)
-{
-       int ret = isp_cmd_sectors_skel(arg_count, args, "erase", 'E');
-       
-       if (ret != 0) {
-               printf("Error when trying to erase sectors.\n");
-               return ret;
-       }
-       printf("Sectors erased.\n");
-
-       return 0;
-}
-
-
 
index fc2100b..8f6e3d3 100644 (file)
@@ -4,7 +4,7 @@
  *
  *
  * 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/>
  *
 #define ISP_COMMANDS_H
 
 
+extern char* error_codes[];
+
+#define CMD_SUCCESS 0
+#define INVALID_COMMAND 1
+#define SRC_ADDR_ERROR 2
+#define DST_ADDR_ERROR 3
+#define SRC_ADDR_NOT_MAPPED 4
+#define DST_ADDR_NOT_MAPPED 5
+#define COUNT_ERROR 6
+#define INVALID_SECTOR 7
+#define SECTOR_NOT_BLANK 8
+#define SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9
+#define COMPARE_ERROR 10
+#define BUSY 11
+#define PARAM_ERROR 12
+#define ADDR_ERROR 13
+#define ADDR_NOT_MAPPED 14
+#define CMD_LOCKED 15
+#define INVALID_CODE 16
+#define INVALID_BAUD_RATE 17
+#define INVALID_STOP_BIT 18
+#define CODE_READ_PROTECTION_ENABLED 19
+
 
 /* Connect or reconnect to the target.
  * Return positive or NULL value when connection is OK, or negative value otherwise.
 int isp_connect(unsigned int crystal_freq, int quiet);
 
 
-
-int isp_send_buf_to_ram(char* data, unsigned long int addr, unsigned int count);
+/*
+ * Helper functions
+ */
+int isp_send_cmd_no_args(char* cmd_name, char* cmd, int quiet);
+int isp_send_cmd_two_args(char* cmd_name, char cmd, unsigned int arg1, unsigned int arg2);
+int isp_send_cmd_address(char cmd, uint32_t addr1, uint32_t addr2, uint32_t length, char* name);
+int isp_send_cmd_sectors(char* name, char cmd, int first_sector, int last_sector);
 
 
 int isp_cmd_unlock(int quiet);
@@ -33,15 +61,47 @@ int isp_cmd_part_id(int quiet);
 
 int isp_cmd_boot_version(void);
 
+/*
+ * read-memory
+ * aruments : address count file
+ * read 'count' bytes from 'address', store then in 'file'
+ */
 int isp_cmd_read_memory(int arg_count, char** args);
+/*
+ * perform read-memory operation
+ * read 'count' bytes from 'addr' to 'data' buffer
+ */
+int isp_read_memory(char* data, uint32_t addr, unsigned int count);
 
+/*
+ * write-to-ram
+ * aruments : address file
+ * send 'file' to 'address' in ram
+ */
 int isp_cmd_write_to_ram(int arg_count, char** args);
+/*
+ * perform write-to-ram operation
+ * send 'count' bytes from 'data' to 'addr' in RAM
+ */
+int isp_send_buf_to_ram(char* data, unsigned long int addr, unsigned int count);
+
 
 int isp_cmd_compare(int arg_count, char** args);
 
 int isp_cmd_copy_ram_to_flash(int arg_count, char** args);
 
+/*
+ * go
+ * aruments : address mode
+ * execute programm at 'address' (> 0x200) in 'mode' ('arm' or 'thumb')
+ */
 int isp_cmd_go(int arg_count, char** args);
+/*
+ * perform go operation
+ * start user programm at 'addr' in 'mode'
+ * mode is 'T' for thumb or 'A' for arm.
+ */
+int isp_send_cmd_go(uint32_t addr, char mode);
 
 int isp_cmd_blank_check(int arg_count, char** args);
 
diff --git a/isp_wrapper.c b/isp_wrapper.c
new file mode 100644 (file)
index 0000000..b7898ef
--- /dev/null
@@ -0,0 +1,388 @@
+/*********************************************************************
+ *
+ *   LPC1114 ISP Commands
+ *
+ *
+ * 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>
+#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_commands.h"
+#include "isp_utils.h"
+
+extern int trace_on;
+
+
+#define RAM_MAX_SIZE (8 * 1024) /* 8 KB */
+
+#define REP_BUFSIZE 40
+
+
+
+/*
+ * read-memory
+ * aruments : address count file
+ * read 'count' bytes from 'address', store then in 'file'
+ */
+int isp_cmd_read_memory(int arg_count, char** args)
+{
+       /* Arguments */
+       unsigned long int addr = 0, count = 0;
+       char* out_file_name = NULL;
+       /* Reply handling */
+       char* data;
+       int ret = 0, len = 0;
+
+       /* Check read-memory arguments */
+       if (arg_count != 3) {
+               printf("read-memory command needs address and count. Both must be multiple of 4.\n");
+               return -12;
+       }
+       addr = strtoul(args[0], NULL, 0);
+       count = strtoul(args[1], NULL, 0);
+       if (trace_on) {
+               printf("read-memory command called for 0x%08lx (%lu) bytes at address 0x%08lx.\n",
+                               count, count, addr);
+       }
+       if ((addr & 0x03) || (count & 0x03)) {
+               printf("Address and count must be multiple of 4 for read-memory command.\n");
+               return -11;
+       }
+       out_file_name = args[2];
+
+       /* Allocate buffer */
+       data = malloc(count);
+       if (data == NULL) {
+               printf("Unable to allocate read buffer, asked %lu.\n", count);
+               return -10;
+       }
+
+       /* Read data */
+       len = isp_read_memory(data, addr, count);
+       if (len != (int)count) {
+               printf("Read returned %d bytes instead of %lu.\n", len, count);
+       }
+
+       /* Write data to file */
+       ret = isp_buff_to_file(data, len, out_file_name);
+
+       /* Free memory */
+       free(data);
+
+       return ret;
+}
+
+/*
+ * write-to-ram
+ * aruments : address file
+ * send 'file' to 'address' in ram
+ */
+int isp_cmd_write_to_ram(int arg_count, char** args)
+{
+       /* Arguments */
+       unsigned long int addr = 0;
+       char* in_file_name = NULL;
+       int in_fd = -1;
+       char file_buff[RAM_MAX_SIZE];
+       unsigned int bytes_read = 0;
+       int ret = 0;
+
+       /* Check write-to-ram arguments */
+       if (arg_count != 2) {
+               printf("write-to-ram command needs ram address. Must be multiple of 4.\n");
+               return -15;
+       }
+       addr = strtoul(args[0], NULL, 0);
+       if (trace_on) {
+               printf("write-to-ram command called, destination address in ram is 0x%08lx.\n", addr);
+       }
+       if (addr & 0x03) {
+               printf("Address must be multiple of 4 for write-to-ram command.\n");
+               return -14;
+       }
+       in_file_name = args[1];
+
+       /* Open file for reading if input is not stdin */
+       if (strncmp(in_file_name, "-", strlen(in_file_name)) == 0) {
+               /* FIXME : set as non blocking ? */
+               in_fd = STDIN_FILENO;
+       } else {
+               in_fd = open(in_file_name, O_RDONLY | O_NONBLOCK);
+               if (in_fd <= 0) {
+                       perror("Unable to open file for reading");
+                       printf("Tried to open \"%s\".\n", in_file_name);
+                       return -13;
+               }
+       }
+       /* Read file content */
+       do {
+               int nb = read(in_fd, &file_buff[bytes_read], (RAM_MAX_SIZE - bytes_read));
+               if (nb < 0) {
+                       if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
+                               usleep( 50 );
+                               continue;
+                       }
+                       perror("Input file read error");
+                       if (in_fd != STDIN_FILENO) {
+                               close(in_fd);
+                       }
+                       return -12;
+               } else if (nb == 0) {
+                       /* End of file */
+                       break;
+               }
+               bytes_read += nb;
+       } while (bytes_read < RAM_MAX_SIZE);
+       if (in_fd != STDIN_FILENO) {
+               close(in_fd);
+       }
+       if (trace_on) {
+               printf("Read %d octet(s) from input file\n", bytes_read);
+       }
+
+       /* Pad data size to 4 */
+       if (bytes_read & 0x03) {
+               bytes_read = (bytes_read & ~0x03) + 0x04;
+       }
+
+       /* And send to ram */
+       ret = isp_send_buf_to_ram(file_buff, addr, bytes_read);
+
+       return ret;
+}
+
+int isp_cmd_address_wrapper(int arg_count, char** args, char* name, char cmd)
+{
+       int ret = 0, len = 0;
+       /* Arguments */
+       unsigned long int addr1 = 0, addr2 = 0;
+       unsigned long int length = 0;
+
+       /* Check arguments */
+       if (arg_count != 3) {
+               printf("%s command needs two addresses and byte count.\n", name);
+               return -7;
+       }
+       addr1 = strtoul(args[0], NULL, 0);
+       addr2 = strtoul(args[1], NULL, 0);
+       length = strtoul(args[2], NULL, 0);
+       if (trace_on) {
+               printf("%s command called for %lu bytes between addresses %lu and %lu.\n",
+                               name, length, addr1, addr2);
+       }
+       switch (cmd) {
+               case 'M':
+                       if ((addr1 & 0x03) || (addr2 & 0x03) || (length & 0x03)) {
+                               printf("Error: addresses and count must be multiples of 4 for %s command.\n", name);
+                               return -7;
+                       }
+                       break;
+               case 'C':
+                       if ((addr1 & 0x00FF) || (addr2 & 0x03)) {
+                               printf("Error: flash address must be on 256 bytes boundary, ram address on 4 bytes boundary.\n");
+                               return -8;
+                       }
+                       /* According to section 21.5.7 of LPC11xx user's manual (UM10398), number of bytes
+                        * written should be 256 | 512 | 1024 | 4096 */
+                       len = ((length >> 8) & 0x01) + ((length >> 9) & 0x01);
+                       len += ((length >> 10) & 0x01) + ((length >> 12) & 0x01);
+                       if (len != 1) {
+                               printf("Error: bytes count must be one of 256 | 512 | 1024 | 4096\n");
+                               return -7;
+                       }
+                       break;
+               default:
+                       printf("Error: unsupported command code: '%c'\n", cmd);
+                       return -6;
+       }
+
+       ret = isp_send_cmd_address(cmd, addr1, addr2, length, name);
+       return ret;
+}
+
+int isp_cmd_compare(int arg_count, char** args)
+{
+       char buf[REP_BUFSIZE];
+       int ret = 0, len = 0;
+       unsigned long int offset = 0;
+
+       ret = isp_cmd_address_wrapper(arg_count, args, "compare", 'M');
+       switch (ret) {
+               case CMD_SUCCESS:
+                       printf("Source and destination data are equal.\n");
+                       break;
+               case COMPARE_ERROR:
+                       /* read remaining data */
+                       usleep( 2000 );
+                       len = isp_serial_read(buf, REP_BUFSIZE, 3);
+                       if (len <= 0) {
+                               printf("Error reading blank-check result.\n");
+                               return -3;
+                       }
+                       offset = strtoul(buf, NULL, 10);
+                       printf("First mismatch occured at offset 0x%08lx\n", offset);
+                       break;
+               default :
+                       printf("Error for compare command.\n");
+                       return -1;
+       }
+
+       return 0;
+}
+
+int isp_cmd_copy_ram_to_flash(int arg_count, char** args)
+{
+       int ret = 0;
+
+       ret = isp_cmd_address_wrapper(arg_count, args, "copy-ram-to-flash", 'C');
+
+       if (ret != 0) {
+               printf("Error when trying to copy data from ram to flash.\n");
+               return ret;
+       }
+       printf("Data copied from ram to flash.\n");
+
+       return 0;
+}
+
+int isp_cmd_go(int arg_count, char** args)
+{
+       int ret = 0;
+       /* Arguments */
+       unsigned long int addr = 0;
+       char* mode = NULL;
+
+       /* Check go arguments */
+       if (arg_count != 2) {
+               printf("go command needs address (> 0x200) and mode ('thumb' or 'arm').\n");
+               return -7;
+       }
+       addr = strtoul(args[0], NULL, 0);
+       mode = args[1];
+       if (trace_on) {
+               printf("go command called with address 0x%08lx and mode %s.\n", addr, mode);
+       }
+       if (addr < 0x200) {
+               printf("Error: address must be 0x00000200 or greater for go command.\n");
+               return -6;
+       }
+       if (strncmp(mode, "thumb", strlen(mode)) == 0) {
+               mode[0] = 'T';
+       } else if (strncmp(mode, "arm", strlen(mode)) == 0) {
+               mode[0] = 'A';
+       } else {
+               printf("Error: mode must be 'thumb' or 'arm' for go command.\n");
+               return -5;
+       }
+
+       ret = isp_send_cmd_go(addr, mode[0]);
+
+       return ret;
+}
+
+int isp_cmd_sectors_skel(int arg_count, char** args, char* name, char cmd)
+{
+       int ret = 0;
+       /* Arguments */
+       unsigned long int first_sector = 0, last_sector = 0;
+
+       /* Check arguments */
+       if (arg_count != 2) {
+               printf("%s command needs first and last sectors (1 sector = 4KB of flash).\n", name);
+               return -7;
+       }
+       first_sector = strtoul(args[0], NULL, 0);
+       last_sector = strtoul(args[1], NULL, 0);
+       if (trace_on) {
+               printf("%s command called for sectors %lu to %lu.\n", name, first_sector, last_sector);
+       }
+
+       ret = isp_send_cmd_sectors(name, cmd, first_sector, last_sector);
+
+       return ret;
+}
+
+int isp_cmd_blank_check(int arg_count, char** args)
+{
+       char* tmp = NULL;
+       unsigned long int offset = 0, content = 0;
+       char buf[REP_BUFSIZE];
+       int ret = 0, len = 0;
+
+       ret = isp_cmd_sectors_skel(arg_count, args, "blank-check", 'I');
+       if (ret < 0) {
+               return ret;
+       }
+
+       switch (ret) {
+               case CMD_SUCCESS:
+                       printf("Specified sector(s) all blank(s).\n");
+                       break;
+               case SECTOR_NOT_BLANK:
+                       /* read remaining data */
+                       usleep( 2000 );
+                       len = isp_serial_read(buf, REP_BUFSIZE, 3);
+                       if (len <= 0) {
+                               printf("Error reading blank-check result.\n");
+                               return -3;
+                       }
+                       offset = strtoul(buf, &tmp, 10);
+                       content = strtoul(tmp, NULL, 10);
+                       printf("First non blank word is at offset 0x%08lx and contains 0x%08lx\n", offset, content);
+                       break;
+               case INVALID_SECTOR :
+                       printf("Invalid sector for blank-check command.\n");
+                       return -2;
+               case PARAM_ERROR:
+                       printf("Param error for blank-check command.\n");
+                       return -1;
+       }
+
+       return 0;
+}
+
+int isp_cmd_prepare_for_write(int arg_count, char** args)
+{
+       int ret = isp_cmd_sectors_skel(arg_count, args, "prepare-for-write", 'P');
+
+       if (ret != 0) {
+               printf("Error when trying to prepare sectors for write operation.\n");
+               return ret;
+       }
+       printf("Sectors prepared for write operation.\n");
+
+       return 0;
+}
+
+int isp_cmd_erase(int arg_count, char** args)
+{
+       int ret = isp_cmd_sectors_skel(arg_count, args, "erase", 'E');
+
+       if (ret != 0) {
+               printf("Error when trying to erase sectors.\n");
+               return ret;
+       }
+       printf("Sectors erased.\n");
+
+       return 0;
+}
+
+
+