Beispiel #1
0
int jlink_spi_init(void)
{
	char *arg;
	unsigned long speed = 0;

	register_shutdown(jlink_spi_shutdown, NULL);

	arg = extract_programmer_param("spispeed");

	if (arg) {
		char *endptr;

		errno = 0;
		speed = strtoul(arg, &endptr, 10);

		if (*endptr != '\0' || errno != 0) {
			msg_perr("Invalid SPI speed specified: %s.\n", arg);
			free(arg);
			return 1;
		}

		if (speed < 1) {
			msg_perr("SPI speed must be at least 1 kHz.\n");
			free(arg);
			return 1;
		}
	}

	free(arg);

	int ret;
	bool use_serial_number;
	uint32_t serial_number;

	arg = extract_programmer_param("serial");

	if (arg) {
		if (!strlen(arg)) {
			msg_perr("Emptpy serial number specified.\n");
			free(arg);
			return 1;
		}

		ret = jaylink_parse_serial_number(arg, &serial_number);

		if (ret == JAYLINK_ERR) {
			msg_perr("Invalid serial number specified: %s.\n", arg);
			free(arg);
			return 1;
		} if (ret != JAYLINK_OK) {
			msg_perr("jaylink_parse_serial_number() failed: %s.\n", jaylink_strerror(ret));
			free(arg);
			return 1;
		}

		use_serial_number = true;
	} else {
		use_serial_number = false;
	}

	free(arg);

	reset_cs = true;
	arg = extract_programmer_param("cs");

	if (arg) {
		if (!strcasecmp(arg, "reset")) {
			reset_cs = true;
		} else if (!strcasecmp(arg, "trst")) {
			reset_cs = false;
		} else {
			msg_perr("Invalid chip select pin specified: '%s'.\n", arg);
			free(arg);
			return 1;
		}
	}

	free(arg);

	if (reset_cs)
		msg_pdbg("Using RESET as chip select signal.\n");
	else
		msg_pdbg("Using TRST as chip select signal.\n");

	ret = jaylink_init(&jaylink_ctx);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_init() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	ret = jaylink_discovery_scan(jaylink_ctx, 0);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_discover_scan() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	struct jaylink_device **devs;

	ret = jaylink_get_devices(jaylink_ctx, &devs, NULL);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_get_devices() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	if (!use_serial_number)
		msg_pdbg("No device selected, using first device.\n");

	size_t i;
	struct jaylink_device *dev;
	bool device_found = false;

	for (i = 0; devs[i]; i++) {
		if (use_serial_number) {
			uint32_t tmp;

			ret = jaylink_device_get_serial_number(devs[i], &tmp);

			if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
				continue;
			} else if (ret != JAYLINK_OK) {
				msg_pwarn("jaylink_device_get_serial_number() failed: %s.\n",
					jaylink_strerror(ret));
				continue;
			}

			if (serial_number != tmp)
				continue;
		}

		ret = jaylink_open(devs[i], &jaylink_devh);

		if (ret == JAYLINK_OK) {
			dev = devs[i];
			device_found = true;
			break;
		}

		jaylink_devh = NULL;
	}

	jaylink_free_devices(devs, true);

	if (!device_found) {
		msg_perr("No J-Link device found.\n");
		return 1;
	}

	size_t length;
	char *firmware_version;

	ret = jaylink_get_firmware_version(jaylink_devh, &firmware_version,
		&length);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_get_firmware_version() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	} else if (length > 0) {
		msg_pdbg("Firmware: %s\n", firmware_version);
		free(firmware_version);
	}

	ret = jaylink_device_get_serial_number(dev, &serial_number);

	if (ret == JAYLINK_OK) {
		msg_pdbg("S/N: %" PRIu32 "\n", serial_number);
	} else if (ret == JAYLINK_ERR_NOT_AVAILABLE) {
		msg_pdbg("S/N: N/A\n");
	} else {
		msg_perr("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE];

	memset(caps, 0, sizeof(caps));
	ret = jaylink_get_caps(jaylink_devh, caps);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_get_caps() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
		ret = jaylink_get_extended_caps(jaylink_devh, caps);

		if (ret != JAYLINK_OK) {
			msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret));
			return 1;
		}
	}

	uint32_t ifaces;

	ret = jaylink_get_available_interfaces(jaylink_devh, &ifaces);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	if (!(ifaces & (1 << JAYLINK_TIF_JTAG))) {
		msg_perr("Device does not support JTAG interface.\n");
		return 1;
	}

	ret = jaylink_select_interface(jaylink_devh, JAYLINK_TIF_JTAG, NULL);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_select_interface() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	struct jaylink_hardware_status hwstat;

	ret = jaylink_get_hardware_status(jaylink_devh, &hwstat);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_get_hardware_status() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	msg_pdbg("VTarget: %u.%03u V\n", hwstat.target_voltage / 1000,
		hwstat.target_voltage % 1000);

	if (hwstat.target_voltage < MIN_TARGET_VOLTAGE) {
		msg_perr("Target voltage is below %u.%03u V. You need to attach VTref to the I/O voltage of "
			"the chip.\n", MIN_TARGET_VOLTAGE / 1000, MIN_TARGET_VOLTAGE % 1000);
		return 1;
	}

	struct jaylink_speed device_speeds;

	device_speeds.freq = DEFAULT_FREQ;
	device_speeds.div = DEFAULT_FREQ_DIV;

	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) {
		ret = jaylink_get_speeds(jaylink_devh, &device_speeds);

		if (ret != JAYLINK_OK) {
			msg_perr("jaylink_get_speeds() failed: %s.\n", jaylink_strerror(ret));
			return 1;
		}
	}

	device_speeds.freq /= 1000;

	msg_pdbg("Maximum SPI speed: %" PRIu32 " kHz\n", device_speeds.freq / device_speeds.div);

	if (!speed) {
		speed = device_speeds.freq / device_speeds.div;
		msg_pdbg("SPI speed not specified, using %lu kHz.\n", speed);
	}

	if (speed > (device_speeds.freq / device_speeds.div)) {
		msg_perr("Specified SPI speed of %lu kHz is too high. Maximum is %" PRIu32 " kHz.\n", speed,
			device_speeds.freq / device_speeds.div);
		return 1;
	}

	ret = jaylink_set_speed(jaylink_devh, speed);

	if (ret != JAYLINK_OK) {
		msg_perr("jaylink_set_speed() failed: %s.\n", jaylink_strerror(ret));
		return 1;
	}

	msg_pdbg("SPI speed: %lu kHz\n", speed);

	/* Ensure that the CS signal is not active initially. */
	if (!deassert_cs())
		return 1;

	register_spi_master(&spi_master_jlink_spi);

	return 0;
}
Beispiel #2
0
static int jlink_init(void)
{
	int ret;
	struct jaylink_device **devs;
	unsigned int i;
	bool found_device;
	uint32_t tmp;
	char *firmware_version;
	struct jaylink_hardware_version hwver;
	struct jaylink_hardware_status hwstatus;

	ret = jaylink_init(&jayctx);

	if (ret != JAYLINK_OK) {
		LOG_ERROR("jaylink_init() failed: %s.",
			jaylink_strerror_name(ret));
		return ERROR_JTAG_INIT_FAILED;
	}

	ret = jaylink_get_device_list(jayctx, &devs);

	if (ret < 0) {
		LOG_ERROR("jaylink_get_device_list() failed: %s.",
			jaylink_strerror_name(ret));
		jaylink_exit(jayctx);
		return ERROR_JTAG_INIT_FAILED;
	}

	found_device = false;

	if (!use_serial_number && !use_usb_address)
		LOG_INFO("No device selected, using first device.");

	for (i = 0; devs[i]; i++) {
		jaylink_device_get_serial_number(devs[i], &tmp);
		ret = jaylink_device_get_usb_address(devs[i]);

		if (use_usb_address && usb_address != ret)
			continue;

		if (use_serial_number && tmp != serial_number)
			continue;

		ret = jaylink_open(devs[i], &devh);

		if (ret != JAYLINK_OK) {
			LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret));
			continue;
		}

		found_device = true;
		break;
	}

	jaylink_free_device_list(devs, 1);

	if (!found_device) {
		LOG_ERROR("No J-Link device found.");
		jaylink_exit(jayctx);
		return ERROR_JTAG_INIT_FAILED;
	}

	/*
	 * Be careful with changing the following initialization sequence because
	 * some devices are known to be sensitive regarding the order.
	 */

	ret = jaylink_get_firmware_version(devh, &firmware_version);

	if (ret > 0) {
		LOG_INFO("%s", firmware_version);
		free(firmware_version);
	} else if (!ret) {
		LOG_WARNING("Device responds empty firmware version string.");
	} else {
		LOG_ERROR("jaylink_get_firmware_version() failed: %s.",
			jaylink_strerror_name(ret));
		jaylink_close(devh);
		jaylink_exit(jayctx);
		return ERROR_JTAG_INIT_FAILED;
	}

	memset(caps, 0, JAYLINK_DEV_EXT_CAPS_SIZE);
	ret = jaylink_get_caps(devh, caps);

	if (ret != JAYLINK_OK) {
		LOG_ERROR("jaylink_get_caps() failed: %s.", jaylink_strerror_name(ret));
		jaylink_close(devh);
		jaylink_exit(jayctx);
		return ERROR_JTAG_INIT_FAILED;
	}

	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
		ret = jaylink_get_extended_caps(devh, caps);

		if (ret != JAYLINK_OK) {
			LOG_ERROR("jaylink_get_extended_caps() failed:  %s.",
				jaylink_strerror_name(ret));
			jaylink_close(devh);
			jaylink_exit(jayctx);
			return ERROR_JTAG_INIT_FAILED;
		}
	}

	jtag_command_version = JAYLINK_JTAG_V2;

	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) {
		ret = jaylink_get_hardware_version(devh, &hwver);

		if (ret != JAYLINK_OK) {
			LOG_ERROR("Failed to retrieve hardware version: %s.",
				jaylink_strerror_name(ret));
			jaylink_close(devh);
			jaylink_exit(jayctx);
			return ERROR_JTAG_INIT_FAILED;
		}

		LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor);

		if (hwver.major >= 5)
			jtag_command_version = JAYLINK_JTAG_V3;
	}

	if (iface == JAYLINK_TIF_SWD) {
		/*
		 * Adjust the SWD transaction buffer size in case there is already
		 * allocated memory on the device. This happens for example if the
		 * memory for SWO capturing is still allocated because the software
		 * which used the device before has not been shut down properly.
		 */
		if (!adjust_swd_buffer_size()) {
			jaylink_close(devh);
			jaylink_exit(jayctx);
			return ERROR_JTAG_INIT_FAILED;
		}
	}

	if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) {
		if (!read_device_config(&config)) {
			LOG_ERROR("Failed to read device configuration data.");
			jaylink_close(devh);
			jaylink_exit(jayctx);
			return ERROR_JTAG_INIT_FAILED;
		}

		memcpy(&tmp_config, &config, sizeof(struct device_config));
	}

	ret = jaylink_get_hardware_status(devh, &hwstatus);

	if (ret != JAYLINK_OK) {
		LOG_ERROR("jaylink_get_hardware_status() failed: %s.",
			jaylink_strerror_name(ret));
		jaylink_close(devh);
		jaylink_exit(jayctx);
		return ERROR_JTAG_INIT_FAILED;
	}

	LOG_INFO("VTarget = %u.%03u V", hwstatus.target_voltage / 1000,
		hwstatus.target_voltage % 1000);

	conn.handle = 0;
	conn.pid = 0;
	conn.hid = 0;
	conn.iid = 0;
	conn.cid = 0;

	ret = jlink_register();

	if (ret != ERROR_OK) {
		jaylink_close(devh);
		jaylink_exit(jayctx);
		return ERROR_JTAG_INIT_FAILED;
	}

	ret = select_interface();

	if (ret != ERROR_OK) {
		jaylink_close(devh);
		jaylink_exit(jayctx);
		return ret;
	}

	jlink_reset(0, 0);
	jtag_sleep(3000);
	jlink_tap_init();

	jlink_speed(jtag_get_speed_khz());

	if (iface == JAYLINK_TIF_JTAG) {
		/*
		 * J-Link devices with firmware version v5 and v6 seems to have an issue
		 * if the first tap move is not divisible by 8, so we send a TLR on
		 * first power up.
		 */
		uint8_t tms = 0xff;
		jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 8);

		jlink_flush();
	}

	return ERROR_OK;
}