diff --git a/src/term.c b/src/term.c index 36849da9..77da4a4d 100644 --- a/src/term.c +++ b/src/term.c @@ -332,7 +332,8 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, char * e; int len, maxsize; char * memtype; - unsigned long addr, i; + long addr; + long i; unsigned char * buf; unsigned char b; int rc; @@ -345,7 +346,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, "Usage: write \n" " write <...>\n\n" " Add a suffix to manually specify the size for each field:\n" - " H/h/S/s: 16-bit, L/l: 32-bit, F/f: 32-bit float\n"); + " H/h/S/s: 16-bit, L/l: 32-bit, LL/ll: 6-bit, F/f: 32-bit float\n"); return -1; } @@ -403,43 +404,55 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, return -1; } - // Union to represent the data to write to memory - union Data { - float f; - int32_t i; - uint8_t a[4]; + // Structure related to data that is being written to memory + struct Data { + // Data info + int32_t bytes_grown; + uint8_t size; + bool is_float; + // Data union + union { + float f; + int64_t ll; + uint8_t a[8]; + }; } data; - int32_t bytes_grown = 0; - for (i = start_offset; i < len + start_offset - bytes_grown; i++) { - bool is_float = false; - uint8_t data_length = 0; + for (i = start_offset; i < len + start_offset - data.bytes_grown; i++) { + data.is_float = false; + data.size = 0; // Handle the next argument if (i < argc - start_offset + 3) { // Get suffix if present - char suffix = argv[i][strlen(argv[i]) - 1]; - if ((suffix == 'F' || suffix == 'f' || suffix == 'L' || suffix == 'l') && \ - strncmp(argv[i], "0x", 2) != 0) { + char suffix = argv[i][strlen(argv[i]) - 1]; + char lsuffix = argv[i][strlen(argv[i]) - 2]; + if ((suffix == 'L' && lsuffix == 'L') || (suffix == 'l' && lsuffix == 'l')) { + argv[i][strlen(argv[i]) - 2] = '\0'; + data.size = 8; + } else if (suffix == 'L' || suffix == 'l') { argv[i][strlen(argv[i]) - 1] = '\0'; - data_length = 4; + data.size = 4; + } else if ((suffix == 'F' || suffix == 'f') && strncmp(argv[i], "0x", 2) != 0) { + argv[i][strlen(argv[i]) - 1] = '\0'; + data.size = 4; } else if (suffix == 'H' || suffix == 'h' || suffix == 'S' || suffix == 's') { argv[i][strlen(argv[i]) - 1] = '\0'; - data_length = 2; + data.size = 2; } else if (suffix == '\'') { - data_length = 1; - } + data.size = 1; + } // Try integers - data.i = strtol(argv[i], &e, 0); + data.ll = strtoll(argv[i], &e, 0); if (*e || (e == argv[i])) { // Try float data.f = strtof(argv[i], &e); - is_float = true; + data.is_float = true; if (*e || (e == argv[i])) { - is_float = false; + data.is_float = false; // Try single character if (argv[i][0] == '\'') { - data.i = argv[i][1]; + data.ll = argv[i][1]; } else { avrdude_message(MSG_INFO, "\n%s (write): can't parse data \"%s\"\n", progname, argv[i]); @@ -449,30 +462,37 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, } } // Print warning if data size might be ambiguous - if(!data_length && \ + if(!data.size && \ (((strncmp(argv[i], "0x", 2) == 0) && strlen(argv[i]) > 3) || \ - (data.i > 0xFF && strlen(argv[i]) > 2))) { + (data.ll > 0xFF && strlen(argv[i]) > 2))) { avrdude_message(MSG_INFO, "Warning: no size suffix specified for \"%s\". " "Writing %d bytes\n", argv[i], - is_float || labs(data.i) > 0xFFFF ? 4 : \ - labs(data.i) > 0x00FF ? 2 : 1); + llabs(data.ll) > 0xFFFFFFFF ? 8 : + llabs(data.ll) > 0x0000FFFF || data.is_float ? 4 : \ + llabs(data.ll) > 0x000000FF ? 2 : 1); } } - buf[i - start_offset + bytes_grown] = data.a[0]; - if (is_float || labs(data.i) > 0x00FF || data_length >= 2) - buf[i - start_offset + ++bytes_grown] = data.a[1]; - if (is_float || labs(data.i) > 0xFFFF || data_length >= 4) { - buf[i - start_offset + ++bytes_grown] = data.a[2]; - buf[i - start_offset + ++bytes_grown] = data.a[3]; + buf[i - start_offset + data.bytes_grown] = data.a[0]; + if (llabs(data.ll) > 0x000000FF || data.size >= 2 || data.is_float) + buf[i - start_offset + ++data.bytes_grown] = data.a[1]; + if (llabs(data.ll) > 0x0000FFFF || data.size >= 4 || data.is_float) { + buf[i - start_offset + ++data.bytes_grown] = data.a[2]; + buf[i - start_offset + ++data.bytes_grown] = data.a[3]; + } + if (llabs(data.ll) > 0xFFFFFFFF || data.size == 8) { + buf[i - start_offset + ++data.bytes_grown] = data.a[4]; + buf[i - start_offset + ++data.bytes_grown] = data.a[5]; + buf[i - start_offset + ++data.bytes_grown] = data.a[6]; + buf[i - start_offset + ++data.bytes_grown] = data.a[7]; } } // When in "fill" mode, the maximum size is already predefined if (write_mode == WRITE_MODE_FILL) - bytes_grown = 0; + data.bytes_grown = 0; - if ((addr + len + bytes_grown) > maxsize) { + if ((addr + len + data.bytes_grown) > maxsize) { avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed " "range for %s memory\n", progname, memtype); @@ -480,7 +500,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, } pgm->err_led(pgm, OFF); - for (werror=0, i=0; i < (len + bytes_grown); i++) { + for (werror=0, i=0; i < (len + data.bytes_grown); i++) { rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]); if (rc) { avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",