]> git.sur5r.net Git - openocd/commitdiff
jlink: Add EMUCOM support
authorMarc Schink <openocd-dev@marcschink.de>
Wed, 30 Sep 2015 16:58:19 +0000 (18:58 +0200)
committerPaul Fertser <fercerpav@gmail.com>
Thu, 8 Dec 2016 13:32:11 +0000 (13:32 +0000)
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>
doc/openocd.texi
src/jtag/drivers/jlink.c

index b47d2c4479209ee1e7c8697793d4033d38f3eeb9..440aa04ad87f6d5b5035a3b9e4791bcdfbf92730 100644 (file)
@@ -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
index 95c6d8db3068d3ab21f2dd3bef98c397c4585f9a..e5bfd322fa2f2597e9cf3f6671126bfec1db9bc8 100644 (file)
@@ -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
 };