Rename JTAG command version enums
[libjaylink.git] / libjaylink / swo.c
blob79d08d941c60d3e63f7a1a99182566ad287072c9
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_IO Input/output error.
61 * @retval JAYLINK_ERR_DEV Unspecified device error.
62 * @retval JAYLINK_ERR Other error conditions.
64 * @see jaylink_swo_get_speeds()
65 * @see jaylink_get_free_memory()
67 * @since 0.1.0
69 JAYLINK_API int jaylink_swo_start(struct jaylink_device_handle *devh,
70 enum jaylink_swo_mode mode, uint32_t baudrate, uint32_t size)
72 int ret;
73 struct jaylink_context *ctx;
74 uint8_t buf[32];
75 uint32_t tmp;
77 if (!devh || !baudrate || !size)
78 return JAYLINK_ERR_ARG;
80 if (mode != JAYLINK_SWO_MODE_UART)
81 return JAYLINK_ERR_ARG;
83 ctx = devh->dev->ctx;
84 ret = transport_start_write_read(devh, 21, 4, true);
86 if (ret != JAYLINK_OK) {
87 log_err(ctx, "transport_start_write_read() failed: %s.",
88 jaylink_strerror(ret));
89 return ret;
92 buf[0] = CMD_SWO;
93 buf[1] = SWO_CMD_START;
95 buf[2] = 0x04;
96 buf[3] = SWO_PARAM_MODE;
97 buffer_set_u32(buf, mode, 4);
99 buf[8] = 0x04;
100 buf[9] = SWO_PARAM_BAUDRATE;
101 buffer_set_u32(buf, baudrate, 10);
103 buf[14] = 0x04;
104 buf[15] = SWO_PARAM_BUFFER_SIZE;
105 buffer_set_u32(buf, size, 16);
107 buf[20] = 0x00;
109 ret = transport_write(devh, buf, 21);
111 if (ret != JAYLINK_OK) {
112 log_err(ctx, "transport_write() failed: %s.",
113 jaylink_strerror(ret));
114 return ret;
117 ret = transport_read(devh, buf, 4);
119 if (ret != JAYLINK_OK) {
120 log_err(ctx, "transport_read() failed: %s.",
121 jaylink_strerror(ret));
122 return ret;
125 tmp = buffer_get_u32(buf, 0);
127 if (tmp > 0) {
128 log_err(ctx, "Failed to start capture: %u.", tmp);
129 return JAYLINK_ERR_DEV;
132 return JAYLINK_OK;
136 * Stop SWO capture.
138 * @note This function must be used only if the device has the
139 * #JAYLINK_DEV_CAP_SWO capability.
141 * @param[in,out] devh Device handle.
143 * @retval JAYLINK_OK Success.
144 * @retval JAYLINK_ERR_ARG Invalid arguments.
145 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
146 * @retval JAYLINK_ERR_IO Input/output error.
147 * @retval JAYLINK_ERR_DEV Unspecified device error.
148 * @retval JAYLINK_ERR Other error conditions.
150 * @see jaylink_swo_start()
152 * @since 0.1.0
154 JAYLINK_API int jaylink_swo_stop(struct jaylink_device_handle *devh)
156 int ret;
157 struct jaylink_context *ctx;
158 uint8_t buf[4];
159 uint32_t tmp;
161 if (!devh)
162 return JAYLINK_ERR_ARG;
164 ctx = devh->dev->ctx;
165 ret = transport_start_write_read(devh, 3, 4, true);
167 if (ret != JAYLINK_OK) {
168 log_err(ctx, "transport_start_write_read() failed: %s.",
169 jaylink_strerror(ret));
170 return ret;
173 buf[0] = CMD_SWO;
174 buf[1] = SWO_CMD_STOP;
175 buf[2] = 0x00;
177 ret = transport_write(devh, buf, 3);
179 if (ret != JAYLINK_OK) {
180 log_err(ctx, "transport_write() failed: %s.",
181 jaylink_strerror(ret));
182 return ret;
185 ret = transport_read(devh, buf, 4);
187 if (ret != JAYLINK_OK) {
188 log_err(ctx, "transport_read() failed: %s.",
189 jaylink_strerror(ret));
190 return ret;
193 tmp = buffer_get_u32(buf, 0);
195 if (tmp > 0) {
196 log_err(ctx, "Failed to stop capture: %u.", tmp);
197 return JAYLINK_ERR_DEV;
200 return JAYLINK_OK;
204 * Read SWO trace data.
206 * @note This function must be used only if the device has the
207 * #JAYLINK_DEV_CAP_SWO capability.
209 * @param[in,out] devh Device handle.
210 * @param[out] buffer Buffer to store trace data on success. Its content is
211 * undefined on failure.
212 * @param[in,out] length Maximum number of bytes to read. On success, the value
213 * gets updated with the actual number of bytes read. The
214 * value is undefined on failure.
216 * @retval JAYLINK_OK Success.
217 * @retval JAYLINK_ERR_ARG Invalid arguments.
218 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
219 * @retval JAYLINK_ERR_PROTO Protocol violation.
220 * @retval JAYLINK_ERR_IO Input/output error.
221 * @retval JAYLINK_ERR_DEV Unspecified device error.
222 * @retval JAYLINK_ERR Other error conditions.
224 * @see jaylink_swo_start()
226 * @since 0.1.0
228 JAYLINK_API int jaylink_swo_read(struct jaylink_device_handle *devh,
229 uint8_t *buffer, uint32_t *length)
231 int ret;
232 struct jaylink_context *ctx;
233 uint8_t buf[32];
234 uint32_t status;
235 uint32_t tmp;
237 if (!devh || !buffer || !length)
238 return JAYLINK_ERR_ARG;
240 ctx = devh->dev->ctx;
241 ret = transport_start_write_read(devh, 9, 8, true);
243 if (ret != JAYLINK_OK) {
244 log_err(ctx, "transport_start_write_read() failed: %s.",
245 jaylink_strerror(ret));
246 return ret;
249 buf[0] = CMD_SWO;
250 buf[1] = SWO_CMD_READ;
252 buf[2] = 0x04;
253 buf[3] = SWO_PARAM_READ_SIZE;
254 buffer_set_u32(buf, *length, 4);
256 buf[8] = 0x00;
258 ret = transport_write(devh, buf, 9);
260 if (ret != JAYLINK_OK) {
261 log_err(ctx, "transport_write() failed: %s.",
262 jaylink_strerror(ret));
263 return ret;
266 ret = transport_read(devh, buf, 8);
268 if (ret != JAYLINK_OK) {
269 log_err(ctx, "transport_read() failed: %s.",
270 jaylink_strerror(ret));
271 return ret;
274 status = buffer_get_u32(buf, 0);
275 tmp = buffer_get_u32(buf, 4);
277 if (tmp > *length) {
278 log_err(ctx, "Received %u bytes but only %u bytes were "
279 "requested.", tmp, *length);
280 return JAYLINK_ERR_PROTO;
283 *length = tmp;
285 if (tmp > 0) {
286 ret = transport_start_read(devh, tmp);
288 if (ret != JAYLINK_OK) {
289 log_err(ctx, "transport_start_read() failed: %s.",
290 jaylink_strerror(ret));
291 return ret;
294 ret = transport_read(devh, buffer, tmp);
296 if (ret != JAYLINK_OK) {
297 log_err(ctx, "transport_read() failed: %s.",
298 jaylink_strerror(ret));
299 return ret;
303 if (status > 0) {
304 log_err(ctx, "Failed to read data: %u.", status);
305 return JAYLINK_ERR_DEV;
308 return JAYLINK_OK;
312 * Retrieve SWO speeds.
314 * The speeds are calculated as follows:
316 * @par
317 * <tt>speeds = @a freq / n</tt> with <tt>n >= @a min_div</tt> and
318 * <tt>n <= @a max_div</tt>, where @p n is an integer
320 * Assuming, for example, a base frequency @a freq of 4500 kHz, a minimum
321 * divider @a min_div of 1 and a maximum divider @a max_div of 8 then the
322 * highest possible SWO speed is 4500 kHz / 1 = 4500 kHz. The next highest
323 * speed is 2250 kHz for a divider of 2, and so on. Accordingly, the lowest
324 * possible speed is 4500 kHz / 8 = 562.5 kHz.
326 * @note This function must be used only if the device has the
327 * #JAYLINK_DEV_CAP_SWO capability.
329 * @param[in,out] devh Device handle.
330 * @param[in] mode Capture mode to retrieve speeds for.
331 * @param[out] speed Speed information on success, and undefined on failure.
333 * @retval JAYLINK_OK Success.
334 * @retval JAYLINK_ERR_ARG Invalid arguments.
335 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
336 * @retval JAYLINK_ERR_PROTO Protocol violation.
337 * @retval JAYLINK_ERR_IO Input/output error.
338 * @retval JAYLINK_ERR_DEV Unspecified device error.
339 * @retval JAYLINK_ERR Other error conditions.
341 * @since 0.1.0
343 JAYLINK_API int jaylink_swo_get_speeds(struct jaylink_device_handle *devh,
344 enum jaylink_swo_mode mode, struct jaylink_swo_speed *speed)
346 int ret;
347 struct jaylink_context *ctx;
348 uint8_t buf[24];
349 uint32_t length;
351 if (!devh || !speed)
352 return JAYLINK_ERR_ARG;
354 if (mode != JAYLINK_SWO_MODE_UART)
355 return JAYLINK_ERR_ARG;
357 ctx = devh->dev->ctx;
358 ret = transport_start_write_read(devh, 9, 4, true);
360 if (ret != JAYLINK_OK) {
361 log_err(ctx, "transport_start_write_read() failed: %s.",
362 jaylink_strerror(ret));
363 return ret;
366 buf[0] = CMD_SWO;
367 buf[1] = SWO_CMD_GET_SPEEDS;
369 buf[2] = 0x04;
370 buf[3] = SWO_PARAM_MODE;
371 buffer_set_u32(buf, mode, 4);
373 buf[8] = 0x00;
375 ret = transport_write(devh, buf, 9);
377 if (ret != JAYLINK_OK) {
378 log_err(ctx, "transport_write() failed: %s.",
379 jaylink_strerror(ret));
380 return ret;
383 ret = transport_read(devh, buf, 4);
385 if (ret != JAYLINK_OK) {
386 log_err(ctx, "transport_read() failed: %s.",
387 jaylink_strerror(ret));
388 return ret;
391 length = buffer_get_u32(buf, 0);
393 if (length == 0xffffffff) {
394 log_err(ctx, "Failed to retrieve speed information.");
395 return JAYLINK_ERR_DEV;
398 if (length != 28) {
399 log_err(ctx, "Unexpected number of bytes received: %u.",
400 length);
401 return JAYLINK_ERR_PROTO;
404 length = length - 4;
405 ret = transport_start_read(devh, length);
407 if (ret != JAYLINK_OK) {
408 log_err(ctx, "transport_start_read() failed: %s.",
409 jaylink_strerror(ret));
410 return ret;
413 ret = transport_read(devh, buf, length);
415 if (ret != JAYLINK_OK) {
416 log_err(ctx, "transport_read() failed: %s.",
417 jaylink_strerror(ret));
418 return ret;
421 speed->freq = buffer_get_u32(buf, 4);
422 speed->min_div = buffer_get_u32(buf, 8);
424 if (!speed->min_div) {
425 log_err(ctx, "Minimum frequency divider is zero.");
426 return JAYLINK_ERR_PROTO;
429 speed->max_div = buffer_get_u32(buf, 12);
431 if (speed->max_div < speed->min_div) {
432 log_err(ctx, "Maximum frequency divider is less than minimum "
433 "frequency divider.");
434 return JAYLINK_ERR_PROTO;
437 speed->min_prescaler = buffer_get_u32(buf, 16);
438 speed->max_prescaler = buffer_get_u32(buf, 20);
440 if (speed->max_prescaler < speed->min_prescaler) {
441 log_err(ctx, "Maximum prescaler is less than minimum "
442 "prescaler.");
443 return JAYLINK_ERR_PROTO;
446 return JAYLINK_OK;