aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <openocd-dev@marcschink.de>2015-09-30 18:58:19 +0200
committerPaul Fertser <fercerpav@gmail.com>2016-12-08 13:32:11 +0000
commit2e0e11b76645d6b38bc4986d8000e4e47e391596 (patch)
treeb0edd6e3e265e63af932fec3b1d50752049d867c
parentc37a88c92f0234df6206a4b58c23d20563a22afc (diff)
jlink: Add EMUCOM support
EMUCOM is a way to communicate with a J-Link device via so called channels. A channel can either be read or written in a single operation. Beside the reserved channels for SEGGER, there are channels available to implement vendor and/or device specific functionalities. For example, EMUCOM is used on many starter and development kits from Silicon Labs to access power measurements and various other information and settings. Change-Id: I6094109c043b34aed4a40ceabe71f30ff896bf1d Signed-off-by: Marc Schink <openocd-dev@marcschink.de> Reviewed-on: http://openocd.zylin.com/3794 Tested-by: jenkins Reviewed-by: Paul Fertser <fercerpav@gmail.com>
-rw-r--r--doc/openocd.texi20
-rw-r--r--src/jtag/drivers/jlink.c143
2 files changed, 163 insertions, 0 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index b47d2c44..440aa04a 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -2702,6 +2702,26 @@ Reset the current configuration.
@deffn {Command} {jlink config write}
Write the current configuration to the internal persistent storage.
@end deffn
+@deffn {Command} {jlink emucom write <channel> <data>}
+Write data to an EMUCOM channel. The data needs to be encoded as hexadecimal
+pairs.
+
+The following example shows how to write the three bytes 0xaa, 0x0b and 0x23 to
+the EMUCOM channel 0x10:
+@example
+> jlink emucom write 0x10 aa0b23
+@end example
+@end deffn
+@deffn {Command} {jlink emucom read <channel> <length>}
+Read data from an EMUCOM channel. The read data is encoded as hexadecimal
+pairs.
+
+The following example shows how to read 4 bytes from the EMUCOM channel 0x0:
+@example
+> jlink emucom read 0x0 4
+77a90000
+@end example
+@end deffn
@deffn {Config} {jlink usb} <@option{0} to @option{3}>
Set the USB address of the interface, in case more than one adapter is connected
to the host. If not specified, USB addresses are not considered. Device
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 95c6d8db..e5bfd322 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -1602,6 +1602,125 @@ COMMAND_HANDLER(jlink_handle_config_command)
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_name(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_name(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_CTX, "%s", buf + length);
+ free(buf);
+
+ return ERROR_OK;
+}
+
static const struct command_registration jlink_config_subcommand_handlers[] = {
{
.name = "usb",
@@ -1647,6 +1766,24 @@ static const struct command_registration jlink_config_subcommand_handlers[] = {
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 = "<channel> <data>",
+ },
+ {
+ .name = "read",
+ .handler = &jlink_handle_emucom_read_command,
+ .mode = COMMAND_EXEC,
+ .help = "read from a channel",
+ .usage = "<channel> <length>"
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
static const struct command_registration jlink_subcommand_handlers[] = {
{
.name = "jtag",
@@ -1696,6 +1833,12 @@ static const struct command_registration jlink_subcommand_handlers[] = {
"this will show the device configuration",
.chain = jlink_config_subcommand_handlers,
},
+ {
+ .name = "emucom",
+ .mode = COMMAND_EXEC,
+ .help = "access EMUCOM channel",
+ .chain = jlink_emucom_subcommand_handlers
+ },
COMMAND_REGISTRATION_DONE
};