Adding support for commands prepare-for-write, go, erase, and compare.
authorNathael Pajani <nathael.pajani@ed3l.fr>
Mon, 16 Apr 2012 14:27:37 +0000 (16:27 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Mon, 16 Apr 2012 14:27:37 +0000 (16:27 +0200)
Modified blank-check to factorise some code for sector related commands.

isp_commands.c
isp_main.c

index 296036f..8c886ab 100644 (file)
@@ -488,62 +488,207 @@ int isp_cmd_read_memory(int arg_count, char** args)
        return ret;
 }
 
-int isp_cmd_blank_check(int arg_count, char** args)
+
+int isp_cmd_compare(int arg_count, char** args)
 {
        char buf[SERIAL_BUFSIZE];
        int ret = 0, len = 0;
        char* tmp = NULL;
        /* Arguments */
-       unsigned long int first_sector = 0, last_sector = 0;
+       unsigned long int addr1 = 0, addr2 = 0;
+       unsigned long int cmp_length = 0;
        /* Reply */
-       unsigned long int offset = 0, content = 0;
+       unsigned long int offset = 0;
+
+       /* Check compare arguments */
+       if (arg_count != 3) {
+               printf("compare command needs two addresses and byte count.\n");
+               return -7;
+       }
+       addr1 = strtoul(args[0], NULL, 0);
+       addr2 = strtoul(args[1], NULL, 0);
+       cmp_length = strtoul(args[2], NULL, 0);
+       if (trace_on) {
+               printf("compare command called for %lu bytes between addresses %lu and %lu.\n",
+                               cmp_length, addr1, addr2);
+       }
+       if ((addr1 & 0x03) || (addr2 & 0x03) || (cmp_length & 0x03)) {
+               printf("Error: addresses and count must be multiples of 4 for compare command.\n");
+               return -6;
+       }
+
+       /* Create compare request */
+       len = snprintf(buf, SERIAL_BUFSIZE, "M %lu %lu %lu\r\n", addr1, addr2, cmp_length);
+       if (len > SERIAL_BUFSIZE) {
+               len = SERIAL_BUFSIZE;
+       }
+
+       /* Send compare request */
+       if (isp_serial_write(buf, len) != len) {
+               printf("Unable to send compare request.\n");
+               return -5;
+       }
+       /* Wait for answer */
+       usleep( 5000 );
+       len = isp_serial_read(buf, SERIAL_BUFSIZE, 3);
+       if (len <= 0) {
+               printf("Error reading compare result.\n");
+               return -4;
+       }
+       ret = isp_ret_code(buf, &tmp);
+       switch (ret) {
+               case CMD_SUCCESS:
+                       printf("Source and destination data are equal.\n");
+                       break;
+               case COMPARE_ERROR:
+                       /* possibly read remaining data */
+                       usleep( 2000 );
+                       len += isp_serial_read((buf + len), (SERIAL_BUFSIZE - len), 0);
+                       offset = strtoul(tmp, &tmp, 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_go(int arg_count, char** args)
+{
+       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");
+               return -5;
+       }
+
+       /* Create go request */
+       len = snprintf(buf, SERIAL_BUFSIZE, "G %lu %c\r\n", addr, mode[0]);
+       if (len > SERIAL_BUFSIZE) {
+               len = SERIAL_BUFSIZE;
+       }
+
+       /* Send go request */
+       if (isp_serial_write(buf, len) != len) {
+               printf("Unable to send go request.\n");
+               return -4;
+       }
+       /* Wait for answer */
+       usleep( 5000 );
+       len = isp_serial_read(buf, SERIAL_BUFSIZE, 3);
+       if (len <= 0) {
+               printf("Error reading go result.\n");
+               return -3;
+       }
+       ret = isp_ret_code(buf, NULL);
+       if (ret != 0) {
+               printf("Error when trying to execute programm at 0x%08lx in %s mode.\n", addr, mode);
+               return -1;
+       }
 
-       /* Check blank-check arguments */
+       return 0;
+}
+
+int isp_cmd_sectors_skel(int arg_count, char** args, char* name, char cmd)
+{
+       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("blank-check command needs first and last sectors (1 sector = 4KB of flash).\n");
+               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("blank-check command called for sectors %lu to %lu.\n", first_sector, last_sector);
+               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 blank-check command.\n");
+               printf("Last sector must be after (or equal to) first sector for %s command.\n", name);
                return -6;
        }
 
-       /* Create blank-check request */
-       len = snprintf(buf, SERIAL_BUFSIZE, "I %lu %lu\r\n", first_sector, last_sector);
+       /* Create request */
+       len = snprintf(buf, SERIAL_BUFSIZE, "%c %lu %lu\r\n", cmd, first_sector, last_sector);
        if (len > SERIAL_BUFSIZE) {
                len = SERIAL_BUFSIZE;
        }
-
-       /* Send blank-check request */
+       /* Send request */
        if (isp_serial_write(buf, len) != len) {
-               printf("Unable to send blank-check request.\n");
+               printf("Unable to send %s request.\n", name);
                return -5;
        }
        /* Wait for answer */
        usleep( 5000 );
-       len = isp_serial_read(buf, SERIAL_BUFSIZE, 3);
+       len = isp_serial_read(buf, 3, 3); /* Read at exactly 3 bytes, so caller can retreive info */
        if (len <= 0) {
-               printf("Error reading blank-check result.\n");
+               printf("Error reading %s result.\n", name);
                return -4;
        }
-       ret = isp_ret_code(buf, &tmp);
+       ret = isp_ret_code(buf, NULL);
+
+       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:
-                       offset = strtoul(tmp, &tmp, 10);
+                       /* 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 -1;
+                       return -2;
                case PARAM_ERROR:
                        printf("Param error for blank-check command.\n");
                        return -1;
@@ -552,6 +697,34 @@ int isp_cmd_blank_check(int arg_count, char** args)
        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 -1;
+       }
+       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 -1;
+       }
+       printf("Sectors erased.\n");
+
+       return 0;
+}
+
+
+
 /* FIXME : Temporary place-holder */
 int isp_cmd_null(int arg_count, char** args)
 {
@@ -567,14 +740,14 @@ static struct isp_command isp_cmds_list[] = {
        {"unlock", 0, isp_cmd_unlock},
        {"write-to-ram", 0, isp_cmd_null}, /* isp_cmd_write-to-ram} */
        {"read-memory", 3, isp_cmd_read_memory},
-       {"prepare-for-write", 0, isp_cmd_null}, /* isp_cmd_prepare-for-write} */
+       {"prepare-for-write", 2, isp_cmd_prepare_for_write},
        {"copy-ram-to-flash", 0, isp_cmd_null}, /* isp_cmd_copy-ram-to-flash} */
-       {"go", 0, isp_cmd_null}, /* isp_cmd_go} */
-       {"erase", 0, isp_cmd_null}, /* isp_cmd_erase} */
+       {"go", 2, isp_cmd_go},
+       {"erase", 2, isp_cmd_erase},
        {"blank-check", 2, isp_cmd_blank_check},
        {"read-part-id", 0, isp_cmd_part_id},
        {"read-boot-version", 0, isp_cmd_boot_version},
-       {"compare", 0, isp_cmd_null}, /* isp_cmd_compare} */
+       {"compare", 3, isp_cmd_compare},
        {"read-uid", 0, isp_cmd_read_uid},
        {NULL, 0, NULL}
 };
index 13793d5..1562806 100644 (file)
@@ -51,14 +51,14 @@ void help(char *prog_name)
                "  \t unlock \n" \
                "  \t write-to-ram \n" \
                "  \t read-memory address count file : read 'count' byte(s) from 'address', store then in 'file'\n" \
-               "  \t prepare-for-write \n" \
+               "  \t prepare-for-write first last : prepare sectors from 'first' to 'last' for write operation\n" \
                "  \t copy-ram-to-flash \n" \
-               "  \t go \n" \
-               "  \t erase \n" \
-               "  \t blank-check first last : check flash starting from 'first' setcor to 'last' sector is blank\n" \
+               "  \t go address mode : execute programm at 'address' (> 0x200) in 'mode' ('arm' or 'thumb')\n" \
+               "  \t erase first last : erase flash starting from 'first' sector up to (including) 'last' sector \n" \
+               "  \t blank-check first last : check flash starting from 'first' sector to 'last' sector is blank\n" \
                "  \t read-part-id \n" \
                "  \t read-boot-version \n" \
-               "  \t compare \n" \
+               "  \t compare address1 address2 count : compare count bytes between address1 and address2\n" \
                "  \t read-uid \n" \
                "  Notes:\n" \
                "   - Access to the ISP mode is done by calling this utility once with the synchronize\n" \
@@ -69,6 +69,8 @@ void help(char *prog_name)
                "   - The set-baud-rate command is not available. The SAME baudrate MUST be used for the\n" \
                "     whole session. It must be specified on each successive call if the default baudrate\n" \
                "     is not used.\n" \
+               "   - User must issue an 'unlock' command before any of 'copy-ram-to-flash', 'erase',\n" \
+               "     and 'go' commands.\n" \
                "  Available options:\n" \
                "  \t -s | --synchronize : Perform synchronization (open session)\n" \
                "  \t -b | --baudrate=N : Use this baudrate (does not issue the set-baud-rate command)\n" \