Esempio n. 1
0
/* Load previously loaded ihx file into device RAM and restart device */
int ezusb_write_image(usb_dev_handle * dev)
{
  struct eeprom_block *block;
  int ret;

  /* Stop the CPU while we load new code */
  if (ezusb_cpucs(dev, 0) < 0)
    return -1;

  for (block = blocks; block; block = block->next) {
    ret = ezusb_poke(dev, block->off, block->data, block->len);
    if (ret < 0)
      return -1;
  }

  /* Reset the CPU to run our downloaded code */
  if (ezusb_cpucs(dev, 1) < 0)
    return -1;

  return 0;
}
Esempio n. 2
0
/*
 * Load a firmware file into target RAM. device is the open libusbx
 * device, and the path is the name of the source file. Open the file,
 * parse the bytes, and write them in one or two phases.
 *
 * If stage == 0, this uses the first stage loader, built into EZ-USB
 * hardware but limited to writing on-chip memory or CPUCS.  Everything
 * is written during one stage, unless there's an error such as the image
 * holding data that needs to be written to external memory.
 *
 * Otherwise, things are written in two stages.  First the external
 * memory is written, expecting a second stage loader to have already
 * been loaded.  Then file is re-parsed and on-chip memory is written.
 */
int ezusb_load_ram(libusb_device_handle *device, const char *path, int fx_type, int img_type, int stage)
{
	FILE *image;
	uint32_t cpucs_addr;
	bool (*is_external)(uint32_t off, size_t len);
	struct ram_poke_context ctx;
	int status;
	uint8_t iic_header[8] = { 0 };

	if (fx_type == FX_TYPE_FX3)
		return fx3_load_ram(device, path);

	image = fopen(path, "rb");
	if (image == NULL) {
		logerror("%s: unable to open for input.\n", path);
		return -2;
	} else if (verbose > 1)
		logerror("open firmware image %s for RAM upload\n", path);

	if (img_type == IMG_TYPE_IIC) {
		if ( (fread(iic_header, 1, sizeof(iic_header), image) != sizeof(iic_header))
		  || (((fx_type == FX_TYPE_FX2LP) || (fx_type == FX_TYPE_FX2)) && (iic_header[0] != 0xC2))
		  || ((fx_type == FX_TYPE_AN21) && (iic_header[0] != 0xB2))
		  || ((fx_type == FX_TYPE_FX1) && (iic_header[0] != 0xB6)) ) {
			logerror("IIC image does not contain executable code - cannot load to RAM.\n");
			return -1;
		}
	}

	/* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
	switch(fx_type) {
	case FX_TYPE_FX2LP:
		cpucs_addr = 0xe600;
		is_external = fx2lp_is_external;
		break;
	case FX_TYPE_FX2:
		cpucs_addr = 0xe600;
		is_external = fx2_is_external;
		break;
	default:
		cpucs_addr = 0x7f92;
		is_external = fx_is_external;
		break;
	}

	/* use only first stage loader? */
	if (stage == 0) {
		ctx.mode = internal_only;

		/* if required, halt the CPU while we overwrite its code/data */
		if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
			return -1;

		/* 2nd stage, first part? loader was already uploaded */
	} else {
		ctx.mode = skip_internal;

		/* let CPU run; overwrite the 2nd stage loader later */
		if (verbose)
			logerror("2nd stage: write external memory\n");
	}

	/* scan the image, first (maybe only) time */
	ctx.device = device;
	ctx.total = ctx.count = 0;
	status = parse[img_type](image, &ctx, is_external, ram_poke);
	if (status < 0) {
		logerror("unable to upload %s\n", path);
		return status;
	}

	/* second part of 2nd stage: rescan */
	// TODO: what should we do for non HEX images there?
	if (stage) {
		ctx.mode = skip_external;

		/* if needed, halt the CPU while we overwrite the 1st stage loader */
		if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, false))
			return -1;

		/* at least write the interrupt vectors (at 0x0000) for reset! */
		rewind(image);
		if (verbose)
			logerror("2nd stage: write on-chip memory\n");
		status = parse_ihex(image, &ctx, is_external, ram_poke);
		if (status < 0) {
			logerror("unable to completely upload %s\n", path);
			return status;
		}
	}

	if (verbose)
		logerror("... WROTE: %d bytes, %d segments, avg %d\n",
		(int)ctx.total, (int)ctx.count, (int)(ctx.total/ctx.count));

	/* if required, reset the CPU so it runs what we just uploaded */
	if (cpucs_addr && !ezusb_cpucs(device, cpucs_addr, true))
		return -1;

	return 0;
}
Esempio n. 3
0
/*
 * Load an Intel HEX file into target RAM. The fd is the open "usbfs"
 * device, and the path is the name of the source file. Open the file,
 * parse the bytes, and write them in one or two phases.
 *
 * If stage == 0, this uses the first stage loader, built into EZ-USB
 * hardware but limited to writing on-chip memory or CPUCS.  Everything
 * is written during one stage, unless there's an error such as the image
 * holding data that needs to be written to external memory.
 *
 * Otherwise, things are written in two stages.  First the external
 * memory is written, expecting a second stage loader to have already
 * been loaded.  Then file is re-parsed and on-chip memory is written.
 */
int ezusb_load_ram (int fd, const char *path, int fx2, int stage)
{
    FILE			*image;
    unsigned short		cpucs_addr;
    int				(*is_external)(unsigned short off, size_t len);
    struct ram_poke_context	ctx;
    int				status;

    image = fopen (path, "r");
    if (image == 0) {
	fprintf (stderr, "%s: unable to open for input.\n", path);
	return -2;
    } else if (verbose)
	fprintf (stderr, "open RAM hexfile image %s\n", path);

    /* EZ-USB original/FX and FX2 devices differ, apart from the 8051 core */
    if (fx2) {
	cpucs_addr = 0xe600;
	is_external = fx2_is_external;
    } else {
	cpucs_addr = 0x7f92;
	is_external = fx_is_external;
    }

    /* use only first stage loader? */
    if (!stage) {
	ctx.mode = internal_only;

	/* don't let CPU run while we overwrite its code/data */
	if (!ezusb_cpucs (fd, cpucs_addr, 0))
	    return -1;

    /* 2nd stage, first part? loader was already downloaded */
    } else {
	ctx.mode = skip_internal;

	/* let CPU run; overwrite the 2nd stage loader later */
	if (verbose)
	    fprintf (stderr, "2nd stage:  write external memory\n");
    }
    
    /* scan the image, first (maybe only) time */
    ctx.device = fd;
    ctx.total = ctx.count = 0;
    status = parse_ihex (image, &ctx, is_external, ram_poke);
    if (status < 0) {
	fprintf (stderr, "unable to download %s\n", path);
	return status;
    }

    /* second part of 2nd stage: rescan */
    if (stage) {
	ctx.mode = skip_external;

	/* don't let CPU run while we overwrite the 1st stage loader */
	if (!ezusb_cpucs (fd, cpucs_addr, 0))
	    return -1;

	/* at least write the interrupt vectors (at 0x0000) for reset! */
	rewind (image);
	if (verbose)
	    fprintf (stderr, "2nd stage:  write on-chip memory\n");
	status = parse_ihex (image, &ctx, is_external, ram_poke);
	if (status < 0) {
	    fprintf (stderr, "unable to completely download %s\n", path);
	    return status;
	}
    }

    if (verbose)
	fprintf (stderr, "... WROTE: %d bytes, %d segments, avg %d\n",
	    ctx.total, ctx.count, ctx.total / ctx.count);
	
    /* now reset the CPU so it runs what we just downloaded */
    if (!ezusb_cpucs (fd, cpucs_addr, 1))
	return -1;

    return 0;
}