OpenOCD
libjaylink/libjaylink/jtag.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libjaylink project.
3  *
4  * Copyright (C) 2014-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_JTAG_IO_V2 0xce
34 #define CMD_JTAG_IO_V3 0xcf
35 #define CMD_JTAG_CLEAR_TRST 0xde
36 #define CMD_JTAG_SET_TRST 0xdf
37 
42 #define JTAG_IO_ERR_NO_MEMORY 0x06
43 
76  const uint8_t *tms, const uint8_t *tdi, uint8_t *tdo,
77  uint16_t length, enum jaylink_jtag_version version)
78 {
79  int ret;
80  struct jaylink_context *ctx;
81  uint8_t buf[4];
82  uint16_t num_bytes;
83  uint16_t read_length;
84  uint8_t status;
85  uint8_t cmd;
86 
87  if (!devh || !tms || !tdi || !tdo || !length)
88  return JAYLINK_ERR_ARG;
89 
90  num_bytes = (length + 7) / 8;
91  read_length = num_bytes;
92 
93  switch (version) {
95  cmd = CMD_JTAG_IO_V2;
96  break;
98  cmd = CMD_JTAG_IO_V3;
99  /* In this version, the response includes a status byte. */
100  read_length++;
101  break;
102  default:
103  return JAYLINK_ERR_ARG;
104  }
105 
106  ctx = devh->dev->ctx;
107  ret = transport_start_write_read(devh, 4 + 2 * num_bytes,
108  read_length, true);
109 
110  if (ret != JAYLINK_OK) {
111  log_err(ctx, "transport_start_write_read() failed: %s.",
112  jaylink_strerror(ret));
113  return ret;
114  }
115 
116  buf[0] = cmd;
117  buf[1] = 0x00;
118  buffer_set_u16(buf, length, 2);
119 
120  ret = transport_write(devh, buf, 4);
121 
122  if (ret != JAYLINK_OK) {
123  log_err(ctx, "transport_write() failed: %s.",
124  jaylink_strerror(ret));
125  return ret;
126  }
127 
128  ret = transport_write(devh, tms, num_bytes);
129 
130  if (ret != JAYLINK_OK) {
131  log_err(ctx, "transport_write() failed: %s.",
132  jaylink_strerror(ret));
133  return ret;
134  }
135 
136  ret = transport_write(devh, tdi, num_bytes);
137 
138  if (ret != JAYLINK_OK) {
139  log_err(ctx, "transport_write() failed: %s.",
140  jaylink_strerror(ret));
141  return ret;
142  }
143 
144  ret = transport_read(devh, tdo, num_bytes);
145 
146  if (ret != JAYLINK_OK) {
147  log_err(ctx, "transport_read() failed: %s.",
148  jaylink_strerror(ret));
149  return ret;
150  }
151 
152  if (version == JAYLINK_JTAG_VERSION_2)
153  return JAYLINK_OK;
154 
155  ret = transport_read(devh, &status, 1);
156 
157  if (ret != JAYLINK_OK) {
158  log_err(ctx, "transport_read() failed: %s.",
159  jaylink_strerror(ret));
160  return ret;
161  }
162 
163  if (status == JTAG_IO_ERR_NO_MEMORY) {
165  } else if (status > 0) {
166  log_err(ctx, "JTAG I/O operation failed: 0x%x.", status);
167  return JAYLINK_ERR_DEV;
168  }
169 
170  return JAYLINK_OK;
171 }
172 
187 {
188  int ret;
189  struct jaylink_context *ctx;
190  uint8_t buf[1];
191 
192  if (!devh)
193  return JAYLINK_ERR_ARG;
194 
195  ctx = devh->dev->ctx;
196  ret = transport_start_write(devh, 1, true);
197 
198  if (ret != JAYLINK_OK) {
199  log_err(ctx, "transport_start_write() failed: %s.",
200  jaylink_strerror(ret));
201  return ret;
202  }
203 
204  buf[0] = CMD_JTAG_CLEAR_TRST;
205 
206  ret = transport_write(devh, buf, 1);
207 
208  if (ret != JAYLINK_OK) {
209  log_err(ctx, "transport_write() failed: %s.",
210  jaylink_strerror(ret));
211  return ret;
212  }
213 
214  return JAYLINK_OK;
215 }
216 
231 {
232  int ret;
233  struct jaylink_context *ctx;
234  uint8_t buf[1];
235 
236  if (!devh)
237  return JAYLINK_ERR_ARG;
238 
239  ctx = devh->dev->ctx;
240  ret = transport_start_write(devh, 1, true);
241 
242  if (ret != JAYLINK_OK) {
243  log_err(ctx, "transport_start_write() failed: %s.",
244  jaylink_strerror(ret));
245  return ret;
246  }
247 
248  buf[0] = CMD_JTAG_SET_TRST;
249 
250  ret = transport_write(devh, buf, 1);
251 
252  if (ret != JAYLINK_OK) {
253  log_err(ctx, "transport_write() failed: %s.",
254  jaylink_strerror(ret));
255  return ret;
256  }
257 
258  return JAYLINK_OK;
259 }
JAYLINK_PRIV void buffer_set_u16(uint8_t *buffer, uint16_t value, size_t offset)
Write a 16-bit unsigned integer value to a buffer.
Definition: buffer.c:43
JAYLINK_API const char * jaylink_strerror(int error_code)
Return a human-readable description of a libjaylink error code.
Definition: error.c:40