File: urjtag-python.txt

package info (click to toggle)
liburjtag 2024.03.24-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 16,492 kB
  • sloc: ansic: 53,835; yacc: 2,159; lex: 1,545; vhdl: 1,324; makefile: 1,249; python: 72; sed: 16; sh: 11
file content (234 lines) | stat: -rw-r--r-- 6,902 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

Python bindings for liburjtag: a brief introduction.


Python bindings will be built automaticly if urjtag's configure
process detects python and its necessary development libraries.

To require a urjtag build with python, and fail if the python
prerequesites aren't found, explicitly mention python to configure:
	      ./configure --enable-python

Configure can also be told to ignore python entirely:
	      ./configure --disable-python

If the interpreter for your preferred python version is named somthing
besides python, or is not in your path, you can set $PYTHON in the
environment before calling configure.  For example, to build
additional python version 3 bindings in an OS where "python" is
version 2.7, run:

  PYTHON=python3 ./configure --enable-python




So much for building. In order to use urjtag from python, we must
import its module into our program or interactive session.

 import urjtag



About all we can do directly in the urjtag module is change
the urjag logging verbosity level:

 urjtag.loglevel( urjtag.URJ_LOG_LEVEL_ALL )
 urjtag.loglevel( urjtag.URJ_LOG_LEVEL_WARNING )
 urjtag.loglevel( urjtag.URJ_LOG_LEVEL_SILENT )


The must fundamental object in urjtag is the chain, and to do anything
else we need to create one:

 urc = urjtag.chain()

An empty, disconnected chain isn't very useful.  In order to use a
chain object, we must specify the interface and cable type used to
connect to it.

 urc.cable("JTAGKey")

Some cables let you query and change the frequency at which they operate:

 f = urc.get_frequency()
 urc.set_frequency(1000000)  # TCK frequency in Hz


To detect what chips are on the chain:

 urc.tap_detect()

After calling detect, we can query how many devices are on the chain,
and what their IDCODE values are.  The idcode returned by partid() is
an integer; you'll typicaly want to print it in hex.

 length = urc.len()
 for i in range(0,urc.len()):
     idcode = urc.partid(0)
     print "[%d] 0x%08x" % (i, idcode)

Optionally, urc.tap_detect may be called with an integer argument that
specifies the maximum combined length of all instruction registers expected to
be on the jtag chain:
   maxirlen = 90
   urc.tap_detect(maxirlen)
Specifying a smaller value than the default 1024 can make detect return faster
if the cable is disconnected or the chain is broken.  Specifying a larger value
may be necessary for very long jtag chains.


Some devices implement the TRST signal:

 urc.set_trst(0)    	   # assert TRST
 urc.set_trst(1)	   # deassert TRST


Other devices and chains use JTAG synchronous reset, using TCK and TMS:

 urc.reset()

Some cables impelment a non-JTAG system reset signal and allow
directly manipulating other signals:
 urc.set_pod_signal(urjtag.URJ_POD_CS_RESET, 0)
 urc.set_pod_signal(urjtag.URJ_POD_CS_RESET, 1)
 v = urc.get_pod_signal(urjtag.URJ_POD_CS_RESET)




A jtag chain object keeps track of a current instruction and a current part.

 urc.part(0)
 urc.set_instruction("SAMPLE/PRELOAD")
 urc.set_instruction("IDCODE")
 urc.set_instruction("EXTEST")

To shift the instruction stored in the chain object into the actual hardware,
we must call shift_ir:

 urc.shift_ir()

For each data register, the chain object tracks two values.
The "input" register value is sent to the device(s) on the TDI pin,
and changes the device's status in the DR_UPDATE state.  The "output"
register value is built up of the values observed on the TDO pin.
The shift_dr method performs a complete data register shift operation:

 inval = urc.get_dr_in_string()
 print "BSR dr_in", inval
 urc.shift_dr()
 outval = urc.get_dr_out_string()
 printf "BSR dr_out", outval

Both holding registers can be modified:

 s = "1001001001"
 urc.set_dr_in_string(s)
 urc.set_dr_out_string(s)

More commonly, you'll want to change only a few bits.  This can be
done with strings and lists.  Note that the ascii strings of '1' and
'0' representing binary values print with bit 0 last, the way you'd
typicaly write a binary number.  But the indexes of entries in a list
or string count from the left.

 drval = urc.get_dr_in()
 drlen=len(drval)
 drl = list(drval);
 drl[drlen-1-13] = '1';
 drl[drlen-1-14] = '0';
 ndrval = "".join(drl);
 urc.set_dr_in(ndrval)

But there is an easier way to set a single bit of a register:

 urc.set_dr_out(1, 13);
 urc.set_dr_out(0, 14);


Retrieving and setting contiguous subfields of a register (up to 64
bits) is also possible:

 urc.set_dr_out(0x0d, 4, 7);
 r = urc.get_dr_out(4,7);
 drval = urc.get_dr_out_string();
 printf("  set_dr_out result: %s %02x\n", drval, r)

Remember to call shift_dr() before making use of values read with get_dr_in(),
and after changing values written with set_dr_out().



Urjtag register objects

When using multiple data registers, not remembering to call set_instruction
and shift_ir before doing set_dr and shift_dr can lead to annoying
bugs.  Avoid this and write cleaner code by obtaining a python object
corresponding to each data register:

 # part 0, data register FOOREG, using instruction INSTFOO
 regf = urc.get_register(0, 'FOOREG', 'INSTFOO');
 # part 1, BARREG, INSTBAR1
 regb = urc.get_register(1, 'BARREG', 'INSTBAR1');

 regf.set_dr_out(0, 3, 7);
 regb.set_dr_out(1, 8, 5);
 regf.shift_dr();
 regb.shift_dr();
 regb.shift_dr('INSTBAR2');  // use alternate instruction with BARREG

 v = regb.get_dr_in(15, 11);
 s = regf.get_dr_in_string();

Calling shift_dr on a register object has the same effect as calling
chain.part() followed by chain.set_instruction().




Sometimes your chip isn't known to urjtag's database.  You can
create a .jtag file and add it to the database (usually in
/usr/share/urjtag or /usr/local/share/urjtag).
Or, you can access it by adding it specialy within your script.

 urc = urjtag.chain()
 urc.cable("JTAGKey")
 urc.reset();

 urc.addpart(8); # instruction length of the one chip on your chain.

 urc.add_instruction("CLAMP", "11101110", BYPASS) # another instruction that selects the BYPASS register.  The bypass register always exists.

 urc.add_register("IDREG", 32);  # another register, with its  length
 urc.add_instruction("IDCODE", "11111110", "IDREG");  #

Then you can set and scan the new registers:

 urc.set_instruction("IDCODE")
 urc.shift_ir()
 urc.shift_dr()
 print urc.get_dr_out_string()


SVF files can be applied to a chain:

 urc.run_svf(filename, stop=0, ref_freq=0)



Bus support within the python bindings works somewhat like the jtag
program's interactive mode.  It is not properly object oriented yet.

 urc.initbus("foo", "bar");

FUTURE: urc.initbus will return a urjtag.bus object.  Currently, there is one
implicit global bus, and only one bus can be active at a time.

 urc.detectflash(i)
 val = urc.peek(addr)
 urc.poke(addr,val)
 urc.flashmem(options, filename, noverify=0)

FUTURE: detectflash, peek, poke, and flashmem will be a methods in a new
urjtag.bus class, not methods of urjtag.chain.