Use error description in log messages
[libjaylink.git] / libjaylink / swo.c
blob07e5f0374671368b138144ea3e4494619d0a6f8e
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2015 Marc Schink <jaylink-dev@marcschink.de>
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.
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.
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/>.
20 #include <stdint.h>
21 #include <stdbool.h>
23 #include "libjaylink.h"
24 #include "libjaylink-internal.h"
26 /**
27 * @file
29 * Serial Wire Output (SWO) functions.
32 /** @cond PRIVATE */
33 #define CMD_SWO 0xeb
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
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 /** @endcond */
46 /**
47 * Start SWO capture.
49 * @note This function must be used only if the device has the
50 * #JAYLINK_DEV_CAP_SWO capability.
52 * @param[in,out] devh Device handle.
53 * @param[in] mode Mode to capture data with.
54 * @param[in] baudrate Baudrate to capture data in bit per second.
55 * @param[in] size Device internal buffer size in bytes to use for capturing.
57 * @retval JAYLINK_OK Success.
58 * @retval JAYLINK_ERR_ARG Invalid arguments.
59 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
60 * @retval JAYLINK_ERR_DEV Unspecified device error.
61 * @retval JAYLINK_ERR Other error conditions.
63 * @see jaylink_swo_get_speeds()
64 * @see jaylink_get_free_memory()
66 * @since 0.1.0
68 JAYLINK_API int jaylink_swo_start(struct jaylink_device_handle *devh,
69 enum jaylink_swo_mode mode, uint32_t baudrate, uint32_t size)
71 int ret;
72 struct jaylink_context *ctx;
73 uint8_t buf[32];
74 uint32_t tmp;
76 if (!devh || !baudrate || !size)
77 return JAYLINK_ERR_ARG;
79 if (mode != JAYLINK_SWO_MODE_UART)
80 return JAYLINK_ERR_ARG;
82 ctx = devh->dev->ctx;
83 ret = transport_start_write_read(devh, 21, 4, true);
85 if (ret != JAYLINK_OK) {
86 log_err(ctx, "transport_start_write_read() failed: %s.",
87 jaylink_strerror(ret));
88 return ret;
91 buf[0] = CMD_SWO;
92 buf[1] = SWO_CMD_START;
94 buf[2] = 0x04;
95 buf[3] = SWO_PARAM_MODE;
96 buffer_set_u32(buf, mode, 4);
98 buf[8] = 0x04;
99 buf[9] = SWO_PARAM_BAUDRATE;
100 buffer_set_u32(buf, baudrate, 10);
102 buf[14] = 0x04;
103 buf[15] = SWO_PARAM_BUFFER_SIZE;
104 buffer_set_u32(buf, size, 16);
106 buf[20] = 0x00;
108 ret = transport_write(devh, buf, 21);
110 if (ret != JAYLINK_OK) {
111 log_err(ctx, "transport_write() failed: %s.",
112 jaylink_strerror(ret));
113 return ret;
116 ret = transport_read(devh, buf, 4);
118 if (ret != JAYLINK_OK) {
119 log_err(ctx, "transport_read() failed: %s.",
120 jaylink_strerror(ret));
121 return ret;
124 tmp = buffer_get_u32(buf, 0);
126 if (tmp > 0) {
127 log_err(ctx, "Failed to start capture: %u.", tmp);
128 return JAYLINK_ERR_DEV;
131 return JAYLINK_OK;
135 * Stop SWO capture.
137 * @note This function must be used only if the device has the
138 * #JAYLINK_DEV_CAP_SWO capability.
140 * @param[in,out] devh Device handle.
142 * @retval JAYLINK_OK Success.
143 * @retval JAYLINK_ERR_ARG Invalid arguments.
144 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
145 * @retval JAYLINK_ERR_DEV Unspecified device error.
146 * @retval JAYLINK_ERR Other error conditions.
148 * @see jaylink_swo_start()
150 * @since 0.1.0
152 JAYLINK_API int jaylink_swo_stop(struct jaylink_device_handle *devh)
154 int ret;
155 struct jaylink_context *ctx;
156 uint8_t buf[4];
157 uint32_t tmp;
159 if (!devh)
160 return JAYLINK_ERR_ARG;
162 ctx = devh->dev->ctx;
163 ret = transport_start_write_read(devh, 3, 4, true);
165 if (ret != JAYLINK_OK) {
166 log_err(ctx, "transport_start_write_read() failed: %s.",
167 jaylink_strerror(ret));
168 return ret;
171 buf[0] = CMD_SWO;
172 buf[1] = SWO_CMD_STOP;
173 buf[2] = 0x00;
175 ret = transport_write(devh, buf, 3);
177 if (ret != JAYLINK_OK) {
178 log_err(ctx, "transport_write() failed: %s.",
179 jaylink_strerror(ret));
180 return ret;
183 ret = transport_read(devh, buf, 4);
185 if (ret != JAYLINK_OK) {
186 log_err(ctx, "transport_read() failed: %s.",
187 jaylink_strerror(ret));
188 return ret;
191 tmp = buffer_get_u32(buf, 0);
193 if (tmp > 0) {
194 log_err(ctx, "Failed to stop capture: %u.", tmp);
195 return JAYLINK_ERR_DEV;
198 return JAYLINK_OK;
202 * Read SWO trace data.
204 * @note This function must be used only if the device has the
205 * #JAYLINK_DEV_CAP_SWO capability.
207 * @param[in,out] devh Device handle.
208 * @param[out] buffer Buffer to store trace data on success. Its content is
209 * undefined on failure.
210 * @param[in,out] length Maximum number of bytes to read. On success, the value
211 * gets updated with the actual number of bytes read. The
212 * value is undefined on failure.
214 * @retval JAYLINK_OK Success.
215 * @retval JAYLINK_ERR_ARG Invalid arguments.
216 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
217 * @retval JAYLINK_ERR_PROTO Protocol violation.
218 * @retval JAYLINK_ERR_DEV Unspecified device error.
219 * @retval JAYLINK_ERR Other error conditions.
221 * @see jaylink_swo_start()
223 * @since 0.1.0
225 JAYLINK_API int jaylink_swo_read(struct jaylink_device_handle *devh,
226 uint8_t *buffer, uint32_t *length)
228 int ret;
229 struct jaylink_context *ctx;
230 uint8_t buf[32];
231 uint32_t tmp;
233 if (!devh || !buffer || !length)
234 return JAYLINK_ERR_ARG;
236 ctx = devh->dev->ctx;
237 ret = transport_start_write_read(devh, 9, 8, true);
239 if (ret != JAYLINK_OK) {
240 log_err(ctx, "transport_start_write_read() failed: %s.",
241 jaylink_strerror(ret));
242 return ret;
245 buf[0] = CMD_SWO;
246 buf[1] = SWO_CMD_READ;
248 buf[2] = 0x04;
249 buf[3] = SWO_PARAM_READ_SIZE;
250 buffer_set_u32(buf, *length, 4);
252 buf[8] = 0x00;
254 ret = transport_write(devh, buf, 9);
256 if (ret != JAYLINK_OK) {
257 log_err(ctx, "transport_write() failed: %s.",
258 jaylink_strerror(ret));
259 return ret;
262 ret = transport_read(devh, buf, 8);
264 if (ret != JAYLINK_OK) {
265 log_err(ctx, "transport_read() failed: %s.",
266 jaylink_strerror(ret));
267 return ret;
270 tmp = buffer_get_u32(buf, 0);
272 if (tmp > 0) {
273 log_err(ctx, "Failed to read data: %u.", tmp);
274 return JAYLINK_ERR_DEV;
277 tmp = buffer_get_u32(buf, 4);
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;
285 *length = tmp;
287 if (tmp > 0) {
288 ret = transport_start_read(devh, tmp);
290 if (ret != JAYLINK_OK) {
291 log_err(ctx, "transport_start_read() failed: %s.",
292 jaylink_strerror(ret));
293 return ret;
296 ret = transport_read(devh, buffer, tmp);
298 if (ret != JAYLINK_OK) {
299 log_err(ctx, "transport_read() failed: %s.",
300 jaylink_strerror(ret));
301 return ret;
305 return JAYLINK_OK;
309 * Retrieve SWO speeds.
311 * The speeds are calculated as follows:
313 * @par
314 * <tt>speeds = @a freq / n</tt> with <tt>n >= @a min_div</tt> and
315 * <tt>n <= @a max_div</tt>, where @p n is an integer
317 * Assuming, for example, a base frequency @a freq of 4500 kHz, a minimum
318 * divider @a min_div of 1 and a maximum divider @a max_div of 8 then the
319 * highest possible SWO speed is 4500 kHz / 1 = 4500 kHz. The next highest
320 * speed is 2250 kHz for a divider of 2, and so on. Accordingly, the lowest
321 * possible speed is 4500 kHz / 8 = 562.5 kHz.
323 * @note This function must be used only if the device has the
324 * #JAYLINK_DEV_CAP_SWO capability.
326 * @param[in,out] devh Device handle.
327 * @param[in] mode Capture mode to retrieve speeds for.
328 * @param[out] speed Speed information on success, and undefined on failure.
330 * @retval JAYLINK_OK Success.
331 * @retval JAYLINK_ERR_ARG Invalid arguments.
332 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
333 * @retval JAYLINK_ERR_PROTO Protocol violation.
334 * @retval JAYLINK_ERR_DEV Unspecified device error.
335 * @retval JAYLINK_ERR Other error conditions.
337 * @since 0.1.0
339 JAYLINK_API int jaylink_swo_get_speeds(struct jaylink_device_handle *devh,
340 enum jaylink_swo_mode mode, struct jaylink_swo_speed *speed)
342 int ret;
343 struct jaylink_context *ctx;
344 uint8_t buf[24];
345 uint32_t length;
347 if (!devh || !speed)
348 return JAYLINK_ERR_ARG;
350 if (mode != JAYLINK_SWO_MODE_UART)
351 return JAYLINK_ERR_ARG;
353 ctx = devh->dev->ctx;
354 ret = transport_start_write_read(devh, 9, 4, true);
356 if (ret != JAYLINK_OK) {
357 log_err(ctx, "transport_start_write_read() failed: %s.",
358 jaylink_strerror(ret));
359 return ret;
362 buf[0] = CMD_SWO;
363 buf[1] = SWO_CMD_GET_SPEEDS;
365 buf[2] = 0x04;
366 buf[3] = SWO_PARAM_MODE;
367 buffer_set_u32(buf, mode, 4);
369 buf[8] = 0x00;
371 ret = transport_write(devh, buf, 9);
373 if (ret != JAYLINK_OK) {
374 log_err(ctx, "transport_write() failed: %s.",
375 jaylink_strerror(ret));
376 return ret;
379 ret = transport_read(devh, buf, 4);
381 if (ret != JAYLINK_OK) {
382 log_err(ctx, "transport_read() failed: %s.",
383 jaylink_strerror(ret));
384 return ret;
387 length = buffer_get_u32(buf, 0);
389 if (length == 0xffffffff) {
390 log_err(ctx, "Failed to retrieve speed information.");
391 return JAYLINK_ERR_DEV;
394 if (length != 28) {
395 log_err(ctx, "Unexpected number of bytes received: %u.",
396 length);
397 return JAYLINK_ERR_PROTO;
400 length = length - 4;
401 ret = transport_start_read(devh, length);
403 if (ret != JAYLINK_OK) {
404 log_err(ctx, "transport_start_read() failed: %s.",
405 jaylink_strerror(ret));
406 return ret;
409 ret = transport_read(devh, buf, length);
411 if (ret != JAYLINK_OK) {
412 log_err(ctx, "transport_read() failed: %s.",
413 jaylink_strerror(ret));
414 return ret;
417 speed->freq = buffer_get_u32(buf, 4);
418 speed->min_div = buffer_get_u32(buf, 8);
420 if (!speed->min_div) {
421 log_err(ctx, "Minimum frequency divider is zero.");
422 return JAYLINK_ERR_PROTO;
425 speed->max_div = buffer_get_u32(buf, 12);
427 if (speed->max_div < speed->min_div) {
428 log_err(ctx, "Maximum frequency divider is less than minimum "
429 "frequency divider.");
430 return JAYLINK_ERR_PROTO;
433 speed->min_prescaler = buffer_get_u32(buf, 16);
434 speed->max_prescaler = buffer_get_u32(buf, 20);
436 if (speed->max_prescaler < speed->min_prescaler) {
437 log_err(ctx, "Maximum prescaler is less than minimum "
438 "prescaler.");
439 return JAYLINK_ERR_PROTO;
442 return JAYLINK_OK;