OpenOCD
swo.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libjaylink project.
3  *
4  * Copyright (C) 2015 Marc Schink <jaylink-dev@marcschink.de>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <stdint.h>
21 #include <stdbool.h>
22 
23 #include "libjaylink.h"
24 #include "libjaylink-internal.h"
25 
33 #define CMD_SWO 0xeb
34 
35 #define SWO_CMD_START 0x64
36 #define SWO_CMD_STOP 0x65
37 #define SWO_CMD_READ 0x66
38 #define SWO_CMD_GET_SPEEDS 0x6e
39 
40 #define SWO_PARAM_MODE 0x01
41 #define SWO_PARAM_BAUDRATE 0x02
42 #define SWO_PARAM_READ_SIZE 0x03
43 #define SWO_PARAM_BUFFER_SIZE 0x04
44 
45 #define SWO_ERR 0x80000000
46 
72  enum jaylink_swo_mode mode, uint32_t baudrate, uint32_t size)
73 {
74  int ret;
75  struct jaylink_context *ctx;
76  uint8_t buf[32];
77  uint32_t status;
78 
79  if (!devh || !baudrate || !size)
80  return JAYLINK_ERR_ARG;
81 
82  if (mode != JAYLINK_SWO_MODE_UART)
83  return JAYLINK_ERR_ARG;
84 
85  ctx = devh->dev->ctx;
86  ret = transport_start_write_read(devh, 21, 4, true);
87 
88  if (ret != JAYLINK_OK) {
89  log_err(ctx, "transport_start_write_read() failed: %s.",
90  jaylink_strerror(ret));
91  return ret;
92  }
93 
94  buf[0] = CMD_SWO;
95  buf[1] = SWO_CMD_START;
96 
97  buf[2] = 0x04;
98  buf[3] = SWO_PARAM_MODE;
99  buffer_set_u32(buf, mode, 4);
100 
101  buf[8] = 0x04;
102  buf[9] = SWO_PARAM_BAUDRATE;
103  buffer_set_u32(buf, baudrate, 10);
104 
105  buf[14] = 0x04;
106  buf[15] = SWO_PARAM_BUFFER_SIZE;
107  buffer_set_u32(buf, size, 16);
108 
109  buf[20] = 0x00;
110 
111  ret = transport_write(devh, buf, 21);
112 
113  if (ret != JAYLINK_OK) {
114  log_err(ctx, "transport_write() failed: %s.",
115  jaylink_strerror(ret));
116  return ret;
117  }
118 
119  ret = transport_read(devh, buf, 4);
120 
121  if (ret != JAYLINK_OK) {
122  log_err(ctx, "transport_read() failed: %s.",
123  jaylink_strerror(ret));
124  return ret;
125  }
126 
127  status = buffer_get_u32(buf, 0);
128 
129  if (status > 0) {
130  log_err(ctx, "Failed to start capture: 0x%x.", status);
131  return JAYLINK_ERR_DEV;
132  }
133 
134  return JAYLINK_OK;
135 }
136 
157 {
158  int ret;
159  struct jaylink_context *ctx;
160  uint8_t buf[4];
161  uint32_t status;
162 
163  if (!devh)
164  return JAYLINK_ERR_ARG;
165 
166  ctx = devh->dev->ctx;
167  ret = transport_start_write_read(devh, 3, 4, true);
168 
169  if (ret != JAYLINK_OK) {
170  log_err(ctx, "transport_start_write_read() failed: %s.",
171  jaylink_strerror(ret));
172  return ret;
173  }
174 
175  buf[0] = CMD_SWO;
176  buf[1] = SWO_CMD_STOP;
177  buf[2] = 0x00;
178 
179  ret = transport_write(devh, buf, 3);
180 
181  if (ret != JAYLINK_OK) {
182  log_err(ctx, "transport_write() failed: %s.",
183  jaylink_strerror(ret));
184  return ret;
185  }
186 
187  ret = transport_read(devh, buf, 4);
188 
189  if (ret != JAYLINK_OK) {
190  log_err(ctx, "transport_read() failed: %s.",
191  jaylink_strerror(ret));
192  return ret;
193  }
194 
195  status = buffer_get_u32(buf, 0);
196 
197  if (status > 0) {
198  log_err(ctx, "Failed to stop capture: 0x%x.", status);
199  return JAYLINK_ERR_DEV;
200  }
201 
202  return JAYLINK_OK;
203 }
204 
231  uint8_t *buffer, uint32_t *length)
232 {
233  int ret;
234  struct jaylink_context *ctx;
235  uint8_t buf[32];
236  uint32_t status;
237  uint32_t tmp;
238 
239  if (!devh || !buffer || !length)
240  return JAYLINK_ERR_ARG;
241 
242  ctx = devh->dev->ctx;
243  ret = transport_start_write_read(devh, 9, 8, true);
244 
245  if (ret != JAYLINK_OK) {
246  log_err(ctx, "transport_start_write_read() failed: %s.",
247  jaylink_strerror(ret));
248  return ret;
249  }
250 
251  buf[0] = CMD_SWO;
252  buf[1] = SWO_CMD_READ;
253 
254  buf[2] = 0x04;
255  buf[3] = SWO_PARAM_READ_SIZE;
256  buffer_set_u32(buf, *length, 4);
257 
258  buf[8] = 0x00;
259 
260  ret = transport_write(devh, buf, 9);
261 
262  if (ret != JAYLINK_OK) {
263  log_err(ctx, "transport_write() failed: %s.",
264  jaylink_strerror(ret));
265  return ret;
266  }
267 
268  ret = transport_read(devh, buf, 8);
269 
270  if (ret != JAYLINK_OK) {
271  log_err(ctx, "transport_read() failed: %s.",
272  jaylink_strerror(ret));
273  return ret;
274  }
275 
276  status = buffer_get_u32(buf, 0);
277  tmp = buffer_get_u32(buf, 4);
278 
279  if (tmp > *length) {
280  log_err(ctx, "Received %u bytes but only %u bytes were "
281  "requested.", tmp, *length);
282  return JAYLINK_ERR_PROTO;
283  }
284 
285  *length = tmp;
286 
287  if (tmp > 0) {
288  ret = transport_start_read(devh, tmp);
289 
290  if (ret != JAYLINK_OK) {
291  log_err(ctx, "transport_start_read() failed: %s.",
292  jaylink_strerror(ret));
293  return ret;
294  }
295 
296  ret = transport_read(devh, buffer, tmp);
297 
298  if (ret != JAYLINK_OK) {
299  log_err(ctx, "transport_read() failed: %s.",
300  jaylink_strerror(ret));
301  return ret;
302  }
303  }
304 
305  if (status > 0) {
306  log_err(ctx, "Failed to read data: 0x%x.", status);
307  return JAYLINK_ERR_DEV;
308  }
309 
310  return JAYLINK_OK;
311 }
312 
346  enum jaylink_swo_mode mode, struct jaylink_swo_speed *speed)
347 {
348  int ret;
349  struct jaylink_context *ctx;
350  uint8_t buf[24];
351  uint32_t tmp;
352  uint32_t length;
353 
354  if (!devh || !speed)
355  return JAYLINK_ERR_ARG;
356 
357  if (mode != JAYLINK_SWO_MODE_UART)
358  return JAYLINK_ERR_ARG;
359 
360  ctx = devh->dev->ctx;
361  ret = transport_start_write_read(devh, 9, 4, true);
362 
363  if (ret != JAYLINK_OK) {
364  log_err(ctx, "transport_start_write_read() failed: %s.",
365  jaylink_strerror(ret));
366  return ret;
367  }
368 
369  buf[0] = CMD_SWO;
370  buf[1] = SWO_CMD_GET_SPEEDS;
371 
372  buf[2] = 0x04;
373  buf[3] = SWO_PARAM_MODE;
374  buffer_set_u32(buf, mode, 4);
375 
376  buf[8] = 0x00;
377 
378  ret = transport_write(devh, buf, 9);
379 
380  if (ret != JAYLINK_OK) {
381  log_err(ctx, "transport_write() failed: %s.",
382  jaylink_strerror(ret));
383  return ret;
384  }
385 
386  ret = transport_read(devh, buf, 4);
387 
388  if (ret != JAYLINK_OK) {
389  log_err(ctx, "transport_read() failed: %s.",
390  jaylink_strerror(ret));
391  return ret;
392  }
393 
394  tmp = buffer_get_u32(buf, 0);
395 
396  if (tmp & SWO_ERR) {
397  log_err(ctx, "Failed to retrieve speed information: 0x%x.",
398  tmp);
399  return JAYLINK_ERR_DEV;
400  }
401 
402  length = tmp;
403 
404  if (length != 28) {
405  log_err(ctx, "Unexpected number of bytes received: %u.",
406  length);
407  return JAYLINK_ERR_PROTO;
408  }
409 
410  length = length - 4;
411  ret = transport_start_read(devh, length);
412 
413  if (ret != JAYLINK_OK) {
414  log_err(ctx, "transport_start_read() failed: %s.",
415  jaylink_strerror(ret));
416  return ret;
417  }
418 
419  ret = transport_read(devh, buf, length);
420 
421  if (ret != JAYLINK_OK) {
422  log_err(ctx, "transport_read() failed: %s.",
423  jaylink_strerror(ret));
424  return ret;
425  }
426 
427  speed->freq = buffer_get_u32(buf, 4);
428  speed->min_div = buffer_get_u32(buf, 8);
429 
430  if (!speed->min_div) {
431  log_err(ctx, "Minimum frequency divider is zero.");
432  return JAYLINK_ERR_PROTO;
433  }
434 
435  speed->max_div = buffer_get_u32(buf, 12);
436 
437  if (speed->max_div < speed->min_div) {
438  log_err(ctx, "Maximum frequency divider is less than minimum "
439  "frequency divider.");
440  return JAYLINK_ERR_PROTO;
441  }
442 
443  speed->min_prescaler = buffer_get_u32(buf, 16);
444  speed->max_prescaler = buffer_get_u32(buf, 20);
445 
446  if (speed->max_prescaler < speed->min_prescaler) {
447  log_err(ctx, "Maximum prescaler is less than minimum "
448  "prescaler.");
449  return JAYLINK_ERR_PROTO;
450  }
451 
452  return JAYLINK_OK;
453 }
JAYLINK_API int jaylink_swo_read(struct jaylink_device_handle *devh, uint8_t *buffer, uint32_t *length)
Read SWO trace data.
Definition: swo.c:230
JAYLINK_PRIV uint32_t buffer_get_u32(const uint8_t *buffer, size_t offset)
Read a 32-bit unsigned integer value from a buffer.
Definition: buffer.c:122
enum arm_mode mode
Definition: armv4_5.c:288
JAYLINK_API int jaylink_swo_start(struct jaylink_device_handle *devh, enum jaylink_swo_mode mode, uint32_t baudrate, uint32_t size)
Start SWO capture.
Definition: swo.c:71
JAYLINK_API int jaylink_swo_stop(struct jaylink_device_handle *devh)
Stop SWO capture.
Definition: swo.c:156
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:37
JAYLINK_API const char * jaylink_strerror(int error_code)
Return a human-readable description of a libjaylink error code.
Definition: error.c:40
JAYLINK_API int jaylink_swo_get_speeds(struct jaylink_device_handle *devh, enum jaylink_swo_mode mode, struct jaylink_swo_speed *speed)
Retrieve SWO speeds.
Definition: swo.c:345
JAYLINK_PRIV void buffer_set_u32(uint8_t *buffer, uint32_t value, size_t offset)
Write a 32-bit unsigned integer value to a buffer.
Definition: buffer.c:95