From 4a793005fdbd3239cc2af24ddf1f0807815b330a Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Sat, 19 May 2012 01:43:22 +0200 Subject: [PATCH] Splitting isp commands in two parts (creating a new file) to allow easier re-use of the functions. --- Makefile | 2 +- isp_commands.c | 382 +++++------------------------------------------- isp_commands.h | 66 ++++++++- isp_wrapper.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 486 insertions(+), 352 deletions(-) create mode 100644 isp_wrapper.c diff --git a/Makefile b/Makefile index c262640..b7d01f9 100644 --- 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 diff --git a/isp_commands.c b/isp_commands.c index f1f2f7a..b073f5c 100644 --- a/isp_commands.c +++ b/isp_commands.c @@ -4,7 +4,7 @@ * * * Written by Nathael Pajani - * + * * This programm is released under the terms of the GNU GPLv3 licence * as can be found on the GNU website : * @@ -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> 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; -} - - diff --git a/isp_commands.h b/isp_commands.h index fc2100b..8f6e3d3 100644 --- a/isp_commands.h +++ b/isp_commands.h @@ -4,7 +4,7 @@ * * * Written by Nathael Pajani - * + * * This programm is released under the terms of the GNU GPLv3 licence * as can be found on the GNU website : * @@ -14,6 +14,29 @@ #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. @@ -21,8 +44,13 @@ 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 index 0000000..b7898ef --- /dev/null +++ b/isp_wrapper.c @@ -0,0 +1,388 @@ +/********************************************************************* + * + * LPC1114 ISP Commands + * + * + * 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 +#include +#include +#include /* strncmp */ +#include +#include + +#include /* for open, close */ +#include +#include +#include + +#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; +} + + + -- 2.43.0