Example #1
0
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;
}
Example #2
0
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);
}