- rlink interface support from Lou Deluxe <lou.openocd012@fixit.nospammail.net>
[openocd.git] / src / jtag / rlink / call.m4
1 m4_divert(`-1')
2 /***************************************************************************
3 * Copyright (C) 2008 Lou Deluxe *
4 * lou.openocd012@fixit.nospammail.net *
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, write to the *
18 * Free Software Foundation, Inc., *
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
21
22 m4_dnl Setup and hold times depend on SHIFTER_PRESCALER
23 m4_define(`SETUP_DELAY_CYCLES', m4_eval(`('SHIFTER_PRESCALER` + 1) / 2'))
24 m4_define(`HOLD_DELAY_CYCLES', m4_eval(`'SHIFTER_PRESCALER` / 2'))
25
26 m4_dnl Some macros to make nybble handling a little easier
27 m4_define(`m4_high_nybble', `m4_eval(`(($1) >> 4) & 0xf')')
28 m4_define(`m4_low_nybble', `m4_eval(`($1) & 0xf')')
29
30 m4_dnl A macro to generate a number of NOPs depending on the argument
31 m4_define(`m4_0_to_5_nops', `m4_ifelse(m4_eval(`($1) >= 1'), 1, ` NOP
32 'm4_ifelse(m4_eval(`($1) >= 2'), 1, ` NOP
33 'm4_ifelse(m4_eval(`($1) >= 3'), 1, ` NOP
34 'm4_ifelse(m4_eval(`($1) >= 4'), 1, ` NOP
35 'm4_ifelse(m4_eval(`($1) >= 5'), 1, ` NOP
36 ')))))')
37
38
39 m4_dnl Some macros to facilitate bit-banging delays.
40 m4_dnl There are 3 of them. One for self-contained delays, and two for those which must be split between setup and loop to keep from disturbing A at delay time.
41 m4_dnl The argument passed to any of them is the number of cycles which the delay should consume.
42
43 m4_dnl This one is self-contained.
44
45 m4_define(`m4_delay',
46 `; delay (m4_eval($1) cycles)'
47 `m4_ifelse(m4_eval(`('$1`) < 6'), 1,
48 m4_0_to_5_nops($1)
49 ,
50 m4_ifelse(m4_eval(`(('$1`) - 3) % 2'), 1, ` NOP')
51 A.H = m4_high_nybble(`(('$1`) - 3) / 2')
52 A.L = m4_low_nybble(`(('$1`) - 3) / 2')
53 Y = A
54 DECY
55 JP -1
56 )')
57
58
59 m4_dnl These are the setup and loop parts of the split delay.
60 m4_dnl The argument passed to both must match for the result to make sense.
61 m4_dnl The setup does not figure into the delay. It takes 3 cycles when a loop is used and none if nops are used.
62
63 m4_define(`m4_delay_setup',
64 `; delay setup (m4_eval($1) cycles)'
65 `m4_ifelse(m4_eval(`('$1`) < 6'), 0, ` '
66 A.H = m4_high_nybble(`('$1`) / 2')
67 A.L = m4_low_nybble(`('$1`) / 2')
68 Y = A
69 )')
70
71 m4_define(`m4_delay_loop',
72 `; delay loop (m4_eval($1) cycles)'
73 `m4_ifelse(m4_eval(`('$1`) < 6'), 1,
74 m4_0_to_5_nops($1)
75 ,
76 m4_ifelse(m4_eval(`('$1`) % 2'), 1, ` NOP')
77 DECY
78 JP -1
79 )')
80
81 m4_dnl These are utility macros for use with delays. Specifically, there is code below which needs some predictability in code size for relative jumps to reach. The m4_delay macro generates an extra NOP when an even delay is needed, and the m4_delay_loop macro generates an extra NOP when an odd delay is needed. Using this for the argument to the respective macro rounds up the argument so that the extra NOP will not be generated. There is also logic built in to cancel the rounding when the result is small enough that a loop would not be generated.
82
83 m4_define(`m4_delay_loop_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) + 1) / 2 * 2'))')
84 m4_define(`m4_delay_round_up', `m4_ifelse(m4_eval($1` < 6'), 1, $1, m4_eval(`(('$1`) / 2 * 2) + 1'))')
85
86
87 m4_divert(`0')m4_dnl
88
89 ;------------------------------------------------------------------------------
90 :opcode_error
91 ; This is at address 0x00 in case of empty LUT entries
92 STATUS STOP ERROR
93
94 ;------------------------------------------------------------------------------
95 ; Command interpreter at address 0x01 because it is branched to a lot and having it be 0x01 means we can use X for it, which is already used for other purposes which want it to be 1.
96 ; Assumes X is 1
97 ; Assumes ADR_BUFFER0 points to the next command byte
98 ; Stores the current command byte in CMP01
99
100 :command_interpreter
101 A = DATA_BUFFER0
102 ADR_BUFFER0 += X
103 CMP01 = A ; store the current command for later
104
105 EXCHANGE ; put MSN into LSN
106 A.H = 0xc ; lookup table at 0x1550 + 0xc0 = 0x1610
107
108 ; branch to address in lookup table
109 Y = A
110 A = <Y>
111 BRANCH
112
113 ;------------------------------------------------------------------------------
114 ; LUT for high nybble
115
116 ;LUT; c0 opcode_error
117 ;LUT; c1 opcode_shift_tdi_andor_tms_bytes
118 ;LUT; c2 opcode_shift_tdi_andor_tms_bytes
119 ;LUT; c3 opcode_shift_tdi_andor_tms_bytes
120 ;LUT; c4 opcode_shift_tdo_bytes
121 ;LUT; c5 opcode_error
122 ;LUT; c6 opcode_shift_tdio_bytes
123 ;LUT; c7 opcode_error
124 ;LUT; c8 opcode_shift_tms_tdi_bit_pair
125 ;LUT; c9 opcode_shift_tms_bits
126 ;LUT; ca opcode_error
127 ;LUT; cb opcode_error
128 ;LUT; cc opcode_error
129 ;LUT; cd opcode_error
130 ;LUT; ce opcode_shift_tdio_bits
131 ;LUT; cf opcode_stop
132
133
134 ;------------------------------------------------------------------------------
135 ; USB/buffer handling
136 ;
137
138 ;ENTRY; download entry_download
139
140 opcode_stop:
141 opcode_next_buffer:
142 ; pointer to completion flag
143 A.H = 0xf
144 A.L = 0xf
145 Y = A
146
147 A = OR_MPEG ; buffer indicator from previous iteration
148 <Y> = A ; either indicator will have bit 0 set
149 BSET 1 ; was buffer 1 previously current?
150 ; A.H = 0 ; already zero from OR_MPEG
151 JP opcode_next_buffer_0
152
153 opcode_next_buffer_1:
154 A.L = 0x1 ; ack buffer 0
155 BUFFER_MNGT = A
156 ; A.H = 0x0 ; already zero from BUFFER_MNGT
157 A.L = 0x3 ; Input buffer 1 = 0x1850 (0x0300)
158 JP +4
159
160 opcode_next_buffer_0:
161 A.L = 0x2 ; ack buffer 1
162 BUFFER_MNGT = A
163 entry_download:
164 A = X ; Input buffer 0 = 0x1650 (0x0100)
165
166 ADR_BUFFER01 = A
167 OR_MPEG = A ; store for next iteration
168
169 A.L = 0x0
170 BUFFER_MNGT = A ; finish acking previous buffer
171 Y = A
172 ADR_BUFFER00 = A
173 ADR_BUFFER11 = A
174
175 A.H = 0x4 ; Output buffer = 0x1590 (0x0040)
176 ADR_BUFFER10 = A
177
178 EXCHANGE ; 0x04
179 X = A ; for the spin loop below
180
181 ; pointer to status in shared memory
182 DECY ; setting to 0 above and decrementing here saves a byte
183
184 ; wait until a command buffer is available
185 A = BUFFER_MNGT ; spin while neither of bits 2 or 3 are set
186 CP A<X ; this is slightly faster and smaller than trying to AND and compare the result, and it lets us just use the nybble-swapped 0x40 from the output buffer setup.
187 JP -2
188 <Y> = A ; update status once done spinning
189
190 ; restore X, since we used it
191 ; A.H = 0 ; high nybble of BUFFER_MNGT will always be 0 the way we use it
192 A.L = 1
193 X = A
194
195 ; go to command interpreter
196 BRANCH
197
198
199 ;;------------------------------------------------------------------------------
200 ;:opcode_stop
201 ;;
202 ;
203 ; ; Ack buffer 0 in download mode
204 ; A.L = 0x1
205 ; BUFFER_MNGT = A
206 ;
207 ; STATUS STOP
208
209
210 ;------------------------------------------------------------------------------
211 :opcode_shift_tdi_andor_tms_bytes
212 ;
213
214 A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
215 A.H = 0
216 Y = A ; loop counter
217
218 A = CMP01
219 EXCHANGE
220 CMP01 = A ; we're interested in bits in the high nybble
221
222 opcode_shift_tdi_andor_tms_bytes__loop:
223
224 ; set tdi to supplied byte or zero
225 A = CMP01
226 BSET 1
227 JP +4
228 A.H = 0
229 A.L = 0
230 JP +3
231 A = DATA_BUFFER0
232 ADR_BUFFER0 += X
233 SHIFT_MPEG = A
234
235 ; set tms to supplied byte or zero
236 A = CMP01
237 BCLR 0
238 JP +5
239 A = DATA_BUFFER0
240 ADR_BUFFER0 += X
241 SHIFT_CARD = A
242 SHIFT CARD OUT=>PIN0
243
244 ; run both shifters as nearly simultaneously as possible
245 SHIFT MPEG OUT=>PIN1
246
247 A = CTRL_FCI
248 EXCHANGE
249 BCLR 3
250 JP -3
251
252 DECY
253 JP opcode_shift_tdi_andor_tms_bytes__loop
254
255 A = X
256 BRANCH
257
258
259 ;------------------------------------------------------------------------------
260 :opcode_shift_tdo_bytes
261 ;
262
263 A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
264 A.H = 0
265 Y = A ; loop counter
266
267 opcode_shift_tdo_bytes__loop:
268 SHIFT MPEG PIN0=>IN
269
270 A = CTRL_FCI
271 EXCHANGE
272 BCLR 3
273 JP -3
274
275 ; put shifted byte into output buffer
276 A = SHIFT_MPEG
277 DATA_BUFFER1 = A
278 ADR_BUFFER1 += X
279
280 DECY
281 JP opcode_shift_tdo_bytes__loop
282
283 A = X
284 BRANCH
285
286
287 ;------------------------------------------------------------------------------
288 :opcode_shift_tdio_bytes
289 ;
290
291 A = CMP01 ; bits 3..0 contain the number of bytes to shift - 1
292 A.H = 0
293 CMP10 = A ; byte loop counter
294
295 A.H = opcode_shift_tdio_bytes__sub_return
296 A.L = opcode_shift_tdio_bytes__sub_return
297 CMP00 = A ; return address
298
299 opcode_shift_tdio_bytes__loop:
300 A.H = 0
301 A.L = 7
302 CMP11 = A ; always use 8 bits
303
304 JP sub_shift_tdio_bits
305 opcode_shift_tdio_bytes__sub_return:
306
307 A = CMP10 ; byte loop counter
308 CP A=>X
309 CLC
310 A -= X
311 CMP10 = A
312 JP opcode_shift_tdio_bytes__loop
313
314 A = X
315 ;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
316 BRANCH
317
318
319 ;------------------------------------------------------------------------------
320 :opcode_shift_tdio_bits
321 ;
322
323 A = CMP01 ; bits 2..0 contain the number of bits to shift - 1
324 A.H = 0
325 BCLR 3 ; set TMS=1 if bit 3 was set
326 CMP11 = A ; bit loop counter
327
328 A.H = opcode_shift_tdio_bits__sub_return
329 A.L = opcode_shift_tdio_bits__sub_return
330 CMP00 = A ; return address
331
332 JP sub_shift_tdio_bits
333 A.L = 0x1 ; TMS=1
334 DR_CARD = A
335 JP sub_shift_tdio_bits
336 opcode_shift_tdio_bits__sub_return:
337
338 A = X
339 ;DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
340 BRANCH
341
342
343 ;------------------------------------------------------------------------------
344 :sub_shift_tdio_bits
345 ;
346
347 A = DATA_BUFFER0 ; get byte from input buffer
348 ADR_BUFFER0 += X
349 MASK = A ; put it in MASK where bit routine will use it
350
351 :sub_shift_tdio_bits__loop
352 m4_delay_setup(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1))
353
354 A = MASK ; shift TDO into and TDI out of MASK via carry
355 A += MASK
356 MASK = A
357
358 ; shifting out TDI
359 A.L = 0x2 ; TCK=0, TDI=1
360 CP CARRY
361 JP +2
362 A.L = 0x0 ; TCK=0, TDI=0
363 DR_MPEG = A
364
365 m4_delay_loop(m4_delay_loop_round_up(SETUP_DELAY_CYCLES - 1))
366
367 BSET 2 ; TCK high
368 DR_MPEG = A
369
370 A = DR_MPEG ; set carry bit to TDO
371 CLC
372 BCLR 0
373 JP +2
374 SEC
375
376 m4_delay(HOLD_DELAY_CYCLES - 10)
377
378 A = CMP11 ; bit loop counter
379 Y = A ; use Y to avoid corrupting carry bit with subtract
380 DECY
381 A = Y
382 CMP11 = A
383 JP :sub_shift_tdio_bits__loop
384
385 ; shift last TDO bit into result
386 A = MASK
387 A += MASK
388 DATA_BUFFER1 = A
389 ADR_BUFFER1 += X
390
391 A = CMP00 ; return to caller
392 BRANCH
393
394
395 ;------------------------------------------------------------------------------
396 :opcode_shift_tms_tdi_bit_pair
397 ;
398
399 ; set TMS line manually
400 A = CMP01 ; bits 3..0 contain TDI and TMS bits and whether to return TDO
401 BSET 0 ; TMS bit
402 A.L = 0x1 ; TMS=1
403 JP +2
404 A.L = 0x0 ; TMS=0
405 DR_CARD = A
406
407 ; stuff command buffer with bitmap of single TDI bit
408 A = CMP01
409 BSET 1 ; TDI bit
410 A.H = 0x8 ; TDI=1
411 JP +2
412 A.H = 0x0 ; TDI=0
413 ADR_BUFFER0 -= X
414 DATA_BUFFER0 = A
415
416 A.H = 0
417 A.L = 0
418 CMP11 = A ; bit loop counter (only doing one bit)
419
420 A.H = opcode_shift_tms_tdi_bit_pair__sub_return
421 A.L = opcode_shift_tms_tdi_bit_pair__sub_return
422 CMP00 = A ; return address
423
424 ; jump this way due to relative jump range issues
425 A.H = sub_shift_tdio_bits
426 A.L = sub_shift_tdio_bits
427 BRANCH
428 opcode_shift_tms_tdi_bit_pair__sub_return:
429
430 A = CMP01
431 BSET 3 ; bit says whether to return TDO
432 JP +2
433 ADR_BUFFER1 -= X ; subroutine returns it, so undo that
434
435 A = X
436 DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
437 BRANCH
438
439
440 ;------------------------------------------------------------------------------
441 :opcode_shift_tms_bits
442 ;
443
444 A = CMP01 ; bits 3..0 contain the number of bits to shift - 1 (only 1-8 bits is valid... no checking, just improper operation)
445 A.H = 0
446 CMP11 = A ; bit loop counter
447
448 A = DATA_BUFFER0 ; get byte from input buffer
449 ADR_BUFFER0 += X
450 MASK = A ; The byte we'll be shifting
451
452 :opcode_shift_tms_bits__loop
453 m4_delay_setup(SETUP_DELAY_CYCLES - 1)
454
455 A = MASK ; shift TMS out of MASK via carry
456 A += MASK
457 MASK = A
458
459 ; shifting out TMS
460 A.L = 0x1 ; TCK=0, TDI=0, TMS=1
461 CP CARRY
462 JP +2
463 A.L = 0x0 ; TCK=0, TDI=0, TMS=0
464 DR_CARD = A
465 DR_MPEG = A
466
467 m4_delay_loop(SETUP_DELAY_CYCLES - 1)
468
469 BSET 2 ; TCK high
470 DR_MPEG = A
471
472 m4_delay(HOLD_DELAY_CYCLES - 10)
473
474 A = CMP11 ; bit loop counter
475 CP A=>X
476 CLC
477 A -= X
478 CMP11 = A
479 JP :opcode_shift_tms_bits__loop
480
481 A = X
482 DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
483 BRANCH
484
485

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)