1 // SPDX-License-Identifier: LGPL-2.1-or-later
4 * BlueZ - Bluetooth protocol stack for Linux
6 * Copyright (C) 2018 Codecoup
25 #define RTT_CONTROL_START 0
26 #define RTT_CONTROL_STOP 1
27 #define RTT_CONTROL_GET_DESC 2
28 #define RTT_CONTROL_GET_NUM_BUF 3
29 #define RTT_CONTROL_GET_STAT 4
31 #define RTT_DIRECTION_UP 0
32 #define RTT_DIRECTION_DOWN 1
34 static const char * const jlink_so_name[] = {
35 "/usr/lib/libjlinkarm.so",
36 "/usr/lib/libjlinkarm.so.6",
37 "/opt/SEGGER/JLink/libjlinkarm.so",
38 "/opt/SEGGER/JLink/libjlinkarm.so.6",
49 static struct rtt_desc rtt_desc;
51 typedef int (*jlink_emu_selectbyusbsn_func) (unsigned int sn);
52 typedef int (*jlink_open_func) (void);
53 typedef int (*jlink_execcommand_func) (char *in, char *out, int size);
54 typedef int (*jlink_tif_select_func) (int);
55 typedef void (*jlink_setspeed_func) (long int speed);
56 typedef int (*jlink_connect_func) (void);
57 typedef unsigned int (*jlink_getsn_func) (void);
58 typedef void (*jlink_emu_getproductname_func) (char *out, int size);
59 typedef int (*jlink_rtterminal_control_func) (int cmd, void *data);
60 typedef int (*jlink_rtterminal_read_func) (int cmd, char *buf, int size);
63 jlink_emu_selectbyusbsn_func emu_selectbyusbsn;
65 jlink_execcommand_func execcommand;
66 jlink_tif_select_func tif_select;
67 jlink_setspeed_func setspeed;
68 jlink_connect_func connect;
69 jlink_getsn_func getsn;
70 jlink_emu_getproductname_func emu_getproductname;
71 jlink_rtterminal_control_func rtterminal_control;
72 jlink_rtterminal_read_func rtterminal_read;
75 static struct jlink jlink;
78 #define NELEM(x) (sizeof(x) / sizeof((x)[0]))
86 for (i = 0; i < NELEM(jlink_so_name); i++) {
87 so = dlopen(jlink_so_name[i], RTLD_LAZY);
95 jlink.emu_selectbyusbsn = dlsym(so, "JLINK_EMU_SelectByUSBSN");
96 jlink.open = dlsym(so, "JLINK_Open");
97 jlink.execcommand = dlsym(so, "JLINK_ExecCommand");
98 jlink.tif_select = dlsym(so, "JLINK_TIF_Select");
99 jlink.setspeed = dlsym(so, "JLINK_SetSpeed");
100 jlink.connect = dlsym(so, "JLINK_Connect");
101 jlink.getsn = dlsym(so, "JLINK_GetSN");
102 jlink.emu_getproductname = dlsym(so, "JLINK_EMU_GetProductName");
103 jlink.rtterminal_control = dlsym(so, "JLINK_RTTERMINAL_Control");
104 jlink.rtterminal_read = dlsym(so, "JLINK_RTTERMINAL_Read");
106 if (!jlink.emu_selectbyusbsn || !jlink.open || !jlink.execcommand ||
107 !jlink.tif_select || !jlink.setspeed ||
108 !jlink.connect || !jlink.getsn ||
109 !jlink.emu_getproductname ||
110 !jlink.rtterminal_control || !jlink.rtterminal_read) {
115 /* don't dlclose(so) here cause symbols from it are in use now */
119 int jlink_connect(char *cfg)
121 const char *device = NULL;
123 unsigned int speed = 1000;
124 unsigned int serial_no = 0;
128 tok = strtok(cfg, ",");
131 tok = strtok(NULL, ",");
135 serial_no = atoi(tok);
137 tok = strtok(NULL, ",");
141 if (!strcasecmp("swd", tok))
147 tok = strtok(NULL, ",");
155 if (jlink.emu_selectbyusbsn(serial_no) < 0) {
156 fprintf(stderr, "Failed to select emu by SN\n");
160 if (jlink.open() < 0) {
161 fprintf(stderr, "Failed to open J-Link\n");
165 snprintf(buf, sizeof(buf), "device=%s", device);
166 if (jlink.execcommand(buf, NULL, 0) < 0) {
167 fprintf(stderr, "Failed to select target device\n");
171 if (jlink.tif_select(tif) < 0) {
172 fprintf(stderr, "Failed to select target interface\n");
176 jlink.setspeed(speed);
178 if (jlink.connect() < 0) {
179 fprintf(stderr, "Failed to open target\n");
183 serial_no = jlink.getsn();
184 jlink.emu_getproductname(buf, sizeof(buf));
186 printf("Connected to %s (S/N: %u)\n", buf, serial_no);
191 int jlink_start_rtt(char *cfg)
193 unsigned int address = 0;
194 unsigned int area_size = 0;
195 const char *buffer = "btmonitor";
205 tok = strtok(cfg, ",");
207 address = strtol(tok, NULL, 0);
211 tok = strtok(NULL, ",");
215 area_size = strtol(tok, NULL, 0);
217 tok = strtok(NULL, ",");
224 if (address || area_size) {
226 snprintf(cmd, sizeof(cmd), "SetRTTAddr 0x%x", address);
228 snprintf(cmd, sizeof(cmd),
229 "SetRTTSearchRanges 0x%x 0x%x",
232 if (jlink.execcommand(cmd, NULL, 0) < 0)
236 if (jlink.rtterminal_control(RTT_CONTROL_START, NULL) < 0) {
237 fprintf(stderr, "Failed to initialize RTT\n");
241 /* RTT may need some time to find control block so we need to wait */
244 rtt_dir = RTT_DIRECTION_UP;
245 count = jlink.rtterminal_control(RTT_CONTROL_GET_NUM_BUF,
249 for (i = 0; i < count; i++) {
250 memset(&rtt_desc, 0, sizeof(rtt_desc));
252 rtt_desc.direction = RTT_DIRECTION_UP;
254 if (jlink.rtterminal_control(RTT_CONTROL_GET_DESC,
258 if (rtt_desc.size > 0 && !strcmp(buffer, rtt_desc.name))
265 printf("Using RTT up buffer #%d (size: %d)\n", i, rtt_desc.size);
270 int jlink_rtt_read(void *buf, size_t size)
272 return jlink.rtterminal_read(rtt_desc.index, buf, size);