MIPS: optimize pracc access
[openocd.git] / src / target / mips32_pracc.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2009 by David N. Claffey <dnclaffey@gmail.com> *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program; if not, write to the *
21 * Free Software Foundation, Inc., *
22 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23 ***************************************************************************/
24
25 /*
26 This version has optimized assembly routines for 32 bit operations:
27 - read word
28 - write word
29 - write array of words
30
31 One thing to be aware of is that the MIPS32 cpu will execute the
32 instruction after a branch instruction (one delay slot).
33
34 For example:
35
36 LW $2, ($5 +10)
37 B foo
38 LW $1, ($2 +100)
39
40 The LW $1, ($2 +100) instruction is also executed. If this is
41 not wanted a NOP can be inserted:
42
43 LW $2, ($5 +10)
44 B foo
45 NOP
46 LW $1, ($2 +100)
47
48 or the code can be changed to:
49
50 B foo
51 LW $2, ($5 +10)
52 LW $1, ($2 +100)
53
54 The original code contained NOPs. I have removed these and moved
55 the branches.
56
57 I also moved the PRACC_STACK to 0xFF204000. This allows
58 the use of 16 bits offsets to get pointers to the input
59 and output area relative to the stack. Note that the stack
60 isn't really a stack (the stack pointer is not 'moving')
61 but a FIFO simulated in software.
62
63 These changes result in a 35% speed increase when programming an
64 external flash.
65
66 More improvement could be gained if the registers do no need
67 to be preserved but in that case the routines should be aware
68 OpenOCD is used as a flash programmer or as a debug tool.
69
70 Nico Coesel
71 */
72
73 #ifdef HAVE_CONFIG_H
74 #include "config.h"
75 #endif
76
77 #include "mips32.h"
78 #include "mips32_pracc.h"
79
80 struct mips32_pracc_context
81 {
82 uint32_t *local_iparam;
83 int num_iparam;
84 uint32_t *local_oparam;
85 int num_oparam;
86 const uint32_t *code;
87 int code_len;
88 uint32_t stack[32];
89 int stack_offset;
90 struct mips_ejtag *ejtag_info;
91 };
92
93 static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
94 {
95 uint32_t ejtag_ctrl;
96
97 while (1)
98 {
99 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
100 ejtag_ctrl = ejtag_info->ejtag_ctrl;
101 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
102 if (ejtag_ctrl & EJTAG_CTRL_PRACC)
103 break;
104 LOG_DEBUG("DEBUGMODULE: No memory access in progress!\n");
105 return ERROR_JTAG_DEVICE_ERROR;
106 }
107
108 *ctrl = ejtag_ctrl;
109 return ERROR_OK;
110 }
111
112 static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t address)
113 {
114 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
115 int offset;
116 uint32_t ejtag_ctrl, data;
117
118 if ((address >= MIPS32_PRACC_PARAM_IN)
119 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
120 {
121 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
122 data = ctx->local_iparam[offset];
123 }
124 else if ((address >= MIPS32_PRACC_PARAM_OUT)
125 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
126 {
127 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
128 data = ctx->local_oparam[offset];
129 }
130 else if ((address >= MIPS32_PRACC_TEXT)
131 && (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4))
132 {
133 offset = (address - MIPS32_PRACC_TEXT) / 4;
134 data = ctx->code[offset];
135 }
136 else if (address == MIPS32_PRACC_STACK)
137 {
138 /* save to our debug stack */
139 data = ctx->stack[--ctx->stack_offset];
140 }
141 else
142 {
143 /* TODO: send JMP 0xFF200000 instruction. Hopefully processor jump back
144 * to start of debug vector */
145
146 data = 0;
147 LOG_ERROR("Error reading unexpected address 0x%8.8" PRIx32 "", address);
148 return ERROR_JTAG_DEVICE_ERROR;
149 }
150
151 /* Send the data out */
152 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
153 mips_ejtag_drscan_32(ctx->ejtag_info, &data);
154
155 /* Clear the access pending bit (let the processor eat!) */
156 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
157 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
158 mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
159
160 jtag_add_clocks(5);
161 jtag_execute_queue();
162
163 return ERROR_OK;
164 }
165
166 static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t address)
167 {
168 uint32_t ejtag_ctrl,data;
169 int offset;
170 struct mips_ejtag *ejtag_info = ctx->ejtag_info;
171
172 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA, NULL);
173 mips_ejtag_drscan_32(ctx->ejtag_info, &data);
174
175 /* Clear access pending bit */
176 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
177 mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_CONTROL, NULL);
178 mips_ejtag_drscan_32(ctx->ejtag_info, &ejtag_ctrl);
179
180 jtag_add_clocks(5);
181 jtag_execute_queue();
182
183 if ((address >= MIPS32_PRACC_PARAM_IN)
184 && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4))
185 {
186 offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
187 ctx->local_iparam[offset] = data;
188 }
189 else if ((address >= MIPS32_PRACC_PARAM_OUT)
190 && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4))
191 {
192 offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
193 ctx->local_oparam[offset] = data;
194 }
195 else if (address == MIPS32_PRACC_STACK)
196 {
197 /* save data onto our stack */
198 ctx->stack[ctx->stack_offset++] = data;
199 }
200 else
201 {
202 LOG_ERROR("Error writing unexpected address 0x%8.8" PRIx32 "", address);
203 return ERROR_JTAG_DEVICE_ERROR;
204 }
205
206 return ERROR_OK;
207 }
208
209 int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_t *code, int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
210 {
211 uint32_t ejtag_ctrl;
212 uint32_t address, data;
213 struct mips32_pracc_context ctx;
214 int retval;
215 int pass = 0;
216
217 ctx.local_iparam = param_in;
218 ctx.local_oparam = param_out;
219 ctx.num_iparam = num_param_in;
220 ctx.num_oparam = num_param_out;
221 ctx.code = code;
222 ctx.code_len = code_len;
223 ctx.ejtag_info = ejtag_info;
224 ctx.stack_offset = 0;
225
226 while (1)
227 {
228 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
229 return retval;
230
231 address = data = 0;
232 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
233 mips_ejtag_drscan_32(ejtag_info, &address);
234
235 /* Check for read or write */
236 if (ejtag_ctrl & EJTAG_CTRL_PRNW)
237 {
238 if ((retval = mips32_pracc_exec_write(&ctx, address)) != ERROR_OK)
239 return retval;
240 }
241 else
242 {
243 /* Check to see if its reading at the debug vector. The first pass through
244 * the module is always read at the vector, so the first one we allow. When
245 * the second read from the vector occurs we are done and just exit. */
246 if ((address == MIPS32_PRACC_TEXT) && (pass++))
247 {
248 break;
249 }
250
251 if ((retval = mips32_pracc_exec_read(&ctx, address)) != ERROR_OK)
252 return retval;
253 }
254
255 if (cycle == 0)
256 break;
257 }
258
259 /* stack sanity check */
260 if (ctx.stack_offset != 0)
261 {
262 LOG_DEBUG("Pracc Stack not zero");
263 }
264
265 return ERROR_OK;
266 }
267
268 int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
269 {
270 switch (size)
271 {
272 case 1:
273 return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf);
274 case 2:
275 return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf);
276 case 4:
277 if (count == 1)
278 return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf);
279 else
280 return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf);
281 }
282
283 return ERROR_OK;
284 }
285
286 int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
287 {
288 static const uint32_t code[] = {
289 /* start: */
290 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
291 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
292 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
293 MIPS32_SW(8,0,15), /* sw $8,($15) */
294 MIPS32_SW(9,0,15), /* sw $9,($15) */
295 MIPS32_SW(10,0,15), /* sw $10,($15) */
296 MIPS32_SW(11,0,15), /* sw $11,($15) */
297
298 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
299 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
300 MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */
301 MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */
302 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
303 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
304 /* loop: */
305 MIPS32_BEQ(0,10,8), /* beq 0, $10, end */
306 MIPS32_NOP,
307
308 MIPS32_LW(8,0,9), /* lw $8,0($9), Load $8 with the word @mem[$9] */
309 MIPS32_SW(8,0,11), /* sw $8,0($11) */
310
311 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
312 MIPS32_ADDI(9,9,4), /* $1 += 4 */
313 MIPS32_ADDI(11,11,4), /* $11 += 4 */
314
315 MIPS32_B(NEG16(8)), /* b loop */
316 MIPS32_NOP,
317 /* end: */
318 MIPS32_LW(11,0,15), /* lw $11,($15) */
319 MIPS32_LW(10,0,15), /* lw $10,($15) */
320 MIPS32_LW(9,0,15), /* lw $9,($15) */
321 MIPS32_LW(8,0,15), /* lw $8,($15) */
322 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
323 MIPS32_B(NEG16(28)), /* b start */
324 MIPS32_NOP,
325 };
326
327 int retval = ERROR_OK;
328 int blocksize;
329 int bytesread;
330 uint32_t param_in[2];
331
332 bytesread = 0;
333
334 while (count > 0)
335 {
336 blocksize = count;
337 if (count > 0x400)
338 blocksize = 0x400;
339
340 param_in[0] = addr;
341 param_in[1] = blocksize;
342
343 if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
344 ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1)) != ERROR_OK)
345 {
346 return retval;
347 }
348
349 count -= blocksize;
350 addr += blocksize;
351 bytesread += blocksize;
352 }
353
354 return retval;
355 }
356
357 int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
358 {
359 static const uint32_t code[] = {
360 /* start: */
361 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
362 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
363 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
364 MIPS32_SW(8,0,15), /* sw $8,($15) */
365
366 MIPS32_LW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN),15), /* load R8 @ param_in[0] = address */
367
368 MIPS32_LW(8,0,8), /* lw $8,0($8), Load $8 with the word @mem[$8] */
369 MIPS32_SW(8,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_OUT),15), /* store R8 @ param_out[0] */
370
371 MIPS32_LW(8,0,15), /* lw $8,($15) */
372 MIPS32_B(NEG16(9)), /* b start */
373 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
374 };
375
376 int retval = ERROR_OK;
377 uint32_t param_in[1];
378
379 param_in[0] = addr;
380
381 if ((retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
382 ARRAY_SIZE(param_in), param_in, 1, buf, 1)) != ERROR_OK)
383 {
384 return retval;
385 }
386
387 return retval;
388 }
389
390 int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
391 {
392 static const uint32_t code[] = {
393 /* start: */
394 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
395 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
396 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
397 MIPS32_SW(8,0,15), /* sw $8,($15) */
398 MIPS32_SW(9,0,15), /* sw $9,($15) */
399 MIPS32_SW(10,0,15), /* sw $10,($15) */
400 MIPS32_SW(11,0,15), /* sw $11,($15) */
401
402 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
403 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
404 MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */
405 MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */
406 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
407 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
408 /* loop: */
409 MIPS32_BEQ(0,10,8), /* beq 0, $10, end */
410 MIPS32_NOP,
411
412 MIPS32_LHU(8,0,9), /* lw $8,0($9), Load $8 with the halfword @mem[$9] */
413 MIPS32_SW(8,0,11), /* sw $8,0($11) */
414
415 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
416 MIPS32_ADDI(9,9,2), /* $9 += 2 */
417 MIPS32_ADDI(11,11,4), /* $11 += 4 */
418 MIPS32_B(NEG16(8)), /* b loop */
419 MIPS32_NOP,
420 /* end: */
421 MIPS32_LW(11,0,15), /* lw $11,($15) */
422 MIPS32_LW(10,0,15), /* lw $10,($15) */
423 MIPS32_LW(9,0,15), /* lw $9,($15) */
424 MIPS32_LW(8,0,15), /* lw $8,($15) */
425 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
426 MIPS32_B(NEG16(28)), /* b start */
427 MIPS32_NOP,
428 };
429
430 /* TODO remove array */
431 uint32_t *param_out = malloc(count * sizeof(uint32_t));
432 int i;
433
434 // int retval;
435 int blocksize;
436 int bytesread;
437 uint32_t param_in[2];
438
439 bytesread = 0;
440
441 //while (count > 0)
442 {
443 blocksize = count;
444 if (count > 0x400)
445 blocksize = 0x400;
446
447 param_in[0] = addr;
448 param_in[1] = blocksize;
449
450 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
451 ARRAY_SIZE(param_in), param_in, count, param_out, 1);
452
453 // count -= blocksize;
454 // addr += blocksize;
455 // bytesread += blocksize;
456 }
457
458 for (i = 0; i < count; i++)
459 {
460 buf[i] = param_out[i];
461 }
462
463 free(param_out);
464
465 return ERROR_OK;
466 }
467
468 int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
469 {
470 static const uint32_t code[] = {
471 /* start: */
472 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
473 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
474 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
475 MIPS32_SW(8,0,15), /* sw $8,($15) */
476 MIPS32_SW(9,0,15), /* sw $9,($15) */
477 MIPS32_SW(10,0,15), /* sw $10,($15) */
478 MIPS32_SW(11,0,15), /* sw $11,($15) */
479
480 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
481 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
482 MIPS32_LW(9,0,8), /* $9 = mem[$8]; read addr */
483 MIPS32_LW(10,4,8), /* $10 = mem[$8 + 4]; read count */
484 MIPS32_LUI(11,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $11 = MIPS32_PRACC_PARAM_OUT */
485 MIPS32_ORI(11,11,LOWER16(MIPS32_PRACC_PARAM_OUT)),
486 /* loop: */
487 MIPS32_BEQ(0,10,8), /* beq 0, $10, end */
488 MIPS32_NOP,
489
490 MIPS32_LBU(8,0,9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */
491 MIPS32_SW(8,0,11), /* sw $8,0($11) */
492
493 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
494 MIPS32_ADDI(9,9,1), /* $9 += 1 */
495 MIPS32_ADDI(11,11,4), /* $11 += 4 */
496 MIPS32_B(NEG16(8)), /* b loop */
497 MIPS32_NOP,
498 /* end: */
499 MIPS32_LW(11,0,15), /* lw $11,($15) */
500 MIPS32_LW(10,0,15), /* lw $10,($15) */
501 MIPS32_LW(9,0,15), /* lw $9,($15) */
502 MIPS32_LW(8,0,15), /* lw $8,($15) */
503 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
504 MIPS32_B(NEG16(28)), /* b start */
505 MIPS32_NOP,
506 };
507
508 /* TODO remove array */
509 uint32_t *param_out = malloc(count * sizeof(uint32_t));
510 int i;
511
512 // int retval;
513 int blocksize;
514 int bytesread;
515 uint32_t param_in[2];
516
517 bytesread = 0;
518
519 // while (count > 0)
520 {
521 blocksize = count;
522 if (count > 0x400)
523 blocksize = 0x400;
524
525 param_in[0] = addr;
526 param_in[1] = blocksize;
527
528 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
529 ARRAY_SIZE(param_in), param_in, count, param_out, 1);
530
531 // count -= blocksize;
532 // addr += blocksize;
533 // bytesread += blocksize;
534 }
535
536 for (i = 0; i < count; i++)
537 {
538 buf[i] = param_out[i];
539 }
540
541 free(param_out);
542
543 return ERROR_OK;
544 }
545
546 int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf)
547 {
548 switch (size)
549 {
550 case 1:
551 return mips32_pracc_write_mem8(ejtag_info, addr, count, (uint8_t*)buf);
552 case 2:
553 return mips32_pracc_write_mem16(ejtag_info, addr, count,(uint16_t*)buf);
554 case 4:
555 if (count == 1)
556 return mips32_pracc_write_u32(ejtag_info, addr, (uint32_t*)buf);
557 else
558 return mips32_pracc_write_mem32(ejtag_info, addr, count, (uint32_t*)buf);
559 }
560
561 return ERROR_OK;
562 }
563
564 int mips32_pracc_write_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf)
565 {
566 static const uint32_t code[] = {
567 /* start: */
568 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
569 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
570 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
571 MIPS32_SW(8,0,15), /* sw $8,($15) */
572 MIPS32_SW(9,0,15), /* sw $9,($15) */
573 MIPS32_SW(10,0,15), /* sw $10,($15) */
574 MIPS32_SW(11,0,15), /* sw $11,($15) */
575
576 MIPS32_ADDI(8,15,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)), /* $8= MIPS32_PRACC_PARAM_IN */
577 MIPS32_LW(9,0,8), /* Load write addr to $9 */
578 MIPS32_LW(10,4,8), /* Load write count to $10 */
579 MIPS32_ADDI(8,8,8), /* $8 += 8 beginning of data */
580
581 /* loop: */
582 MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
583 MIPS32_SW(11,0,9), /* sw $11,0($9) */
584
585 MIPS32_ADDI(9,9,4), /* $9 += 4 */
586 MIPS32_BNE(10,9,NEG16(4)), /* bne $10, $9, loop */
587 MIPS32_ADDI(8,8,4), /* $8 += 4 */
588
589 /* end: */
590 MIPS32_LW(11,0,15), /* lw $11,($15) */
591 MIPS32_LW(10,0,15), /* lw $10,($15) */
592 MIPS32_LW(9,0,15), /* lw $9,($15) */
593 MIPS32_LW(8,0,15), /* lw $8,($15) */
594 MIPS32_B(NEG16(21)), /* b start */
595 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
596 };
597
598 /* TODO remove array */
599 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
600 param_in[0] = addr;
601 param_in[1] = addr + (count * sizeof(uint32_t)); /* last address */
602
603 memcpy(&param_in[2], buf, count * sizeof(uint32_t));
604
605 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
606 count + 2, param_in, 0, NULL, 1);
607
608 free(param_in);
609
610 return ERROR_OK;
611 }
612
613 int mips32_pracc_write_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf)
614 {
615 static const uint32_t code[] = {
616 /* start: */
617 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
618 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
619 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
620 MIPS32_SW(8,0,15), /* sw $8,($15) */
621 MIPS32_SW(9,0,15), /* sw $9,($15) */
622
623 MIPS32_LW(8,NEG16((MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN)-4), 15), /* load R8 @ param_in[1] = data */
624 MIPS32_LW(9,NEG16(MIPS32_PRACC_STACK-MIPS32_PRACC_PARAM_IN), 15), /* load R9 @ param_in[0] = address */
625
626 MIPS32_SW(8,0,9), /* sw $8,0($9) */
627
628 MIPS32_LW(9,0,15), /* lw $9,($15) */
629 MIPS32_LW(8,0,15), /* lw $8,($15) */
630 MIPS32_B(NEG16(11)), /* b start */
631 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
632 };
633
634 /* TODO remove array */
635 uint32_t param_in[1 + 1];
636 param_in[0] = addr;
637 param_in[1] = *buf;
638
639 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
640 ARRAY_SIZE(param_in), param_in, 0, NULL, 1);
641
642 return ERROR_OK;
643 }
644
645 int mips32_pracc_write_mem16(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint16_t *buf)
646 {
647 static const uint32_t code[] = {
648 /* start: */
649 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
650 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
651 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
652 MIPS32_SW(8,0,15), /* sw $8,($15) */
653 MIPS32_SW(9,0,15), /* sw $9,($15) */
654 MIPS32_SW(10,0,15), /* sw $10,($15) */
655 MIPS32_SW(11,0,15), /* sw $11,($15) */
656
657 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
658 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
659 MIPS32_LW(9,0,8), /* Load write addr to $9 */
660 MIPS32_LW(10,4,8), /* Load write count to $10 */
661 MIPS32_ADDI(8,8,8), /* $8 += 8 */
662 /* loop: */
663 MIPS32_BEQ(0,10,8), /* beq $0, $10, end */
664 MIPS32_NOP,
665
666 MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
667 MIPS32_SH(11,0,9), /* sh $11,0($9) */
668
669 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
670 MIPS32_ADDI(9,9,2), /* $9 += 2 */
671 MIPS32_ADDI(8,8,4), /* $8 += 4 */
672
673 MIPS32_B(NEG16(8)), /* b loop */
674 MIPS32_NOP,
675 /* end: */
676 MIPS32_LW(11,0,15), /* lw $11,($15) */
677 MIPS32_LW(10,0,15), /* lw $10,($15) */
678 MIPS32_LW(9,0,15), /* lw $9,($15) */
679 MIPS32_LW(8,0,15), /* lw $8,($15) */
680 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
681 MIPS32_B(NEG16(27)), /* b start */
682 MIPS32_NOP,
683 };
684
685 /* TODO remove array */
686 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
687 int i;
688 param_in[0] = addr;
689 param_in[1] = count;
690
691 for (i = 0; i < count; i++)
692 {
693 param_in[i + 2] = buf[i];
694 }
695
696 mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
697 count + 2, param_in, 0, NULL, 1);
698
699 free(param_in);
700
701 return ERROR_OK;
702 }
703
704 int mips32_pracc_write_mem8(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint8_t *buf)
705 {
706 static const uint32_t code[] = {
707 /* start: */
708 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
709 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
710 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
711 MIPS32_SW(8,0,15), /* sw $8,($15) */
712 MIPS32_SW(9,0,15), /* sw $9,($15) */
713 MIPS32_SW(10,0,15), /* sw $10,($15) */
714 MIPS32_SW(11,0,15), /* sw $11,($15) */
715
716 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $8 = MIPS32_PRACC_PARAM_IN */
717 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_PARAM_IN)),
718 MIPS32_LW(9,0,8), /* Load write addr to $9 */
719 MIPS32_LW(10,4,8), /* Load write count to $10 */
720 MIPS32_ADDI(8,8,8), /* $8 += 8 */
721 /* loop: */
722 MIPS32_BEQ(0,10,8), /* beq $0, $10, end */
723 MIPS32_NOP,
724
725 MIPS32_LW(11,0,8), /* lw $11,0($8), Load $11 with the word @mem[$8] */
726 MIPS32_SB(11,0,9), /* sb $11,0($9) */
727
728 MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */
729 MIPS32_ADDI(9,9,1), /* $9 += 1 */
730 MIPS32_ADDI(8,8,4), /* $8 += 4 */
731
732 MIPS32_B(NEG16(8)), /* b loop */
733 MIPS32_NOP,
734 /* end: */
735 MIPS32_LW(11,0,15), /* lw $11,($15) */
736 MIPS32_LW(10,0,15), /* lw $10,($15) */
737 MIPS32_LW(9,0,15), /* lw $9,($15) */
738 MIPS32_LW(8,0,15), /* lw $8,($15) */
739 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
740 MIPS32_B(NEG16(27)), /* b start */
741 MIPS32_NOP,
742 };
743
744 /* TODO remove array */
745 uint32_t *param_in = malloc((count + 2) * sizeof(uint32_t));
746 int retval;
747 int i;
748 param_in[0] = addr;
749 param_in[1] = count;
750
751 for (i = 0; i < count; i++)
752 {
753 param_in[i + 2] = buf[i];
754 }
755
756 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
757 count + 2, param_in, 0, NULL, 1);
758
759 free(param_in);
760
761 return retval;
762 }
763
764 int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
765 {
766 static const uint32_t code[] = {
767 /* start: */
768 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $2 = MIPS32_PRACC_PARAM_IN */
769 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_IN)),
770 MIPS32_LW(1,1*4,2), /* lw $1,1*4($2) */
771 MIPS32_LW(15,15*4,2), /* lw $15,15*4($2) */
772 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
773 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
774 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
775 MIPS32_SW(1,0,15), /* sw $1,($15) */
776 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_IN)), /* $1 = MIPS32_PRACC_PARAM_IN */
777 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_IN)),
778 MIPS32_LW(3,3*4,1), /* lw $3,3*4($1) */
779 MIPS32_LW(4,4*4,1), /* lw $4,4*4($1) */
780 MIPS32_LW(5,5*4,1), /* lw $5,5*4($1) */
781 MIPS32_LW(6,6*4,1), /* lw $6,6*4($1) */
782 MIPS32_LW(7,7*4,1), /* lw $7,7*4($1) */
783 MIPS32_LW(8,8*4,1), /* lw $8,8*4($1) */
784 MIPS32_LW(9,9*4,1), /* lw $9,9*4($1) */
785 MIPS32_LW(10,10*4,1), /* lw $10,10*4($1) */
786 MIPS32_LW(11,11*4,1), /* lw $11,11*4($1) */
787 MIPS32_LW(12,12*4,1), /* lw $12,12*4($1) */
788 MIPS32_LW(13,13*4,1), /* lw $13,13*4($1) */
789 MIPS32_LW(14,14*4,1), /* lw $14,14*4($1) */
790 MIPS32_LW(16,16*4,1), /* lw $16,16*4($1) */
791 MIPS32_LW(17,17*4,1), /* lw $17,17*4($1) */
792 MIPS32_LW(18,18*4,1), /* lw $18,18*4($1) */
793 MIPS32_LW(19,19*4,1), /* lw $19,19*4($1) */
794 MIPS32_LW(20,20*4,1), /* lw $20,20*4($1) */
795 MIPS32_LW(21,21*4,1), /* lw $21,21*4($1) */
796 MIPS32_LW(22,22*4,1), /* lw $22,22*4($1) */
797 MIPS32_LW(23,23*4,1), /* lw $23,23*4($1) */
798 MIPS32_LW(24,24*4,1), /* lw $24,24*4($1) */
799 MIPS32_LW(25,25*4,1), /* lw $25,25*4($1) */
800 MIPS32_LW(26,26*4,1), /* lw $26,26*4($1) */
801 MIPS32_LW(27,27*4,1), /* lw $27,27*4($1) */
802 MIPS32_LW(28,28*4,1), /* lw $28,28*4($1) */
803 MIPS32_LW(29,29*4,1), /* lw $29,29*4($1) */
804 MIPS32_LW(30,30*4,1), /* lw $30,30*4($1) */
805 MIPS32_LW(31,31*4,1), /* lw $31,31*4($1) */
806
807 MIPS32_LW(2,32*4,1), /* lw $2,32*4($1) */
808 MIPS32_MTC0(2,12,0), /* move $2 to status */
809 MIPS32_LW(2,33*4,1), /* lw $2,33*4($1) */
810 MIPS32_MTLO(2), /* move $2 to lo */
811 MIPS32_LW(2,34*4,1), /* lw $2,34*4($1) */
812 MIPS32_MTHI(2), /* move $2 to hi */
813 MIPS32_LW(2,35*4,1), /* lw $2,35*4($1) */
814 MIPS32_MTC0(2,8,0), /* move $2 to badvaddr */
815 MIPS32_LW(2,36*4,1), /* lw $2,36*4($1) */
816 MIPS32_MTC0(2,13,0), /* move $2 to cause*/
817 MIPS32_LW(2,37*4,1), /* lw $2,37*4($1) */
818 MIPS32_MTC0(2,24,0), /* move $2 to pc */
819
820 MIPS32_LW(2,2*4,1), /* lw $2,2*4($1) */
821 MIPS32_LW(1,0,15), /* lw $1,($15) */
822 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
823 MIPS32_B(NEG16(54)), /* b start */
824 MIPS32_NOP,
825 };
826
827 int retval;
828
829 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
830 MIPS32NUMCOREREGS, regs, 0, NULL, 1);
831
832 return retval;
833 }
834
835 int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
836 {
837 static const uint32_t code[] = {
838 /* start: */
839 MIPS32_MTC0(2,31,0), /* move $2 to COP0 DeSave */
840 MIPS32_LUI(2,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $2 = MIPS32_PRACC_PARAM_OUT */
841 MIPS32_ORI(2,2,LOWER16(MIPS32_PRACC_PARAM_OUT)),
842 MIPS32_SW(0,0*4,2), /* sw $0,0*4($2) */
843 MIPS32_SW(1,1*4,2), /* sw $1,1*4($2) */
844 MIPS32_SW(15,15*4,2), /* sw $15,15*4($2) */
845 MIPS32_MFC0(2,31,0), /* move COP0 DeSave to $2 */
846 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
847 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_STACK)), /* $15 = MIPS32_PRACC_STACK */
848 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_STACK)),
849 MIPS32_SW(1,0,15), /* sw $1,($15) */
850 MIPS32_SW(2,0,15), /* sw $2,($15) */
851 MIPS32_LUI(1,UPPER16(MIPS32_PRACC_PARAM_OUT)), /* $1 = MIPS32_PRACC_PARAM_OUT */
852 MIPS32_ORI(1,1,LOWER16(MIPS32_PRACC_PARAM_OUT)),
853 MIPS32_SW(2,2*4,1), /* sw $2,2*4($1) */
854 MIPS32_SW(3,3*4,1), /* sw $3,3*4($1) */
855 MIPS32_SW(4,4*4,1), /* sw $4,4*4($1) */
856 MIPS32_SW(5,5*4,1), /* sw $5,5*4($1) */
857 MIPS32_SW(6,6*4,1), /* sw $6,6*4($1) */
858 MIPS32_SW(7,7*4,1), /* sw $7,7*4($1) */
859 MIPS32_SW(8,8*4,1), /* sw $8,8*4($1) */
860 MIPS32_SW(9,9*4,1), /* sw $9,9*4($1) */
861 MIPS32_SW(10,10*4,1), /* sw $10,10*4($1) */
862 MIPS32_SW(11,11*4,1), /* sw $11,11*4($1) */
863 MIPS32_SW(12,12*4,1), /* sw $12,12*4($1) */
864 MIPS32_SW(13,13*4,1), /* sw $13,13*4($1) */
865 MIPS32_SW(14,14*4,1), /* sw $14,14*4($1) */
866 MIPS32_SW(16,16*4,1), /* sw $16,16*4($1) */
867 MIPS32_SW(17,17*4,1), /* sw $17,17*4($1) */
868 MIPS32_SW(18,18*4,1), /* sw $18,18*4($1) */
869 MIPS32_SW(19,19*4,1), /* sw $19,19*4($1) */
870 MIPS32_SW(20,20*4,1), /* sw $20,20*4($1) */
871 MIPS32_SW(21,21*4,1), /* sw $21,21*4($1) */
872 MIPS32_SW(22,22*4,1), /* sw $22,22*4($1) */
873 MIPS32_SW(23,23*4,1), /* sw $23,23*4($1) */
874 MIPS32_SW(24,24*4,1), /* sw $24,24*4($1) */
875 MIPS32_SW(25,25*4,1), /* sw $25,25*4($1) */
876 MIPS32_SW(26,26*4,1), /* sw $26,26*4($1) */
877 MIPS32_SW(27,27*4,1), /* sw $27,27*4($1) */
878 MIPS32_SW(28,28*4,1), /* sw $28,28*4($1) */
879 MIPS32_SW(29,29*4,1), /* sw $29,29*4($1) */
880 MIPS32_SW(30,30*4,1), /* sw $30,30*4($1) */
881 MIPS32_SW(31,31*4,1), /* sw $31,31*4($1) */
882
883 MIPS32_MFC0(2,12,0), /* move status to $2 */
884 MIPS32_SW(2,32*4,1), /* sw $2,32*4($1) */
885 MIPS32_MFLO(2), /* move lo to $2 */
886 MIPS32_SW(2,33*4,1), /* sw $2,33*4($1) */
887 MIPS32_MFHI(2), /* move hi to $2 */
888 MIPS32_SW(2,34*4,1), /* sw $2,34*4($1) */
889 MIPS32_MFC0(2,8,0), /* move badvaddr to $2 */
890 MIPS32_SW(2,35*4,1), /* sw $2,35*4($1) */
891 MIPS32_MFC0(2,13,0), /* move cause to $2 */
892 MIPS32_SW(2,36*4,1), /* sw $2,36*4($1) */
893 MIPS32_MFC0(2,24,0), /* move pc to $2 */
894 MIPS32_SW(2,37*4,1), /* sw $2,37*4($1) */
895
896 MIPS32_LW(2,0,15), /* lw $2,($15) */
897 MIPS32_LW(1,0,15), /* lw $1,($15) */
898 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
899 MIPS32_B(NEG16(59)), /* b start */
900 MIPS32_NOP,
901 };
902
903 int retval;
904
905 retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, \
906 0, NULL, MIPS32NUMCOREREGS, regs, 1);
907
908 return retval;
909 }
910
911 /* fastdata upload/download requires an initialized working area
912 * to load the download code; it should not be called otherwise
913 * fetch order from the fastdata area
914 * 1. start addr
915 * 2. end addr
916 * 3. data ...
917 */
918 int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
919 int write, uint32_t addr, int count, uint32_t *buf)
920 {
921 uint32_t handler_code[] = {
922 /* caution when editing, table is modified below */
923 /* r15 points to the start of this code */
924 MIPS32_SW(8,MIPS32_FASTDATA_HANDLER_SIZE - 4,15),
925 MIPS32_SW(9,MIPS32_FASTDATA_HANDLER_SIZE - 8,15),
926 MIPS32_SW(10,MIPS32_FASTDATA_HANDLER_SIZE - 12,15),
927 MIPS32_SW(11,MIPS32_FASTDATA_HANDLER_SIZE - 16,15),
928 /* start of fastdata area in t0 */
929 MIPS32_LUI(8,UPPER16(MIPS32_PRACC_FASTDATA_AREA)),
930 MIPS32_ORI(8,8,LOWER16(MIPS32_PRACC_FASTDATA_AREA)),
931 MIPS32_LW(9,0,8), /* start addr in t1 */
932 MIPS32_LW(10,0,8), /* end addr to t2 */
933 /* loop: */
934 /* 8 */ MIPS32_LW(11,0,0), /* lw t3,[t8 | r9] */
935 /* 9 */ MIPS32_SW(11,0,0), /* sw t3,[r9 | r8] */
936 MIPS32_BNE(10,9,NEG16(3)), /* bne $t2,t1,loop */
937 MIPS32_ADDI(9,9,4), /* addi t1,t1,4 */
938
939 MIPS32_LW(8,MIPS32_FASTDATA_HANDLER_SIZE - 4,15),
940 MIPS32_LW(9,MIPS32_FASTDATA_HANDLER_SIZE - 8,15),
941 MIPS32_LW(10,MIPS32_FASTDATA_HANDLER_SIZE - 12,15),
942 MIPS32_LW(11,MIPS32_FASTDATA_HANDLER_SIZE - 16,15),
943
944 MIPS32_LUI(15,UPPER16(MIPS32_PRACC_TEXT)),
945 MIPS32_ORI(15,15,LOWER16(MIPS32_PRACC_TEXT)),
946 MIPS32_JR(15), /* jr start */
947 MIPS32_MFC0(15,31,0), /* move COP0 DeSave to $15 */
948 };
949
950 uint32_t jmp_code[] = {
951 MIPS32_MTC0(15,31,0), /* move $15 to COP0 DeSave */
952 /* 1 */ MIPS32_LUI(15,0), /* addr of working area added below */
953 /* 2 */ MIPS32_ORI(15,15,0), /* addr of working area added below */
954 MIPS32_JR(15), /* jump to ram program */
955 MIPS32_NOP,
956 };
957
958 int retval, i;
959 uint32_t val, ejtag_ctrl, address;
960
961 if (source->size < MIPS32_FASTDATA_HANDLER_SIZE)
962 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
963
964 if (write)
965 {
966 handler_code[8] = MIPS32_LW(11,0,8); /* load data from probe at fastdata area */
967 handler_code[9] = MIPS32_SW(11,0,9); /* store data to RAM @ r9 */
968 }
969 else
970 {
971 handler_code[8] = MIPS32_LW(11,0,9); /* load data from RAM @ r9 */
972 handler_code[9] = MIPS32_SW(11,0,8); /* store data to probe at fastdata area */
973 }
974
975 /* write program into RAM */
976 mips32_pracc_write_mem32(ejtag_info, source->address, ARRAY_SIZE(handler_code), handler_code);
977
978 /* quick verify RAM is working */
979 mips32_pracc_read_u32(ejtag_info, source->address, &val);
980 if (val != handler_code[0])
981 {
982 LOG_ERROR("fastdata handler verify failed\n");
983 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
984 }
985
986 LOG_INFO("%s using 0x%.8x for write handler\n", __func__, source->address);
987
988 jmp_code[1] |= UPPER16(source->address);
989 jmp_code[2] |= LOWER16(source->address);
990
991 for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++)
992 {
993 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
994 return retval;
995
996 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA, NULL);
997 mips_ejtag_drscan_32(ejtag_info, &jmp_code[i]);
998
999 /* Clear the access pending bit (let the processor eat!) */
1000 ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC;
1001 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL, NULL);
1002 mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
1003 }
1004
1005 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
1006 return retval;
1007
1008 /* next fetch to dmseg should be in FASTDATA_AREA, check */
1009 address = 0;
1010 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
1011 mips_ejtag_drscan_32(ejtag_info, &address);
1012
1013 if (address != MIPS32_PRACC_FASTDATA_AREA)
1014 return ERROR_FAIL;
1015
1016 /* Send the load start address */
1017 val = addr;
1018 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA, NULL);
1019 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1020
1021 /* Send the load end address */
1022 val = addr + (count - 1) * 4;
1023 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA, NULL);
1024 mips_ejtag_fastdata_scan(ejtag_info, 1, &val);
1025
1026 for (i = 0; i < count; i++)
1027 {
1028 /* Send the data out using fastdata (clears the access pending bit) */
1029 if ((retval = mips_ejtag_fastdata_scan(ejtag_info, write, buf++)) != ERROR_OK)
1030 return retval;
1031 }
1032
1033 if ((retval = jtag_execute_queue()) != ERROR_OK)
1034 {
1035 LOG_ERROR("fastdata load failed");
1036 return retval;
1037 }
1038
1039 if ((retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl)) != ERROR_OK)
1040 return retval;
1041
1042 address = 0;
1043 mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS, NULL);
1044 mips_ejtag_drscan_32(ejtag_info, &address);
1045
1046 if (address != MIPS32_PRACC_TEXT)
1047 LOG_ERROR("mini program did not return to start\n");
1048
1049 return retval;
1050 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)