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/>.
23 #include "libjaylink.h"
24 #include "libjaylink-internal.h"
29 * Serial Wire Output (SWO) functions.
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
45 #define SWO_ERR 0x80000000
51 * @note This function must be used only if the device has the
52 * #JAYLINK_DEV_CAP_SWO capability.
54 * @param[in,out] devh Device handle.
55 * @param[in] mode Mode to capture data with.
56 * @param[in] baudrate Baudrate to capture data in bit per second.
57 * @param[in] size Device internal buffer size in bytes to use for capturing.
59 * @retval JAYLINK_OK Success.
60 * @retval JAYLINK_ERR_ARG Invalid arguments.
61 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
62 * @retval JAYLINK_ERR_IO Input/output error.
63 * @retval JAYLINK_ERR_DEV Unspecified device error.
64 * @retval JAYLINK_ERR Other error conditions.
66 * @see jaylink_swo_get_speeds()
67 * @see jaylink_get_free_memory()
71 JAYLINK_API
int jaylink_swo_start(struct jaylink_device_handle
*devh
,
72 enum jaylink_swo_mode mode
, uint32_t baudrate
, uint32_t size
)
75 struct jaylink_context
*ctx
;
79 if (!devh
|| !baudrate
|| !size
)
80 return JAYLINK_ERR_ARG
;
82 if (mode
!= JAYLINK_SWO_MODE_UART
)
83 return JAYLINK_ERR_ARG
;
86 ret
= transport_start_write_read(devh
, 21, 4, true);
88 if (ret
!= JAYLINK_OK
) {
89 log_err(ctx
, "transport_start_write_read() failed: %s",
90 jaylink_strerror(ret
));
95 buf
[1] = SWO_CMD_START
;
98 buf
[3] = SWO_PARAM_MODE
;
99 buffer_set_u32(buf
, mode
, 4);
102 buf
[9] = SWO_PARAM_BAUDRATE
;
103 buffer_set_u32(buf
, baudrate
, 10);
106 buf
[15] = SWO_PARAM_BUFFER_SIZE
;
107 buffer_set_u32(buf
, size
, 16);
111 ret
= transport_write(devh
, buf
, 21);
113 if (ret
!= JAYLINK_OK
) {
114 log_err(ctx
, "transport_write() failed: %s",
115 jaylink_strerror(ret
));
119 ret
= transport_read(devh
, buf
, 4);
121 if (ret
!= JAYLINK_OK
) {
122 log_err(ctx
, "transport_read() failed: %s",
123 jaylink_strerror(ret
));
127 status
= buffer_get_u32(buf
, 0);
130 log_err(ctx
, "Failed to start capture: 0x%x", status
);
131 return JAYLINK_ERR_DEV
;
140 * @note This function must be used only if the device has the
141 * #JAYLINK_DEV_CAP_SWO capability.
143 * @param[in,out] devh Device handle.
145 * @retval JAYLINK_OK Success.
146 * @retval JAYLINK_ERR_ARG Invalid arguments.
147 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
148 * @retval JAYLINK_ERR_IO Input/output error.
149 * @retval JAYLINK_ERR_DEV Unspecified device error.
150 * @retval JAYLINK_ERR Other error conditions.
152 * @see jaylink_swo_start()
156 JAYLINK_API
int jaylink_swo_stop(struct jaylink_device_handle
*devh
)
159 struct jaylink_context
*ctx
;
164 return JAYLINK_ERR_ARG
;
166 ctx
= devh
->dev
->ctx
;
167 ret
= transport_start_write_read(devh
, 3, 4, true);
169 if (ret
!= JAYLINK_OK
) {
170 log_err(ctx
, "transport_start_write_read() failed: %s",
171 jaylink_strerror(ret
));
176 buf
[1] = SWO_CMD_STOP
;
179 ret
= transport_write(devh
, buf
, 3);
181 if (ret
!= JAYLINK_OK
) {
182 log_err(ctx
, "transport_write() failed: %s",
183 jaylink_strerror(ret
));
187 ret
= transport_read(devh
, buf
, 4);
189 if (ret
!= JAYLINK_OK
) {
190 log_err(ctx
, "transport_read() failed: %s",
191 jaylink_strerror(ret
));
195 status
= buffer_get_u32(buf
, 0);
198 log_err(ctx
, "Failed to stop capture: 0x%x", status
);
199 return JAYLINK_ERR_DEV
;
206 * Read SWO trace data.
208 * @note This function must be used only if the device has the
209 * #JAYLINK_DEV_CAP_SWO capability.
211 * @param[in,out] devh Device handle.
212 * @param[out] buffer Buffer to store trace data on success. Its content is
213 * undefined on failure.
214 * @param[in,out] length Maximum number of bytes to read. On success, the value
215 * gets updated with the actual number of bytes read. The
216 * value is undefined on failure.
218 * @retval JAYLINK_OK Success.
219 * @retval JAYLINK_ERR_ARG Invalid arguments.
220 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
221 * @retval JAYLINK_ERR_PROTO Protocol violation.
222 * @retval JAYLINK_ERR_IO Input/output error.
223 * @retval JAYLINK_ERR_DEV Unspecified device error.
224 * @retval JAYLINK_ERR Other error conditions.
226 * @see jaylink_swo_start()
230 JAYLINK_API
int jaylink_swo_read(struct jaylink_device_handle
*devh
,
231 uint8_t *buffer
, uint32_t *length
)
234 struct jaylink_context
*ctx
;
239 if (!devh
|| !buffer
|| !length
)
240 return JAYLINK_ERR_ARG
;
242 ctx
= devh
->dev
->ctx
;
243 ret
= transport_start_write_read(devh
, 9, 8, true);
245 if (ret
!= JAYLINK_OK
) {
246 log_err(ctx
, "transport_start_write_read() failed: %s",
247 jaylink_strerror(ret
));
252 buf
[1] = SWO_CMD_READ
;
255 buf
[3] = SWO_PARAM_READ_SIZE
;
256 buffer_set_u32(buf
, *length
, 4);
260 ret
= transport_write(devh
, buf
, 9);
262 if (ret
!= JAYLINK_OK
) {
263 log_err(ctx
, "transport_write() failed: %s",
264 jaylink_strerror(ret
));
268 ret
= transport_read(devh
, buf
, 8);
270 if (ret
!= JAYLINK_OK
) {
271 log_err(ctx
, "transport_read() failed: %s",
272 jaylink_strerror(ret
));
276 status
= buffer_get_u32(buf
, 0);
277 tmp
= buffer_get_u32(buf
, 4);
280 log_err(ctx
, "Received %u bytes but only %u bytes were "
281 "requested", tmp
, *length
);
282 return JAYLINK_ERR_PROTO
;
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
));
296 ret
= transport_read(devh
, buffer
, tmp
);
298 if (ret
!= JAYLINK_OK
) {
299 log_err(ctx
, "transport_read() failed: %s",
300 jaylink_strerror(ret
));
306 log_err(ctx
, "Failed to read data: 0x%x", status
);
307 return JAYLINK_ERR_DEV
;
314 * Retrieve SWO speeds.
316 * The speeds are calculated as follows:
319 * <tt>speeds = @a freq / n</tt> with <tt>n >= @a min_div</tt> and
320 * <tt>n <= @a max_div</tt>, where @p n is an integer
322 * Assuming, for example, a base frequency @a freq of 4500 kHz, a minimum
323 * divider @a min_div of 1 and a maximum divider @a max_div of 8 then the
324 * highest possible SWO speed is 4500 kHz / 1 = 4500 kHz. The next highest
325 * speed is 2250 kHz for a divider of 2, and so on. Accordingly, the lowest
326 * possible speed is 4500 kHz / 8 = 562.5 kHz.
328 * @note This function must be used only if the device has the
329 * #JAYLINK_DEV_CAP_SWO capability.
331 * @param[in,out] devh Device handle.
332 * @param[in] mode Capture mode to retrieve speeds for.
333 * @param[out] speed Speed information on success, and undefined on failure.
335 * @retval JAYLINK_OK Success.
336 * @retval JAYLINK_ERR_ARG Invalid arguments.
337 * @retval JAYLINK_ERR_TIMEOUT A timeout occurred.
338 * @retval JAYLINK_ERR_PROTO Protocol violation.
339 * @retval JAYLINK_ERR_IO Input/output error.
340 * @retval JAYLINK_ERR_DEV Unspecified device error.
341 * @retval JAYLINK_ERR Other error conditions.
345 JAYLINK_API
int jaylink_swo_get_speeds(struct jaylink_device_handle
*devh
,
346 enum jaylink_swo_mode mode
, struct jaylink_swo_speed
*speed
)
349 struct jaylink_context
*ctx
;
355 return JAYLINK_ERR_ARG
;
357 if (mode
!= JAYLINK_SWO_MODE_UART
)
358 return JAYLINK_ERR_ARG
;
360 ctx
= devh
->dev
->ctx
;
361 ret
= transport_start_write_read(devh
, 9, 4, true);
363 if (ret
!= JAYLINK_OK
) {
364 log_err(ctx
, "transport_start_write_read() failed: %s",
365 jaylink_strerror(ret
));
370 buf
[1] = SWO_CMD_GET_SPEEDS
;
373 buf
[3] = SWO_PARAM_MODE
;
374 buffer_set_u32(buf
, mode
, 4);
378 ret
= transport_write(devh
, buf
, 9);
380 if (ret
!= JAYLINK_OK
) {
381 log_err(ctx
, "transport_write() failed: %s",
382 jaylink_strerror(ret
));
386 ret
= transport_read(devh
, buf
, 4);
388 if (ret
!= JAYLINK_OK
) {
389 log_err(ctx
, "transport_read() failed: %s",
390 jaylink_strerror(ret
));
394 tmp
= buffer_get_u32(buf
, 0);
397 log_err(ctx
, "Failed to retrieve speed information: 0x%x",
399 return JAYLINK_ERR_DEV
;
405 log_err(ctx
, "Unexpected number of bytes received: %u",
407 return JAYLINK_ERR_PROTO
;
411 ret
= transport_start_read(devh
, length
);
413 if (ret
!= JAYLINK_OK
) {
414 log_err(ctx
, "transport_start_read() failed: %s",
415 jaylink_strerror(ret
));
419 ret
= transport_read(devh
, buf
, length
);
421 if (ret
!= JAYLINK_OK
) {
422 log_err(ctx
, "transport_read() failed: %s",
423 jaylink_strerror(ret
));
427 speed
->freq
= buffer_get_u32(buf
, 4);
428 speed
->min_div
= buffer_get_u32(buf
, 8);
430 if (!speed
->min_div
) {
431 log_err(ctx
, "Minimum frequency divider is zero");
432 return JAYLINK_ERR_PROTO
;
435 speed
->max_div
= buffer_get_u32(buf
, 12);
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
;
443 speed
->min_prescaler
= buffer_get_u32(buf
, 16);
444 speed
->max_prescaler
= buffer_get_u32(buf
, 20);
446 if (speed
->max_prescaler
< speed
->min_prescaler
) {
447 log_err(ctx
, "Maximum prescaler is less than minimum "
449 return JAYLINK_ERR_PROTO
;