X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fjlink.c;h=09b3a858bcc1203d02c5144b2f59e994987e6737;hb=refs%2Fchanges%2F91%2F4891%2F3;hp=cda51bc0ce8bd0d50305e9fe454a160cfb049282;hpb=d0e763ac7ef6aa17b17bd00ccdfbccfb4eacda69;p=openocd.git diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index cda51bc0ce..09b3a858bc 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -50,6 +51,7 @@ static uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE]; static uint32_t serial_number; static bool use_serial_number; +static bool use_usb_location; static enum jaylink_usb_address usb_address; static bool use_usb_address; static enum jaylink_target_interface iface = JAYLINK_TIF_JTAG; @@ -122,13 +124,13 @@ static int queued_retval; static void jlink_execute_stableclocks(struct jtag_command *cmd) { - DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + LOG_DEBUG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); jlink_stableclocks(cmd->cmd.runtest->num_cycles); } static void jlink_execute_runtest(struct jtag_command *cmd) { - DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); jlink_end_state(cmd->cmd.runtest->end_state); @@ -137,7 +139,7 @@ static void jlink_execute_runtest(struct jtag_command *cmd) static void jlink_execute_statemove(struct jtag_command *cmd) { - DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state); + LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state); jlink_end_state(cmd->cmd.statemove->end_state); jlink_state_move(); @@ -145,7 +147,7 @@ static void jlink_execute_statemove(struct jtag_command *cmd) static void jlink_execute_pathmove(struct jtag_command *cmd) { - DEBUG_JTAG_IO("pathmove: %i states, end in %i", + LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); @@ -154,7 +156,7 @@ static void jlink_execute_pathmove(struct jtag_command *cmd) static void jlink_execute_scan(struct jtag_command *cmd) { - DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", + LOG_DEBUG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", jtag_scan_type(cmd->cmd.scan)); /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */ @@ -188,7 +190,7 @@ static void jlink_execute_scan(struct jtag_command *cmd) for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { scan_size += field->num_bits; - DEBUG_JTAG_IO("%s%s field %d/%d %d bits", + LOG_DEBUG_IO("%s%s field %d/%d %d bits", field->in_value ? "in" : "", field->out_value ? "out" : "", i, @@ -217,7 +219,7 @@ static void jlink_execute_scan(struct jtag_command *cmd) field->num_bits - 1, 1); tap_set_state(tap_state_transition(tap_get_state(), 1)); - jlink_clock_data(&last_bit, + jlink_clock_data(NULL, 0, &tms_bits, 1, @@ -240,14 +242,14 @@ static void jlink_execute_scan(struct jtag_command *cmd) jlink_state_move(); } - DEBUG_JTAG_IO("%s scan, %i bits, end in %s", + LOG_DEBUG_IO("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, tap_state_name(tap_get_end_state())); } static void jlink_execute_reset(struct jtag_command *cmd) { - DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, + LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); jlink_flush(); @@ -257,7 +259,7 @@ static void jlink_execute_reset(struct jtag_command *cmd) static void jlink_execute_sleep(struct jtag_command *cmd) { - DEBUG_JTAG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us); + LOG_DEBUG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us); jlink_flush(); jtag_sleep(cmd->cmd.sleep->us); } @@ -314,21 +316,20 @@ static int jlink_execute_queue(void) static int jlink_speed(int speed) { int ret; - uint32_t freq; - uint16_t divider; + struct jaylink_speed tmp; int max_speed; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) { - ret = jaylink_get_speeds(devh, &freq, ÷r); + ret = jaylink_get_speeds(devh, &tmp); if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_speeds() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_JTAG_DEVICE_ERROR; } - freq = freq / 1000; - max_speed = freq / divider; + tmp.freq /= 1000; + max_speed = tmp.freq / tmp.div; } else { max_speed = JLINK_MAX_SPEED; } @@ -350,7 +351,7 @@ static int jlink_speed(int speed) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_set_speed() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_JTAG_DEVICE_ERROR; } @@ -379,7 +380,7 @@ static bool read_device_config(struct device_config *cfg) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_read_raw_config() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return false; } @@ -410,7 +411,7 @@ static int select_interface(void) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_available_interfaces() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_JTAG_INIT_FAILED; } @@ -423,7 +424,7 @@ static int select_interface(void) if (ret < 0) { LOG_ERROR("jaylink_select_interface() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_JTAG_INIT_FAILED; } @@ -433,23 +434,23 @@ static int select_interface(void) static int jlink_register(void) { int ret; - int i; + size_t i; bool handle_found; + size_t count; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) return ERROR_OK; - ret = jaylink_register(devh, &conn, connlist, NULL, NULL); + ret = jaylink_register(devh, &conn, connlist, &count); - if (ret < 0) { - LOG_ERROR("jaylink_register() failed: %s.", - jaylink_strerror_name(ret)); + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_register() failed: %s.", jaylink_strerror(ret)); return ERROR_FAIL; } handle_found = false; - for (i = 0; i < ret; i++) { + for (i = 0; i < count; i++) { if (connlist[i].handle == conn.handle) { handle_found = true; break; @@ -482,7 +483,7 @@ static bool adjust_swd_buffer_size(void) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_free_memory() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return false; } @@ -502,6 +503,64 @@ static bool adjust_swd_buffer_size(void) return true; } +static int jaylink_log_handler(const struct jaylink_context *ctx, + enum jaylink_log_level level, const char *format, va_list args, + void *user_data) +{ + enum log_levels tmp; + + switch (level) { + case JAYLINK_LOG_LEVEL_ERROR: + tmp = LOG_LVL_ERROR; + break; + case JAYLINK_LOG_LEVEL_WARNING: + tmp = LOG_LVL_WARNING; + break; + /* + * Forward info messages to the debug output because they are more verbose + * than info messages of OpenOCD. + */ + case JAYLINK_LOG_LEVEL_INFO: + case JAYLINK_LOG_LEVEL_DEBUG: + tmp = LOG_LVL_DEBUG; + break; + case JAYLINK_LOG_LEVEL_DEBUG_IO: + tmp = LOG_LVL_DEBUG_IO; + break; + default: + tmp = LOG_LVL_WARNING; + } + + log_vprintf_lf(tmp, __FILE__, __LINE__, __func__, format, args); + + return 0; +} + +static bool jlink_usb_location_equal(struct jaylink_device *dev) +{ + int retval; + uint8_t bus; + uint8_t *ports; + size_t num_ports; + bool equal = false; + + retval = jaylink_device_get_usb_bus_ports(dev, &bus, &ports, &num_ports); + + if (retval == JAYLINK_ERR_NOT_SUPPORTED) { + return false; + } else if (retval != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_usb_bus_ports() failed: %s.", + jaylink_strerror(retval)); + return false; + } + + equal = jtag_usb_location_equal(bus, ports, num_ports); + free(ports); + + return equal; +} + + static int jlink_init(void) { int ret; @@ -514,38 +573,77 @@ static int jlink_init(void) struct jaylink_hardware_status hwstatus; enum jaylink_usb_address address; size_t length; + size_t num_devices; + uint32_t host_interfaces; + + LOG_DEBUG("Using libjaylink %s (compiled with %s).", + jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING); + + if (!jaylink_library_has_cap(JAYLINK_CAP_HIF_USB) && use_usb_address) { + LOG_ERROR("J-Link driver does not support USB devices."); + return ERROR_JTAG_INIT_FAILED; + } ret = jaylink_init(&jayctx); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_init() failed: %s.", - jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_init() failed: %s.", jaylink_strerror(ret)); return ERROR_JTAG_INIT_FAILED; } - ret = jaylink_get_device_list(jayctx, &devs); + ret = jaylink_log_set_callback(jayctx, &jaylink_log_handler, NULL); - if (ret < 0) { - LOG_ERROR("jaylink_get_device_list() failed: %s.", - jaylink_strerror_name(ret)); + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_log_set_callback() failed: %s.", + jaylink_strerror(ret)); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; } - found_device = false; + host_interfaces = JAYLINK_HIF_USB; - if (!use_serial_number && !use_usb_address) - LOG_INFO("No device selected, using first device."); + if (use_serial_number) + host_interfaces |= JAYLINK_HIF_TCP; + + ret = jaylink_discovery_scan(jayctx, host_interfaces); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_discovery_scan() failed: %s.", + jaylink_strerror(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + ret = jaylink_get_devices(jayctx, &devs, &num_devices); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + use_usb_location = (jtag_usb_get_location() != NULL); + + if (!use_serial_number && !use_usb_address && !use_usb_location && num_devices > 1) { + LOG_ERROR("Multiple devices found, specify the desired device."); + jaylink_free_devices(devs, true); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + found_device = false; for (i = 0; devs[i]; i++) { + struct jaylink_device *dev = devs[i]; + if (use_serial_number) { - ret = jaylink_device_get_serial_number(devs[i], &tmp); + ret = jaylink_device_get_serial_number(dev, &tmp); if (ret == JAYLINK_ERR_NOT_AVAILABLE) { continue; } else if (ret != JAYLINK_OK) { LOG_WARNING("jaylink_device_get_serial_number() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); continue; } @@ -554,11 +652,13 @@ static int jlink_init(void) } if (use_usb_address) { - ret = jaylink_device_get_usb_address(devs[i], &address); + ret = jaylink_device_get_usb_address(dev, &address); - if (ret != JAYLINK_OK) { + if (ret == JAYLINK_ERR_NOT_SUPPORTED) { + continue; + } else if (ret != JAYLINK_OK) { LOG_WARNING("jaylink_device_get_usb_address() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); continue; } @@ -566,17 +666,20 @@ static int jlink_init(void) continue; } - ret = jaylink_open(devs[i], &devh); + if (use_usb_location && !jlink_usb_location_equal(dev)) + continue; + + ret = jaylink_open(dev, &devh); if (ret == JAYLINK_OK) { found_device = true; break; } - LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret)); + LOG_ERROR("Failed to open device: %s.", jaylink_strerror(ret)); } - jaylink_free_device_list(devs, 1); + jaylink_free_devices(devs, true); if (!found_device) { LOG_ERROR("No J-Link device found."); @@ -593,7 +696,7 @@ static int jlink_init(void) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_firmware_version() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); jaylink_close(devh); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -608,7 +711,7 @@ static int jlink_init(void) ret = jaylink_get_caps(devh, caps); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_get_caps() failed: %s.", jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_get_caps() failed: %s.", jaylink_strerror(ret)); jaylink_close(devh); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -619,21 +722,21 @@ static int jlink_init(void) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_extended_caps() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); jaylink_close(devh); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; } } - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; 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_strerror(ret)); jaylink_close(devh); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -642,7 +745,7 @@ static int jlink_init(void) LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor); if (hwver.major >= 5) - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; } if (iface == JAYLINK_TIF_SWD) { @@ -674,7 +777,7 @@ static int jlink_init(void) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_hardware_status() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); jaylink_close(devh); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -685,7 +788,7 @@ static int jlink_init(void) conn.handle = 0; conn.pid = 0; - conn.hid = 0; + strcpy(conn.hid, "0.0.0.0"); conn.iid = 0; conn.cid = 0; @@ -729,21 +832,21 @@ static int jlink_init(void) static int jlink_quit(void) { int ret; + size_t count; if (trace_enabled) { ret = jaylink_swo_stop(devh); if (ret != JAYLINK_OK) - LOG_ERROR("jaylink_swo_stop() failed: %s.", - jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror(ret)); } if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) { - ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL); + ret = jaylink_unregister(devh, &conn, connlist, &count); - if (ret < 0) + if (ret != JAYLINK_OK) LOG_ERROR("jaylink_unregister() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); } jaylink_close(devh); @@ -854,17 +957,17 @@ COMMAND_HANDLER(jlink_usb_command) int tmp; if (CMD_ARGC != 1) { - command_print(CMD_CTX, "Need exactly one argument for jlink usb."); + command_print(CMD, "Need exactly one argument for jlink usb."); return ERROR_COMMAND_SYNTAX_ERROR; } if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { - command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid USB address: %s.", CMD_ARGV[0]); return ERROR_FAIL; } if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) { - command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid USB address: %s.", CMD_ARGV[0]); return ERROR_FAIL; } @@ -878,13 +981,21 @@ COMMAND_HANDLER(jlink_usb_command) COMMAND_HANDLER(jlink_serial_command) { + int ret; + if (CMD_ARGC != 1) { - command_print(CMD_CTX, "Need exactly one argument for jlink serial."); + command_print(CMD, "Need exactly one argument for jlink serial."); return ERROR_COMMAND_SYNTAX_ERROR; } - if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) { - command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]); + ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number); + + if (ret == JAYLINK_ERR) { + command_print(CMD, "Invalid serial number: %s.", CMD_ARGV[0]); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + command_print(CMD, "jaylink_parse_serial_number() failed: %s.", + jaylink_strerror(ret)); return ERROR_FAIL; } @@ -902,20 +1013,20 @@ COMMAND_HANDLER(jlink_handle_hwstatus_command) ret = jaylink_get_hardware_status(devh, &status); if (ret != JAYLINK_OK) { - command_print(CMD_CTX, "jaylink_get_hardware_status() failed: %s.", - jaylink_strerror_name(ret)); + command_print(CMD, "jaylink_get_hardware_status() failed: %s.", + jaylink_strerror(ret)); return ERROR_FAIL; } - command_print(CMD_CTX, "VTarget = %u.%03u V", + command_print(CMD, "VTarget = %u.%03u V", status.target_voltage / 1000, status.target_voltage % 1000); - command_print(CMD_CTX, "TCK = %u TDI = %u TDO = %u TMS = %u SRST = %u " + command_print(CMD, "TCK = %u TDI = %u TDO = %u TMS = %u SRST = %u " "TRST = %u", status.tck, status.tdi, status.tdo, status.tms, status.tres, status.trst); if (status.target_voltage < 1500) - command_print(CMD_CTX, "Target voltage too low. Check target power."); + command_print(CMD, "Target voltage too low. Check target power."); return ERROR_OK; } @@ -926,7 +1037,7 @@ COMMAND_HANDLER(jlink_handle_free_memory_command) uint32_t tmp; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_FREE_MEMORY)) { - command_print(CMD_CTX, "Retrieval of free memory is not supported by " + command_print(CMD, "Retrieval of free memory is not supported by " "the device."); return ERROR_OK; } @@ -934,12 +1045,12 @@ COMMAND_HANDLER(jlink_handle_free_memory_command) ret = jaylink_get_free_memory(devh, &tmp); if (ret != JAYLINK_OK) { - command_print(CMD_CTX, "jaylink_get_free_memory() failed: %s.", - jaylink_strerror_name(ret)); + command_print(CMD, "jaylink_get_free_memory() failed: %s.", + jaylink_strerror(ret)); return ERROR_FAIL; } - command_print(CMD_CTX, "Device has %u bytes of free memory.", tmp); + command_print(CMD, "Device has %u bytes of free memory.", tmp); return ERROR_OK; } @@ -951,36 +1062,36 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) if (!CMD_ARGC) { switch (jtag_command_version) { - case JAYLINK_JTAG_V2: + case JAYLINK_JTAG_VERSION_2: version = 2; break; - case JAYLINK_JTAG_V3: + case JAYLINK_JTAG_VERSION_3: version = 3; break; default: return ERROR_FAIL; } - command_print(CMD_CTX, "JTAG command version: %i", version); + command_print(CMD, "JTAG command version: %i", version); } else if (CMD_ARGC == 1) { if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { - command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid argument: %s.", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } switch (tmp) { case 2: - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; break; case 3: - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; break; default: - command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid argument: %s.", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; } } else { - command_print(CMD_CTX, "Need exactly one argument for jlink jtag."); + command_print(CMD, "Need exactly one argument for jlink jtag."); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -993,13 +1104,13 @@ COMMAND_HANDLER(jlink_handle_target_power_command) int enable; if (CMD_ARGC != 1) { - command_print(CMD_CTX, "Need exactly one argument for jlink " + command_print(CMD, "Need exactly one argument for jlink " "targetpower."); return ERROR_COMMAND_SYNTAX_ERROR; } if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) { - command_print(CMD_CTX, "Target power supply is not supported by the " + command_print(CMD, "Target power supply is not supported by the " "device."); return ERROR_OK; } @@ -1009,64 +1120,64 @@ COMMAND_HANDLER(jlink_handle_target_power_command) } else if (!strcmp(CMD_ARGV[0], "off")) { enable = false; } else { - command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid argument: %s.", CMD_ARGV[0]); return ERROR_FAIL; } ret = jaylink_set_target_power(devh, enable); if (ret != JAYLINK_OK) { - command_print(CMD_CTX, "jaylink_set_target_power() failed: %s.", - jaylink_strerror_name(ret)); + command_print(CMD, "jaylink_set_target_power() failed: %s.", + jaylink_strerror(ret)); return ERROR_FAIL; } return ERROR_OK; } -static void show_config_usb_address(struct command_context *ctx) +static void show_config_usb_address(struct command_invocation *cmd) { if (config.usb_address != tmp_config.usb_address) - command_print(ctx, "USB address: %u [%u]", config.usb_address, + command_print(cmd, "USB address: %u [%u]", config.usb_address, tmp_config.usb_address); else - command_print(ctx, "USB address: %u", config.usb_address); + command_print(cmd, "USB address: %u", config.usb_address); } -static void show_config_ip_address(struct command_context *ctx) +static void show_config_ip_address(struct command_invocation *cmd) { if (!memcmp(config.ip_address, tmp_config.ip_address, 4)) - command_print(ctx, "IP address: %d.%d.%d.%d", + command_print(cmd, "IP address: %d.%d.%d.%d", config.ip_address[3], config.ip_address[2], config.ip_address[1], config.ip_address[0]); else - command_print(ctx, "IP address: %d.%d.%d.%d [%d.%d.%d.%d]", + command_print(cmd, "IP address: %d.%d.%d.%d [%d.%d.%d.%d]", config.ip_address[3], config.ip_address[2], config.ip_address[1], config.ip_address[0], tmp_config.ip_address[3], tmp_config.ip_address[2], tmp_config.ip_address[1], tmp_config.ip_address[0]); if (!memcmp(config.subnet_mask, tmp_config.subnet_mask, 4)) - command_print(ctx, "Subnet mask: %d.%d.%d.%d", + command_print(cmd, "Subnet mask: %d.%d.%d.%d", config.subnet_mask[3], config.subnet_mask[2], config.subnet_mask[1], config.subnet_mask[0]); else - command_print(ctx, "Subnet mask: %d.%d.%d.%d [%d.%d.%d.%d]", + command_print(cmd, "Subnet mask: %d.%d.%d.%d [%d.%d.%d.%d]", config.subnet_mask[3], config.subnet_mask[2], config.subnet_mask[1], config.subnet_mask[0], tmp_config.subnet_mask[3], tmp_config.subnet_mask[2], tmp_config.subnet_mask[1], tmp_config.subnet_mask[0]); } -static void show_config_mac_address(struct command_context *ctx) +static void show_config_mac_address(struct command_invocation *cmd) { if (!memcmp(config.mac_address, tmp_config.mac_address, 6)) - command_print(ctx, "MAC address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x", + command_print(cmd, "MAC address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x", config.mac_address[5], config.mac_address[4], config.mac_address[3], config.mac_address[2], config.mac_address[1], config.mac_address[0]); else - command_print(ctx, "MAC address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x " + command_print(cmd, "MAC address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x " "[%.02x:%.02x:%.02x:%.02x:%.02x:%.02x]", config.mac_address[5], config.mac_address[4], config.mac_address[3], config.mac_address[2], @@ -1076,7 +1187,7 @@ static void show_config_mac_address(struct command_context *ctx) tmp_config.mac_address[1], tmp_config.mac_address[0]); } -static void show_config_target_power(struct command_context *ctx) +static void show_config_target_power(struct command_invocation *cmd) { const char *target_power; const char *current_target_power; @@ -1092,24 +1203,24 @@ static void show_config_target_power(struct command_context *ctx) current_target_power = "on"; if (config.target_power != tmp_config.target_power) - command_print(ctx, "Target power supply: %s [%s]", target_power, + command_print(cmd, "Target power supply: %s [%s]", target_power, current_target_power); else - command_print(ctx, "Target power supply: %s", target_power); + command_print(cmd, "Target power supply: %s", target_power); } -static void show_config(struct command_context *ctx) +static void show_config(struct command_invocation *cmd) { - command_print(ctx, "J-Link device configuration:"); + command_print(cmd, "J-Link device configuration:"); - show_config_usb_address(ctx); + show_config_usb_address(cmd); if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) - show_config_target_power(ctx); + show_config_target_power(cmd); if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_ETHERNET)) { - show_config_ip_address(ctx); - show_config_mac_address(ctx); + show_config_ip_address(cmd); + show_config_mac_address(cmd); } } @@ -1123,7 +1234,7 @@ static int poll_trace(uint8_t *buf, size_t *size) ret = jaylink_swo_read(devh, buf, &length); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_swo_read() failed: %s.", jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_swo_read() failed: %s.", jaylink_strerror(ret)); return ERROR_FAIL; } @@ -1144,7 +1255,7 @@ static uint32_t calculate_trace_buffer_size(void) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_free_memory() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_FAIL; } @@ -1186,7 +1297,7 @@ static bool check_trace_freq(struct jaylink_swo_speed speed, return false; } -static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, +static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { int ret; @@ -1198,7 +1309,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, return ERROR_FAIL; } - if (pin_protocol != ASYNC_UART) { + if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) { LOG_ERROR("Selected pin protocol is not supported."); return ERROR_FAIL; } @@ -1208,7 +1319,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, ret = jaylink_swo_stop(devh); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_swo_stop() failed: %s.", jaylink_strerror(ret)); return ERROR_FAIL; } @@ -1234,7 +1345,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_swo_get_speeds() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_FAIL; } @@ -1250,8 +1361,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, buffer_size); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_start_swo() failed: %s.", - jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_start_swo() failed: %s.", jaylink_strerror(ret)); return ERROR_FAIL; } @@ -1270,27 +1380,27 @@ COMMAND_HANDLER(jlink_handle_config_usb_address_command) uint8_t tmp; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { - command_print(CMD_CTX, "Reading configuration is not supported by the " + command_print(CMD, "Reading configuration is not supported by the " "device."); return ERROR_OK; } if (!CMD_ARGC) { - show_config_usb_address(CMD_CTX); + show_config_usb_address(CMD); } else if (CMD_ARGC == 1) { if (sscanf(CMD_ARGV[0], "%" SCNd8, &tmp) != 1) { - command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid USB address: %s.", CMD_ARGV[0]); return ERROR_FAIL; } if (tmp > JAYLINK_USB_ADDRESS_3) { - command_print(CMD_CTX, "Invalid USB address: %u.", tmp); + command_print(CMD, "Invalid USB address: %u.", tmp); return ERROR_FAIL; } tmp_config.usb_address = tmp; } else { - command_print(CMD_CTX, "Need exactly one argument for jlink config " + command_print(CMD, "Need exactly one argument for jlink config " "usb."); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1303,32 +1413,32 @@ COMMAND_HANDLER(jlink_handle_config_target_power_command) int enable; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { - command_print(CMD_CTX, "Reading configuration is not supported by the " + command_print(CMD, "Reading configuration is not supported by the " "device."); return ERROR_OK; } if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) { - command_print(CMD_CTX, "Target power supply is not supported by the " + command_print(CMD, "Target power supply is not supported by the " "device."); return ERROR_OK; } if (!CMD_ARGC) { - show_config_target_power(CMD_CTX); + show_config_target_power(CMD); } else if (CMD_ARGC == 1) { if (!strcmp(CMD_ARGV[0], "on")) { enable = true; } else if (!strcmp(CMD_ARGV[0], "off")) { enable = false; } else { - command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); + command_print(CMD, "Invalid argument: %s.", CMD_ARGV[0]); return ERROR_FAIL; } tmp_config.target_power = enable; } else { - command_print(CMD_CTX, "Need exactly one argument for jlink config " + command_print(CMD, "Need exactly one argument for jlink config " "targetpower."); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1344,25 +1454,25 @@ COMMAND_HANDLER(jlink_handle_config_mac_address_command) const char *str; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { - command_print(CMD_CTX, "Reading configuration is not supported by the " + command_print(CMD, "Reading configuration is not supported by the " "device."); return ERROR_OK; } if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_ETHERNET)) { - command_print(CMD_CTX, "Ethernet connectivity is not supported by the " + command_print(CMD, "Ethernet connectivity is not supported by the " "device."); return ERROR_OK; } if (!CMD_ARGC) { - show_config_mac_address(CMD_CTX); + show_config_mac_address(CMD); } else if (CMD_ARGC == 1) { str = CMD_ARGV[0]; if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || \ str[8] != ':' || str[11] != ':' || str[14] != ':')) { - command_print(CMD_CTX, "Invalid MAC address format."); + command_print(CMD, "Invalid MAC address format."); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1372,18 +1482,18 @@ COMMAND_HANDLER(jlink_handle_config_mac_address_command) } if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) { - command_print(CMD_CTX, "Invalid MAC address: zero address."); + command_print(CMD, "Invalid MAC address: zero address."); return ERROR_COMMAND_SYNTAX_ERROR; } if (!(0x01 & addr[0])) { - command_print(CMD_CTX, "Invalid MAC address: multicast address."); + command_print(CMD, "Invalid MAC address: multicast address."); return ERROR_COMMAND_SYNTAX_ERROR; } memcpy(tmp_config.mac_address, addr, sizeof(addr)); } else { - command_print(CMD_CTX, "Need exactly one argument for jlink config " + command_print(CMD, "Need exactly one argument for jlink config " " mac."); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1432,19 +1542,19 @@ COMMAND_HANDLER(jlink_handle_config_ip_address_command) uint8_t subnet_bits = 24; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { - command_print(CMD_CTX, "Reading configuration is not supported by the " + command_print(CMD, "Reading configuration is not supported by the " "device."); return ERROR_OK; } if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_ETHERNET)) { - command_print(CMD_CTX, "Ethernet connectivity is not supported by the " + command_print(CMD, "Ethernet connectivity is not supported by the " "device."); return ERROR_OK; } if (!CMD_ARGC) { - show_config_ip_address(CMD_CTX); + show_config_ip_address(CMD); } else { if (!string_to_ip(CMD_ARGV[0], ip_address, &i)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -1489,19 +1599,19 @@ COMMAND_HANDLER(jlink_handle_config_write_command) int ret; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { - command_print(CMD_CTX, "Reading configuration is not supported by the " + command_print(CMD, "Reading configuration is not supported by the " "device."); return ERROR_OK; } if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_WRITE_CONFIG)) { - command_print(CMD_CTX, "Writing configuration is not supported by the " + command_print(CMD, "Writing configuration is not supported by the " "device."); return ERROR_OK; } if (!memcmp(&config, &tmp_config, sizeof(struct device_config))) { - command_print(CMD_CTX, "Operation not performed due to no changes in " + command_print(CMD, "Operation not performed due to no changes in " "the configuration."); return ERROR_OK; } @@ -1510,7 +1620,7 @@ COMMAND_HANDLER(jlink_handle_config_write_command) if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_write_raw_config() failed: %s.", - jaylink_strerror_name(ret)); + jaylink_strerror(ret)); return ERROR_FAIL; } @@ -1526,7 +1636,7 @@ COMMAND_HANDLER(jlink_handle_config_write_command) } memcpy(&tmp_config, &config, sizeof(struct device_config)); - command_print(CMD_CTX, "The new device configuration applies after power " + command_print(CMD, "The new device configuration applies after power " "cycling the J-Link device."); return ERROR_OK; @@ -1535,12 +1645,129 @@ COMMAND_HANDLER(jlink_handle_config_write_command) COMMAND_HANDLER(jlink_handle_config_command) { if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_READ_CONFIG)) { - command_print(CMD_CTX, "Device doesn't support reading configuration."); + command_print(CMD, "Device doesn't support reading configuration."); return ERROR_OK; } if (CMD_ARGC == 0) - show_config(CMD_CTX); + show_config(CMD); + + return ERROR_OK; +} + +COMMAND_HANDLER(jlink_handle_emucom_write_command) +{ + int ret; + size_t tmp; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t dummy; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + + tmp = strlen(CMD_ARGV[1]); + + if (tmp % 2 != 0) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + buf = malloc(tmp / 2); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + dummy = unhexify(buf, CMD_ARGV[1], tmp / 2); + + if (dummy != (tmp / 2)) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + free(buf); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + length = tmp / 2; + ret = jaylink_emucom_write(devh, channel, buf, &length); + + free(buf); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel not supported by the device."); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to write to channel: %s.", jaylink_strerror(ret)); + return ERROR_FAIL; + } + + if (length != (tmp / 2)) + LOG_WARNING("Only %" PRIu32 " bytes written to the channel.", length); + + return ERROR_OK; +} + +COMMAND_HANDLER(jlink_handle_emucom_read_command) +{ + int ret; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t tmp; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + + buf = malloc(length * 3 + 1); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + ret = jaylink_emucom_read(devh, channel, buf, &length); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel is not supported by the device."); + free(buf); + return ERROR_FAIL; + } else if (ret == JAYLINK_ERR_DEV_NOT_AVAILABLE) { + LOG_ERROR("Channel is not available for the requested amount of data. " + "%" PRIu32 " bytes are avilable.", length); + free(buf); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to read from channel: %s.", jaylink_strerror(ret)); + free(buf); + return ERROR_FAIL; + } + + tmp = hexify((char *)buf + length, buf, length, 2 * length + 1); + + if (tmp != 2 * length) { + LOG_ERROR("Failed to convert data into hexadecimal string."); + free(buf); + return ERROR_FAIL; + } + + command_print(CMD, "%s", buf + length); + free(buf); return ERROR_OK; } @@ -1579,13 +1806,33 @@ static const struct command_registration jlink_config_subcommand_handlers[] = { .name = "reset", .handler = &jlink_handle_config_reset_command, .mode = COMMAND_EXEC, - .help = "undo configuration changes" + .help = "undo configuration changes", + .usage = "", }, { .name = "write", .handler = &jlink_handle_config_write_command, .mode = COMMAND_EXEC, - .help = "write configuration to the device" + .help = "write configuration to the device", + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration jlink_emucom_subcommand_handlers[] = { + { + .name = "write", + .handler = &jlink_handle_emucom_write_command, + .mode = COMMAND_EXEC, + .help = "write to a channel", + .usage = " ", + }, + { + .name = "read", + .handler = &jlink_handle_emucom_read_command, + .mode = COMMAND_EXEC, + .help = "read from a channel", + .usage = " " }, COMMAND_REGISTRATION_DONE }; @@ -1609,13 +1856,15 @@ static const struct command_registration jlink_subcommand_handlers[] = { .name = "freemem", .handler = &jlink_handle_free_memory_command, .mode = COMMAND_EXEC, - .help = "show free device memory" + .help = "show free device memory", + .usage = "", }, { .name = "hwstatus", .handler = &jlink_handle_hwstatus_command, .mode = COMMAND_EXEC, - .help = "show the hardware status" + .help = "show the hardware status", + .usage = "", }, { .name = "usb", @@ -1638,6 +1887,14 @@ static const struct command_registration jlink_subcommand_handlers[] = { .help = "access the device configuration. If no argument is given " "this will show the device configuration", .chain = jlink_config_subcommand_handlers, + .usage = "[]", + }, + { + .name = "emucom", + .mode = COMMAND_EXEC, + .help = "access EMUCOM channel", + .chain = jlink_emucom_subcommand_handlers, + .usage = "", }, COMMAND_REGISTRATION_DONE }; @@ -1648,6 +1905,7 @@ static const struct command_registration jlink_command_handlers[] = { .mode = COMMAND_ANY, .help = "perform jlink management", .chain = jlink_subcommand_handlers, + .usage = "", }, COMMAND_REGISTRATION_DONE }; @@ -1671,14 +1929,6 @@ static void jlink_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_c jlink_swd_queue_cmd(cmd, value, 0, ap_delay_clk); } -static int_least32_t jlink_swd_frequency(int_least32_t hz) -{ - if (hz > 0) - jlink_speed(hz / 1000); - - return hz; -} - /***************************************************************************/ /* J-Link tap functions */ @@ -1708,7 +1958,8 @@ static void jlink_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; - memset(tms_buffer, 0, sizeof(tdi_buffer)); + memset(tms_buffer, 0, sizeof(tms_buffer)); + memset(tdi_buffer, 0, sizeof(tdi_buffer)); } static void jlink_clock_data(const uint8_t *out, unsigned out_offset, @@ -1768,7 +2019,7 @@ static int jlink_flush(void) tap_length, jtag_command_version); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_jtag_io() failed: %s.", jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_jtag_io() failed: %s.", jaylink_strerror(ret)); jlink_tap_init(); return ERROR_JTAG_QUEUE_FAILED; } @@ -1779,7 +2030,7 @@ static int jlink_flush(void) buf_set_buf(tdo_buffer, p->first, p->buffer, p->buffer_offset, p->length); - DEBUG_JTAG_IO("Pending scan result, length = %d.", p->length); + LOG_DEBUG_IO("Pending scan result, length = %d.", p->length); } jlink_tap_init(); @@ -1874,7 +2125,7 @@ static int jlink_swd_run_queue(void) ret = jaylink_swd_io(devh, tms_buffer, tdi_buffer, tdo_buffer, tap_length); if (ret != JAYLINK_OK) { - LOG_ERROR("jaylink_swd_io() failed: %s.", jaylink_strerror_name(ret)); + LOG_ERROR("jaylink_swd_io() failed: %s.", jaylink_strerror(ret)); goto skip; } @@ -1912,7 +2163,7 @@ skip: static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk) { uint8_t data_parity_trn[DIV_ROUND_UP(32 + 1, 8)]; - if (tap_length + 46 + 8 + ap_delay_clk >= sizeof(tdi_buffer) * 8 || + if (tap_length + 46 + 8 + ap_delay_clk >= swd_buffer_size * 8 || pending_scan_results_length == MAX_PENDING_SCAN_RESULTS) { /* Not enough room in the queue. Run the queue. */ queued_retval = jlink_swd_run_queue(); @@ -1953,7 +2204,6 @@ static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint3 static const struct swd_driver jlink_swd = { .init = &jlink_swd_init, - .frequency = &jlink_swd_frequency, .switch_seq = &jlink_swd_switch_seq, .read_reg = &jlink_swd_read_reg, .write_reg = &jlink_swd_write_reg,