Re: [PATCH BlueZ 3/3] monitor: Add support for reading over J-Link RTT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marcel,

On Mon, Feb 26, 2018 at 2:59 PM, Marcel Holtmann <marcel@xxxxxxxxxxxx> wrote:
> Hi Andrzej,
>
>> This patch adds support for reading data over J-Link RTT. It can be
>> used as replacement for TTY when reading from embedded devices since
>> it's much faster and does block a UART. Data format is the same as
>> for TTY. At the moment monitor over RTT is only supported by Apache
>> Mynewt project.
>>
>> Reading data is done by polling RTT every 1 msec since there is no
>> blocking API to read something from RTT buffer.
>
> have you check with top or something that you are not causing massive load on your system by polling every 1 msec. And frankly such interfaces are horrible. How is the RTT actually exposed? Is that via HID reports or what. Have you tried usbmon and see if you see packets when using the library.

RTT works over J-Link connection and every time you want to read
something it just reads it directly from MCU memory - it just works
like this.
Polling every 1 msec adds a bit of load (few % perhaps when system is
in idle) but it is not something that you will have running all the
time, just when you need it. I use this quite often and honestly don't
even notice that it is running.

>> To enable reading from RTT, J-Link and RTT configuration needs to be
>> passed via command line:
>> -J --jlink <device>,<interface>,<speed>,<serialno>
>> -R --rtt <address>,<area>,<buffer>
>>
>> <device> - one of devices supported by J-Link (no default)
>> <interface> - only 'swd' supported for now (default: swd)
>> <speed> - interface speed (default: 1000)
>> <serialno> - emu serial number or 0 if not used (detault: 0)
>> <address> - RTT control block address (default: 0)
>> <area> - RTT control block search area length (default: 0)
>> <buffer> - RTT buffer name with monitor data stream (default: monitor)
>>
>> Parameters with default values can be omitted.
>>
>> For example, to read from default nRF52 device and look for RTT buffer
>> with default name over entire RAM area use:
>> btmon -J nrf52 -R 0x20000000,0x10000
>> ---
>> Makefile.tools    |  3 ++-
>> monitor/control.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
>> monitor/control.h |  1 +
>> monitor/main.c    | 30 ++++++++++++++++++++++++++----
>> 4 files changed, 79 insertions(+), 5 deletions(-)
>>
>> diff --git a/Makefile.tools b/Makefile.tools
>> index 71d083e71..7466633bb 100644
>> --- a/Makefile.tools
>> +++ b/Makefile.tools
>> @@ -59,9 +59,10 @@ monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
>>                               monitor/analyze.h monitor/analyze.c \
>>                               monitor/intel.h monitor/intel.c \
>>                               monitor/broadcom.h monitor/broadcom.c \
>> +                             monitor/jlink.h monitor/jlink.c \
>>                               monitor/tty.h
>> monitor_btmon_LDADD = lib/libbluetooth-internal.la \
>> -                             src/libshared-mainloop.la @UDEV_LIBS@
>> +                             src/libshared-mainloop.la @UDEV_LIBS@ -ldl
>> endif
>>
>> if TESTING
>> diff --git a/monitor/control.c b/monitor/control.c
>> index 98f414be9..73462be42 100644
>> --- a/monitor/control.c
>> +++ b/monitor/control.c
>> @@ -54,6 +54,7 @@
>> #include "ellisys.h"
>> #include "tty.h"
>> #include "control.h"
>> +#include "jlink.h"
>>
>> static struct btsnoop *btsnoop_file = NULL;
>> static bool hcidump_fallback = false;
>> @@ -1376,6 +1377,55 @@ int control_tty(const char *path, unsigned int speed)
>>       return 0;
>> }
>>
>> +static void rtt_callback(int id, void *user_data)
>> +{
>> +     struct control_data *data = user_data;
>> +     ssize_t len;
>> +
>> +     do {
>> +             len = jlink_rtt_read(data->buf + data->offset,
>> +                                     sizeof(data->buf) - data->offset);
>> +             data->offset += len;
>> +             process_data(data);
>> +     } while (len > 0);
>> +
>> +     if (mainloop_modify_timeout(id, 1) < 0)
>> +             mainloop_exit_failure();
>> +}
>> +
>> +int control_rtt(char *jlink, char *rtt)
>> +{
>> +     struct control_data *data;
>> +
>> +     if (jlink_init() < 0) {
>> +             fprintf(stderr, "Failed to initialize J-Link library\n");
>> +             return -EIO;
>> +     }
>> +
>> +     if (jlink_connect(jlink) < 0) {
>> +             fprintf(stderr, "Failed to connect to target device\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     if (jlink_start_rtt(rtt) < 0) {
>> +             fprintf(stderr, "Failed to initialize RTT\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     printf("--- RTT opened ---\n”);
>
> What is this? Debugging code?

A printout when RTT is opened - the same as for TTY when connected and
for socket on incoming connection.

>> +
>> +     data = new0(struct control_data, 1);
>> +     data->channel = HCI_CHANNEL_MONITOR;
>> +     data->fd = -1;
>> +
>> +     if (mainloop_add_timeout(1, rtt_callback, data, free_data) < 0) {
>> +             free(data);
>> +             return -EIO;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> bool control_writer(const char *path)
>> {
>>       btsnoop_file = btsnoop_create(path, BTSNOOP_FORMAT_MONITOR);
>> diff --git a/monitor/control.h b/monitor/control.h
>> index 630a852e4..c315eb7db 100644
>> --- a/monitor/control.h
>> +++ b/monitor/control.h
>> @@ -28,6 +28,7 @@ bool control_writer(const char *path);
>> void control_reader(const char *path);
>> void control_server(const char *path);
>> int control_tty(const char *path, unsigned int speed);
>> +int control_rtt(char *jlink, char *rtt);
>> int control_tracing(void);
>> void control_disable_decoding(void);
>>
>> diff --git a/monitor/main.c b/monitor/main.c
>> index 3e61a4661..27132e3c3 100644
>> --- a/monitor/main.c
>> +++ b/monitor/main.c
>> @@ -72,6 +72,10 @@ static void usage(void)
>>               "\t-S, --sco              Dump SCO traffic\n"
>>               "\t-A, --a2dp             Dump A2DP stream traffic\n"
>>               "\t-E, --ellisys [ip]     Send Ellisys HCI Injection\n"
>> +             "\t-R  --rtt <device>,[<interface>],[<speed>],[<serialno>]\n"
>> +             "\t                       Read data from RTT\n"
>> +             "\t-C  --rtt-cb [<address>],[<area>],[<name>]\n"
>> +             "\t                       RTT control block parameters\n"
>>               "\t-h, --help             Show help options\n");
>> }
>>
>> @@ -89,6 +93,8 @@ static const struct option main_options[] = {
>>       { "sco",     no_argument,       NULL, 'S' },
>>       { "a2dp",    no_argument,       NULL, 'A' },
>>       { "ellisys", required_argument, NULL, 'E' },
>> +     { "jlink",   required_argument, NULL, 'J' },
>> +     { "rtt",     required_argument, NULL, 'R' },
>>       { "todo",    no_argument,       NULL, '#' },
>>       { "version", no_argument,       NULL, 'v' },
>>       { "help",    no_argument,       NULL, 'h' },
>> @@ -106,6 +112,8 @@ int main(int argc, char *argv[])
>>       unsigned int tty_speed = B115200;
>>       unsigned short ellisys_port = 0;
>>       const char *str;
>> +     char *jlink = NULL;
>> +     char *rtt = NULL;
>>       int exit_status;
>>       sigset_t mask;
>>
>> @@ -117,7 +125,7 @@ int main(int argc, char *argv[])
>>               int opt;
>>               struct sockaddr_un addr;
>>
>> -             opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tTSAE:vh",
>> +             opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tTSAE:J:R:vh",
>>                                               main_options, NULL);
>>               if (opt < 0)
>>                       break;
>> @@ -182,6 +190,12 @@ int main(int argc, char *argv[])
>>                       ellisys_server = optarg;
>>                       ellisys_port = 24352;
>>                       break;
>> +             case 'J':
>> +                     jlink = optarg;
>> +                     break;
>> +             case 'R':
>> +                     rtt = optarg;
>> +                     break;
>>               case '#':
>>                       packet_todo();
>>                       lmp_todo();
>> @@ -240,11 +254,19 @@ int main(int argc, char *argv[])
>>       if (ellisys_server)
>>               ellisys_enable(ellisys_server, ellisys_port);
>>
>> -     if (!tty && control_tracing() < 0)
>> +     if (tty && jlink)
>>               return EXIT_FAILURE;
>>
>> -     if (tty && control_tty(tty, tty_speed) < 0)
>> -             return EXIT_FAILURE;
>> +     if (tty) {
>> +             if (control_tty(tty, tty_speed) < 0)
>> +                     return EXIT_FAILURE;
>> +     } else if (jlink) {
>> +             if (control_rtt(jlink, rtt) < 0)
>> +                     return EXIT_FAILURE;
>> +     } else {
>> +             if (control_tracing() < 0)
>> +                     return EXIT_FAILURE;
>> +     }
>
> This is getting to complicated and needs a cleanup first.

Any idea how to clean this up? It's pretty clean for me.

> Regards
>
> Marcel

Best regards,
Andrzej
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux