static bool hex_load(const char *file, long firmsize, uint8_t *image) { FILE *f; char s[0x80]; f = fopen(file, "r"); if(f == NULL){ return false; } fseek(f, 0, SEEK_SET); struct record *t = ihex_new(); bool ret = true; while(fgets(s, 0x80, f) != NULL){ if(ihex_load(s, t) == false){ ret = false; break; } ihex_write(t, firmsize, image); } ihex_destory(t); return ret; }
int main(int argc, char **argv) { unsigned int start; int bytes_count = 0; char filename[256]; memset(filename, 0, sizeof(filename)); // Parsing command line char c; action_t action = NONE; bool start_addr_specified = false, pgm_specified = false, part_specified = false, bytes_count_specified = false; memtype_t memtype = FLASH; int i; programmer_t *pgm = NULL; const stm8_device_t *part = NULL; while((c = getopt (argc, argv, "r:w:v:nc:p:s:b:luV")) != (char)-1) { switch(c) { case 'c': pgm_specified = true; for(i = 0; pgms[i].name; i++) { if(!strcmp(optarg, pgms[i].name)) pgm = &pgms[i]; } break; case 'p': part_specified = true; part = get_part(optarg); break; case 'l': for(i = 0; stm8_devices[i].name; i++) printf("%s ", stm8_devices[i].name); printf("\n"); exit(0); case 'r': action = READ; strcpy(filename, optarg); break; case 'w': action = WRITE; strcpy(filename, optarg); break; case 'v': action = VERIFY; strcpy(filename, optarg); break; case 'u': action = UNLOCK; start = 0x4800; memtype = OPT; strcpy(filename, "Workaround"); break; case 's': // Start addr is depending on MCU type if(strcasecmp(optarg, "flash") == 0) { memtype = FLASH; } else if(strcasecmp(optarg, "eeprom") == 0) { memtype = EEPROM; } else if(strcasecmp(optarg, "ram") == 0) { memtype = RAM; } else if(strcasecmp(optarg, "opt") == 0) { memtype = OPT; } else { // Start addr is specified explicitely memtype = UNKNOWN; int success = sscanf(optarg, "%x", &start); assert(success); start_addr_specified = true; } break; case 'b': bytes_count = atoi(optarg); bytes_count_specified = true; break; case 'V': print_version_and_exit( (bool)0); break; case '?': print_help_and_exit(argv[0], false); default: print_help_and_exit(argv[0], true); } } if(argc <= 1) print_help_and_exit(argv[0], true); if(pgm_specified && !pgm) { fprintf(stderr, "No valid programmer specified. Possible values are:\n"); dump_pgms( (programmer_t *) &pgms); exit(-1); } if(!pgm) spawn_error("No programmer has been specified"); if(part_specified && !part) { fprintf(stderr, "No valid part specified. Use -l to see the list of supported devices.\n"); exit(-1); } if(!part) spawn_error("No part has been specified"); // Try define memory type by address if(memtype == UNKNOWN) { if((start >= 0x4800) && (start < 0x4880)) { memtype = OPT; } if((start >= part->ram_start) && (start < part->ram_start + part->ram_size)) { memtype = RAM; } else if((start >= part->flash_start) && (start < part->flash_start + part->flash_size)) { memtype = FLASH; } else if((start >= part->eeprom_start) && (start < part->eeprom_start + part->eeprom_size)) { memtype = EEPROM; } } if(memtype != UNKNOWN) { // Selecting start addr depending on // specified part and memtype switch(memtype) { case RAM: if(!start_addr_specified) { start = part->ram_start; } if(!bytes_count_specified || bytes_count > part->ram_size) { bytes_count = part->ram_size; } fprintf(stderr, "Determine RAM area\r\n"); break; case EEPROM: if(!start_addr_specified) { start = part->eeprom_start; } if(!bytes_count_specified || bytes_count > part->eeprom_size) { bytes_count = part->eeprom_size; } fprintf(stderr, "Determine EEPROM area\r\n"); break; case FLASH: if(!start_addr_specified) { start = part->flash_start; } if(!bytes_count_specified || bytes_count > part->flash_size) { bytes_count = part->flash_size; } fprintf(stderr, "Determine FLASH area\r\n"); break; case OPT: if(!start_addr_specified) { start = 0x4800; } size_t opt_size = (part->flash_size <= 8*1024 ? 0x40 : 0x80); if(!bytes_count_specified || bytes_count > opt_size) { bytes_count = opt_size; } fprintf(stderr, "Determine OPT area\r\n"); break; } start_addr_specified = true; } if(!action) spawn_error("No action has been specified"); if(!start_addr_specified) spawn_error("No memtype or start_addr has been specified"); if (!strlen(filename)) spawn_error("No filename has been specified"); if(!action || !start_addr_specified || !strlen(filename)) print_help_and_exit(argv[0], true); if(!usb_init(pgm, pgm->usb_vid, pgm->usb_pid)) spawn_error("Couldn't initialize stlink"); if(!pgm->open(pgm)) spawn_error("Error communicating with MCU. Please check your SWIM connection."); FILE *f; if(action == READ) { fprintf(stderr, "Reading %d bytes at 0x%x... ", bytes_count, start); fflush(stderr); int bytes_count_align = ((bytes_count-1)/256+1)*256; // Reading should be done in blocks of 256 bytes unsigned char *buf = malloc(bytes_count_align); if(!buf) spawn_error("malloc failed"); int recv = pgm->read_range(pgm, part, buf, start, bytes_count_align); if(recv < bytes_count_align) { fprintf(stderr, "\r\nRequested %d bytes but received only %d.\r\n", bytes_count_align, recv); spawn_error("Failed to read MCU"); } if(!(f = fopen(filename, "w"))) spawn_error("Failed to open file"); if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) { fprintf(stderr, "Reading from Intel hex file "); ihex_write(f, buf, start, start+bytes_count); } else if(is_ext(filename, ".s19") || is_ext(filename, ".s8") || is_ext(filename, ".srec")) { printf("Reading from Motorola S-record files are not implemented (yet)\n"); printf("Exiting...\n"); exit(-1); //TODO Remove the above message and exit, and implement reading from S-record. fprintf(stderr, "Reading from Motorola S-record file "); srec_write(f, buf, start, start+bytes_count); } else { fwrite(buf, 1, bytes_count, f); } fclose(f); fprintf(stderr, "OK\n"); fprintf(stderr, "Bytes received: %d\n", bytes_count); } else if (action == VERIFY) { fprintf(stderr, "Verifing %d bytes at 0x%x... ", bytes_count, start); fflush(stderr); int bytes_count_align = ((bytes_count-1)/256+1)*256; // Reading should be done in blocks of 256 bytes unsigned char *buf = malloc(bytes_count_align); if(!buf) spawn_error("malloc failed"); int recv = pgm->read_range(pgm, part, buf, start, bytes_count_align); if(recv < bytes_count_align) { fprintf(stderr, "\r\nRequested %d bytes but received only %d.\r\n", bytes_count_align, recv); spawn_error("Failed to read MCU"); } if(!(f = fopen(filename, "r"))) spawn_error("Failed to open file"); unsigned char *buf2 = malloc(bytes_count); if(!buf2) spawn_error("malloc failed"); int bytes_to_verify; /* reading bytes to RAM */ if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) { bytes_to_verify = ihex_read(f, buf, start, start + bytes_count); } else { fseek(f, 0L, SEEK_END); bytes_to_verify = ftell(f); if(bytes_count_specified) { bytes_to_verify = bytes_count; } else if(bytes_count < bytes_to_verify) { bytes_to_verify = bytes_count; } fseek(f, 0, SEEK_SET); fread(buf2, 1, bytes_to_verify, f); } fclose(f); if(memcmp(buf, buf2, bytes_to_verify) == 0) { fprintf(stderr, "OK\n"); fprintf(stderr, "Bytes verified: %d\n", bytes_to_verify); } else { fprintf(stderr, "FAILED\n"); exit(-1); } } else if (action == WRITE) { if(!(f = fopen(filename, "r"))) spawn_error("Failed to open file"); int bytes_count_align = ((bytes_count-1)/part->flash_block_size+1)*part->flash_block_size; unsigned char *buf = malloc(bytes_count_align); if(!buf) spawn_error("malloc failed"); memset(buf, 0, bytes_count_align); // Clean aligned buffer int bytes_to_write; /* reading bytes to RAM */ if(is_ext(filename, ".ihx") || is_ext(filename, ".hex")) { fprintf(stderr, "Writing Intel hex file "); bytes_to_write = ihex_read(f, buf, start, start + bytes_count); } else if (is_ext(filename, ".s19") || is_ext(filename, ".s8") || is_ext(filename, ".srec")) { fprintf(stderr, "Writing Motorola S-record file "); bytes_to_write = srec_read(f, buf, start, start + bytes_count); } else { fprintf(stderr, "Writing binary file "); fseek(f, 0L, SEEK_END); bytes_to_write = ftell(f); if(bytes_count_specified) { bytes_to_write = bytes_count; } else if(bytes_count < bytes_to_write) { bytes_to_write = bytes_count; } fseek(f, 0, SEEK_SET); fread(buf, 1, bytes_to_write, f); } fprintf(stderr, "%d bytes at 0x%x... ", bytes_to_write, start); /* flashing MCU */ int sent = pgm->write_range(pgm, part, buf, start, bytes_to_write, memtype); if(pgm->reset) { // Restarting core (if applicable) pgm->reset(pgm); } fprintf(stderr, "OK\n"); fprintf(stderr, "Bytes written: %d\n", sent); fclose(f); } else if (action == UNLOCK) { int bytes_to_write=part->option_bytes_size; if (part->read_out_protection_mode==ROP_UNKNOWN) spawn_error("No unlocking mode defined for this device. You may need to edit the file stm8.c"); unsigned char *buf=malloc(bytes_to_write); if(!buf) spawn_error("malloc failed"); if (part->read_out_protection_mode==ROP_STM8S_STD) { for (int i=0; i<bytes_to_write;i++) { buf[i]=0; if ((i>0)&&((i&1)==0)) buf[i]=0xff; } } /* flashing MCU */ int sent = pgm->write_range(pgm, part, buf, start, bytes_to_write, memtype); if(pgm->reset) { // Restarting core (if applicable) pgm->reset(pgm); } fprintf(stderr, "Unlocked device. Option bytes reset to default state.\n"); fprintf(stderr, "Bytes written: %d\n", sent); } return(0); }