This is an automated email from Gerrit.

"Grant Ramsay <grant.ram...@hotmail.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8343

-- gerrit

commit f9e5584fb3fc93e47542f83bafb71ec08e7e8175
Author: Grant Ramsay <grant.ram...@hotmail.com>
Date:   Sun Jun 16 20:27:11 2024 +1200

    rtt: Add support for multiple RTT control block instances
    
    This is useful when a device has multiple RTT control blocks, probably on
    multiple AMP cores. A new command "rtt select_instance <instance_id>"
    allows creating/selecting the RTT instance to be used by other RTT
    commands.
    
    Change-Id: If02ebb2ca7075198a32bec6acae35840147ec86b
    Signed-off-by: Grant Ramsay <grant.ram...@hotmail.com>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index e46e6004bc..c9cfcdde85 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9482,10 +9482,6 @@ This interface is especially of interest for targets 
without
 Serial Wire Output (SWO), such as ARM Cortex-M0, or where semihosting is not
 applicable because of real-time constraints.
 
-@quotation Note
-The current implementation supports only single target devices.
-@end quotation
-
 The data transfer between host and target device is organized through
 unidirectional up/down-channels for target-to-host and host-to-target
 communication, respectively.
@@ -9541,6 +9537,14 @@ Start a TCP server on @var{port} for the channel 
@var{channel}. When
 Stop the TCP sever with port @var{port}.
 @end deffn
 
+@deffn {Command} {rtt select_instance} instance_id
+Select the active RTT instance (not to be confused with RTT channels).
+@var{instance_id} is an integer handle to the active RTT instance.
+Other RTT commands will use the currently selected RTT instance.
+This is useful when a device has multiple RTT control blocks, probably
+on multiple AMP cores. The initial selected instance is 0.
+@end deffn
+
 The following example shows how to setup RTT using the SEGGER RTT 
implementation
 on the target device.
 
@@ -9557,6 +9561,18 @@ In this example, OpenOCD searches the control block with 
the ID "SEGGER RTT"
 starting at 0x20000000 for 2048 bytes. The RTT channel 0 is exposed through the
 TCP/IP port 9090.
 
+The following example adds a second RTT instance, seaching for another control
+block at 0x21000000 for 2048 bytes. This instances RTT channel 0 is exposed
+through the TCP/IP port 9091.
+
+@example
+rtt select_instance 1
+
+rtt setup 0x21000000 2048 "SEGGER RTT1"
+rtt start
+
+rtt server start 9091 0
+@end example
 
 @section Misc Commands
 
diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c
index e31e75410d..dd3bd9b313 100644
--- a/src/rtt/rtt.c
+++ b/src/rtt/rtt.c
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (C) 2016-2020 by Marc Schink <d...@zapb.de>
+ * Copyright (C) 2024 Grant Ramsay <grant.ram...@hotmail.com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -19,7 +20,7 @@
 
 #include "rtt.h"
 
-static struct {
+struct rtt {
        struct rtt_source source;
        /** Control block. */
        struct rtt_control ctrl;
@@ -43,49 +44,116 @@ static struct {
        size_t sink_list_length;
 
        unsigned int polling_interval;
-} rtt;
 
-int rtt_init(void)
+       unsigned int instance_id;
+       struct list_head lh;
+};
+
+/** A list of all created RTT instances (used for cleanup). */
+static LIST_HEAD(rtt_list);
+
+/** The currently selected RTT instance. */
+static struct rtt *selected_instance;
+
+static struct rtt *rtt_new(int instance_id)
 {
-       rtt.sink_list_length = 1;
-       rtt.sink_list = calloc(rtt.sink_list_length,
+       struct rtt *rtt = calloc(1, sizeof(*rtt));
+       if (!rtt)
+               return NULL;
+
+       rtt->sink_list_length = 1;
+       rtt->sink_list = calloc(rtt->sink_list_length,
                sizeof(struct rtt_sink_list *));
 
-       if (!rtt.sink_list)
-               return ERROR_FAIL;
+       if (!rtt->sink_list)
+               return NULL;
 
-       rtt.sink_list[0] = NULL;
-       rtt.started = false;
+       rtt->sink_list[0] = NULL;
+       rtt->started = false;
 
-       rtt.polling_interval = 100;
+       rtt->polling_interval = 100;
 
-       return ERROR_OK;
+       rtt->instance_id = instance_id;
+       list_add_tail(&rtt->lh, &rtt_list);
+
+       return rtt;
+}
+
+static void rtt_free(struct rtt *rtt)
+{
+       list_del(&rtt->lh);
+       free(rtt->sink_list);
+       free(rtt);
+}
+
+static struct rtt *rtt_instance_by_id(unsigned int instance_id)
+{
+       struct rtt *rtt;
+
+       list_for_each_entry(rtt, &rtt_list, lh) {
+               if (rtt->instance_id == instance_id)
+                       return rtt;
+       }
+
+       return NULL;
+}
+
+int rtt_init(void)
+{
+       /* Create and select instance 0 */
+       return rtt_select_instance(0);
 }
 
 int rtt_exit(void)
 {
-       free(rtt.sink_list);
+       struct rtt *rtt, *tmp;
+
+       list_for_each_entry_safe(rtt, tmp, &rtt_list, lh) {
+               rtt_free(rtt);
+       }
 
        return ERROR_OK;
 }
 
+int rtt_select_instance(unsigned int instance_id)
+{
+       struct rtt *rtt = rtt_instance_by_id(instance_id);
+
+       /* Create a new instance if it does not exist */
+       if (!rtt) {
+               rtt = rtt_new(instance_id);
+               if (!rtt)
+                       return ERROR_FAIL;
+       }
+
+       selected_instance = rtt;
+
+       return ERROR_OK;
+}
+
+struct rtt *rtt_get_selected_instance(void)
+{
+       return selected_instance;
+}
+
 static int read_channel_callback(void *user_data)
 {
        int ret;
+       struct rtt *rtt = user_data;
 
-       ret = rtt.source.read(rtt.target, &rtt.ctrl, rtt.sink_list,
-               rtt.sink_list_length, NULL);
+       ret = rtt->source.read(rtt->target, &rtt->ctrl, rtt->sink_list,
+               rtt->sink_list_length, NULL);
 
        if (ret != ERROR_OK) {
-               target_unregister_timer_callback(&read_channel_callback, NULL);
-               rtt.source.stop(rtt.target, NULL);
+               target_unregister_timer_callback(&read_channel_callback, rtt);
+               rtt->source.stop(rtt->target, NULL);
                return ret;
        }
 
        return ERROR_OK;
 }
 
-int rtt_setup(target_addr_t address, size_t size, const char *id)
+int rtt_setup(struct rtt *rtt, target_addr_t address, size_t size, const char 
*id)
 {
        size_t id_length = strlen(id);
 
@@ -94,16 +162,16 @@ int rtt_setup(target_addr_t address, size_t size, const 
char *id)
                return ERROR_COMMAND_ARGUMENT_INVALID;
        }
 
-       rtt.addr = address;
-       rtt.size = size;
-       strncpy(rtt.id, id, id_length + 1);
-       rtt.changed = true;
-       rtt.configured = true;
+       rtt->addr = address;
+       rtt->size = size;
+       strncpy(rtt->id, id, id_length + 1);
+       rtt->changed = true;
+       rtt->configured = true;
 
        return ERROR_OK;
 }
 
-int rtt_register_source(const struct rtt_source source,
+int rtt_register_source(struct rtt *rtt, const struct rtt_source source,
                struct target *target)
 {
        if (!source.find_cb || !source.read_cb || !source.read_channel_info)
@@ -115,66 +183,66 @@ int rtt_register_source(const struct rtt_source source,
        if (!source.read || !source.write)
                return ERROR_FAIL;
 
-       rtt.source = source;
-       rtt.target = target;
+       rtt->source = source;
+       rtt->target = target;
 
        return ERROR_OK;
 }
 
-int rtt_start(void)
+int rtt_start(struct rtt *rtt)
 {
        int ret;
-       target_addr_t addr = rtt.addr;
+       target_addr_t addr = rtt->addr;
 
-       if (rtt.started)
+       if (rtt->started)
                return ERROR_OK;
 
-       if (!rtt.found_cb || rtt.changed) {
-               rtt.source.find_cb(rtt.target, &addr, rtt.size, rtt.id,
-                       &rtt.found_cb, NULL);
+       if (!rtt->found_cb || rtt->changed) {
+               rtt->source.find_cb(rtt->target, &addr, rtt->size, rtt->id,
+                       &rtt->found_cb, NULL);
 
-               rtt.changed = false;
+               rtt->changed = false;
 
-               if (rtt.found_cb) {
+               if (rtt->found_cb) {
                        LOG_INFO("rtt: Control block found at 0x%" 
TARGET_PRIxADDR,
                                addr);
-                       rtt.ctrl.address = addr;
+                       rtt->ctrl.address = addr;
                } else {
                        LOG_INFO("rtt: No control block found");
                        return ERROR_OK;
                }
        }
 
-       ret = rtt.source.read_cb(rtt.target, rtt.ctrl.address, &rtt.ctrl, NULL);
+       ret = rtt->source.read_cb(rtt->target, rtt->ctrl.address, &rtt->ctrl, 
NULL);
 
        if (ret != ERROR_OK)
                return ret;
 
-       ret = rtt.source.start(rtt.target, &rtt.ctrl, NULL);
+       ret = rtt->source.start(rtt->target, &rtt->ctrl, NULL);
 
        if (ret != ERROR_OK)
                return ret;
 
        target_register_timer_callback(&read_channel_callback,
-               rtt.polling_interval, 1, NULL);
-       rtt.started = true;
+               rtt->polling_interval, 1, rtt);
+       rtt->started = true;
 
        return ERROR_OK;
 }
 
-int rtt_stop(void)
+int rtt_stop(struct rtt *rtt)
 {
        int ret;
 
-       if (!rtt.configured) {
+       if (!rtt->configured) {
                LOG_ERROR("rtt: Not configured");
                return ERROR_FAIL;
        }
 
-       target_unregister_timer_callback(&read_channel_callback, NULL);
-       rtt.started = false;
+       target_unregister_timer_callback(&read_channel_callback, rtt);
+       rtt->started = false;
 
-       ret = rtt.source.stop(rtt.target, NULL);
+       ret = rtt->source.stop(rtt->target, NULL);
 
        if (ret != ERROR_OK)
                return ret;
@@ -182,34 +250,34 @@ int rtt_stop(void)
        return ERROR_OK;
 }
 
-static int adjust_sink_list(size_t length)
+static int adjust_sink_list(struct rtt *rtt, size_t length)
 {
        struct rtt_sink_list **tmp;
 
-       if (length <= rtt.sink_list_length)
+       if (length <= rtt->sink_list_length)
                return ERROR_OK;
 
-       tmp = realloc(rtt.sink_list, sizeof(struct rtt_sink_list *) * length);
+       tmp = realloc(rtt->sink_list, sizeof(struct rtt_sink_list *) * length);
 
        if (!tmp)
                return ERROR_FAIL;
 
-       for (size_t i = rtt.sink_list_length; i < length; i++)
+       for (size_t i = rtt->sink_list_length; i < length; i++)
                tmp[i] = NULL;
 
-       rtt.sink_list = tmp;
-       rtt.sink_list_length = length;
+       rtt->sink_list = tmp;
+       rtt->sink_list_length = length;
 
        return ERROR_OK;
 }
 
-int rtt_register_sink(unsigned int channel_index, rtt_sink_read read,
+int rtt_register_sink(struct rtt *rtt, unsigned int channel_index, 
rtt_sink_read read,
                void *user_data)
 {
        struct rtt_sink_list *tmp;
 
-       if (channel_index >= rtt.sink_list_length) {
-               if (adjust_sink_list(channel_index + 1) != ERROR_OK)
+       if (channel_index >= rtt->sink_list_length) {
+               if (adjust_sink_list(rtt, channel_index + 1) != ERROR_OK)
                        return ERROR_FAIL;
        }
 
@@ -222,31 +290,31 @@ int rtt_register_sink(unsigned int channel_index, 
rtt_sink_read read,
 
        tmp->read = read;
        tmp->user_data = user_data;
-       tmp->next = rtt.sink_list[channel_index];
+       tmp->next = rtt->sink_list[channel_index];
 
-       rtt.sink_list[channel_index] = tmp;
+       rtt->sink_list[channel_index] = tmp;
 
        return ERROR_OK;
 }
 
-int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read,
+int rtt_unregister_sink(struct rtt *rtt, unsigned int channel_index, 
rtt_sink_read read,
                void *user_data)
 {
        struct rtt_sink_list *prev_sink;
 
        LOG_DEBUG("rtt: Unregistering sink for channel %u", channel_index);
 
-       if (channel_index >= rtt.sink_list_length)
+       if (channel_index >= rtt->sink_list_length)
                return ERROR_FAIL;
 
-       prev_sink = rtt.sink_list[channel_index];
+       prev_sink = rtt->sink_list[channel_index];
 
-       for (struct rtt_sink_list *sink = rtt.sink_list[channel_index]; sink;
+       for (struct rtt_sink_list *sink = rtt->sink_list[channel_index]; sink;
                        prev_sink = sink, sink = sink->next) {
                if (sink->read == read && sink->user_data == user_data) {
 
-                       if (sink == rtt.sink_list[channel_index])
-                               rtt.sink_list[channel_index] = sink->next;
+                       if (sink == rtt->sink_list[channel_index])
+                               rtt->sink_list[channel_index] = sink->next;
                        else
                                prev_sink->next = sink->next;
 
@@ -259,67 +327,67 @@ int rtt_unregister_sink(unsigned int channel_index, 
rtt_sink_read read,
        return ERROR_OK;
 }
 
-int rtt_get_polling_interval(unsigned int *interval)
+int rtt_get_polling_interval(struct rtt *rtt, unsigned int *interval)
 {
        if (!interval)
                return ERROR_FAIL;
 
-       *interval = rtt.polling_interval;
+       *interval = rtt->polling_interval;
 
        return ERROR_OK;
 }
 
-int rtt_set_polling_interval(unsigned int interval)
+int rtt_set_polling_interval(struct rtt *rtt, unsigned int interval)
 {
        if (!interval)
                return ERROR_FAIL;
 
-       if (rtt.polling_interval != interval) {
-               target_unregister_timer_callback(&read_channel_callback, NULL);
+       if (rtt->polling_interval != interval) {
+               target_unregister_timer_callback(&read_channel_callback, rtt);
                target_register_timer_callback(&read_channel_callback, 
interval, 1,
-                       NULL);
+                       rtt);
        }
 
-       rtt.polling_interval = interval;
+       rtt->polling_interval = interval;
 
        return ERROR_OK;
 }
 
-int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
+int rtt_write_channel(struct rtt *rtt, unsigned int channel_index, const 
uint8_t *buffer,
                size_t *length)
 {
-       if (channel_index >= rtt.ctrl.num_up_channels) {
+       if (channel_index >= rtt->ctrl.num_up_channels) {
                LOG_WARNING("rtt: Down-channel %u is not available", 
channel_index);
                return ERROR_OK;
        }
 
-       return rtt.source.write(rtt.target, &rtt.ctrl, channel_index, buffer,
+       return rtt->source.write(rtt->target, &rtt->ctrl, channel_index, buffer,
                length, NULL);
 }
 
-bool rtt_started(void)
+bool rtt_started(struct rtt *rtt)
 {
-       return rtt.started;
+       return rtt->started;
 }
 
-bool rtt_configured(void)
+bool rtt_configured(struct rtt *rtt)
 {
-       return rtt.configured;
+       return rtt->configured;
 }
 
-bool rtt_found_cb(void)
+bool rtt_found_cb(struct rtt *rtt)
 {
-       return rtt.found_cb;
+       return rtt->found_cb;
 }
 
-const struct rtt_control *rtt_get_control(void)
+const struct rtt_control *rtt_get_control(struct rtt *rtt)
 {
-       return &rtt.ctrl;
+       return &rtt->ctrl;
 }
 
-int rtt_read_channel_info(unsigned int channel_index,
+int rtt_read_channel_info(struct rtt *rtt, unsigned int channel_index,
        enum rtt_channel_type type, struct rtt_channel_info *info)
 {
-       return rtt.source.read_channel_info(rtt.target, &rtt.ctrl,
+       return rtt->source.read_channel_info(rtt->target, &rtt->ctrl,
                channel_index, type, info, NULL);
 }
diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h
index a5630a9515..9f544e68c9 100644
--- a/src/rtt/rtt.h
+++ b/src/rtt/rtt.h
@@ -27,6 +27,9 @@
 /* Minimal channel buffer size in bytes. */
 #define RTT_CHANNEL_BUFFER_MIN_SIZE    2
 
+/** Forward declaration of opaque RTT instance */
+struct rtt;
+
 /** RTT control block. */
 struct rtt_control {
        /** Control block address on the target. */
@@ -128,6 +131,7 @@ struct rtt_source {
 
 /**
  * Initialize Real-Time Transfer (RTT).
+ * Creates and selects instance 0.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
@@ -140,127 +144,165 @@ int rtt_init(void);
  */
 int rtt_exit(void);
 
+/**
+ * Select which RTT instance will be returned by rtt_get_selected_instance().
+ * If the instance does not exist it will be created.
+ * Useful for multicore devices that have multiple RTT control blocks.
+ *
+ * @param[in] instance_id The ID of the RTT instance to select.
+ *
+ * @returns ERROR_OK on success, an error code on failure.
+ */
+int rtt_select_instance(unsigned int instance_id);
+
+/**
+ * Get the currently selected RTT instance.
+ *
+ * @returns a pointer to the currently selected RTT instance.
+ */
+struct rtt *rtt_get_selected_instance(void);
+
 /**
  * Register an RTT source for a target.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] source RTT source.
  * @param[in,out] target Target.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_register_source(const struct rtt_source source,
+int rtt_register_source(struct rtt *rtt, const struct rtt_source source,
                struct target *target);
 
 /**
  * Setup RTT.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] address Start address to search for the control block.
  * @param[in] size Size of the control block search area.
  * @param[in] id Identifier of the control block. Must be null-terminated.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_setup(target_addr_t address, size_t size, const char *id);
+int rtt_setup(struct rtt *rtt, target_addr_t address, size_t size, const char 
*id);
 
 /**
  * Start Real-Time Transfer (RTT).
  *
+ * @param[in] rtt RTT instance.
+ *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_start(void);
+int rtt_start(struct rtt *rtt);
 
 /**
  * Stop Real-Time Transfer (RTT).
  *
+ * @param[in] rtt RTT instance.
+ *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_stop(void);
+int rtt_stop(struct rtt *rtt);
 
 /**
  * Get the polling interval.
  *
+ * @param[in] rtt RTT instance.
  * @param[out] interval Polling interval in milliseconds.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_get_polling_interval(unsigned int *interval);
+int rtt_get_polling_interval(struct rtt *rtt, unsigned int *interval);
 
 /**
  * Set the polling interval.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] interval Polling interval in milliseconds.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_set_polling_interval(unsigned int interval);
+int rtt_set_polling_interval(struct rtt *rtt, unsigned int interval);
 
 /**
  * Get whether RTT is started.
  *
+ * @param[in] rtt RTT instance.
+ *
  * @returns Whether RTT is started.
  */
-bool rtt_started(void);
+bool rtt_started(struct rtt *rtt);
 
 /**
  * Get whether RTT is configured.
  *
+ * @param[in] rtt RTT instance.
+ *
  * @returns Whether RTT is configured.
  */
-bool rtt_configured(void);
+bool rtt_configured(struct rtt *rtt);
 
 /**
  * Get whether RTT control block was found.
  *
+ * @param[in] rtt RTT instance.
+ *
  * @returns Whether RTT was found.
  */
-bool rtt_found_cb(void);
+bool rtt_found_cb(struct rtt *rtt);
 
 /**
  * Get the RTT control block.
  *
+ * @param[in] rtt RTT instance.
+ *
  * @returns The RTT control block.
  */
-const struct rtt_control *rtt_get_control(void);
+const struct rtt_control *rtt_get_control(struct rtt *rtt);
 
 /**
  * Read channel information.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] channel_index Channel index.
  * @param[in] type Channel type.
  * @param[out] info Channel information.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_read_channel_info(unsigned int channel_index,
+int rtt_read_channel_info(struct rtt *rtt, unsigned int channel_index,
        enum rtt_channel_type type, struct rtt_channel_info *info);
 
 /**
  * Register an RTT sink.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] channel_index Channel index.
  * @param[in] read Read callback function.
  * @param[in,out] user_data User data to be passed to the callback function.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_register_sink(unsigned int channel_index, rtt_sink_read read,
+int rtt_register_sink(struct rtt *rtt, unsigned int channel_index, 
rtt_sink_read read,
                void *user_data);
 
 /**
  * Unregister an RTT sink.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] channel_index Channel index.
  * @param[in] read Read callback function.
  * @param[in,out] user_data User data to be passed to the callback function.
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read,
+int rtt_unregister_sink(struct rtt *rtt, unsigned int channel_index, 
rtt_sink_read read,
                void *user_data);
 
 /**
  * Write to an RTT channel.
  *
+ * @param[in] rtt RTT instance.
  * @param[in] channel_index Channel index.
  * @param[in] buffer Buffer with data that should be written to the channel.
  * @param[in,out] length Number of bytes to write. On success, the argument 
gets
@@ -268,7 +310,7 @@ int rtt_unregister_sink(unsigned int channel_index, 
rtt_sink_read read,
  *
  * @returns ERROR_OK on success, an error code on failure.
  */
-int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer,
+int rtt_write_channel(struct rtt *rtt, unsigned int channel_index, const 
uint8_t *buffer,
                size_t *length);
 
 extern const struct command_registration rtt_target_command_handlers[];
diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c
index 2b8822fce8..d328c1b3d3 100644
--- a/src/rtt/tcl.c
+++ b/src/rtt/tcl.c
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (C) 2019-2020 by Marc Schink <d...@zapb.de>
+ * Copyright (C) 2024 Grant Ramsay <grant.ram...@hotmail.com>
  */
 
 #ifdef HAVE_CONFIG_H
@@ -36,9 +37,14 @@ COMMAND_HANDLER(handle_rtt_setup_command)
        COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[0], address);
        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size);
 
-       rtt_register_source(source, get_current_target(CMD_CTX));
+       struct rtt *rtt = rtt_get_selected_instance();
+       if (!rtt)
+               return ERROR_FAIL;
+
+       if (rtt_register_source(rtt, source, get_current_target(CMD_CTX)) != 
ERROR_OK)
+               return ERROR_FAIL;
 
-       if (rtt_setup(address, size, CMD_ARGV[2]) != ERROR_OK)
+       if (rtt_setup(rtt, address, size, CMD_ARGV[2]) != ERROR_OK)
                return ERROR_FAIL;
 
        return ERROR_OK;
@@ -49,12 +55,16 @@ COMMAND_HANDLER(handle_rtt_start_command)
        if (CMD_ARGC > 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (!rtt_configured()) {
+       struct rtt *rtt = rtt_get_selected_instance();
+       if (!rtt)
+               return ERROR_FAIL;
+
+       if (!rtt_configured(rtt)) {
                command_print(CMD, "RTT is not configured");
                return ERROR_FAIL;
        }
 
-       return rtt_start();
+       return rtt_start(rtt);
 }
 
 COMMAND_HANDLER(handle_rtt_stop_command)
@@ -62,16 +72,24 @@ COMMAND_HANDLER(handle_rtt_stop_command)
        if (CMD_ARGC > 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       return rtt_stop();
+       struct rtt *rtt = rtt_get_selected_instance();
+       if (!rtt)
+               return ERROR_FAIL;
+
+       return rtt_stop(rtt);
 }
 
 COMMAND_HANDLER(handle_rtt_polling_interval_command)
 {
+       struct rtt *rtt = rtt_get_selected_instance();
+       if (!rtt)
+               return ERROR_FAIL;
+
        if (CMD_ARGC == 0) {
                int ret;
                unsigned int interval;
 
-               ret = rtt_get_polling_interval(&interval);
+               ret = rtt_get_polling_interval(rtt, &interval);
 
                if (ret != ERROR_OK) {
                        command_print(CMD, "Failed to get polling interval");
@@ -84,7 +102,7 @@ COMMAND_HANDLER(handle_rtt_polling_interval_command)
                unsigned int interval;
 
                COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], interval);
-               ret = rtt_set_polling_interval(interval);
+               ret = rtt_set_polling_interval(rtt, interval);
 
                if (ret != ERROR_OK) {
                        command_print(CMD, "Failed to set polling interval");
@@ -104,12 +122,16 @@ COMMAND_HANDLER(handle_rtt_channels_command)
        const struct rtt_control *ctrl;
        struct rtt_channel_info info;
 
-       if (!rtt_found_cb()) {
+       struct rtt *rtt = rtt_get_selected_instance();
+       if (!rtt)
+               return ERROR_FAIL;
+
+       if (!rtt_found_cb(rtt)) {
                command_print(CMD, "rtt: Control block not available");
                return ERROR_FAIL;
        }
 
-       ctrl = rtt_get_control();
+       ctrl = rtt_get_control(rtt);
 
        command_print(CMD, "Channels: up=%u, down=%u", ctrl->num_up_channels,
                ctrl->num_down_channels);
@@ -120,7 +142,7 @@ COMMAND_HANDLER(handle_rtt_channels_command)
        info.name_length = sizeof(channel_name);
 
        for (unsigned int i = 0; i < ctrl->num_up_channels; i++) {
-               ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info);
+               ret = rtt_read_channel_info(rtt, i, RTT_CHANNEL_TYPE_UP, &info);
 
                if (ret != ERROR_OK)
                        return ret;
@@ -135,7 +157,7 @@ COMMAND_HANDLER(handle_rtt_channels_command)
        command_print(CMD, "Down-channels:");
 
        for (unsigned int i = 0; i < ctrl->num_down_channels; i++) {
-               ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info);
+               ret = rtt_read_channel_info(rtt, i, RTT_CHANNEL_TYPE_DOWN, 
&info);
 
                if (ret != ERROR_OK)
                        return ret;
@@ -159,12 +181,16 @@ COMMAND_HANDLER(handle_channel_list)
        if (CMD_ARGC != 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (!rtt_found_cb()) {
+       struct rtt *rtt = rtt_get_selected_instance();
+       if (!rtt)
+               return ERROR_FAIL;
+
+       if (!rtt_found_cb(rtt)) {
                command_print(CMD, "rtt: Control block not available");
                return ERROR_FAIL;
        }
 
-       ctrl = rtt_get_control();
+       ctrl = rtt_get_control(rtt);
 
        info.name = channel_name;
        info.name_length = sizeof(channel_name);
@@ -172,7 +198,7 @@ COMMAND_HANDLER(handle_channel_list)
        command_print(CMD, "{");
 
        for (unsigned int i = 0; i < ctrl->num_up_channels; i++) {
-               int ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info);
+               int ret = rtt_read_channel_info(rtt, i, RTT_CHANNEL_TYPE_UP, 
&info);
                if (ret != ERROR_OK)
                        return ret;
 
@@ -191,7 +217,7 @@ COMMAND_HANDLER(handle_channel_list)
        command_print(CMD, "}\n{");
 
        for (unsigned int i = 0; i < ctrl->num_down_channels; i++) {
-               int ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, 
&info);
+               int ret = rtt_read_channel_info(rtt, i, RTT_CHANNEL_TYPE_DOWN, 
&info);
                if (ret != ERROR_OK)
                        return ret;
 
@@ -212,6 +238,18 @@ COMMAND_HANDLER(handle_channel_list)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(handle_rtt_select_instance)
+{
+       unsigned int instance_id;
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], instance_id);
+
+       return rtt_select_instance(instance_id);
+}
+
 static const struct command_registration rtt_subcommand_handlers[] = {
        {
                .name = "setup",
@@ -255,6 +293,13 @@ static const struct command_registration 
rtt_subcommand_handlers[] = {
                .help = "list available channels",
                .usage = ""
        },
+       {
+               .name = "select_instance",
+               .handler = handle_rtt_select_instance,
+               .mode = COMMAND_ANY,
+               .help = "select RTT instance",
+               .usage = "<instance_id>"
+       },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c
index 9769153475..25816e1b04 100644
--- a/src/server/rtt_server.c
+++ b/src/server/rtt_server.c
@@ -24,6 +24,7 @@
  */
 
 struct rtt_service {
+       struct rtt *rtt;
        unsigned int channel;
        char *hello_message;
 };
@@ -61,7 +62,7 @@ static int rtt_new_connection(struct connection *connection)
 
        LOG_DEBUG("rtt: New connection for channel %u", service->channel);
 
-       ret = rtt_register_sink(service->channel, &read_callback, connection);
+       ret = rtt_register_sink(service->rtt, service->channel, &read_callback, 
connection);
 
        if (ret != ERROR_OK)
                return ret;
@@ -77,7 +78,7 @@ static int rtt_connection_closed(struct connection 
*connection)
        struct rtt_service *service;
 
        service = (struct rtt_service *)connection->service->priv;
-       rtt_unregister_sink(service->channel, &read_callback, connection);
+       rtt_unregister_sink(service->rtt, service->channel, &read_callback, 
connection);
 
        LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
 
@@ -102,7 +103,7 @@ static int rtt_input(struct connection *connection)
        }
 
        length = bytes_read;
-       rtt_write_channel(service->channel, buffer, &length);
+       rtt_write_channel(service->rtt, service->channel, buffer, &length);
 
        return ERROR_OK;
 }
@@ -129,6 +130,12 @@ COMMAND_HANDLER(handle_rtt_start_command)
        if (!service)
                return ERROR_FAIL;
 
+       service->rtt = rtt_get_selected_instance();
+       if (!service->rtt) {
+               free(service);
+               return ERROR_FAIL;
+       }
+
        COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
 
        if (CMD_ARGC >= 3) {

-- 

Reply via email to